Skip to content

Commit 4e19cd7

Browse files
authored
Merge pull request #451 from ricekot/passive-scripts-metadata
Implement `getMetadata` for some more Passive scripts
2 parents 8fbe274 + 6924e7a commit 4e19cd7

File tree

6 files changed

+169
-166
lines changed

6 files changed

+169
-166
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2929
- passive/Find Emails.js
3030
- passive/Find Hashes.js
3131
- passive/Find HTML Comments.js
32+
- passive/Find IBANs.js
33+
- passive/Find Internal IPs.js
34+
- passive/find_reflected_params.py
35+
- passive/HUNT.py
36+
- passive/Mutliple Security Header Check.js
3237

3338
## [18] - 2024-01-29
3439
### Added

passive/Find IBANs.js

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,31 @@
55
// Runs as a part of nightly baseline scans in many DevSecOps environments
66
// Complements the Pluralsight course - Writing Custom Scripts for Zed Attack Proxy
77

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

12+
function getMetadata() {
13+
return ScanRuleMetadata.fromYaml(`
14+
id: 100012
15+
name: Information Disclosure - IBAN Numbers
16+
description: An IBAN number was discovered in the HTTP response body.
17+
solution: Investigate IBAN numbers found in the response, remove or mask as required.
18+
risk: low
19+
confidence: high
20+
cweId: 200 # CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
21+
wascId: 13 # WASC-13: Information Leakage
22+
status: alpha
23+
codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/Find%20IBANs.js
24+
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
25+
`);
26+
}
27+
28+
function scan(helper, msg, src) {
1929
// lets build a regular expression that can find IBAN addresses
2030
// the regex must appear within /( and )/g
2131
var re = /([A-Za-z]{2}[0-9]{2}[A-Za-z]{4}[0-9]{10})/g;
2232

23-
// we need to set the url variable to the request or we cant track the alert later
24-
var url = msg.getRequestHeader().getURI().toString();
25-
2633
// lets check its not one of the files types that are never likely to contain stuff, like pngs and jpegs
2734
var contentType = msg.getResponseHeader().getHeader("Content-Type");
2835
var unwantedFileTypes = [
@@ -48,20 +55,11 @@ function scan(ps, msg, src) {
4855
foundIBAN.push(comm[0]);
4956
}
5057
// woohoo we found an IBAN lets make an alert for it
51-
ps.raiseAlert(
52-
alertRisk,
53-
alertConfidence,
54-
alertTitle,
55-
alertDesc,
56-
url,
57-
"",
58-
"",
59-
foundIBAN.toString(),
60-
alertSolution,
61-
foundIBAN.toString(),
62-
cweId,
63-
wascId,
64-
msg
65-
);
58+
helper
59+
.newAlert()
60+
.setEvidence(foundIBAN[0])
61+
.setOtherInfo(`Other instances: ${foundIBAN.slice(1).toString()}`)
62+
.setMessage(msg)
63+
.raise();
6664
}
6765
}

passive/Find Internal IPs.js

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
// RFC1918 internal IP Finder by freakyclown@gmail.com
22

3-
function scan(ps, msg, src) {
4-
var url = msg.getRequestHeader().getURI().toString();
5-
var alertRisk = 2;
6-
var alertConfidence = 2;
7-
var alertTitle = "Private IP address in Body(script)";
8-
var alertDesc =
9-
"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. ";
10-
var alertSolution =
11-
"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.";
3+
var ScanRuleMetadata = Java.type(
4+
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
5+
);
126

13-
var cweId = 0;
14-
var wascId = 0;
7+
function getMetadata() {
8+
return ScanRuleMetadata.fromYaml(`
9+
id: 100013
10+
name: Information Disclosure - Private IP Address
11+
description: >
12+
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.
13+
This information might be helpful for further attacks targeting internal systems.
14+
solution: >
15+
Remove the private IP address from the HTTP response body.
16+
For comments, use JSP/ASP comment instead of HTML/JavaScript comment which can be seen by client browsers.
17+
risk: medium
18+
confidence: medium
19+
cweId: 200 # CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
20+
wascId: 13 # WASC-13: Information Leakage
21+
status: alpha
22+
codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/Find%20Internal%20IPs.js
23+
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
24+
`);
25+
}
26+
27+
function scan(helper, msg, src) {
1528
// regex must appear within /( and )/g
1629
var re =
1730
/((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;
@@ -42,21 +55,12 @@ function scan(ps, msg, src) {
4255
while ((comm = re.exec(body))) {
4356
foundIP.push(comm[0]);
4457
}
45-
ps.raiseAlert(
46-
alertRisk,
47-
alertConfidence,
48-
alertTitle,
49-
alertDesc,
50-
url,
51-
"",
52-
"",
53-
foundIP.toString(),
54-
alertSolution,
55-
"",
56-
cweId,
57-
wascId,
58-
msg
59-
);
58+
helper
59+
.newAlert()
60+
.setEvidence(foundIP[0])
61+
.setOtherInfo(`Other instances: ${foundIP.slice(1).toString()}`)
62+
.setMessage(msg)
63+
.raise();
6064
}
6165
}
6266
}

passive/HUNT.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
import re
22
from org.zaproxy.zap.extension.script import ScriptVars
3+
from org.zaproxy.addon.commonlib.scanrules import ScanRuleMetadata
34

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

67

8+
def getMetadata():
9+
return ScanRuleMetadata.fromYaml("""
10+
id: 100015
11+
name: HUNT Methodology
12+
description: >
13+
Find possible vulnerable entry points using HUNT Methodology (https://github.com/bugcrowd/HUNT).
14+
risk: info
15+
confidence: low
16+
status: alpha
17+
codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/HUNT.py
18+
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
19+
""")
20+
21+
22+
723
def appliesToHistoryType(histType):
824
"""
925
Limit scanned history types, which otherwise default to
@@ -23,7 +39,7 @@ def find_words_in_params(param_list, word_list):
2339
return result
2440

2541

26-
def hunt_alert(ps, msg, uri, result, title, desc):
42+
def hunt_alert(helper, msg, uri, result, title, desc):
2743
if not result:
2844
return
2945

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

37-
# Docs on alert raising function:
38-
# raiseAlert(int risk, int confidence, str name, str description, str uri,
39-
# str param, str attack, str otherInfo, str solution,
40-
# str evidence, int cweId, int wascId, HttpMessage msg)
41-
# risk: 0: info, 1: low, 2: medium, 3: high
42-
# confidence: 0: falsePositive, 1: low, 2: medium, 3: high, 4: confirmed
43-
ps.raiseAlert(0, 1, title, desc, uri, result_repr,
44-
None, info, None, None, 0, 0, msg)
53+
helper.newAlert().setName(title).setDescription(
54+
desc).setParam(result_repr).setOtherInfo(info).setMessage(msg).raise()
4555

4656

4757
def scan(ps, msg, src):

passive/Mutliple Security Header Check.js

Lines changed: 64 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
// Multiple Security Header checker by freakyclown@gmail.com
22

3-
function scan(ps, msg, src) {
4-
var url = msg.getRequestHeader().getURI().toString();
5-
var responseHeader = msg.getResponseHeader().toString();
6-
var alertRisk = [0, 1, 2, 3]; //0=informational, 1=low, 2=medium, 3=high
7-
var alertConfidence = [0, 1, 2, 3, 4]; //0=fp,1=low,2=medium,3=high,4=confirmed
3+
var ScanRuleMetadata = Java.type(
4+
"org.zaproxy.addon.commonlib.scanrules.ScanRuleMetadata"
5+
);
6+
7+
function getMetadata() {
8+
return ScanRuleMetadata.fromYaml(`
9+
id: 100016
10+
name: Missing Security Headers
11+
description: >
12+
Some of the following security headers are missing from the HTTP response:
13+
Strict-Transport-Security, Content-Security-Policy,
14+
X-XSS-Protection, X-Content-Type-Options, X-Frame-Options.
15+
solution: >
16+
Ensure that your web server, application server, load balancer, etc.
17+
is configured to set the missing security headers.
18+
risk: low
19+
confidence: high
20+
cweId: 693 # CWE-693: Protection Mechanism Failure
21+
wascId: 15 # WASC-15: Application Misconfiguration
22+
status: alpha
23+
codeLink: https://github.com/zaproxy/community-scripts/blob/main/passive/Mutliple%20Security%20Header%20Check.js
24+
helpLink: https://www.zaproxy.org/docs/desktop/addons/community-scripts/
25+
`);
26+
}
27+
28+
function scan(helper, msg, src) {
829
var alertTitle = [
9-
"Strict Transport Security(STS) Header Not Set (script)",
30+
"Strict-Transport-Security (HSTS) Header Not Set (script)",
1031
"Content-Security-Policy (script)",
1132
"Web Browser XSS Protection Not Enabled (script)",
1233
"X-Content-Type-Options Header Missing (script)",
@@ -29,27 +50,17 @@ function scan(ps, msg, src) {
2950
"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).",
3051
"",
3152
];
32-
var cweId = [0, 1];
33-
var wascId = [0, 1];
3453

3554
// test sts
3655
if (msg.getRequestHeader().isSecure()) {
3756
if (msg.getResponseHeader().getHeaders("Strict-Transport-Security") == null)
38-
ps.raiseAlert(
39-
alertRisk[1],
40-
alertConfidence[3],
41-
alertTitle[0],
42-
alertDesc[0],
43-
url,
44-
"",
45-
"",
46-
"",
47-
alertSolution[0],
48-
"",
49-
cweId[0],
50-
wascId[0],
51-
msg
52-
);
57+
helper
58+
.newAlert()
59+
.setName(alertTitle[0])
60+
.setDescription(alertDesc[0])
61+
.setSolution(alertSolution[0])
62+
.setMessage(msg)
63+
.raise();
5364
}
5465
// test csp
5566
if (
@@ -59,83 +70,53 @@ function scan(ps, msg, src) {
5970
"X-WebKit-CSP",
6071
])
6172
)
62-
ps.raiseAlert(
63-
alertRisk[1],
64-
alertConfidence[3],
65-
alertTitle[1],
66-
alertDesc[1],
67-
url,
68-
"",
69-
"",
70-
"",
71-
alertSolution[1],
72-
"",
73-
cweId[0],
74-
wascId[0],
75-
msg
76-
);
73+
helper
74+
.newAlert()
75+
.setName(alertTitle[1])
76+
.setDescription(alertDesc[1])
77+
.setSolution(alertSolution[1])
78+
.setMessage(msg)
79+
.raise();
7780

7881
// test xxs protection
7982
var re_xss = /(X\-XSS\-Protection\:.+1)/g;
8083
if (!re_xss.test(responseHeader)) {
8184
//if its false
82-
ps.raiseAlert(
83-
alertRisk[1],
84-
alertConfidence[3],
85-
alertTitle[2],
86-
alertDesc[2],
87-
url,
88-
"",
89-
"",
90-
"",
91-
alertSolution[2],
92-
"",
93-
cweId[0],
94-
wascId[0],
95-
msg
96-
);
85+
helper
86+
.newAlert()
87+
.setName(alertTitle[2])
88+
.setDescription(alertDesc[2])
89+
.setSolution(alertSolution[2])
90+
.setMessage(msg)
91+
.raise();
9792
}
9893

9994
// test xcontent no sniff protection
10095
var re_nosniff = /(X\-Content\-Type\-Options\:.*nosniff.*)/g;
10196
if (!re_nosniff.test(responseHeader)) {
10297
//if its false
103-
ps.raiseAlert(
104-
alertRisk[2],
105-
alertConfidence[2],
106-
alertTitle[3],
107-
alertDesc[3],
108-
url,
109-
"",
110-
"",
111-
"",
112-
alertSolution[3],
113-
"",
114-
cweId[0],
115-
wascId[0],
116-
msg
117-
);
98+
helper
99+
.newAlert()
100+
.setRisk(2)
101+
.setConfidence(2)
102+
.setName(alertTitle[3])
103+
.setDescription(alertDesc[3])
104+
.setSolution(alertSolution[3])
105+
.setMessage(msg)
106+
.raise();
118107
}
119108

120109
// test xcontent no sniff protection
121110
var re_clickjack = /(X\-Frame\-Options\:.+[Dd][Ee][Nn][Yy])/g;
122111
if (!re_clickjack.test(responseHeader)) {
123112
//if its false
124-
ps.raiseAlert(
125-
alertRisk[1],
126-
alertConfidence[3],
127-
alertTitle[4],
128-
alertDesc[4],
129-
url,
130-
"",
131-
"",
132-
"",
133-
alertSolution[4],
134-
"",
135-
cweId[0],
136-
wascId[0],
137-
msg
138-
);
113+
helper
114+
.newAlert()
115+
.setName(alertTitle[4])
116+
.setDescription(alertDesc[4])
117+
.setSolution(alertSolution[4])
118+
.setMessage(msg)
119+
.raise();
139120
}
140121
}
141122

0 commit comments

Comments
 (0)