View Javadoc
1   package com.jsql.model.suspendable;
2   
3   import com.jsql.model.InjectionModel;
4   import com.jsql.model.exception.JSqlException;
5   import com.jsql.model.exception.StoppedByUserSlidingException;
6   import com.jsql.model.injection.vendor.model.VendorYaml;
7   import com.jsql.model.suspendable.callable.CallablePageSource;
8   import com.jsql.util.LogLevelUtil;
9   import org.apache.commons.lang3.StringUtils;
10  import org.apache.logging.log4j.LogManager;
11  import org.apache.logging.log4j.Logger;
12  
13  import java.util.concurrent.CompletionService;
14  import java.util.concurrent.ExecutionException;
15  import java.util.concurrent.ExecutorCompletionService;
16  import java.util.concurrent.ExecutorService;
17  import java.util.regex.Pattern;
18  
19  /**
20   * Runnable class, search the correct number of fields in the SQL query.
21   * Concurrent search with stop capability
22   */
23  public class SuspendableGetIndexes extends AbstractSuspendable {
24      
25      /**
26       * Log4j logger sent to view.
27       */
28      private static final Logger LOGGER = LogManager.getRootLogger();
29      
30      public SuspendableGetIndexes(InjectionModel injectionModel) {
31          super(injectionModel);
32      }
33  
34      @Override
35      public String run(Object... args) throws JSqlException {
36          // Concurrent search
37          ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetIndexes");
38          CompletionService<CallablePageSource> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
39  
40          String initialQuery = StringUtils.EMPTY;
41          int nbIndex;
42          
43          int countUnionIndex = this.injectionModel.getMediatorUtils().getPreferencesUtil().isLimitingUnionIndex()
44              ? this.injectionModel.getMediatorUtils().getPreferencesUtil().countUnionIndex()
45              : 50;
46  
47          // SQL fields are built like 1337[index]7330+1
48          // 7330+1 allows to exclude false positive when page contains injection URL
49          // Search if the source contains 1337[index]7331
50          for (nbIndex = 1 ; nbIndex <= countUnionIndex ; nbIndex++) {
51              taskCompletionService.submit(
52                  new CallablePageSource(
53                      this.injectionModel.getMediatorVendor().getVendor().instance().sqlIndices(nbIndex),
54                      this.injectionModel,
55                      "union#" + nbIndex,
56                      nbIndex
57                  )
58              );
59          }
60          
61          nbIndex = 1;
62          try {
63              while (nbIndex <= countUnionIndex) {
64                  if (this.isSuspended()) {
65                      throw new StoppedByUserSlidingException();
66                  }
67                  CallablePageSource currentCallable = taskCompletionService.take().get();
68                  nbIndex++;
69                  // Found a correct mark 1337[index]7331 in the source
70                  String regexAllIndexes = String.format(VendorYaml.FORMAT_INDEX, "\\d+");
71                  if (Pattern.compile("(?s).*"+ regexAllIndexes +".*").matcher(currentCallable.getContent()).matches()) {
72                      
73                      this.injectionModel.getMediatorStrategy().getSpecificUnion().setNbIndexesFound(currentCallable.getNbIndex());
74                      this.injectionModel.getMediatorStrategy().getSpecificUnion().setSourceIndexesFound(currentCallable.getContent());
75                      initialQuery = currentCallable.getQuery().replace("0%2b1", "1");
76                      
77                      if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isPerfIndexDisabled()) {
78                          String regexIndexesExceptFirst = String.format(VendorYaml.FORMAT_INDEX, "(?!17331)\\d+");
79                          initialQuery = initialQuery.replaceAll(regexIndexesExceptFirst, "1");
80                          LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "Calibrating indexes disabled, forcing to index [1]");
81                      }
82                      LOGGER.log(
83                          LogLevelUtil.CONSOLE_INFORM,
84                          "Strategy [Union] triggered by [{}]",
85                          () -> currentCallable.getQuery().trim()
86                          .replaceAll("1337(\\d*)7330%2b1", "$1")
87                          .replaceAll("\\s+", StringUtils.SPACE)
88                      );
89                      break;
90                  }
91              }
92              this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor);
93          } catch (InterruptedException e) {
94              LOGGER.log(LogLevelUtil.IGNORE, e, e);
95              Thread.currentThread().interrupt();
96          } catch (ExecutionException e) {
97              LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
98          }
99          return initialQuery;
100     }
101 }