diff --git a/CHANGELOG.md b/CHANGELOG.md index 680fee6d..d5ed95a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add cautionary note to help and readme. - Maintenance and documentation changes. - Active and passive READMEs to include lastest JS script examples. +- Reduce usage of fully qualified objects in loops or main methods to address potential classloader performance issues, in JavaScript scripts. ### Fixed - The following scripts were not being loaded as scan rules: diff --git a/httpfuzzerprocessor/addCacheBusting.js b/httpfuzzerprocessor/addCacheBusting.js index a720daa5..fd302792 100644 --- a/httpfuzzerprocessor/addCacheBusting.js +++ b/httpfuzzerprocessor/addCacheBusting.js @@ -1,3 +1,6 @@ +const HtmlParameter = Java.type("org.parosproxy.paros.network.HtmlParameter"); +const URL_TYPE = org.parosproxy.paros.network.HtmlParameter.Type.url; + function processMessage(utils, message) { var cbValue = "" + Math.floor(Math.random() * 10000); setCacheBusting(message, cbValue); @@ -5,8 +8,6 @@ function processMessage(utils, message) { } function setCacheBusting(message, cbValue) { - var HtmlParameter = Java.type("org.parosproxy.paros.network.HtmlParameter"); - var URL_TYPE = org.parosproxy.paros.network.HtmlParameter.Type.url; var params = message.getUrlParams(); var newParam = new HtmlParameter( URL_TYPE, diff --git a/httpfuzzerprocessor/add_msgs_sites_tree.js b/httpfuzzerprocessor/add_msgs_sites_tree.js index a21afe94..116fc6aa 100644 --- a/httpfuzzerprocessor/add_msgs_sites_tree.js +++ b/httpfuzzerprocessor/add_msgs_sites_tree.js @@ -1,6 +1,10 @@ // A Fuzzer HTTP Processor script that allows to populate the Sites tree // with messages sent by the fuzzer (by default the fuzz result/messages // are not shown in the Fuzzer tab). +const HistoryReference = Java.type( + "org.parosproxy.paros.model.HistoryReference" +); +const EventQueue = Java.type("java.awt.EventQueue"); var session = model.getSession(); @@ -11,9 +15,9 @@ function processResult(utils, fuzzResult) { // The type 15 indicates that the message was sent by the user. // Refer to the HistoryReference for more details on the available types. // Persist the message to the session. - var ref = new org.parosproxy.paros.model.HistoryReference(session, 15, msg); + var ref = new HistoryReference(session, 15, msg); // Add the message to Sites tree. - java.awt.EventQueue.invokeLater(function () { + EventQueue.invokeLater(function () { session.getSiteTree().addPath(ref, msg); }); diff --git a/httpfuzzerprocessor/unexpected_responses.js b/httpfuzzerprocessor/unexpected_responses.js index 042e36e8..5a6aeb3d 100644 --- a/httpfuzzerprocessor/unexpected_responses.js +++ b/httpfuzzerprocessor/unexpected_responses.js @@ -14,7 +14,7 @@ // This script needs Diff add-on -var DiffTool = Java.type("org.zaproxy.zap.extension.diff.diff_match_patch"); +const DiffTool = Java.type("org.zaproxy.zap.extension.diff.diff_match_patch"); /* * Declare parameters diff --git a/httpsender/Alert on HTTP Response Code Errors.js b/httpsender/Alert on HTTP Response Code Errors.js index 910b8b39..3144b9f6 100644 --- a/httpsender/Alert on HTTP Response Code Errors.js +++ b/httpsender/Alert on HTTP Response Code Errors.js @@ -2,7 +2,21 @@ // By default it will raise 'Info' level alerts for Client Errors (4xx) (apart from 404s) and 'Low' Level alerts for Server Errors (5xx) // But it can be easily changed. -var Pattern = Java.type("java.util.regex.Pattern"); +const Integer = Java.type("java.lang.Integer"); +const Pattern = Java.type("java.util.regex.Pattern"); + +const Alert = Java.type("org.parosproxy.paros.core.scanner.Alert"); +const ExtensionAlert = Java.type( + "org.zaproxy.zap.extension.alert.ExtensionAlert" +); +const HistoryReference = Java.type( + "org.parosproxy.paros.model.HistoryReference" +); + +const extensionAlert = control + .getExtensionLoader() + .getExtension(ExtensionAlert.NAME); + pluginid = 100000; // https://github.com/zaproxy/zaproxy/blob/main/docs/scanners.md function sendingRequest(msg, initiator, helper) { @@ -14,12 +28,10 @@ function responseReceived(msg, initiator, helper) { // Not of interest. return; } - var extensionAlert = control - .getExtensionLoader() - .getExtension(org.zaproxy.zap.extension.alert.ExtensionAlert.NAME); + if (extensionAlert != null) { var code = msg.getResponseHeader().getStatusCode(); - if (code < 400 || code >= 600 || code == 404) { + if (code < 400 || code >= 600) { // Do nothing } else { var risk = 0; // Info @@ -30,17 +42,12 @@ function responseReceived(msg, initiator, helper) { title = "A Server Error response code was returned by the server"; } // CONFIDENCE_HIGH = 3 (we can be pretty sure we're right) - var alert = new org.parosproxy.paros.core.scanner.Alert( - pluginid, - risk, - 3, - title - ); + var alert = new Alert(pluginid, risk, 3, title); var ref = msg.getHistoryRef(); if ( ref != null && - org.parosproxy.paros.model.HistoryReference.getTemporaryTypes().contains( - java.lang.Integer.valueOf(ref.getHistoryType()) + HistoryReference.getTemporaryTypes().contains( + Integer.valueOf(ref.getHistoryType()) ) ) { // Dont use temporary types as they will get deleted @@ -78,11 +85,7 @@ function responseReceived(msg, initiator, helper) { type = 15; // User - fallback break; } - ref = new org.parosproxy.paros.model.HistoryReference( - model.getSession(), - type, - msg - ); + ref = new HistoryReference(model.getSession(), type, msg); } alert.setMessage(msg); alert.setUri(msg.getRequestHeader().getURI().toString()); @@ -93,9 +96,7 @@ function responseReceived(msg, initiator, helper) { "This may indicate that the application is failing to handle unexpected input correctly.\n" + "Raised by the 'Alert on HTTP Response Code Error' script" ); - // Use a regex to extract the evidence from the response header - var regex = new RegExp("^HTTP.*" + code); - alert.setEvidence(msg.getResponseHeader().toString().match(regex)); + alert.setEvidence(code.toString()); alert.setCweId(388); // CWE CATEGORY: Error Handling alert.setWascId(20); // WASC Improper Input Handling extensionAlert.alertFound(alert, ref); diff --git a/httpsender/Alert on Unexpected Content Types.js b/httpsender/Alert on Unexpected Content Types.js index a1229b9f..57ead804 100644 --- a/httpsender/Alert on Unexpected Content Types.js +++ b/httpsender/Alert on Unexpected Content Types.js @@ -2,13 +2,22 @@ // By default it will raise 'Low' level alerts for content types that are not expected to be returned by APIs. // But it can be easily changed. -var Pattern = Java.type("java.util.regex.Pattern"); +const Integer = Java.type("java.lang.Integer"); +const Pattern = Java.type("java.util.regex.Pattern"); -var pluginid = 100001; // https://github.com/zaproxy/zaproxy/blob/main/docs/scanners.md +const Alert = Java.type("org.parosproxy.paros.core.scanner.Alert"); +const ExtensionAlert = Java.type( + "org.zaproxy.zap.extension.alert.ExtensionAlert" +); +const HistoryReference = Java.type( + "org.parosproxy.paros.model.HistoryReference" +); -var extensionAlert = control +const extensionAlert = control .getExtensionLoader() - .getExtension(org.zaproxy.zap.extension.alert.ExtensionAlert.NAME); + .getExtension(ExtensionAlert.NAME); + +var pluginid = 100001; // https://github.com/zaproxy/zaproxy/blob/main/docs/scanners.md var expectedTypes = ["application/octet-stream", "text/plain"]; @@ -23,6 +32,7 @@ function responseReceived(msg, initiator, helper) { // Not of interest. return; } + if (extensionAlert != null) { var ctype = msg.getResponseHeader().getHeader("Content-Type"); if (ctype != null) { @@ -38,17 +48,12 @@ function responseReceived(msg, initiator, helper) { var risk = 1; // Low var title = "Unexpected Content-Type was returned"; // CONFIDENCE_HIGH = 3 (we can be pretty sure we're right) - var alert = new org.parosproxy.paros.core.scanner.Alert( - pluginid, - risk, - 3, - title - ); + var alert = new Alert(pluginid, risk, 3, title); var ref = msg.getHistoryRef(); if ( ref != null && - org.parosproxy.paros.model.HistoryReference.getTemporaryTypes().contains( - java.lang.Integer.valueOf(ref.getHistoryType()) + HistoryReference.getTemporaryTypes().contains( + Integer.valueOf(ref.getHistoryType()) ) ) { // Dont use temporary types as they will get deleted @@ -86,11 +91,7 @@ function responseReceived(msg, initiator, helper) { type = 15; // User - fallback break; } - ref = new org.parosproxy.paros.model.HistoryReference( - model.getSession(), - type, - msg - ); + ref = new HistoryReference(model.getSession(), type, msg); } alert.setMessage(msg); alert.setUri(msg.getRequestHeader().getURI().toString()); diff --git a/passive/Report non static sites.js b/passive/Report non static sites.js index e28571c5..1a6a4c33 100644 --- a/passive/Report non static sites.js +++ b/passive/Report non static sites.js @@ -4,6 +4,9 @@ // Note that new passive scripts will initially be disabled // Right click the script in the Scripts tree and select "enable" +const PluginPassiveScanner = Java.type( + "org.zaproxy.zap.extension.pscan.PluginPassiveScanner" +); var ScanRuleMetadata = Java.type( "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata" ); @@ -73,7 +76,5 @@ function appliesToHistoryType(historyType) { // return historyType == org.parosproxy.paros.model.HistoryReference.TYPE_SPIDER; // Default behaviour scans default types. - return org.zaproxy.zap.extension.pscan.PluginPassiveScanner.getDefaultHistoryTypes().contains( - historyType - ); + return PluginPassiveScanner.getDefaultHistoryTypes().contains(historyType); } diff --git a/passive/Telerik Using Poor Crypto.js b/passive/Telerik Using Poor Crypto.js index d488da77..1477c4f1 100644 --- a/passive/Telerik Using Poor Crypto.js +++ b/passive/Telerik Using Poor Crypto.js @@ -7,6 +7,7 @@ const ScanRuleMetadata = Java.type( "org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata" ); +const Base64 = Java.type("org.apache.commons.codec.binary.Base64"); function getMetadata() { return ScanRuleMetadata.fromYaml(` @@ -54,11 +55,11 @@ function scan(helper, msg, src) { return; } - if (!org.apache.commons.codec.binary.Base64.isBase64(dp)) { + if (!Base64.isBase64(dp)) { return; } - var dpBytes = org.apache.commons.codec.binary.Base64.decodeBase64(dp); + var dpBytes = Base64.decodeBase64(dp); if (dpBytes.length < 48) { return; diff --git a/standalone/historySourceTagger.js b/standalone/historySourceTagger.js index d9ba8aa9..0e8c0bd1 100644 --- a/standalone/historySourceTagger.js +++ b/standalone/historySourceTagger.js @@ -5,6 +5,8 @@ // if they don't already have a tag that starts with TAG_PREFIX as defined below. // Author: kingthorin // 20160207: Initial release +// 20251212: Maintenance changes +const ScriptVars = Java.type("org.zaproxy.zap.extension.script.ScriptVars"); extHist = control .getExtensionLoader() @@ -13,7 +15,7 @@ extHist = control TAG_PREFIX = "SRC_"; if (extHist != null) { - i = org.zaproxy.zap.extension.script.ScriptVars.getGlobalVar("tagged_ref"); // Check for global reference + i = ScriptVars.getGlobalVar("tagged_ref"); // Check for global reference if (i == null) { i = 1; // Global reference was null so 1 } @@ -48,8 +50,5 @@ if (extHist != null) { } i++; } - org.zaproxy.zap.extension.script.ScriptVars.setGlobalVar( - "tagged_ref", - lastRef + 1 - ); // Set global reference + ScriptVars.setGlobalVar("tagged_ref", lastRef + 1); // Set global reference } diff --git a/targeted/Remove 302s.js b/targeted/Remove 302s.js index d51e6b75..738278ad 100644 --- a/targeted/Remove 302s.js +++ b/targeted/Remove 302s.js @@ -2,6 +2,9 @@ // the script was invoked with. // The default criteria is leaf nodes with a response code of 302 but you can change that to anything you need // Targeted scripts can only be invoked by you, the user, eg via a right-click option on the Sites or History tabs +const PopupMenuPurgeSites = Java.type( + "org.zaproxy.zap.extension.history.PopupMenuPurgeSites" +); function recurseDown(sitestree, node) { //print('recurseDown node: ' + node.getHierarchicNodeName() + " " + node.getChildCount()) @@ -15,10 +18,7 @@ function recurseDown(sitestree, node) { } if (deleteThis(node)) { print("Removing node: " + node.getHierarchicNodeName()); - org.zaproxy.zap.extension.history.PopupMenuPurgeSites.purge( - sitestree, - node - ); + PopupMenuPurgeSites.purge(sitestree, node); return true; } return false; diff --git a/targeted/Search www.xssposed.org for known XSS.js b/targeted/Search www.xssposed.org for known XSS.js index b98c25ac..9bc479ef 100644 --- a/targeted/Search www.xssposed.org for known XSS.js +++ b/targeted/Search www.xssposed.org for known XSS.js @@ -1,10 +1,11 @@ // Searches www.xssposed.org for known XSS vulnerabilities. // This script just launches your default browser to perform the search. +const DesktopUtils = Java.type("org.zaproxy.zap.utils.DesktopUtils"); function invokeWith(msg) { var host = msg.getRequestHeader().getURI().getHost(); - org.zaproxy.zap.utils.DesktopUtils.openUrlInBrowser( + DesktopUtils.openUrlInBrowser( "https://www.xssposed.org/search/?search=" + host + "&type=host" ); } diff --git a/targeted/cve-2021-22214.js b/targeted/cve-2021-22214.js index 35079488..603efd28 100644 --- a/targeted/cve-2021-22214.js +++ b/targeted/cve-2021-22214.js @@ -2,6 +2,7 @@ * Contributed by Astra Security (https://www.getastra.com/) * @author Prince Mendiratta */ +const Alert = Java.type("org.parosproxy.paros.core.scanner.Alert"); var pluginid = 100024; @@ -151,12 +152,7 @@ function customAlert( .getExtension(ExtensionAlert.NAME); var ref = new HistoryReference(session, HistoryReference.TYPE_ZAP_USER, msg); - var alert = new org.parosproxy.paros.core.scanner.Alert( - pluginid, - alertRisk, - alertConfidence, - alertName - ); + var alert = new Alert(pluginid, alertRisk, alertConfidence, alertName); alert.setDescription(alertDesc); alert.setAttack(alertAttack); alert.setEvidence(alertEvidence); diff --git a/targeted/cve-2021-41773-apache-path-trav.js b/targeted/cve-2021-41773-apache-path-trav.js index d2fae052..343a2f1c 100644 --- a/targeted/cve-2021-41773-apache-path-trav.js +++ b/targeted/cve-2021-41773-apache-path-trav.js @@ -2,6 +2,7 @@ * Scan rule for Apache 2.4.49 path traversal CVE-2021-41773. * Based on: https://github.com/RootUp/PersonalStuff/blob/master/http-vuln-cve-2021-41773.nse */ +const Alert = java.type("org.parosproxy.paros.core.scanner.Alert"); var HttpSender = Java.type("org.parosproxy.paros.network.HttpSender"); var HistoryReference = Java.type("org.parosproxy.paros.model.HistoryReference"); @@ -93,12 +94,7 @@ function customAlert( .getExtension(ExtensionAlert.NAME); var ref = new HistoryReference(session, HistoryReference.TYPE_ZAP_USER, msg); - var alert = new org.parosproxy.paros.core.scanner.Alert( - -1, - alertRisk, - alertConfidence, - alertName - ); + var alert = new Alert(-1, alertRisk, alertConfidence, alertName); alert.setDescription(alertDesc); alert.setAttack(alertAttack); alert.setEvidence(alertEvidence); diff --git a/targeted/json_csrf_poc_generator.js b/targeted/json_csrf_poc_generator.js index 3b45183e..ca4bb4d6 100644 --- a/targeted/json_csrf_poc_generator.js +++ b/targeted/json_csrf_poc_generator.js @@ -4,6 +4,11 @@ // released under the Apache v2.0 license. //You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 //Author : @haseebeqx +const CONTENT_TYPE = Java.type( + "org.parosproxy.paros.network.HttpHeader.CONTENT_TYPE" +); +const StringSelection = Java.type("java.awt.datatransfer.StringSelection"); +const Toolkit = java.type("java.awt.Toolkit"); function invokeWith(msg) { var string = "\n"; @@ -32,9 +37,7 @@ function invokeWith(msg) { if (body.length() != 0) if (!isJson(body)) { if (ismultipart(msg.getRequestHeader())) { - var type = msg - .getRequestHeader() - .getHeader(org.parosproxy.paros.network.HttpHeader.CONTENT_TYPE); + var type = msg.getRequestHeader().getHeader(CONTENT_TYPE); var delim = type.substring(type.search("=") + 1, type.length()); var h = body.split("--" + delim); var k = 0; @@ -98,8 +101,8 @@ function invokeWith(msg) { string += "\n"; print("\n\n\n"); print(string); - var selected = new java.awt.datatransfer.StringSelection(string); - var clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard(); + var selected = new StringSelection(string); + var clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(selected, null); } diff --git a/targeted/request_to_xml.js b/targeted/request_to_xml.js index 6792b386..1647c450 100644 --- a/targeted/request_to_xml.js +++ b/targeted/request_to_xml.js @@ -11,6 +11,12 @@ // tested on: ZAP 2.7.0 // rule1: pure JSON , no CODE // rule2: correct body (make edits only after conversion) +const CONTENT_TYPE = Java.type( + "org.parosproxy.paros.network.HttpHeader.CONTENT_TYPE" +); +const CONTENT_LENGTH = Java.type( + "org.parosproxy.paros.network.HttpHeader.CONTENT_LENGTH" +); var requester = control.getExtensionLoader().getExtension("ExtensionRequester"); @@ -30,14 +36,8 @@ function invokeWith(msg) { msg.setRequestBody(body); msg.getRequestHeader().setContentLength(msg.getRequestBody().length()); var header = msg.getRequestHeader(); - header.setHeader( - org.parosproxy.paros.network.HttpHeader.CONTENT_TYPE, - "application/xml" - ); - header.setHeader( - org.parosproxy.paros.network.HttpHeader.CONTENT_LENGTH, - body.length - ); + header.setHeader(CONTENT_TYPE, "application/xml"); + header.setHeader(CONTENT_LENGTH, body.length); msg.setRequestHeader(header); requester.displayMessage(msg.cloneRequest()); } @@ -52,9 +52,7 @@ function isJson(str) { } function ismultipart(header) { - var type = header.getHeader( - org.parosproxy.paros.network.HttpHeader.CONTENT_TYPE - ); + var type = header.getHeader(CONTENT_TYPE); if (type == null) return false; if (type.contains("multipart/form-data")) return true; return false; @@ -149,9 +147,7 @@ function toXml(key, value, att) { } } function multiToJson(msg) { - var type = msg - .getRequestHeader() - .getHeader(org.parosproxy.paros.network.HttpHeader.CONTENT_TYPE); + var type = msg.getRequestHeader().getHeader(CONTENT_TYPE); var delim = type.substring(type.search("=") + 1, type.length()); var h = msg .getRequestBody() diff --git a/targeted/search cvedetails using target server header.js b/targeted/search cvedetails using target server header.js index 912d5099..a9bcb9dd 100644 --- a/targeted/search cvedetails using target server header.js +++ b/targeted/search cvedetails using target server header.js @@ -1,9 +1,10 @@ // Captures Server header from the application response and searches cvedetails.com for known target server vulnerabilities. +const DesktopUtils = Java.type("org.zaproxy.zap.utils.DesktopUtils"); function invokeWith(msg) { var header = msg.getResponseHeader().getHeader("Server"); if (header != null) { - org.zaproxy.zap.utils.DesktopUtils.openUrlInBrowser( + DesktopUtils.openUrlInBrowser( "http://www.cvedetails.com/google-search-results.php?q=" + encodeURIComponent(header) + "&sa=Search"