Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement getMetadata for some more Passive scripts #451

Merged
merged 1 commit into from
Jun 12, 2024
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- passive/Find Emails.js
- passive/Find Hashes.js
- passive/Find HTML Comments.js
- passive/Find IBANs.js
- passive/Find Internal IPs.js
- passive/find_reflected_params.py
- passive/HUNT.py
- passive/Mutliple Security Header Check.js

## [18] - 2024-01-29
### Added
Expand Down
54 changes: 26 additions & 28 deletions passive/Find IBANs.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,31 @@
// Runs as a part of nightly baseline scans in many DevSecOps environments
// Complements the Pluralsight course - Writing Custom Scripts for Zed Attack Proxy

function scan(ps, msg, src) {
// first lets set up some details incase we find an IBAN, these will populate the alert later
var alertRisk = 1;
var alertConfidence = 3;
var alertTitle = "IBAN found - investigation required (script)";
var alertDesc = "IBAN numbers were found";
var alertSolution =
"Investigate IBAN numbers found in the response, remove or mask as required";
var cweId = 200;
var wascId = 0;
var ScanRuleMetadata = Java.type(
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);

function getMetadata() {
return ScanRuleMetadata.fromYaml(`
id: 100012
name: Information Disclosure - IBAN Numbers
description: An IBAN number was discovered in the HTTP response body.
solution: Investigate IBAN numbers found in the response, remove or mask as required.
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/Find%20IBANs.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function scan(helper, msg, src) {
// lets build a regular expression that can find IBAN addresses
// the regex must appear within /( and )/g
var re = /([A-Za-z]{2}[0-9]{2}[A-Za-z]{4}[0-9]{10})/g;

// we need to set the url variable to the request or we cant track the alert later
var url = msg.getRequestHeader().getURI().toString();

// lets check its not one of the files types that are never likely to contain stuff, like pngs and jpegs
var contentType = msg.getResponseHeader().getHeader("Content-Type");
var unwantedFileTypes = [
Expand All @@ -48,20 +55,11 @@ function scan(ps, msg, src) {
foundIBAN.push(comm[0]);
}
// woohoo we found an IBAN lets make an alert for it
ps.raiseAlert(
alertRisk,
alertConfidence,
alertTitle,
alertDesc,
url,
"",
"",
foundIBAN.toString(),
alertSolution,
foundIBAN.toString(),
cweId,
wascId,
msg
);
helper
.newAlert()
.setEvidence(foundIBAN[0])
.setOtherInfo(`Other instances: ${foundIBAN.slice(1).toString()}`)
.setMessage(msg)
.raise();
}
}
56 changes: 30 additions & 26 deletions passive/Find Internal IPs.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
// RFC1918 internal IP Finder by freakyclown@gmail.com

function scan(ps, msg, src) {
var url = msg.getRequestHeader().getURI().toString();
var alertRisk = 2;
var alertConfidence = 2;
var alertTitle = "Private IP address in Body(script)";
var alertDesc =
"A private IP such as 10.x.x.x, 172.x.x.x, 192.168.x.x or IPV6 fe00:: has been found in the HTTP response body. This information might be helpful for further attacks targeting internal systems. ";
var alertSolution =
"Remove the private IP address from the HTTP response body. For comments, use JSP/ASP comment instead of HTML/JavaScript comment which can be seen by client browsers.";
var ScanRuleMetadata = Java.type(
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);

var cweId = 0;
var wascId = 0;
function getMetadata() {
return ScanRuleMetadata.fromYaml(`
id: 100013
name: Information Disclosure - Private IP Address
description: >
A private IP such as 10.x.x.x, 172.x.x.x, 192.168.x.x or IPV6 fe00:: has been found in the HTTP response body.
This information might be helpful for further attacks targeting internal systems.
solution: >
Remove the private IP address from the HTTP response body.
For comments, use JSP/ASP comment instead of HTML/JavaScript comment which can be seen by client browsers.
risk: medium
confidence: medium
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/Find%20Internal%20IPs.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function scan(helper, msg, src) {
// regex must appear within /( and )/g
var re =
/((172\.\d{1,3}\.\d{1,3}\.\d{1,3})|(192\.168\.\d{1,3}\.\d{1,3})|(10\.\d{1,3}\.\d{1,3}\.\d{1,3})|([fF][eE][89aAbBcCdDeEfF]::))/g;
Expand Down Expand Up @@ -42,21 +55,12 @@ function scan(ps, msg, src) {
while ((comm = re.exec(body))) {
foundIP.push(comm[0]);
}
ps.raiseAlert(
alertRisk,
alertConfidence,
alertTitle,
alertDesc,
url,
"",
"",
foundIP.toString(),
alertSolution,
"",
cweId,
wascId,
msg
);
helper
.newAlert()
.setEvidence(foundIP[0])
.setOtherInfo(`Other instances: ${foundIP.slice(1).toString()}`)
.setMessage(msg)
.raise();
}
}
}
28 changes: 19 additions & 9 deletions passive/HUNT.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import re
from org.zaproxy.zap.extension.script import ScriptVars
from org.zaproxy.addon.commonlib.scanrules import ScanRuleMetadata

'''find possible vulnerable entry points using Hunt Methodology - https://github.com/bugcrowd/HUNT'''


def getMetadata():
return ScanRuleMetadata.fromYaml("""
id: 100015
name: HUNT Methodology
description: >
Find possible vulnerable entry points using HUNT Methodology (https://github.com/bugcrowd/HUNT).
risk: info
confidence: low
status: alpha
codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/HUNT.py
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
""")



def appliesToHistoryType(histType):
"""
Limit scanned history types, which otherwise default to
Expand All @@ -23,7 +39,7 @@ def find_words_in_params(param_list, word_list):
return result


def hunt_alert(ps, msg, uri, result, title, desc):
def hunt_alert(helper, msg, uri, result, title, desc):
if not result:
return

Expand All @@ -34,14 +50,8 @@ def hunt_alert(ps, msg, uri, result, title, desc):
info = msg.getRequestHeader().toString()
info += "\n" + msg.getRequestBody().toString()

# Docs on alert raising function:
# raiseAlert(int risk, int confidence, str name, str description, str uri,
# str param, str attack, str otherInfo, str solution,
# str 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(0, 1, title, desc, uri, result_repr,
None, info, None, None, 0, 0, msg)
helper.newAlert().setName(title).setDescription(
desc).setParam(result_repr).setOtherInfo(info).setMessage(msg).raise()


def scan(ps, msg, src):
Expand Down
147 changes: 64 additions & 83 deletions passive/Mutliple Security Header Check.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
// Multiple Security Header checker by freakyclown@gmail.com

function scan(ps, msg, src) {
var url = msg.getRequestHeader().getURI().toString();
var responseHeader = msg.getResponseHeader().toString();
var alertRisk = [0, 1, 2, 3]; //0=informational, 1=low, 2=medium, 3=high
var alertConfidence = [0, 1, 2, 3, 4]; //0=fp,1=low,2=medium,3=high,4=confirmed
var ScanRuleMetadata = Java.type(
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
);

function getMetadata() {
return ScanRuleMetadata.fromYaml(`
id: 100016
name: Missing Security Headers
description: >
Some of the following security headers are missing from the HTTP response:
Strict-Transport-Security, Content-Security-Policy,
X-XSS-Protection, X-Content-Type-Options, X-Frame-Options.
solution: >
Ensure that your web server, application server, load balancer, etc.
is configured to set the missing security headers.
risk: low
confidence: high
cweId: 693 # CWE-693: Protection Mechanism Failure
wascId: 15 # WASC-15: Application Misconfiguration
status: alpha
codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/Mutliple%20Security%20Header%20Check.js
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
`);
}

function scan(helper, msg, src) {
var alertTitle = [
"Strict Transport Security(STS) Header Not Set (script)",
"Strict-Transport-Security (HSTS) Header Not Set (script)",
"Content-Security-Policy (script)",
"Web Browser XSS Protection Not Enabled (script)",
"X-Content-Type-Options Header Missing (script)",
Expand All @@ -29,27 +50,17 @@ function scan(ps, msg, src) {
"Most modern Web browsers support the X-Frame-Options HTTP header. Ensure it's set on all web pages returned by your site (if you expect the page to be framed only by pages on your server (e.g. it's part of a FRAMESET) then you'll want to use SAMEORIGIN, otherwise if you never expect the page to be framed, you should use DENY. ALLOW-FROM allows specific websites to frame the web page in supported web browsers).",
"",
];
var cweId = [0, 1];
var wascId = [0, 1];

// test sts
if (msg.getRequestHeader().isSecure()) {
if (msg.getResponseHeader().getHeaders("Strict-Transport-Security") == null)
ps.raiseAlert(
alertRisk[1],
alertConfidence[3],
alertTitle[0],
alertDesc[0],
url,
"",
"",
"",
alertSolution[0],
"",
cweId[0],
wascId[0],
msg
);
helper
.newAlert()
.setName(alertTitle[0])
.setDescription(alertDesc[0])
.setSolution(alertSolution[0])
.setMessage(msg)
.raise();
}
// test csp
if (
Expand All @@ -59,83 +70,53 @@ function scan(ps, msg, src) {
"X-WebKit-CSP",
])
)
ps.raiseAlert(
alertRisk[1],
alertConfidence[3],
alertTitle[1],
alertDesc[1],
url,
"",
"",
"",
alertSolution[1],
"",
cweId[0],
wascId[0],
msg
);
helper
.newAlert()
.setName(alertTitle[1])
.setDescription(alertDesc[1])
.setSolution(alertSolution[1])
.setMessage(msg)
.raise();

// test xxs protection
var re_xss = /(X\-XSS\-Protection\:.+1)/g;
if (!re_xss.test(responseHeader)) {
//if its false
ps.raiseAlert(
alertRisk[1],
alertConfidence[3],
alertTitle[2],
alertDesc[2],
url,
"",
"",
"",
alertSolution[2],
"",
cweId[0],
wascId[0],
msg
);
helper
.newAlert()
.setName(alertTitle[2])
.setDescription(alertDesc[2])
.setSolution(alertSolution[2])
.setMessage(msg)
.raise();
}

// test xcontent no sniff protection
var re_nosniff = /(X\-Content\-Type\-Options\:.*nosniff.*)/g;
if (!re_nosniff.test(responseHeader)) {
//if its false
ps.raiseAlert(
alertRisk[2],
alertConfidence[2],
alertTitle[3],
alertDesc[3],
url,
"",
"",
"",
alertSolution[3],
"",
cweId[0],
wascId[0],
msg
);
helper
.newAlert()
.setRisk(2)
.setConfidence(2)
.setName(alertTitle[3])
.setDescription(alertDesc[3])
.setSolution(alertSolution[3])
.setMessage(msg)
.raise();
}

// test xcontent no sniff protection
var re_clickjack = /(X\-Frame\-Options\:.+[Dd][Ee][Nn][Yy])/g;
if (!re_clickjack.test(responseHeader)) {
//if its false
ps.raiseAlert(
alertRisk[1],
alertConfidence[3],
alertTitle[4],
alertDesc[4],
url,
"",
"",
"",
alertSolution[4],
"",
cweId[0],
wascId[0],
msg
);
helper
.newAlert()
.setName(alertTitle[4])
.setDescription(alertDesc[4])
.setSolution(alertSolution[4])
.setMessage(msg)
.raise();
}
}

Expand Down
Loading