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 com.jsql.model.injection.strategy.blind.patch.Diff;
7   import com.jsql.model.injection.strategy.blind.patch.DiffMatchPatch;
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 DiffMatchPatch DIFF_MATCH_PATCH = new DiffMatchPatch();
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              try {  // Fix #96195: NullPointerException on contains()
67                  // Fix #4386: NullPointerException on contains(), diffsWithReference initialized to new LinkedList<>()
68                  if (this.diffsWithReference.contains(falseDiff)) {
69                      return false;
70                  }
71              } catch (NullPointerException e) {
72                  return false;
73              }
74          }
75          List<Diff> trueDiffs = new CopyOnWriteArrayList<>(this.injectionBlind.getTrueDiffs());
76          for (Diff trueDiff: trueDiffs) {
77              try {  // Fix #96134: NullPointerException on contains()
78                  if (!this.diffsWithReference.contains(trueDiff)) {  // required, set to false when empty falseDiffs
79                      return false;
80                  }
81              } catch (NullPointerException e) {
82                  return false;
83              }
84          }
85          return true;  // not in falseDiffs and in trueDiffs
86      }
87  
88      /**
89       * Process the URL HTTP call, use function inject() from the model.
90       * Build the list of differences found between TRUE and the current page.
91       * @return Functional Blind Callable
92       */
93      @Override
94      public CallableBlindBit call() {
95          String result = this.injectionBlind.callUrl(this.booleanUrl, this.metadataInjectionProcess, this);
96          this.diffsWithReference = CallableBlindBit.DIFF_MATCH_PATCH.diffMain(this.injectionBlind.getSourceReferencePage(), result, true);
97          CallableBlindBit.DIFF_MATCH_PATCH.diffCleanupEfficiency(this.diffsWithReference);
98          return this;
99      }
100 
101     public List<Diff> getDiffsWithReference() {
102         return this.diffsWithReference;
103     }
104 }