Skip to content

Commit

Permalink
Implement getMetadata for active JS scripts
Browse files Browse the repository at this point in the history
Signed-off-by: ricekot <[email protected]>
  • Loading branch information
ricekot committed May 2, 2024
1 parent a941beb commit ca7ac93
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 200 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Changed
- Use Prettier to format all JavaScript scripts.
- Update the following scripts to implement the `getMetadata()` function:
- active/Cross Site WebSocket Hijacking.js
- active/cve-2019-5418.js
- active/gof_lite.js
- active/JWT None Exploit.js
- active/SSTI.js

## [18] - 2024-01-29
### Added
Expand Down
60 changes: 32 additions & 28 deletions active/Cross Site WebSocket Hijacking.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,44 @@ var Base64 = Java.type("java.util.Base64");
var Random = Java.type("java.util.Random");
var String = Java.type("java.lang.String");
var ByteArray = Java.type("byte[]");
var ScanRuleMetadata = Java.type(
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);

var LOG_DEBUG_MESSAGES = false; // change to true for more logs

var RISK = 3;
var CONFIDENCE = 2;
var TITLE = "Cross-Site WebSocket Hijacking";
var DESCRIPTION =
"Server accepted WebSocket connection through HTTP Upgrade request with modified Origin header.";
var SOLUTION =
"Validate Origin header on WebSocket connection handshake, to ensure only specified origins are allowed to connect.\
Also, WebSocket handshake should use random tokens, similar to anti CSRF tokens.";
var REFERENCE = "https://tools.ietf.org/html/rfc6455#section-10.2";
var OTHER =
"See also https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking\
or https://christian-schneider.net/CrossSiteWebSocketHijacking.html";
var CWEID = 346; // CWE-346: Origin Validation Error, http://cwe.mitre.org/data/definitions/346.html
var WASCID = 9; // WASC-9 Cross Site Request Forgery, http://projects.webappsec.org/w/page/13246919/Cross%20Site%20Request%20Forgery
function getMetadata() {
return ScanRuleMetadata.fromYaml(`
id: 100025
name: Cross-Site WebSocket Hijacking
description: Server accepted WebSocket connection through HTTP Upgrade request with modified Origin header.
solution: >
Validate Origin header on WebSocket connection handshake, to ensure only specified origins are allowed to connect.
Also, WebSocket handshake should use random tokens, similar to anti CSRF tokens.
references:
- https://tools.ietf.org/html/rfc6455#section-10.2
category: server
risk: high
confidence: medium
cweId: 346 # CWE-346: Origin Validation Error, http://cwe.mitre.org/data/definitions/346.html
wascId: 9 # WASC-9 Cross Site Request Forgery, http://projects.webappsec.org/w/page/13246919/Cross%20Site%20Request%20Forgery
alertTags:
OWASP_2021_A01: https://owasp.org/Top10/A01_2021-Broken_Access_Control/
OWASP_2017_A05: https://owasp.org/www-project-top-ten/2017/A5_2017-Broken_Access_Control.html
WSTG-v42-CLNT-10: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/11-Client-side_Testing/10-Testing_WebSockets
otherInfo: >
See also https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking
or https://christian-schneider.net/CrossSiteWebSocketHijacking.html
status: alpha
codeLink: https://github.com/zaproxy/community-scripts/blob/main/active/Cross%20Site%20WebSocket%20Hijacking.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function scanNode(as, msg) {
var target = msg.getRequestHeader().getURI().toString();

// check if this is a WebSocket HTTP Upgrade request (the message should include also "Connection: Upgrade" header if we wanted to check it strictly)
// TODO: in ZAP 2.11 we might use msg.isWebSocketUpgrade() check instead
var upgradeHeader = msg.getRequestHeader().getHeader("Upgrade");
if (!upgradeHeader || upgradeHeader.toLowerCase() !== "websocket") {
// check if this is a WebSocket HTTP Upgrade request
if (msg.isWebSocketUpgrade()) {
if (LOG_DEBUG_MESSAGES) {
print(
"Cross-Site WebSocket Hijacking rule skipped for url=" +
Expand Down Expand Up @@ -102,17 +115,8 @@ function scanNode(as, msg) {
);
}
as.newAlert()
.setRisk(RISK)
.setConfidence(CONFIDENCE)
.setName(TITLE)
.setDescription(DESCRIPTION)
.setParam(target)
.setEvidence(msg.getResponseHeader().getPrimeHeader())
.setOtherInfo(OTHER)
.setSolution(SOLUTION)
.setReference(REFERENCE)
.setCweId(CWEID)
.setWascId(WASCID)
.setMessage(msg)
.raise();
}
Expand Down
62 changes: 34 additions & 28 deletions active/JWT None Exploit.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,35 @@ var Cookie = Java.type("java.net.HttpCookie");
var Base64 = Java.type("java.util.Base64");
var String = Java.type("java.lang.String");

// Exploit information, used for raising alerts
var RISK = 3;
var CONFIDENCE = 2;
var TITLE = "JWT None Exploit";
var DESCRIPTION =
"The application's JWT implementation allows for the usage of the 'none' algorithm, which bypasses the JWT hash verification.";
var SOLUTION =
"Use a secure JWT library, and (if your library supports it) restrict the allowed hash algorithms.";
var REFERENCE =
"https://www.sjoerdlangkemper.nl/2016/09/28/attacking-jwt-authentication/";
var CWEID = 347; // CWE-347: Improper Verification of Cryptographic Signature
var WASCID = 15; // WASC-15: Application Misconfiguration
var ScanRuleMetadata = Java.type(
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);

function getMetadata() {
return ScanRuleMetadata.fromYaml(`
id: 100026
name: JWT None Exploit
description: >
The application's JWT implementation allows for the usage of the 'none' algorithm,
which bypasses the JWT hash verification.
solution: >
Use a secure JWT library, and (if your library supports it) restrict the allowed hash algorithms.
references:
- https://www.sjoerdlangkemper.nl/2016/09/28/attacking-jwt-authentication/
category: server
risk: high
confidence: medium
cweId: 347
wascId: 15
alertTags:
OWASP_2021_A01: https://owasp.org/Top10/A01_2021-Broken_Access_Control/
OWASP_2017_A02: https://owasp.org/www-project-top-ten/2017/A2_2017-Broken_Authentication
WSTG-v42-CRYP-04: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/04-Testing_for_Weak_Encryption
status: alpha
codeLink: https://github.com/zaproxy/community-scripts/blob/main/active/JWT%20None%20Exploit.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function b64encode(string) {
// Terminate the string with a null byte prior to encoding. I suspect that
Expand Down Expand Up @@ -128,20 +145,9 @@ function scanNode(as, msg) {

function raise_alert(msg, cookie, payload, as) {
print("Vulnerability found, sending alert");
as.raiseAlert(
RISK,
CONFIDENCE,
TITLE,
DESCRIPTION,
msg.getRequestHeader().getURI().toString(),
"",
"",
"",
SOLUTION,
"Cookie: " + cookie.getName() + "=" + payload,
REFERENCE,
CWEID,
WASCID,
msg
);
as.newAlert()
.setEvidence("Cookie: " + cookie.getName() + "=" + payload)
.setUri(msg.getRequestHeader().getURI().toString())
.setMessage(msg)
.raise();
}
58 changes: 30 additions & 28 deletions active/SSTI.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,36 @@
var LoggerManager = Java.type("org.apache.logging.log4j.LogManager");
var log = LoggerManager.getLogger("SSTI");

// HasMap for alertTags
var HashMap = Java.type("java.util.HashMap");
var ScanRuleMetadata = Java.type(
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);

function getMetadata() {
return ScanRuleMetadata.fromYaml(`
id: 100033
name: Server Side Template Injection
description: >
Server Side Template Injection (SSTI) occurs when user input is directly embedded into the template without any
proper sanitization, a hacker can use this vulnerability to inject malicious code and try to achieve remote code execution.
solution: >
Always use proper functions provided by the template engine to insert data,
if that is not possible try to sanitize user input as efficiently as possible.
references:
- https://portswigger.net/research/server-side-template-injection
category: injection
risk: high
confidence: medium
cweId: 20 # CWE-20: Improper Input Validation
wascId: 20 # WASC-20: Improper Input Handling
alertTags:
OWASP_2021_A03: https://owasp.org/Top10/A03_2021-Injection/
OWASP_2017_A01: https://owasp.org/www-project-top-ten/2017/A1_2017-Injection.html
WSTG-v42-INPV-18: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/18-Testing_for_Server-side_Template_Injection
status: alpha
codeLink: https://github.com/zaproxy/community-scripts/blob/main/active/SSTI.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function logger() {
print("[" + this["zap.script.name"] + "] " + arguments[0]);
Expand Down Expand Up @@ -168,44 +196,18 @@ function raiseAlert(as, msg, payload, evidence, confidence, param, engine) {
var badErrors = ["Infinity", "INF"];

//Alert variables
var pluginId = 100033;
var alertName = "Server Side Template Injection";
if (badErrors.indexOf(engine) == -1) {
alertName += " - " + toTitleCase(engine);
}
var alertDesc =
"Server Side Template Injection (SSTI) occurs when user input is directly embedded into the template without any proper sanitization, a hacker can use this vulnerability to inject malicious code and try to achieve remote code execution.";
var alertSol =
"Always use proper functions provided by the template engine to insert data, if that is not possible try to sanitize user input as efficiently as possible.";
var alertRef =
"https://portswigger.net/research/server-side-template-injection";
var cweId = 20; // Improper Input Validation
var wascId = 20; // Improper Input Handling
var alertTags = new HashMap();
alertTags.put(
"OWASP_2021_A03",
"https://owasp.org/Top10/A03_2021-Injection/"
);
alertTags.put(
"OWASP_2017_A01",
"https://owasp.org/www-project-top-ten/2017/A1_2017-Injection.html"
);

as.newAlert()
.setAlertId(pluginId)
.setRisk(3)
.setConfidence(confidence)
.setName(alertName)
.setDescription(alertDesc)
.setParam(param)
.setAttack(payload)
.setEvidence(evidence)
.setSolution(alertSol)
.setReference(alertRef)
.setCweId(cweId)
.setWascId(wascId)
.setMessage(msg)
.setTags(alertTags)
.raise();
}

Expand Down
102 changes: 42 additions & 60 deletions active/cve-2019-5418.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
// Note that new active scripts will initially be disabled
// Right click the script in the Scripts tree and select "enable"

// This active scanner script checks for CVE-2019-5418

/**
* Scans a "node", i.e. an individual entry in the Sites Tree.
* The scanNode function will typically be called once for every page.
*
* @param as - the ActiveScan parent object that will do all the core interface tasks
* (i.e.: sending and receiving messages, providing access to Strength and Threshold settings,
* raising alerts, etc.). This is an ScriptsActiveScanner object.
* @param msg - the HTTP Message being scanned. This is an HttpMessage object.
*/
var ScanRuleMetadata = Java.type(
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);

function getMetadata() {
return ScanRuleMetadata.fromYaml(`
id: 100029
name: "File Content Disclosure (CVE-2019-5418)"
description: >
The application seems to be subject to CVE-2019-5418.
By sending a specially crafted request it was possible to have the target return
data from the server file system.
solution: >
Upgrade to a version of Ruby/Rails where this issue is fixed. (See references for further details).
references:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5418
- https://github.com/mpgn/CVE-2019-5418
category: injection
risk: high
confidence: medium
cweId: 74 # CWE-74: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')
wascId: 33 # WASC-33: Path Traversal
alertTags:
OWASP_2021_A03: https://owasp.org/Top10/A03_2021-Injection/
OWASP_2017_A01: https://owasp.org/www-project-top-ten/2017/A1_2017-Injection.html
WSTG-v42-ATHZ-01: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/05-Authorization_Testing/01-Testing_Directory_Traversal_File_Include
status: alpha
codeLink: https://github.com/zaproxy/community-scripts/blob/main/active/cve-2019-5418.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function scanNode(as, msg) {
// Set some details we will need for alerts later
var alertRisk = 3;
var alertConfidence = 2;
var alertTitle = "CVE-2019-5418 - File Content Disclosure";
var alertDesc =
"The application seems to be subject to CVE-2019-5418. \
By sending a specially crafted request it was possible to have the target return \
data from the server file system.";
var alertSolution =
"Upgrade to a version of Ruby/Rails where this issue is fixed. (See references for further details).";
var alertInfo =
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5418\nhttps://github.com/mpgn/CVE-2019-5418";
var cweId = 74; //Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')
var wascId = 33; // Path Traversal
var url = msg.getRequestHeader().getURI().toString();

var msg2 = msg.cloneRequest();
Expand All @@ -40,21 +46,11 @@ data from the server file system.";
var body = msg2.getResponseBody().toString();

if (re.test(body)) {
as.raiseAlert(
alertRisk,
alertConfidence,
alertTitle,
alertDesc,
url,
"",
"",
alertInfo,
alertSolution,
body.match(re)[0],
cweId,
wascId,
msg2
);
as.newAlert()
.setEvidence(body.match(re)[0])
.setUri(url)
.setMessage(msg2)
.raise();
return; // No need to try further
}
// Just in case there's a simple WaF
Expand All @@ -68,24 +64,10 @@ data from the server file system.";
re = /127.0.0.1/g;
body = msg3.getResponseBody().toString();
if (re.test(body)) {
as.raiseAlert(
alertRisk,
alertConfidence,
alertTitle,
alertDesc,
url,
"",
"",
alertInfo,
alertSolution,
body.match(re)[0],
cweId,
wascId,
msg3
);
as.newAlert()
.setEvidence(body.match(re)[0])
.setUri(url)
.setMessage(msg3)
.raise();
}
}

function scan(as, msg, param, value) {
//Unused
}
Loading

0 comments on commit ca7ac93

Please sign in to comment.