Skip to content

Commit e49a1b7

Browse files
committed
Add AppScan Dynamic scorecard generator. Add support for more vuln
categories in Burp scorecard generator.
1 parent f43941f commit e49a1b7

File tree

4 files changed

+225
-20
lines changed

4 files changed

+225
-20
lines changed

src/main/java/org/owasp/benchmark/score/BenchmarkScore.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
import javax.xml.parsers.DocumentBuilderFactory;
4646

4747
import org.apache.commons.io.FileUtils;
48-
import org.owasp.benchmark.score.parsers.AppscanReader;
48+
import org.owasp.benchmark.score.parsers.AppScanDynamicReader;
49+
import org.owasp.benchmark.score.parsers.AppScanSourceReader;
4950
import org.owasp.benchmark.score.parsers.ArachniReader;
5051
import org.owasp.benchmark.score.parsers.BurpReader;
5152
import org.owasp.benchmark.score.parsers.CheckmarxReader;
@@ -373,7 +374,7 @@ private static TestResults readActualResults(File actual) throws Exception {
373374
TestResults tr = null;
374375

375376
if ( filename.endsWith(".ozasmt" ) ) {
376-
tr = new AppscanReader().parse( actual );
377+
tr = new AppScanSourceReader().parse( actual );
377378
}
378379

379380
else if ( filename.endsWith(".json" ) ) {
@@ -432,7 +433,11 @@ else if ( line2.startsWith( "<report")) {
432433
Document doc = getXMLDocument( actual );
433434
Node root = doc.getDocumentElement();
434435
if ( root.getNodeName().equals( "issues" ) ) {
435-
tr = new BurpReader().parse( doc );
436+
tr = new BurpReader().parse( root );
437+
}
438+
439+
if ( root.getNodeName().equals( "XmlReport") ) {
440+
tr = new AppScanDynamicReader().parse( root );
436441
}
437442
}
438443
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/**
2+
* OWASP Benchmark Project
3+
*
4+
* This file is part of the Open Web Application Security Project (OWASP)
5+
* Benchmark Project For details, please see
6+
* <a href="https://www.owasp.org/index.php/Benchmark">https://www.owasp.org/index.php/Benchmark</a>.
7+
*
8+
* 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+
* The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
12+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details
14+
*
15+
* @author Dave Wichers <a href="https://www.aspectsecurity.com">Aspect Security</a>
16+
* @created 2015
17+
*/
18+
19+
package org.owasp.benchmark.score.parsers;
20+
21+
import java.text.ParseException;
22+
import java.util.HashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
import org.w3c.dom.Node;
27+
28+
public class AppScanDynamicReader extends Reader {
29+
30+
public TestResults parse(Node root) throws Exception {
31+
32+
TestResults tr = new TestResults("IBM AppScan", true, TestResults.ToolType.DAST);
33+
34+
// <AppScanInfo>
35+
// <Version>9.0.1.1</Version>
36+
// <ServicePack />
37+
// </AppScanInfo>
38+
39+
Node info = getNamedChild("AppScanInfo", root);
40+
Node version = getNamedChild( "Version", info );
41+
tr.setToolVersion(version.getTextContent());
42+
43+
// <Summary>
44+
// <TotalScanDuration>14:48:40.9394530</TotalScanDuration>
45+
46+
Node summary = getNamedChild("Summary", root);
47+
Node elapsed = getNamedChild( "TotalScanDuration", summary );
48+
tr.setTime(calculateTime(elapsed.getTextContent()));
49+
50+
// <IssueType ID="SSL_CertWithBadCN" Count="1">
51+
// <RemediationID>fix_60280</RemediationID>
52+
// <advisory>
53+
// <name>SSL Certificate Domain Name Mismatch</name>
54+
// <testDescription>Infrastructure test</testDescription>
55+
// <threatClassification>
56+
// <name>Insufficient Transport Layer Protection</name>
57+
// <reference>http://projects.webappsec.org/Insufficient-Transport-Layer-Protection</reference>
58+
// </threatClassification>
59+
// <testTechnicalDescription>
60+
// </testTechnicalDescription>
61+
// <causes>
62+
// <cause>The web server or application server are configured in an insecure way</cause>
63+
// </causes>
64+
// <securityRisks>
65+
// </securityRisks>
66+
// <affectedProducts>
67+
// <affectedProduct>N/A</affectedProduct>
68+
// </affectedProducts>
69+
// <cwe>
70+
// <link target="http://cwe.mitre.org/data/definitions/297.html" id="CWE-297">297</link>
71+
// </cwe>
72+
// <xfid>
73+
// <link target="http://xforce.iss.net/xforce/xfdb/52881" id="52881">52881</link>
74+
// </xfid>
75+
// <references />
76+
// <fixRecommendations>
77+
// <fixRecommendation type="General">
78+
// </fixRecommendation>
79+
// </fixRecommendations>
80+
// </advisory>
81+
// <Severity>Informational</Severity>
82+
// <Invasive>False</Invasive>
83+
// </IssueType>
84+
85+
// parse issue types list into cweMap
86+
Map<String,Integer> cweMap = new HashMap<String,Integer>();
87+
Node results = getNamedChild("Results", root);
88+
Node issueTypes = getNamedChild("IssueTypes", results);
89+
List<Node> issueTypeList = getNamedChildren("IssueType", issueTypes);
90+
for ( Node issueType : issueTypeList ) {
91+
try {
92+
String key = getAttributeValue( "ID", issueType );
93+
Node advisory = getNamedChild( "advisory", issueType );
94+
Node cwenode = getNamedChild( "cwe", advisory );
95+
Node link = getNamedChild( "link", cwenode );
96+
Integer cwe = Integer.parseInt( link.getTextContent() );
97+
cweMap.put( key, cwe );
98+
} catch( Exception e ) {
99+
// System.out.println( "Found an issueType with no CWE link: " + getAttributeValue( "ID", issueType ));
100+
}
101+
}
102+
103+
Node issues = getNamedChild("Issues", results);
104+
List<Node> issueList = getNamedChildren("Issue", issues);
105+
for (Node issue : issueList) {
106+
TestCaseResult tcr = parseAppScanDynamicVulnerability(issue, cweMap);
107+
if (tcr != null) {
108+
// System.out.println( tcr.getNumber() + "\t" + tcr.getCWE() + "\t" + tcr.getEvidence() );
109+
tr.put(tcr);
110+
}
111+
}
112+
return tr;
113+
}
114+
115+
116+
117+
// <TotalScanDuration>14:48:40.9394530</TotalScanDuration>
118+
private static String calculateTime(String elapsed) {
119+
try {
120+
String[] splits = elapsed.split( "[\\.:]");
121+
int hours = Integer.parseInt( splits[0] );
122+
int minutes = Integer.parseInt( splits[1] );
123+
int seconds = Integer.parseInt( splits[2] );
124+
long millis = 1000 * ( hours * 60 * 60 + minutes * 60 + seconds );
125+
return TestResults.formatTime( millis );
126+
} catch( Exception e ) {
127+
e.printStackTrace();
128+
return "Unknown";
129+
}
130+
}
131+
132+
// <Issue IssueTypeID="attBlindSqlInjectionStrings" Noise="False">
133+
// <Url>https://localhost:8443/benchmark/BenchmarkTest00153</Url>
134+
private TestCaseResult parseAppScanDynamicVulnerability(Node issue, Map<String,Integer> cweMap ) {
135+
TestCaseResult tcr = new TestCaseResult();
136+
String cwekey = getAttributeValue("IssueTypeID", issue);
137+
Integer cwe = cweMap.get(cwekey);
138+
if ( cwe == null ) return null;
139+
tcr.setCWE(translate(cwe));
140+
141+
tcr.setCategory(cwekey);
142+
tcr.setEvidence(cwekey);
143+
144+
// fixme: not really confidence
145+
// fixme: what is "noise" attribute?
146+
String confidence = getNamedChild( "Severity", issue ).getTextContent();
147+
// tcr.setConfidence( makeIntoInt( confidence ) );
148+
149+
String testcase = getNamedChild("Url", issue).getTextContent();
150+
testcase = testcase.substring(testcase.lastIndexOf('/') + 1);
151+
testcase = testcase.split("\\.")[0];
152+
if (testcase.startsWith("BenchmarkTest")) {
153+
String testno = testcase.substring("BenchmarkTest".length() );
154+
try {
155+
tcr.setNumber(Integer.parseInt(testno));
156+
} catch (NumberFormatException e) {
157+
e.printStackTrace();
158+
}
159+
return tcr;
160+
}
161+
162+
return null;
163+
}
164+
165+
private int translate(int id) {
166+
switch (id) {
167+
// //case "Build Misconfiguration" : return 00;
168+
// case "Command Injection" : return 78;
169+
// case "Cookie Security" : return 614;
170+
// case "Cross-Site Scripting" : return 79;
171+
// //case "Dead Code" : return 00;
172+
// //case "Denial of Service" : return 00;
173+
// case "Header Manipulation" : return 113;
174+
// case "Insecure Randomness" : return 330;
175+
// //case "J2EE Bad Practices" : return 00;
176+
// case "LDAP Injection" : return 90;
177+
// //case "Missing Check against Null" : return 00;
178+
// //case "Null Dereference" : return 00;
179+
// case "Password Management" : return 00;
180+
// case "Path Manipulation" : return 22;
181+
// //case "Poor Error Handling" : return 00;
182+
// //case "Poor Logging Practice" : return 00;
183+
// //case "Poor Style" : return 00;
184+
// //case "Resource Injection" : return 00;
185+
// case "SQL Injection" : return 89;
186+
// //case "System Information Leak" : return 00;
187+
// case "Trust Boundary Violation" : return 501;
188+
// //case "Unreleased Resource" : return 00;
189+
// //case "Unsafe Reflection" : return 00;
190+
// case "Weak Cryptographic Hash" : return 328;
191+
// case "Weak Encryption" : return 327;
192+
// case "XPath Injection" : return 643;
193+
}
194+
return id;
195+
}
196+
197+
}

src/main/java/org/owasp/benchmark/score/parsers/AppscanReader.java renamed to src/main/java/org/owasp/benchmark/score/parsers/AppScanSourceReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import org.w3c.dom.NodeList;
3535
import org.xml.sax.InputSource;
3636

37-
public class AppscanReader extends Reader {
37+
public class AppScanSourceReader extends Reader {
3838

3939
public TestResults parse( File f ) throws Exception {
4040
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();

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

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,13 @@
2525

2626
public class BurpReader extends Reader {
2727

28-
public TestResults parse(Document doc) throws Exception {
28+
public TestResults parse(Node root) throws Exception {
2929

30-
TestResults tr = new TestResults("Burp Pro", true, TestResults.ToolType.SAST);
30+
TestResults tr = new TestResults("Burp Suite Pro", true, TestResults.ToolType.DAST);
3131

3232
// <issues burpVersion="1.6.24"
3333
// exportTime="Wed Aug 19 23:27:54 EDT 2015">
3434

35-
Node root = doc.getDocumentElement();
3635
String version = getAttributeValue("burpVersion", root);
3736
tr.setToolVersion(version);
3837

@@ -74,7 +73,7 @@ private TestCaseResult parseBurpVulnerability(Node issue) {
7473
tcr.setCategory(name);
7574
tcr.setEvidence(name);
7675

77-
String confidence = getNamedChild( "confidence", issue ).getTextContent();
76+
//String confidence = getNamedChild( "confidence", issue ).getTextContent();
7877
// tcr.setConfidence( makeIntoInt( confidence ) );
7978

8079
String testcase = getNamedChild("path", issue).getTextContent();
@@ -95,18 +94,25 @@ private TestCaseResult parseBurpVulnerability(Node issue) {
9594

9695
private int translate(String id) {
9796
switch (id) {
98-
case "2097920": return 79; // XSS
97+
case "2097920": return 79; // XSS
9998
case "5247488": return 9999; // DOM Trust Boundary Violation - Map to nothing right now.
100-
case "1048832": return 78; // Command Injection
101-
case "1051392": return 22; // Path Manipulation
102-
case "5243392": return 614; //SSL cookie without secure flag set
103-
case "5244416": return 9998; //cookie without HttpOnly flag set - There is no CWE defined for this weakness
104-
case "1050112": return 643; //XPATH injection
105-
99+
case "1048832": return 78; // Command Injection
100+
case "1051392": return 22; // Path Manipulation
101+
case "5243392": return 614; // SSL cookie without secure flag set
102+
case "5244416": return 9998; // cookie without HttpOnly flag set - There is no CWE defined for this weakness
103+
case "1050112": return 643; // XPATH injection
104+
case "1049344": return 22; // Path Manipulation
105+
case "1049088": return 89; // SQL injection
106+
case "6291968": return 200; // Information Disclosure - Email Address Disclosed
107+
case "6292736": return 200; // Information Disclosure - Credit Card # Disclosed
108+
case "7340288": return 525; // Information Exposure Through Browser Caching-Cacheable HTTPS Response
109+
case "5245344": return 8888; // Clickjacking - There is no CWE # for this.
110+
case "8389632": return 9999; // Incorrect Content Type - Don't care. Map to nothing right now.
111+
case "2098944": return 352; // CSRF Vulnerability
112+
case "8389120": return 9999; // HTML doesn't specify character set - Don't care. Map to nothing.
113+
106114
// //case "Build Misconfiguration" : return 00;
107-
// case "Command Injection" : return 78;
108115
// case "Cookie Security" : return 614;
109-
// case "Cross-Site Scripting" : return 79;
110116
// //case "Dead Code" : return 00;
111117
// //case "Denial of Service" : return 00;
112118
// case "Header Manipulation" : return 113;
@@ -116,19 +122,16 @@ private int translate(String id) {
116122
// //case "Missing Check against Null" : return 00;
117123
// //case "Null Dereference" : return 00;
118124
// case "Password Management" : return 00;
119-
// case "Path Manipulation" : return 22;
120125
// //case "Poor Error Handling" : return 00;
121126
// //case "Poor Logging Practice" : return 00;
122127
// //case "Poor Style" : return 00;
123128
// //case "Resource Injection" : return 00;
124-
// case "SQL Injection" : return 89;
125129
// //case "System Information Leak" : return 00;
126130
// case "Trust Boundary Violation" : return 501;
127131
// //case "Unreleased Resource" : return 00;
128132
// //case "Unsafe Reflection" : return 00;
129133
// case "Weak Cryptographic Hash" : return 328;
130134
// case "Weak Encryption" : return 327;
131-
// case "XPath Injection" : return 643;
132135
}
133136
System.out.println("Unknown id: " + id);
134137
return -1;

0 commit comments

Comments
 (0)