Skip to content

Commit 32b195b

Browse files
committed
Merge pull request #15 from thc202/feature/zap_report_with_merged_alerts
Add support for OWASP ZAP reports with merged alerts
2 parents 7d1beb7 + 6ae2de6 commit 32b195b

File tree

1 file changed

+67
-17
lines changed

1 file changed

+67
-17
lines changed

src/main/java/org/owasp/benchmark/score/parsers/ZapReader.java

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,7 @@ public TestResults parse(File f) throws Exception {
5454

5555
for ( Node flaw : issueList ) {
5656
try {
57-
TestCaseResult tcr = parseZapIssue(flaw);
58-
if (tcr != null ) {
59-
// System.out.println( tcr.getNumber() + " " + tcr.getName() + " -> " + tcr.getCWE() + "\t" + tcr.getEvidence() );
60-
tr.put(tcr);
61-
}
57+
parseAndAddZapIssues(flaw, tr);
6258
} catch( Exception e ) {
6359
// print and continue
6460
e.printStackTrace();
@@ -80,9 +76,20 @@ public TestResults parse(File f) throws Exception {
8076
// <riskdesc>Low (Medium)</riskdesc>
8177
// <desc>Web Browser XSS Protection is not enabled, or is disabled by the configuration of the 'X-XSS-Protection' HTTP response header on the web server
8278
// </desc>
79+
8380
// <uri>http://localhost:8080/benchmark/BenchmarkTest00028.html</uri>
8481
// <param/>
8582
// <attack/>
83+
// OR, for merged reports:
84+
// <instances>
85+
// <instance>
86+
// <uri>http://localhost:8080/benchmark/BenchmarkTest00028.html</uri>
87+
// <param/>
88+
// <attack/>
89+
// </instance>
90+
// <!-- more "instance" elements per merged alert -->
91+
// </instances>
92+
8693
// <otherinfo>The X-XSS-Protection HTTP response header allows the web server to enable or disable the web browser's XSS protection mechanism. The following values would attempt to enable it:
8794
// <solution>Ensure that the web browser's XSS filter is enabled, by setting the X-XSS-Protection HTTP response header to '1'.
8895
// </solution>
@@ -98,23 +105,43 @@ public TestResults parse(File f) throws Exception {
98105

99106

100107

101-
private TestCaseResult parseZapIssue(Node flaw) throws URISyntaxException {
102-
TestCaseResult tcr = new TestCaseResult();
108+
private void parseAndAddZapIssues(Node flaw, TestResults tr) throws URISyntaxException {
109+
int cwe = -1;
103110
Node rule = getNamedChild("cweid", flaw);
104111
if ( rule != null ) {
105-
tcr.setCWE( cweLookup( rule.getTextContent() ) );
112+
cwe = cweLookup( rule.getTextContent() );
106113
}
107114

108115
String cat = getNamedChild("alert", flaw).getTextContent();
109-
tcr.setCategory( cat );
110116

111-
String conf = getNamedChild( "confidence", flaw ).getTextContent();
112-
tcr.setConfidence( Integer.parseInt( conf ) );
117+
int conf = Integer.parseInt(getNamedChild( "confidence", flaw ).getTextContent());
118+
119+
Node instances = getNamedChild("instances", flaw);
120+
if (instances == null) {
121+
addIssue(flaw, tr, cwe, cat, conf);
122+
return;
123+
}
124+
125+
List<Node> instanceList = getNamedChildren("instance", instances);
126+
for (Node instance : instanceList) {
127+
addIssue(instance, tr, cwe, cat, conf);
128+
}
129+
}
130+
131+
private void addIssue(Node alertData, TestResults tr, int cwe, String category, int confidence) throws URISyntaxException {
132+
int testNumber = extractTestNumber(getNamedChild("uri", alertData).getTextContent());
133+
if (testNumber != -1) {
134+
TestCaseResult tcr = createTestCaseResult(cwe, category, confidence, testNumber);
135+
// System.out.println( tcr.getNumber() + " " + tcr.getName() + " -> " + tcr.getCWE() + "\t" + tcr.getEvidence() );
136+
tr.put(tcr);
137+
}
138+
}
113139

114-
tcr.setEvidence( cat );
140+
private static int extractTestNumber(String uri) throws URISyntaxException {
141+
// Remove the query and fragment from the URI because some of alert URIs (e.g. generated by DOM XSS) might be malformed
142+
// (characters that should be escaped are not) which leads to exceptions when parsed by java.net.URI.
143+
URI url = new URI(removeQueryAndFragment(uri));
115144

116-
String uri = getNamedChild( "uri", flaw ).getTextContent();
117-
URI url = new URI( uri );
118145
String testfile = url.getPath();
119146
testfile = testfile.substring( testfile.lastIndexOf('/') +1 );
120147

@@ -124,15 +151,38 @@ private TestCaseResult parseZapIssue(Node flaw) throws URISyntaxException {
124151
testno = testno.substring(0, testno.length() -5 );
125152
}
126153
try {
127-
tcr.setNumber( Integer.parseInt( testno ) );
128-
return tcr;
154+
return Integer.parseInt( testno );
129155
} catch( NumberFormatException e ) {
130156
System.out.println( "> Parse error " + testfile + ":: " + testno );
131157
}
132158
}
133-
return null;
159+
return -1;
134160
}
135161

162+
private static String removeQueryAndFragment(String uri) {
163+
String strippedUri = uri;
164+
int idx = strippedUri.indexOf('?');
165+
if (idx != -1) {
166+
strippedUri = strippedUri.substring(0, idx);
167+
}
168+
idx = strippedUri.indexOf('#');
169+
if (idx != -1) {
170+
strippedUri = strippedUri.substring(0, idx);
171+
}
172+
return strippedUri;
173+
}
174+
175+
private static TestCaseResult createTestCaseResult(int cwe, String category, int confidence, int testNumber) {
176+
TestCaseResult tcr = new TestCaseResult();
177+
if (cwe != -1) {
178+
tcr.setCWE(cwe);
179+
}
180+
tcr.setCategory(category);
181+
tcr.setEvidence(category);
182+
tcr.setConfidence(confidence);
183+
tcr.setNumber(testNumber);
184+
return tcr;
185+
}
136186

137187
private int cweLookup(String orig) {
138188

0 commit comments

Comments
 (0)