diff --git a/CHANGELOG.md b/CHANGELOG.md index f2d56fab..49a720e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - passive/find_reflected_params.py - passive/HUNT.py - passive/Mutliple Security Header Check.js + - passive/google_api_keys_finder.js + - passive/JavaDisclosure.js + - passive/Report non static sites.js + - passive/RPO.js + - passive/s3.js ## [18] - 2024-01-29 ### Added diff --git a/passive/JavaDisclosure.js b/passive/JavaDisclosure.js index c9697355..5e7edd47 100755 --- a/passive/JavaDisclosure.js +++ b/passive/JavaDisclosure.js @@ -1,15 +1,28 @@ //Passive scan for Java error messages containing sensitive information (CWE-209) -function scan(ps, msg, src) { - var alertRisk = 2; - var alertConfidence = 3; - var alertTitle = "Java stack trace disclosure"; - var alertDesc = "Java stack trace disclosure (or similar) was found"; - var alertSolution = - "Investigate Java stack trace disclosures found in the response, remove or mask as required"; - var cweId = 209; - var wascId = 0; +var ScanRuleMetadata = Java.type( + "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata" +); +function getMetadata() { + return ScanRuleMetadata.fromYaml(` +id: 100035 +name: Information Disclosure - Java Stack Trace +description: A Java stack trace was found in the HTTP response body. +solution: > + Catch and handle exceptions properly, avoiding the exposure of stack traces to users. + Configure the web server or application framework to log stack traces instead of displaying them. +risk: medium +confidence: high +cweId: 209 # CWE-209: Generation of Error Message Containing Sensitive Information +wascId: 13 # WASC-13: Information Leakage +status: alpha +codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/JavaDisclosure.js +helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/ +`); +} + +function scan(helper, msg, src) { var re = /springframework|\.java|rootBeanClass/i; var contentType = msg.getResponseHeader().getHeader("Content-Type"); @@ -27,21 +40,13 @@ function scan(ps, msg, src) { var body = msg.getResponseBody().toString(); if (re.test(body)) { - let url = msg.getRequestHeader().getURI().toString(); - ps.raiseAlert( - alertRisk, - alertConfidence, - alertTitle, - alertDesc, - url, - "", - "", - body, - alertSolution, - body, - cweId, - wascId, - msg - ); + re.lastIndex = 0; + var match = re.exec(body)[0]; + helper + .newAlert() + .setEvidence(match) + .setOtherInfo(body) + .setMessage(msg) + .raise(); } } diff --git a/passive/RPO.js b/passive/RPO.js index 2c096d80..b989ea65 100644 --- a/passive/RPO.js +++ b/passive/RPO.js @@ -3,17 +3,32 @@ // for more info see http://www.thespanner.co.uk/2014/03/21/rpo/ // *WARNING* this is a Beta version of this detection and may give many false positives! -function scan(ps, msg, src) { - var url = msg.getRequestHeader().getURI().toString(); - var alertRisk = 2; - var alertConfidence = 2; - var alertTitle = "Potential Relative Path Overwrite - RPO(beta script)"; - var alertDesc = "Potential RPO (Relative Path Overwrite) found "; - var alertSolution = - "Make sure all style sheets are refered by full paths rather than relative paths."; +var ScanRuleMetadata = Java.type( + "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata" +); - var cweId = 0; - var wascId = 0; +function getMetadata() { + return ScanRuleMetadata.fromYaml(` +id: 100018 +name: Relative Path Overwrite +description: > + Potential RPO (Relative Path Overwrite) found. + RPO allows attackers to manipulate URLs to include unintended paths, + potentially leading to the execution of malicious scripts or the disclosure of sensitive information. +solution: > + Use absolute paths in URLs and resources to prevent manipulation. + Validate and sanitize all user inputs that are used to construct URLs. +risk: medium +confidence: medium +cweId: 20 # CWE-20: Improper Input Validation +wascId: 13 # WASC-13: Information Leakage +status: alpha +codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/RPO.js +helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/ +`); +} + +function scan(helper, msg, src) { // regex must appear within /( and )/g var re = /(href\=\"((?!\/|http|www)).*\.css\")/g; @@ -41,21 +56,12 @@ function scan(ps, msg, src) { while ((comm = re.exec(body))) { foundRPO.push(comm[0]); } - ps.raiseAlert( - alertRisk, - alertConfidence, - alertTitle, - alertDesc, - url, - "", - "", - foundRPO.toString(), - alertSolution, - "", - cweId, - wascId, - msg - ); + helper + .newAlert() + .setEvidence(foundRPO[0]) + .setOtherInfo(`Other instances: ${foundRPO.slice(1).toString()}`) + .setMessage(msg) + .raise(); } } } diff --git a/passive/Report non static sites.js b/passive/Report non static sites.js index 1195ef3e..964660da 100644 --- a/passive/Report non static sites.js +++ b/passive/Report non static sites.js @@ -4,58 +4,61 @@ // Note that new passive scripts will initially be disabled // Right click the script in the Scripts tree and select "enable" +var ScanRuleMetadata = Java.type( + "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata" +); + +function getMetadata() { + return ScanRuleMetadata.fromYaml(` +id: 100017 +name: Non Static Site Detected +description: > + A query string or form has been detected in the HTTP response body. + This indicates that this may not be a static site. +solution: > + If this is not a static site then ignore or disable this rule. +risk: high +confidence: medium +status: alpha +codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/Report%20non%20static%20sites.js +helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/ +`); +} + /** * Passively scans an HTTP message. The scan function will be called for * request/response made via ZAP, actual messages depend on the function * "appliesToHistoryType", defined below. * - * @param ps - the PassiveScan parent object that will do all the core interface tasks + * @param helper - the PassiveScan parent object that will do all the core interface tasks * (i.e.: providing access to Threshold settings, raising alerts, etc.). * This is an ScriptsPassiveScanner object. * @param msg - the HTTP Message being scanned. This is an HttpMessage object. * @param src - the Jericho Source representation of the message being scanned. */ -function scan(ps, msg, src) { - // Test the request and/or response here +function scan(helper, msg, src) { if (msg.getRequestHeader().getURI().getEscapedQuery() != null) { - // raiseAlert(risk, int confidence, String name, String description, String uri, - // String param, String attack, String otherInfo, String solution, String evidence, - // int cweId, int wascId, HttpMessage msg) - // risk: 0: info, 1: low, 2: medium, 3: high - // confidence: 0: falsePositive, 1: low, 2: medium, 3: high, 4: confirmed - ps.raiseAlert( - 3, - 2, - "Non static site (query present)", - "A query string has been detected in one of the sites URLs. This indicates that this might well not be a static site", - msg.getRequestHeader().getURI().toString(), - "", - "", - "", - "If this is not a static site then ignore or disable this script", - msg.getRequestHeader().getURI().getEscapedQuery(), - 0, - 0, - msg - ); + helper + .newAlert() + .setName("Non Static Site Detected (query present)") + .setDescription( + "A query string has been detected in the HTTP response body. This indicates that this may not be a static site." + ) + .setEvidence(msg.getRequestHeader().getURI().getEscapedQuery()) + .setMessage(msg) + .raise(); } if (src != null && !src.getFormFields().isEmpty()) { // There are form fields - ps.raiseAlert( - 3, - 2, - "Non static site (form present)", - "One or more forms have been detected in the response. This indicates that this might well not be a static site", - msg.getRequestHeader().getURI().toString(), - "", - "", - "", - "If this is not a static site then ignore or disable this script", - src.getFormFields().toString(), - 0, - 0, - msg - ); + helper + .newAlert() + .setName("Non Static Site Detected (form present)") + .setDescription( + "One or more forms have been detected in the response. This indicates that this may not be a static site." + ) + .setEvidence(src.getFormFields().toString()) + .setMessage(msg) + .raise(); } } diff --git a/passive/google_api_keys_finder.js b/passive/google_api_keys_finder.js index 3f122cab..30fd08bf 100644 --- a/passive/google_api_keys_finder.js +++ b/passive/google_api_keys_finder.js @@ -4,15 +4,27 @@ * @SkypLabs */ -function scan(ps, msg, src) { - var alertRisk = 0; // Informational - var alertConfidence = 3; // High - var alertTitle = "Information Disclosure - Google API Keys Found"; - var alertDesc = "Google API keys have been found."; - var alertSolution = "Make sure the API key is not overly permissive."; - var cweId = 200; // "Exposure of Sensitive Information to an Unauthorized Actor" - var wascId = 13; // "Information Leakage" +var ScanRuleMetadata = Java.type( + "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata" +); +function getMetadata() { + return ScanRuleMetadata.fromYaml(` +id: 100034 +name: Information Disclosure - Google API Key +description: A Google API Key was found in the HTTP response body. +solution: Ensure the API key is not overly permissive. +risk: info +confidence: high +cweId: 200 # CWE-200: Exposure of Sensitive Information to an Unauthorized Actor +wascId: 13 # WASC-13: Information Leakage +status: alpha +codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/google_api_keys_finder.js +helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/ +`); +} + +function scan(helper, msg, src) { // Regex targeting Google API keys. // Taken from Table III of "How Bad Can It Git? Characterizing Secret Leakage in Public GitHub Repositories". // https://www.ndss-symposium.org/ndss-paper/how-bad-can-it-git-characterizing-secret-leakage-in-public-github-repositories/ @@ -45,21 +57,11 @@ function scan(ps, msg, src) { foundKeys.push(key[0]); } - ps.raiseAlert( - alertRisk, - alertConfidence, - alertTitle, - alertDesc, - url, - "", - "", - "The following Google API keys have been found in the page: " + - foundKeys.join(", "), // Other info - alertSolution, - foundKeys[0].toString(), // Evidence - cweId, - wascId, - msg - ); + helper + .newAlert() + .setEvidence(foundKeys[0]) + .setOtherInfo(`Other instances: ${foundKeys.slice(1).toString()}`) + .setMessage(msg) + .raise(); } } diff --git a/passive/s3.js b/passive/s3.js index e2889eab..415fcf17 100644 --- a/passive/s3.js +++ b/passive/s3.js @@ -1,22 +1,29 @@ // S3 bucket finder by alishasinghania09@gmail.com -function scan(ps, msg, src) { - // populate some parameters which will be needed if s3 bucket url is present - var alertRisk = 1; - var alertConfidence = 3; - var alertTitle = "s3 Bucket URL"; - var alertDesc = "s3 Bucket URL found in response."; - var alertSolution = - "Remove s3 Buckets name from response or make sure the permissions in bucket are configured properly."; - var cweId = 200; - var wascId = 13; +var ScanRuleMetadata = Java.type( + "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata" +); +function getMetadata() { + return ScanRuleMetadata.fromYaml(` +id: 100035 +name: Information Disclosure - Amazon S3 Bucket URL +description: An Amazon S3 bucket URL was found in the HTTP response body. +solution: Remove S3 Bucket names from the response or ensure that the permissions in bucket are configured properly. +risk: low +confidence: high +cweId: 200 # CWE-200: Exposure of Sensitive Information to an Unauthorized Actor +wascId: 13 # WASC-13: Information Leakage +status: alpha +codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/s3.js +helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/ +`); +} + +function scan(helper, msg, src) { // the regex for s3 bucket url and it must appear within /( and )/g var re = /((s3:\\[a-zA-Z0-9-\.\\_]+)|((s3-|s3\.)?(.*)\.amazonaws\.com))/g; - // we need to set the url variable to the request or we cant track the alert later - var url = msg.getRequestHeader().getURI().toString(); - // If the file type is image jpeg/png , then the scan will be skipped var contenttype = msg.getResponseHeader().getHeader("Content-Type"); var unwantedfiletypes = [ @@ -39,21 +46,12 @@ function scan(ps, msg, src) { founds3bucket.push(buckets[0]); } //raise the alert - ps.raiseAlert( - alertRisk, - alertConfidence, - alertTitle, - alertDesc, - url, - "", - "", - founds3bucket.toString(), - alertSolution, - "", - cweId, - wascId, - msg - ); + helper + .newAlert() + .setEvidence(founds3bucket[0]) + .setOtherInfo(`Other instances: ${founds3bucket.slice(1).toString()}`) + .setMessage(msg) + .raise(); } } }