Skip to content

Commit

Permalink
SQLiPlugin: Use Comparable Response instead of Response Matcher
Browse files Browse the repository at this point in the history
Signed-off-by: ganesh-dagadi <[email protected]>
  • Loading branch information
ganesh-dagadi committed Jan 28, 2024
1 parent dcee0ee commit 17536ad
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 197 deletions.
1 change: 1 addition & 0 deletions addOns/sqliplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed
- Update minimum ZAP version to 2.14.0.
- Maintenance changes.
- Changed ResponseMatcher to ComparableResponse for assessing similarity between responses.

## [15] - 2021-10-20
### Fixed
Expand Down
2 changes: 1 addition & 1 deletion addOns/sqliplugin/sqliplugin.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ crowdin {

dependencies {
zapAddOn("commonlib")

testImplementation(project(":testutils"))
implementation("org.jdom:jdom:2.0.2")
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.parosproxy.paros.network.HttpHeader;
import org.parosproxy.paros.network.HttpMessage;
import org.zaproxy.addon.commonlib.CommonAlertTag;
import org.zaproxy.addon.commonlib.http.ComparableResponse;
import org.zaproxy.zap.model.Tech;
import org.zaproxy.zap.model.TechSet;

Expand All @@ -54,6 +55,10 @@ public class SQLInjectionScanRule extends AbstractAppParamPlugin {
// ------------------------------------------------------------------
// Plugin Constants
// ------------------------------------------------------------------

// Similarity ratio required to determine if two responses are similar (used in boolean based
// blind check)
private static final double REQUIRED_SIMILARITY = 0.90;
// Coefficient used for a time-based query delay checking (must be >= 7)
public static final int TIME_STDEV_COEFF = 7;
// Standard deviation after which a warning message should be displayed about connection lags
Expand Down Expand Up @@ -114,7 +119,7 @@ public class SQLInjectionScanRule extends AbstractAppParamPlugin {
private static final Pattern randstrPattern = Pattern.compile("\\[RANDSTR(?:\\d+)?\\]");

// Internal dynamic properties
private final ResponseMatcher responseMatcher;
private ComparableResponse originalResponse;
private final List<Long> responseTimes;

private int lastRequestUID;
Expand All @@ -131,7 +136,6 @@ public class SQLInjectionScanRule extends AbstractAppParamPlugin {
*/
public SQLInjectionScanRule() {
responseTimes = new ArrayList<>();
responseMatcher = new ResponseMatcher();
lastRequestUID = 0;
lastErrorPageUID = -1;
}
Expand Down Expand Up @@ -601,6 +605,7 @@ public void scan(HttpMessage msg, String parameter, String value) {
// each plugin execution, then we have to work
// with message copies and use getNewMsg()
origMsg = getBaseMsg();
originalResponse = new ComparableResponse(origMsg, null);

// Threat the parameter original value according to the
// test's <where> tag
Expand Down Expand Up @@ -639,7 +644,7 @@ public void scan(HttpMessage msg, String parameter, String value) {
// exit the plugin
return;
}

originalResponse = new ComparableResponse(origMsg, payloadValue);
break;

case SQLiPayloadManager.WHERE_REPLACE:
Expand Down Expand Up @@ -678,12 +683,10 @@ public void scan(HttpMessage msg, String parameter, String value) {

// prepare string diff matcher
// cleaned by reflective values
// and according to the replacement
// logic set by the plugin
content = origMsg.getResponseBody().toString();
content = SQLiPayloadManager.removeReflectiveValues(content, payloadValue);
responseMatcher.setOriginalResponse(content);
responseMatcher.setLogic(where);
origMsg.setResponseBody(content);
originalResponse = new ComparableResponse(origMsg, payloadValue);

// -----------------------------------------------
// Check 1: Boolean-based blind SQL injection
Expand All @@ -710,7 +713,7 @@ public void scan(HttpMessage msg, String parameter, String value) {
cmpPayload = payloadValue + cmpPayload;

// Send False payload
// Useful to set first matchRatio on
// Useful to tune original to
// the False response content
tempMsg = sendPayload(parameter, cmpPayload, true);
if (tempMsg == null) {
Expand All @@ -722,9 +725,11 @@ public void scan(HttpMessage msg, String parameter, String value) {
content = tempMsg.getResponseBody().toString();
content =
SQLiPayloadManager.removeReflectiveValues(content, cmpPayload);
responseMatcher.setInjectedResponse(content);
// set initial matchRatio
responseMatcher.isComparable();
tempMsg.setResponseBody(content);

ComparableResponse tempResponse =
new ComparableResponse(tempMsg, cmpPayload);
originalResponse.tuneHeuristicsWithResponse(tempResponse);

// Perform the test's True request
tempMsg = sendPayload(parameter, reqPayload, true);
Expand All @@ -737,13 +742,12 @@ public void scan(HttpMessage msg, String parameter, String value) {
content = tempMsg.getResponseBody().toString();
content =
SQLiPayloadManager.removeReflectiveValues(content, reqPayload);
responseMatcher.setInjectedResponse(content);

tempMsg.setResponseBody(content);
tempResponse = new ComparableResponse(tempMsg, reqPayload);
// Check if the TRUE response is equal or
// at less strongly comparable respect to
// the Original response value
if (responseMatcher.isComparable()) {

if (this.isComparableToOriginal(tempResponse)) {
// Perform again the test's False request
tempMsg = sendPayload(parameter, cmpPayload, true);
if (tempMsg == null) {
Expand All @@ -756,13 +760,14 @@ public void scan(HttpMessage msg, String parameter, String value) {
content =
SQLiPayloadManager.removeReflectiveValues(
content, cmpPayload);
responseMatcher.setInjectedResponse(content);
tempMsg.setResponseBody(content);
tempResponse = new ComparableResponse(tempMsg, cmpPayload);

// Now check if the FALSE response is
// completely different from the
// Original response according to the
// responseMatcher ratio criteria
if (!responseMatcher.isComparable()) {
// required ratio criteria
if (!this.isComparableToOriginal(tempResponse)) {
// We Found IT!
// Now create the alert message
String info =
Expand Down Expand Up @@ -1195,20 +1200,26 @@ public boolean wasLastRequestDBMSError() {
* @param pageContent the content that need to be compared
* @return true if similar, false otherwise
*/
protected boolean isComparableToOriginal(String pageContent) {
responseMatcher.setInjectedResponse(pageContent);
return responseMatcher.isComparable();
}

/**
* Get the page comparison ration against the original content
*
* @param pageContent the content that need to be compared
* @param ComparableResponse that need to be compared
* @return a ratio value for this comparison
*/
protected double compareToOriginal(String pageContent) {
responseMatcher.setInjectedResponse(pageContent);
return responseMatcher.getQuickRatio();
protected double compareToOriginal(ComparableResponse response) {
return originalResponse.compareWith(response);
}

/**
* Check if the response is similar to original Response
*
* @param ComparableResponse that need to be compared
* @return boolean indicating similar (true) or not similar(false)
*/
protected boolean isComparableToOriginal(ComparableResponse otherResponse) {
float similarity = originalResponse.compareWith(otherResponse);
return similarity >= REQUIRED_SIMILARITY;
}

/**
Expand Down
Loading

0 comments on commit 17536ad

Please sign in to comment.