Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- active/Cross Site WebSocket Hijacking.js > an active scan for Cross-Site WebSocket Hijacking vulnerability
- targeted/cve-2021-22214.js > A targeted script to check for Unauthorised SSRF on GitLab - CVE 2021-22214
- httpsender/full-session-n-csrf-nashorn.js > full session and csrf token management.
- httpfuzzerprocessor/unexpected_responses.js > compare response codes to a (pass/fail) regex and generate alerts

### Changed
- Update links in READMEs.
Expand Down
137 changes: 137 additions & 0 deletions httpfuzzerprocessor/unexpected_responses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* This fuzz processor script will raise alerts based on HTTP response codes.
* It expects two special parameters:
* - A regular expression used to match the response code
* - A string that is either "pass" or "fail", indicating whether or not a
* matching response is expected ("pass") or unexpected ("fail").
* Unexpected responses will cause an alert to be raised.
*/

// See https://github.com/zaproxy/community-scripts/tree/main/httpfuzzerprocessor

// See https://github.com/zaproxy/community-scripts/blob/main/httpfuzzerprocessor/showDifferences.js
// for inspiration for differencing logic used to document detected defects.

// This script needs Diff add-on

var DiffTool = Java.type("org.zaproxy.zap.extension.diff.diff_match_patch");

/*
* Declare parameters
*/
function getRequiredParamsNames() {
return ["pattern", "sense"];
}

function getOptionalParamsNames() {
return [];
}

/*
* Processes the fuzzed message (payloads already injected).
*
* Called before forwarding the message to the server.
*
* @param {HttpFuzzerTaskProcessorUtils} utils - A utility object that contains functions that ease common tasks.
* @param {HttpMessage} message - The fuzzed message, that will be forward to the server.
*/
function processMessage(utils, message) {
// Take no action
}

/*
* Processes the fuzz result.
*
* Called after receiving the fuzzed message from the server.
*
* @param {HttpFuzzerTaskProcessorUtils} utils - A utility object that contains functions that ease common tasks.
* @param {HttpFuzzResult} fuzzResult - The result of sending the fuzzed message.
* @return {boolean} Whether the result should be accepted, or discarded and not shown.
*/
function processResult(utils, fuzzResult) {
// All the above 'utils' functions are available plus:
// To raise an alert:
// utils.raiseAlert(risk, confidence, name, description)
// To obtain the fuzzed message, received from the server:
// fuzzResult.getHttpMessage()

// Retrieve (string) parameters and convert to required types
var params = utils.getParameters();
var pattern = new RegExp(params.pattern); // response regex
var sense = params.sense == "pass"; // true if regex is expected response

// Retrieve response code and test it against supplied pattern
var fuzzed = fuzzResult.getHttpMessage();
var actual = fuzzed.getResponseHeader().getStatusCode().toString();
var found = actual.search(pattern) != -1;
var expected = found == sense;
var why = "";

// If unexpected, raise an alert
if (!expected) {
// Convert (inverse) of sense to English
if (sense) { // expected a match but did not get it
why = " did not match ";
} else { // expected no match but got one anyway
why = " matched ";
}

// "The original message"
var original = utils.getOriginalMessage();

// Compare the content of the original and fuzzed requests; this will
// indicate what changed to cause the problem. This is very nice if you
// are sending it somewhere that will render HTML, but looks like noise
// anywhere else.
//var diffHtml = createDiffHtml(
// requestAsString(original),
// requestAsString(fuzzed)
//);

// Generate a text difference of the two files
var diffText = createDiffText(
requestAsString(original),
requestAsString(fuzzed)
);

utils.raiseAlert(
3, // High Risk
2, // Medium Confidence
"Unexpected Fuzzer Response", // name
"The application is failing to handle unexpected input correctly.", // description (long)
null, // what parameter was fuzzed? we have no idea...
diffText, // attack
null, // otherInfo (long)
null, // solution (long)
null, // reference (long)
"The received response " + actual + why + params.pattern + ".", // evidence
684, // CWE-684: Incorrect Provision of Specified Functionality
20 // WASC-20: Improper Input Handling
);

// We don't need any more examples; stop this fuzzer
utils.stopFuzzer();
}

// Always accept the result
return true;
}

function requestAsString(httpMessage) {
var requestHeader = httpMessage.getRequestHeader().toString();
var requestBody = httpMessage.getRequestBody().toString();
return requestHeader + "\r\n" + requestBody;
}

function createDiffHtml(original, fuzzed) {
var diffTool = new DiffTool();
var diffList = diffTool.diff_main(original, fuzzed);
return diffTool.diff_prettyHtml(diffList);
}

function createDiffText(original, fuzzed) {
var diffTool = new DiffTool();
diffTool.Patch_Margin = 16; // bytes of context for patches
var patchList = diffTool.patch_make(original, fuzzed);
return diffTool.patch_toText(patchList);
}