Skip to content

Commit

Permalink
Add database vendor blind fingerprinting
Browse files Browse the repository at this point in the history
- Improve falsy/truthy lists on Oracle
- Improve failsafe on Oracle
- Improve mode order on Blind/Time
- Improve characters insertion order
- Remove intermediate jdk20 from GH workflow
- Add TryHackMe and Burp labs to Scan list
- Upgrade dependencies version
  • Loading branch information
ron190 committed Jul 15, 2024
1 parent 997cc14 commit 6911976
Show file tree
Hide file tree
Showing 57 changed files with 559 additions and 182 deletions.
9 changes: 1 addition & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,9 @@ jobs:
- jdk: 3.8.6-eclipse-temurin-18
nashorn: ''
bytebuddy: ''
isPublishing: 'true'
- jdk: 3.9.3-eclipse-temurin-20
nashorn: ''
bytebuddy: ''
isPublishing: 'false'
- jdk: 3.9.7-eclipse-temurin-21
nashorn: ''
bytebuddy: '-Dnet.bytebuddy.experimental=true'
isPublishing: 'false'
# Groovy not compatible jdk22: gmavenplus-plugin JsonUtilSpock.groovy Unsupported class file major version 66
# - jdk: 3.9.7-eclipse-temurin-22
# nashorn: ""
Expand All @@ -34,7 +28,6 @@ jobs:
MAVEN_NASHORN: ${{ matrix.nashorn }}
# experimental enabled on jdk21 to prevent 'Mockito cannot mock this class: class org.jsoup.nodes.Document'
MAVEN_BYTEBUDDY: ${{ matrix.bytebuddy }}
IS_PUBLISHING: ${{ matrix.isPublishing }}
DOCKER_RESOURCES: ${{ inputs.DOCKER_RESOURCES }}
steps:

Expand Down Expand Up @@ -107,7 +100,7 @@ jobs:

- name: Coverage and site
uses: ./.github/workflows/publish-scan/
if: env.IS_PUBLISHING == 'true'
if: matrix.jdk == '3.8.6-eclipse-temurin-18'
with: # composite cannot use secrets directly
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
9 changes: 5 additions & 4 deletions model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,22 @@
<groovy-test-junit5.version>4.0.13</groovy-test-junit5.version>
<h2.version>2.2.224</h2.version>
<hsqldb.version>2.7.3</hsqldb.version>
<informix.jdbc.version>4.50.10.2</informix.jdbc.version>
<informix.jdbc.version>4.50.11</informix.jdbc.version>
<javafaker.version>1.0.2</javafaker.version>
<jaxb-api.version>2.1</jaxb-api.version>
<jaybird.version>5.0.5.java11</jaybird.version>
<jcabi-log.version>0.24.1</jcabi-log.version>
<jna.version>5.14.0</jna.version>
<jquery.version>3.7.1</jquery.version>
<json.version>20240303</json.version>
<jsoup.version>1.17.2</jsoup.version>
<jsoup.version>1.18.1</jsoup.version>
<junit-pioneer.version>2.2.0</junit-pioneer.version>
<juniversalchardet.version>1.0.3</juniversalchardet.version>
<maven-failsafe-plugin.version>3.3.0</maven-failsafe-plugin.version>
<mckoisqldb.version>1.0.5</mckoisqldb.version>
<mimjdbc.version>3.42.3</mimjdbc.version>
<monetdb-jdbc.version>2.29</monetdb-jdbc.version>
<mssql-jdbc.version>12.4.2.jre8</mssql-jdbc.version>
<mssql-jdbc.version>12.6.3.jre11</mssql-jdbc.version>
<mysql-connector-j.version>9.0.0</mysql-connector-j.version>
<nashorn-core.version>15.4</nashorn-core.version>
<neo4j-java-driver.version>5.22.0</neo4j-java-driver.version>
Expand All @@ -86,6 +86,7 @@
<sockjs-client.version>1.5.1</sockjs-client.version>
<spock-core.version>2.4-M4-groovy-4.0</spock-core.version>
<spring-boot-dependencies.version>3.3.1</spring-boot-dependencies.version>
<springloaded.version>1.2.8.RELEASE</springloaded.version>
<sqlite-jdbc.version>3.46.0.0</sqlite-jdbc.version>
<sqlite-dialect.version>0.1.4</sqlite-dialect.version>
<stomp-websocket.version>2.3.4</stomp-websocket.version>
Expand Down Expand Up @@ -514,7 +515,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
<version>${springloaded.version}</version>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
Expand Down
3 changes: 2 additions & 1 deletion model/src/main/java/com/jsql/model/InjectionModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.jsql.model.bean.util.Interaction;
import com.jsql.model.bean.util.Request;
import com.jsql.model.exception.JSqlException;
import com.jsql.model.exception.JSqlRuntimeException;
import com.jsql.model.injection.method.AbstractMethodInjection;
import com.jsql.model.injection.method.MediatorMethod;
import com.jsql.model.injection.strategy.MediatorStrategy;
Expand Down Expand Up @@ -207,7 +208,7 @@ public void beginInjection() {
LOGGER.log(LogLevelUtil.IGNORE, e, e);
Thread.currentThread().interrupt();

} catch (JSqlException | IOException e) { // Catch expected exceptions only
} catch (JSqlRuntimeException | JSqlException | IOException e) { // Catch expected exceptions only

if (e.getMessage() == null) {
LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Unexpected: {}", getImplicitReason(e));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.jsql.model.exception;

public class JSqlRuntimeException extends RuntimeException {

public JSqlRuntimeException(String message) {
super(message);
}

public JSqlRuntimeException(String message, Throwable e) {
super(message, e);
}

public JSqlRuntimeException(Throwable e) {
super(null, e); // get only original implicit reason
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.jsql.model.exception.JSqlException;
import com.jsql.model.injection.vendor.model.VendorYaml;
import com.jsql.model.suspendable.SuspendableGetCharInsertion;
import com.jsql.model.suspendable.SuspendableGetVendor;
import com.jsql.util.LogLevelUtil;
import com.jsql.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -177,6 +178,10 @@ public boolean testStrategies(SimpleEntry<String, String> parameterToInject) thr
);
}

if (this.injectionModel.getMediatorVendor().getVendorByUser() == this.injectionModel.getMediatorVendor().getAuto()) {
new SuspendableGetVendor(this.injectionModel).run();
}

// Test each injection strategies: time < blind < error < normal
// Choose the most efficient strategy: normal > error > blind > time
this.time.checkApplicability();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ public void checkApplicability() throws StoppedByUserSlidingException {
return;
}

checkInjection(BooleanMode.STACKED);
checkInjection(BooleanMode.NO_MODE);
checkInjection(BooleanMode.OR);
checkInjection(BooleanMode.AND);
checkInjection(BooleanMode.STACKED);
checkInjection(BooleanMode.NO_MODE);

if (this.isApplicable) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ public void checkApplicability() throws StoppedByUserSlidingException {
return;
}

checkInjection(BooleanMode.STACKED);
checkInjection(BooleanMode.NO_MODE);
checkInjection(BooleanMode.OR);
checkInjection(BooleanMode.AND);
checkInjection(BooleanMode.STACKED);
checkInjection(BooleanMode.NO_MODE);

if (this.isApplicable) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ public abstract class AbstractInjectionBoolean<T extends AbstractCallableBoolean

// Every FALSE SQL statements will be checked,
// more statements means a more robust application
protected final List<String> falseTests;
protected final List<String> falsy;

// Every TRUE SQL statements will be checked,
// more statements means a more robust application
protected final List<String> trueTests;
protected final List<String> truthy;

public enum BooleanMode {
AND, OR, STACKED, NO_MODE
Expand All @@ -46,8 +46,8 @@ protected AbstractInjectionBoolean(InjectionModel injectionModel, BooleanMode bo

this.injectionModel = injectionModel;
this.booleanMode = booleanMode;
this.falseTests = this.injectionModel.getMediatorVendor().getVendor().instance().getListFalseTest();
this.trueTests = this.injectionModel.getMediatorVendor().getVendor().instance().getListTrueTest();
this.falsy = this.injectionModel.getMediatorVendor().getVendor().instance().getFalsy();
this.truthy = this.injectionModel.getMediatorVendor().getVendor().instance().getTruthy();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.jsql.model.injection.strategy.blind;

import com.jsql.model.injection.strategy.blind.patch.Diff;
import com.jsql.model.injection.strategy.blind.patch.DiffMatchPatch;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CallableVendor extends AbstractCallableBoolean<CallableVendor> {

// List of differences found between the reference page, and the present page
private LinkedList<Diff> opcodes = new LinkedList<>();

private static final DiffMatchPatch DIFF_MATCH_PATCH = new DiffMatchPatch();

private final InjectionVendor injectionCharInsertion;

private final String metadataInjectionProcess;

public CallableVendor(String inj, InjectionVendor injectionCharInsertion, String metadataInjectionProcess) {

this.injectionCharInsertion = injectionCharInsertion;
this.metadataInjectionProcess = metadataInjectionProcess;
this.booleanUrl = inj;
}

@Override
public boolean isTrue() {

List<Diff> copyTrueMarks = new CopyOnWriteArrayList<>(this.injectionCharInsertion.getConstantTrueMark());
for (Diff trueDiff: copyTrueMarks) {
if (!this.opcodes.contains(trueDiff)) {
return false;
}
}

return true;
}

@Override
public CallableVendor call() {

String source = this.injectionCharInsertion.callUrl(this.booleanUrl, this.metadataInjectionProcess, this);

this.opcodes = CallableVendor.DIFF_MATCH_PATCH.diffMain(
this.injectionCharInsertion.getBlankFalseMark(),
source,
false
);

CallableVendor.DIFF_MATCH_PATCH.diffCleanupEfficiency(this.opcodes);

return this;
}

public List<Diff> getOpcodes() {
return this.opcodes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public InjectionBlind(InjectionModel injectionModel, BooleanMode blindMode) {
super(injectionModel, blindMode);

// No blind
if (this.falseTests.isEmpty() || this.injectionModel.isStoppedByUser()) {
if (this.falsy.isEmpty() || this.injectionModel.isStoppedByUser()) {
return;
}

Expand All @@ -59,7 +59,7 @@ public InjectionBlind(InjectionModel injectionModel, BooleanMode blindMode) {
ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetBlindTagFalse");
Collection<CallableBlind> callablesFalseTest = new ArrayList<>();

for (String falseTest: this.falseTests) {
for (String falseTest: this.falsy) {
callablesFalseTest.add(new CallableBlind(
falseTest,
injectionModel,
Expand Down Expand Up @@ -111,7 +111,7 @@ private void cleanTrueDiffs(InjectionModel injectionModel, BooleanMode blindMode

Collection<CallableBlind> callablesTrueTest = new ArrayList<>();

for (String trueTest: this.trueTests) {
for (String trueTest: this.truthy) {
callablesTrueTest.add(new CallableBlind(
trueTest,
injectionModel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class InjectionCharInsertion {

private static final String PREFIX = "prefix";

private final List<String> falseTest;
private final List<String> falsy;

/**
* Create blind attack initialization.
Expand All @@ -56,11 +56,11 @@ public InjectionCharInsertion(InjectionModel injectionModel, String falseCharIns
this.injectionModel = injectionModel;
this.prefixSuffix = prefixSuffix;

List<String> trueTest = this.injectionModel.getMediatorVendor().getVendor().instance().getListTrueTest();
this.falseTest = this.injectionModel.getMediatorVendor().getVendor().instance().getListFalseTest();
List<String> truthy = this.injectionModel.getMediatorVendor().getVendor().instance().getTruthy();
this.falsy = this.injectionModel.getMediatorVendor().getVendor().instance().getFalsy();

// No blind
if (trueTest.isEmpty() || this.injectionModel.isStoppedByUser()) {
if (truthy.isEmpty() || this.injectionModel.isStoppedByUser()) {
return;
}

Expand All @@ -75,7 +75,7 @@ public InjectionCharInsertion(InjectionModel injectionModel, String falseCharIns
ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableCharInsertionTagTrue");
Collection<CallableCharInsertion> listCallableTagTrue = new ArrayList<>();

for (String urlTest: trueTest) {
for (String urlTest: truthy) {
listCallableTagTrue.add(
new CallableCharInsertion(
String.join(
Expand Down Expand Up @@ -127,7 +127,7 @@ private void initializeFalseMarks() {
ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetBlindTagTrue");
Collection<CallableCharInsertion> listCallableTagFalse = new ArrayList<>();

for (String urlTest: this.falseTest) {
for (String urlTest: this.falsy) {
listCallableTagFalse.add(
new CallableCharInsertion(
String.join(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public InjectionTime(InjectionModel injectionModel, BooleanMode booleanMode) {
super(injectionModel, booleanMode);

// No blind
if (this.falseTests.isEmpty() || this.injectionModel.isStoppedByUser()) {
if (this.falsy.isEmpty() || this.injectionModel.isStoppedByUser()) {
return;
}

Expand All @@ -50,7 +50,7 @@ public InjectionTime(InjectionModel injectionModel, BooleanMode booleanMode) {
ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetTimeTagFalse");
Collection<CallableTime> callablesFalseTest = new ArrayList<>();

for (String falseTest: this.falseTests) {
for (String falseTest: this.falsy) {
callablesFalseTest.add(new CallableTime(
falseTest,
injectionModel,
Expand Down Expand Up @@ -97,7 +97,7 @@ private void checkTrueTests(BooleanMode booleanMode) {
ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableGetTimeTagTrue");
Collection<CallableTime> callablesTrueTest = new ArrayList<>();

for (String trueTest: this.trueTests) {
for (String trueTest: this.truthy) {
callablesTrueTest.add(new CallableTime(
trueTest,
this.injectionModel,
Expand Down
Loading

0 comments on commit 6911976

Please sign in to comment.