Skip to content

Commit 74e1efb

Browse files
committed
Reader for WhiteHat Dynamic
1 parent 64f72b2 commit 74e1efb

File tree

5 files changed

+251
-1
lines changed

5 files changed

+251
-1
lines changed

plugin/src/main/java/org/owasp/benchmarkutils/score/ResultFile.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,33 @@ public File file() {
133133
}
134134

135135
public CSVParser csvRecords() {
136+
return csvRecords(content());
137+
}
138+
139+
private static CSVParser csvRecords(String content) {
136140
try {
137141
return CSVFormat.DEFAULT
138142
.builder()
139143
.setHeader()
140144
.setSkipHeaderRecord(false)
141145
.setIgnoreEmptyLines(false)
142146
.build()
143-
.parse(new StringReader(content()));
147+
.parse(new StringReader(content));
144148
} catch (IOException e) {
145149
throw new RuntimeException(e);
146150
}
147151
}
148152

153+
public CSVParser csvRecordsSkipFirstRows(int skipRows) {
154+
List<String> rows = contentAsRows();
155+
156+
return csvRecords(String.join("\n", rows.subList(skipRows, rows.size())));
157+
}
158+
159+
public List<String> contentAsRows() {
160+
return Arrays.asList(content().split("\n"));
161+
}
162+
149163
/**
150164
* Read the specified line of the provided file. Returns empty string if the given file does not
151165
* have as many lines.

plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/Reader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.owasp.benchmarkutils.score.BenchmarkScore;
2929
import org.owasp.benchmarkutils.score.ResultFile;
3030
import org.owasp.benchmarkutils.score.TestSuiteResults;
31+
import org.owasp.benchmarkutils.score.parsers.csv.WhiteHatDynamicReader;
3132
import org.owasp.benchmarkutils.score.parsers.sarif.CodeQLReader;
3233
import org.owasp.benchmarkutils.score.parsers.sarif.ContrastScanReader;
3334
import org.owasp.benchmarkutils.score.parsers.sarif.DatadogSastReader;
@@ -109,6 +110,7 @@ public static List<Reader> allReaders() {
109110
new WapitiJsonReader(),
110111
new WapitiReader(),
111112
new WebInspectReader(),
113+
new WhiteHatDynamicReader(),
112114
new ZapJsonReader(),
113115
new ZapReader());
114116
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/**
2+
* OWASP Benchmark Project
3+
*
4+
* <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For
5+
* details, please see <a
6+
* href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
7+
*
8+
* <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
9+
* of the GNU General Public License as published by the Free Software Foundation, version 2.
10+
*
11+
* <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
12+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13+
* PURPOSE. See the GNU General Public License for more details
14+
*
15+
* @author Sascha Knoop
16+
* @created 2024
17+
*/
18+
package org.owasp.benchmarkutils.score.parsers.csv;
19+
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
import org.apache.commons.csv.CSVParser;
24+
import org.apache.commons.csv.CSVRecord;
25+
import org.owasp.benchmarkutils.score.BenchmarkScore;
26+
import org.owasp.benchmarkutils.score.CweNumber;
27+
import org.owasp.benchmarkutils.score.ResultFile;
28+
import org.owasp.benchmarkutils.score.TestCaseResult;
29+
import org.owasp.benchmarkutils.score.TestSuiteResults;
30+
import org.owasp.benchmarkutils.score.parsers.Reader;
31+
32+
/**
33+
* Reader for <a
34+
* href="https://www.synopsys.com/software-integrity/security-testing/dast.html">WhiteHat Dynamic
35+
* (DAST)</a> results.
36+
*/
37+
public class WhiteHatDynamicReader extends Reader {
38+
39+
private final Map<String, Integer> categoryMappings = new HashMap<>();
40+
41+
public WhiteHatDynamicReader() {
42+
categoryMappings.put("Directory Indexing", 548);
43+
categoryMappings.put("Insecure Indexing", 548);
44+
categoryMappings.put("Insufficient Authorization", 287);
45+
categoryMappings.put("Insufficient Process Validation", 424);
46+
categoryMappings.put("Path Traversal", 35);
47+
categoryMappings.put("Predictable Resource Location", 425);
48+
categoryMappings.put("URL Redirector Abuse", 601);
49+
categoryMappings.put("Cross Site Request Forgery", 352);
50+
categoryMappings.put("Insufficient Transport Layer Protection", 319);
51+
categoryMappings.put("Session Prediction", 330);
52+
categoryMappings.put("Application Code Execution", 94);
53+
categoryMappings.put("Cross Site Scripting", CweNumber.XSS);
54+
categoryMappings.put("HTTP Response Splitting", 113);
55+
categoryMappings.put("Improper Input Handling", 20);
56+
categoryMappings.put("LDAP Injection", CweNumber.LDAP_INJECTION);
57+
categoryMappings.put("Mail Command Injection", 77);
58+
categoryMappings.put("OS Command Injection", CweNumber.COMMAND_INJECTION);
59+
categoryMappings.put("Query Language Injection", 943);
60+
categoryMappings.put("SQL Injection", CweNumber.SQL_INJECTION);
61+
categoryMappings.put("SSI Injection", 97);
62+
categoryMappings.put("XML Injection", 91);
63+
categoryMappings.put("XPath Injection", CweNumber.XPATH_INJECTION);
64+
categoryMappings.put("XQuery Injection", 652);
65+
categoryMappings.put("OS Commanding", CweNumber.COMMAND_INJECTION);
66+
categoryMappings.put("Routing Detour", 610);
67+
categoryMappings.put("Cacheable Sensitive Response", 525);
68+
categoryMappings.put("Frameable Resource", 1021);
69+
categoryMappings.put("Abuse of Functionality", 840);
70+
categoryMappings.put("Brute Force", 799);
71+
categoryMappings.put("Clickjacking", 1021);
72+
categoryMappings.put("Insufficient Anti-automation", 799);
73+
categoryMappings.put("Application Misconfiguration", 16);
74+
categoryMappings.put("Autocomplete Attribute", 16);
75+
categoryMappings.put("Fingerprinting", 497);
76+
categoryMappings.put("Information Leakage", 200);
77+
categoryMappings.put("Non-HttpOnly Session Cookie", 1004);
78+
categoryMappings.put("Server Misconfiguration", 16);
79+
categoryMappings.put("Unsecured Session Cookie", CweNumber.INSECURE_COOKIE);
80+
categoryMappings.put("XML External Entities", CweNumber.XXE);
81+
categoryMappings.put("Missing Secure Headers", 693);
82+
categoryMappings.put("Unpatched Software", 1104);
83+
categoryMappings.put("Insufficient Authentication", 285);
84+
categoryMappings.put("Insufficient Password Policy Implementation", 521);
85+
categoryMappings.put("Insufficient Password Recovery", 640);
86+
categoryMappings.put("Insufficient Session Expiration", 613);
87+
categoryMappings.put("Session Fixation", 384);
88+
categoryMappings.put("Content Spoofing", 451);
89+
categoryMappings.put("Remote File Inclusion", 829);
90+
categoryMappings.put("Denial of Service", 400);
91+
categoryMappings.put("Buffer Overflow", 788);
92+
}
93+
94+
@Override
95+
public boolean canRead(ResultFile resultFile) {
96+
return resultFile.filename().endsWith(".csv")
97+
&& resultFile.line(0).contains("Report As Of");
98+
}
99+
100+
@Override
101+
public TestSuiteResults parse(ResultFile resultFile) throws Exception {
102+
TestSuiteResults tr =
103+
new TestSuiteResults("WhiteHat Dynamic", true, TestSuiteResults.ToolType.DAST);
104+
105+
try (CSVParser records = resultFile.csvRecordsSkipFirstRows(headerRow(resultFile))) {
106+
records.stream()
107+
.filter(WhiteHatDynamicReader::isRelevant)
108+
.forEach(r -> tr.put(toTestCaseResult(r)));
109+
}
110+
111+
return tr;
112+
}
113+
114+
private int headerRow(ResultFile resultFile) {
115+
List<String> rows = resultFile.contentAsRows();
116+
117+
for (int i = 0; i < rows.size(); i++) {
118+
if (rows.get(i).startsWith("Vuln ID")) {
119+
return i;
120+
}
121+
}
122+
123+
throw new RuntimeException("No header row found");
124+
}
125+
126+
private static boolean isRelevant(CSVRecord r) {
127+
return extractFilename(r.get("Attack Vector Path")).startsWith(BenchmarkScore.TESTCASENAME);
128+
}
129+
130+
private TestCaseResult toTestCaseResult(CSVRecord record) {
131+
String filename = record.get("Attack Vector Path");
132+
String category = record.get("Class");
133+
134+
TestCaseResult tcr = new TestCaseResult();
135+
136+
tcr.setCategory(category);
137+
tcr.setCWE(cweLookup(category));
138+
tcr.setNumber(testNumber(filename));
139+
140+
return tcr;
141+
}
142+
143+
private int cweLookup(String category) {
144+
if (categoryMappings.containsKey(category)) {
145+
return categoryMappings.get(category);
146+
}
147+
148+
System.out.println(
149+
"WARNING: WhiteHat result file contained unmapped category: " + category);
150+
return CweNumber.DONTCARE;
151+
}
152+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* OWASP Benchmark Project
3+
*
4+
* <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For
5+
* details, please see <a
6+
* href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
7+
*
8+
* <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
9+
* of the GNU General Public License as published by the Free Software Foundation, version 2.
10+
*
11+
* <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
12+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13+
* PURPOSE. See the GNU General Public License for more details.
14+
*
15+
* @author Sascha Knoop
16+
* @created 2024
17+
*/
18+
package org.owasp.benchmarkutils.score.parsers.csv;
19+
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertTrue;
22+
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.Test;
25+
import org.owasp.benchmarkutils.score.BenchmarkScore;
26+
import org.owasp.benchmarkutils.score.CweNumber;
27+
import org.owasp.benchmarkutils.score.ResultFile;
28+
import org.owasp.benchmarkutils.score.TestHelper;
29+
import org.owasp.benchmarkutils.score.TestSuiteResults;
30+
import org.owasp.benchmarkutils.score.parsers.ReaderTestBase;
31+
32+
public class WhiteHatDynamicReaderTest extends ReaderTestBase {
33+
34+
private ResultFile resultFile;
35+
36+
@BeforeEach
37+
void setUp() {
38+
resultFile = TestHelper.resultFileOf("testfiles/Benchmark_WhiteHat.csv");
39+
BenchmarkScore.TESTCASENAME = "BenchmarkTest";
40+
}
41+
42+
@Test
43+
public void onlyWhiteHatDynamicReaderReportsCanReadAsTrue() {
44+
assertOnlyMatcherClassIs(this.resultFile, WhiteHatDynamicReader.class);
45+
}
46+
47+
@Test
48+
void readerHandlesGivenResultFile() throws Exception {
49+
WhiteHatDynamicReader reader = new WhiteHatDynamicReader();
50+
TestSuiteResults result = reader.parse(resultFile);
51+
52+
assertEquals(TestSuiteResults.ToolType.DAST, result.getToolType());
53+
assertTrue(result.isCommercial());
54+
assertEquals("WhiteHat Dynamic", result.getToolName());
55+
56+
assertEquals(2, result.getTotalResults());
57+
58+
assertEquals(CweNumber.COMMAND_INJECTION, result.get(1).get(0).getCWE());
59+
assertEquals(CweNumber.XSS, result.get(2).get(0).getCWE());
60+
}
61+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"Report As Of: Saturday, January 01, 2000",,,,,,,,,,,,,,,,,,,,,
2+
Prepared By: john.doe@example.com,,,,,,,,,,,,,,,,,,,,,
3+
Report Description: This report provides information about vulnerabilities.,,,,,,,,,,,,,,,,,,,,,
4+
Report Filtered By:,,,,,,,,,,,,,,,,,,,,,
5+
"Vulnerability Status: Closed, Open",,,,,,,,,,,,,,,,,,,,,
6+
"Rating: Note, Low, Medium, High, Critical",,,,,,,,,,,,,,,,,,,,,
7+
Start Date: 2000-01-01,,,,,,,,,,,,,,,,,,,,,
8+
End Date: 2000-02-02,,,,,,,,,,,,,,,,,,,,,
9+
Note: Vulnerability class descriptions and solutions are listed at the end.,,,,,,,,,,,,,,,,,,,,,
10+
,,,,,,,,,,,,,,,,,,,,,
11+
Vuln ID,Vuln URL,Attack Vector ID,Date Opened,Vuln Status,Attack Vector Status,Class,Asset Name,Asset URL,Asset ID,Rating,CVSS Score,CVSS Vector,Custom Description,Custom Solution,Attack Vector Path,Last Tested,Method,HTTP Request Header,Response Header,Notes,Response Status
12+
11111111,somedomain.com/benchmark/cmdi-00/BenchmarkTest0001,111111111,2000-01-01 01:01:01 -0100,Open,Open,OS Commanding,somedomain.com,https://somedomain.com/benchmark,100688,High,10.0,CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H,null,null,https://somedomain.com/benchmark/cmdi-00/BenchmarkTest0001,2000-01-01 01:01:01 -0100,POST,"Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7,Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5,Accept-Language:en-us,en;q=0.5,User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20100101 Firefox/13.0.1 WhiteHat Security,Content-Length:50,Content-Type:application/x-www-form-urlencoded,null","Client-SSL-Version:TLSv1_3,Content-Type:text/html;charset=UTF-8,Client-SSL-Cipher:TLS_AES_128_GCM_SHA256,Client-SSL-Socket-Class:IO::Socket::SSL,X-Content-Type-Options:nosniff,X-Frame-Options:DENY,Client-SSL-Cert-Issuer:/DC=corp/DC=root/DC=accounts/CN=Express Scripts Issuing CA 02,Client-SSL-Cert-Subject:/C=US/O=Some Test/OU=SSL/CN=whitehat-test-benchmark-1-dev,Client-SSL-Warning:Peer certificate not verified,Cache-Control:no-cache, no-store, must-revalidate,Content-Length:471,Content-Security-Policy:frame-ancestors 'self'; form-action 'self'; default-src 'unsafe-inline' 'unsafe-eval' 'self'; style-src 'unsafe-inline' 'self'; style-src-elem 'self' fonts.googleapis.com; font-src 'self' fonts.gstatic.com,Date:Sat, 01 Jan 2000 01:01:01 GMT",null,200
13+
22222222,somedomain.com/benchmark/xss-00/BenchmarkTest00002,222222222,2000-02-02 02:02:02 -0100,Open,Open,Cross Site Scripting,somedomain.com,https://somedomain.com/benchmark,100688,Medium,4.3,CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N,"Some custom description",null,https://somedomain.com/benchmark/xss-00/BenchmarkTest00002,2000-02-02 02:02:02 -0100,POST,"Content-Type:application/x-www-form-urlencoded,User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20100101 Firefox/13.0.1 WhiteHat Security,Accept-Language:en-us,en;q=0.5,Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7,Content-Length:84,Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5,null","Client-SSL-Socket-Class:IO::Socket::SSL,Content-Security-Policy:frame-ancestors 'self'; form-action 'self'; default-src 'unsafe-inline' 'unsafe-eval' 'self'; style-src 'unsafe-inline' 'self'; style-src-elem 'self' fonts.googleapis.com; font-src 'self' fonts.gstatic.com,Client-SSL-Cert-Subject:/C=US/O=Some Test/OU=SSL/CN=whitehat-test-benchmark-1-dev,Content-Type:text/html;charset=UTF-8,X-Content-Type-Options:nosniff,Client-SSL-Warning:Peer certificate not verified,Date:Sun, 02 Jan 2000 02:02:02 GMT,Cache-Control:no-cache, no-store, must-revalidate,X-Xss-Protection:0,Client-SSL-Cipher:TLS_AES_128_GCM_SHA256,Client-SSL-Cert-Issuer:/DC=corp/DC=root/DC=accounts/CN=Express Scripts Issuing CA 02,Content-Length:45,Client-SSL-Version:TLSv1_3,X-Frame-Options:DENY",null,200
14+
,,,,,,,,,,,,,,,,,,,,,
15+
,,,,,,,,,,,,,,,,,,,,,
16+
,,,,,,,,,,,,,,,,,,,,,
17+
Class Name,Description,Solution,,,,,,,,,,,,,,,,,,,
18+
Content Spoofing,"
19+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam.","Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam.",,,,,,,,,,,,,,,,,,,
20+
Cross Site Scripting,"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam.","Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam.",,,,,,,,,,,,,,,,,,,
21+
"Copyright 2024 Synopsys, Inc. - Synopsys Inc. and customer confidential",,,,,,,,,,,,,,,,,,,,,

0 commit comments

Comments
 (0)