View Javadoc
1   package com.jsql.model.injection.strategy.blind.callable;
2   
3   import com.jsql.model.InjectionModel;
4   import com.jsql.model.injection.strategy.blind.AbstractInjectionBit.BlindOperator;
5   import com.jsql.model.injection.strategy.blind.InjectionBlindBit;
6   import name.fraser.neil.plaintext.diff_match_patch;
7   import static name.fraser.neil.plaintext.diff_match_patch.Diff;
8   
9   import java.util.LinkedList;
10  import java.util.List;
11  import java.util.concurrent.CopyOnWriteArrayList;
12  
13  /**
14   * Define a call HTTP to the server, require the associated url, character
15   * position and bit. Diffs represent the differences between
16   * the reference page, and the current page.
17   */
18  public class CallableBlindBit extends AbstractCallableBit<CallableBlindBit> {
19      
20      private LinkedList<Diff> diffsWithReference = new LinkedList<>();  // List of differences found between the reference page, and the current page
21      private static final diff_match_patch DIFF_MATCH_PATCH = new diff_match_patch();
22      private final InjectionBlindBit injectionBlind;
23      
24      private final InjectionModel injectionModel;
25      private final String metadataInjectionProcess;
26      
27      /**
28       * Constructor for preparation and blind confirmation.
29       */
30      public CallableBlindBit(String sqlQuery, InjectionModel injectionModel, InjectionBlindBit injectionBlind, BlindOperator blindOperator, String metadataInjectionProcess) {
31          this.injectionModel = injectionModel;
32          this.injectionBlind = injectionBlind;
33          this.metadataInjectionProcess = metadataInjectionProcess;
34          this.booleanUrl = this.injectionModel.getMediatorVendor().getVendor().instance().sqlTestBlindWithOperator(sqlQuery, blindOperator);
35      }
36      
37      /**
38       * Constructor for bits test.
39       */
40      public CallableBlindBit(
41          String sqlQuery,
42          int indexChar,
43          int bit,
44          InjectionModel injectionModel,
45          InjectionBlindBit injectionBlind,
46          BlindOperator blindOperator,
47          String metadataInjectionProcess
48      ) {
49          this(sqlQuery, injectionModel, injectionBlind, blindOperator, metadataInjectionProcess);
50          this.booleanUrl = this.injectionModel.getMediatorVendor().getVendor().instance().sqlBlindBit(sqlQuery, indexChar, bit, blindOperator);
51          this.currentIndex = indexChar;
52          this.currentBit = bit;
53      }
54  
55      /**
56       * Check if a result page means the SQL query is true,
57       * confirm that nothing in the resulting page is also defined
58       * in the pages from every FALSE SQL queries.
59       * @return true if the current SQL query is true
60       */
61      @Override
62      public boolean isTrue() {
63          // Fix #95426: ConcurrentModificationException on iterator.next()
64          List<Diff> falseDiffs = new CopyOnWriteArrayList<>(this.injectionBlind.getFalseDiffs());
65          for (Diff falseDiff: falseDiffs) {  // ignored when false OR false => falsy empty
66              // Fix #4386: NullPointerException on contains(), diffsWithReference initialized to new LinkedList<>()
67              if (this.diffsWithReference.contains(falseDiff)) {
68                  return false;
69              }
70          }
71          List<Diff> trueDiffs = new CopyOnWriteArrayList<>(this.injectionBlind.getTrueDiffs());
72          for (Diff trueDiff: trueDiffs) {
73              if (!this.diffsWithReference.contains(trueDiff)) {  // required, set to false when empty falseDiffs
74                  return false;
75              }
76          }
77          return true;  // not in falseDiffs and in trueDiffs
78      }
79  
80      /**
81       * Process the URL HTTP call, use function inject() from the model.
82       * Build the list of differences found between TRUE and the current page.
83       * @return Functional Blind Callable
84       */
85      @Override
86      public CallableBlindBit call() {
87          String result = this.injectionBlind.callUrl(this.booleanUrl, this.metadataInjectionProcess, this);
88          this.diffsWithReference = CallableBlindBit.DIFF_MATCH_PATCH.diff_main(this.injectionBlind.getSourceReferencePage(), result, true);
89          CallableBlindBit.DIFF_MATCH_PATCH.diff_cleanupEfficiency(this.diffsWithReference);
90          return this;
91      }
92      
93      public List<Diff> getDiffsWithReference() {
94          return this.diffsWithReference;
95      }
96  }