CallableBlindBin.java
package com.jsql.model.injection.strategy.blind.callable;
import com.jsql.model.InjectionModel;
import com.jsql.model.injection.strategy.blind.AbstractInjectionBit.BlindOperator;
import com.jsql.model.injection.strategy.blind.InjectionBlindBin;
import name.fraser.neil.plaintext.diff_match_patch;
import static name.fraser.neil.plaintext.diff_match_patch.Diff;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Define a call HTTP to the server, require the associated url, character
* position and bit. Diffs represent the differences between
* the reference page, and the current page.
*/
public class CallableBlindBin extends AbstractCallableBit<CallableBlindBin> {
private final int low;
private final int mid;
private final int high;
private LinkedList<Diff> diffsWithReference = new LinkedList<>(); // List of differences found between the reference page, and the current page
private static final diff_match_patch DIFF_MATCH_PATCH = new diff_match_patch();
private final InjectionBlindBin injectionBlind;
private final InjectionModel injectionModel;
private final String metadataInjectionProcess;
/**
* Constructor for preparation and blind confirmation.
*/
public CallableBlindBin(
String sqlQuery,
InjectionModel injectionModel,
InjectionBlindBin injectionBlind,
BlindOperator blindMode,
int low, int mid, int high,
String metadataInjectionProcess
) {
this.isBinary = true;
this.low = low;
this.mid = mid;
this.high = high;
this.injectionModel = injectionModel;
this.injectionBlind = injectionBlind;
this.metadataInjectionProcess = metadataInjectionProcess;
this.booleanUrl = this.injectionModel.getMediatorVendor().getVendor().instance().sqlTestBlindWithOperator(sqlQuery, blindMode);
}
/**
* Constructor for bits test.
*/
public CallableBlindBin(
String sqlQuery,
int indexChar,
InjectionModel injectionModel,
InjectionBlindBin injectionBlind,
BlindOperator blindMode,
int low, int mid, int high,
String metadataInjectionProcess
) {
this(sqlQuery, injectionModel, injectionBlind, blindMode, low, mid, high, metadataInjectionProcess);
this.booleanUrl = this.injectionModel.getMediatorVendor().getVendor().instance().sqlBlindBin(sqlQuery, indexChar, mid, blindMode);
this.currentIndex = indexChar;
}
/**
* Check if a result page means the SQL query is true,
* confirm that nothing in the resulting page is also defined
* in the pages from every FALSE SQL queries.
* @return true if the current SQL query is true
*/
@Override
public boolean isTrue() {
// Fix #95426: ConcurrentModificationException on iterator.next()
List<Diff> falseDiffs = new CopyOnWriteArrayList<>(this.injectionBlind.getFalseDiffs());
for (Diff falseDiff: falseDiffs) {
// Fix #4386: NullPointerException on contains()
// diffsWithReference is initialized to an empty new LinkedList<>()
if (this.diffsWithReference.contains(falseDiff)) {
return false;
}
}
return true;
}
/**
* Process the URL HTTP call, use function inject() from the model.
* Build the list of differences found between TRUE and the current page.
* @return Functional Blind Callable
*/
@Override
public CallableBlindBin call() {
String result = this.injectionBlind.callUrl(this.booleanUrl, this.metadataInjectionProcess, this);
this.diffsWithReference = CallableBlindBin.DIFF_MATCH_PATCH.diff_main(this.injectionBlind.getSourceReferencePage(), result, true);
CallableBlindBin.DIFF_MATCH_PATCH.diff_cleanupEfficiency(this.diffsWithReference);
return this;
}
public List<Diff> getDiffsWithReference() {
return this.diffsWithReference;
}
public int getLow() {
return this.low;
}
public int getMid() {
return this.mid;
}
public int getHigh() {
return this.high;
}
}