Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,22 @@

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.owasp.benchmark.score.BenchmarkScore;
import org.owasp.benchmark.score.TestCaseResult;
import org.owasp.benchmark.score.TestSuiteResults;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

public class AppScanDynamicReader2 extends Reader {

// This is the new AppScan Dynamnic reader, where they generate ".xml" files.
// This is the new AppScan Dynamic reader, where they generate ".xml" files.

public TestSuiteResults parse(File f) throws Exception {

Expand All @@ -44,6 +47,11 @@ public TestSuiteResults parse(File f) throws Exception {

Node root = doc.getDocumentElement();
Node scanInfo = getNamedChild("scan-information", root);

Node scanConfiguration = getNamedChild("scan-configuration", root);
String startingUrl = getNamedChild("starting-url", scanConfiguration).getTextContent();
System.out.println("Starting URL is: " + startingUrl);

TestSuiteResults tr =
new TestSuiteResults("IBM AppScan Dynamic", true, TestSuiteResults.ToolType.DAST);

Expand All @@ -57,60 +65,122 @@ public TestSuiteResults parse(File f) throws Exception {

Node allIssues = getNamedChild("url-group", root);
List<Node> vulnerabilities = getNamedChildren("item", allIssues);

Node allIssueVariants = getNamedChild("issue-group", root);
List<Node> variants = getNamedChildren("item", allIssueVariants);



// Loop through all the vulnerabilities
for (Node vulnerability : vulnerabilities) {

// First get the type of vuln, and if we don't care about that type, move on
String issueType = getNamedChild("issue-type", vulnerability).getTextContent();

String url = getNamedChild("name", vulnerability).getTextContent();
String issueType = getNamedChild("issue-type", vulnerability).getTextContent();

String url = getNamedChild("name", vulnerability).getTextContent();
// to give DAST tools some credit, if they report a similar vuln in a different area, we
// count it.
// e.g., SQLi in the XPATHi tests. To do that, we have to pull out the vuln type from
// the URL.
String urlElements[] = url.split("/");
String testArea =
urlElements[urlElements.length - 2].split("-")[0]; // .split strips off the -##
// System.out.println("Candidate test area is: " + testArea);

int vtype = cweLookup(issueType, testArea);
// System.out.println("Vuln type: " + issueType + " has CWE of: " + vtype);

// Then get the filename containing the vuln. And if not in a test case, skip it.
// Parse out test number from:
// https://localhost:port/benchmark/testarea-##/BenchmarkTest02603
int startOfTestCase = url.lastIndexOf("/") + 1;
String testcase = url.substring(startOfTestCase, url.length());
testcase =
testcase.split("\\.")[
0]; // if test case has extension (e.g., BenchmarkTestCase#####.html),
// strip it off.
// System.out.println("Candidate test case is: " + testcase);
if (testcase.startsWith(BenchmarkScore.TESTCASENAME)) {
int tn = -1;
String testno = testcase.substring(BenchmarkScore.TESTCASENAME.length());
try {
tn = Integer.parseInt(testno);
} catch (NumberFormatException e) {
e.printStackTrace();
}

// if (tn == -1) System.out.println("Found vuln outside of test case of type: " +
// issueType);

// Add the vuln found in a test case to the results for this tool
TestCaseResult tcr = new TestCaseResult();
tcr.setNumber(tn);
tcr.setCategory(issueType); // TODO: Is this right?
tcr.setCWE(vtype);
tcr.setEvidence(issueType);

tr.put(tcr);
}

NamedNodeMap itemNode = vulnerability.getAttributes();
String variantItemID = itemNode.getNamedItem("id").getNodeValue();

List<String> testCaseElementsFromVariants = variantLookup(issueType, variantItemID, startingUrl, variants);
if(testCaseElementsFromVariants.isEmpty()) {
//Handle non-variant issue types , Older xml format as in 9.x release versions and before
// First get the type of vuln, and if we don't care about that type, move on
TestCaseResult tcr = TestCaseLookup(issueType, url);
tr.put(tcr);
}
else {
//Handle issues which are Variants, new xml format after 10.x release
for (String testArea : testCaseElementsFromVariants ) {
TestCaseResult tcr = TestCaseLookup(issueType, testArea);
tr.put(tcr);
}
}
}

return tr;
}

/// Issues which are not variants
private static TestCaseResult TestCaseLookup(String issueType, String url) {
TestCaseResult tcr = new TestCaseResult();
String urlElements[] = url.split("/");
String testArea =
urlElements[urlElements.length - 2].split("-")[0]; // .split strips off the -##

int vtype = cweLookup(issueType, testArea);

// Then get the filename containing the vuln. And if not in a test case, skip it.
// Parse out test number from:
// https://localhost:port/benchmark/testarea-##/BenchmarkTest02603
int startOfTestCase = url.lastIndexOf("/") + 1;
String testcase = url.substring(startOfTestCase, url.length());
testcase =
testcase.split("\\.")[
0]; // if test case has extension (e.g., BenchmarkTestCase#####.html),
// strip it off.
// System.out.println("Candidate test case is: " + testcase);
if (testcase.startsWith(BenchmarkScore.TESTCASENAME)) {
int tn = -1;
String testno = testcase.substring(BenchmarkScore.TESTCASENAME.length());
try {
tn = Integer.parseInt(testno);
} catch (NumberFormatException e) {
e.printStackTrace();
}

// if (tn == -1) System.out.println("Found vuln outside of test case of type: " +
// issueType);

// Add the vuln found in a test case to the results for this tool
tcr.setNumber(tn);
tcr.setCategory(issueType); // TODO: Is this right?
tcr.setCWE(vtype);
tcr.setEvidence(issueType);
}
return tcr;
}


//Fetch Issues listed as variants, to cater to post 10.x release xml format
private static List<String> variantLookup(String issueType, String itemID,String startingUrl, List<Node> variants) {
List<String> testCaseElementsFromVariants = new ArrayList<String>();

//System.out.println("Variant Lookup Item ID: " + itemID);

for (Node variant : variants) {
String variantUrlRefId = getNamedChild("url", variant).getTextContent().trim();
String variantIssueType = getNamedChild("issue-type", variant).getTextContent().trim();
//System.out.println("Variant Url Ref ID: " + variantUrlRefId);


// Add the record only if the issue type matches for the relevant variants
if (issueType.equals(variantIssueType) && itemID.equals(variantUrlRefId)) {
Node variantNodes = getNamedChild("variant-group", variant);
List<Node> variantNodeChildren = getNamedChildren("item", variantNodes);
for (Node variantNodeChild : variantNodeChildren) {
String httpTraffic = getNamedChild("test-http-traffic", variantNodeChild).getTextContent();
String[] variantUrl = httpTraffic.split(" ");

String benchMarkTestCase = variantUrl[1].trim();

if (benchMarkTestCase.contains("BenchmarkTest")) {
String urlElements[] = benchMarkTestCase.split("/");

String testAreaUrl = startingUrl + urlElements[urlElements.length - 2] + "/" + urlElements[urlElements.length - 1];
String testArea = testAreaUrl.split("\\?")[0]; // .split strips off the -##

if (testArea.contains("BenchmarkTest"))
testCaseElementsFromVariants.add(testArea);
}
}
}
}

return testCaseElementsFromVariants;
}

// e.g., 3 Hour(s) 7 Minute(s) 58 Second(s)
/* private String parseTime(String message) {
Expand All @@ -126,15 +196,40 @@ public TestSuiteResults parse(File f) throws Exception {
*/
private static int cweLookup(String vtype, String testArea) {
int cwe = cweLookup(vtype);
if ("xpathi".equals(testArea) && cwe == 89) cwe = 643; // CWE for xpath injection
if ("ldapi".equals(testArea) && cwe == 89) cwe = 90; // CWE for xpath injection
if ("xpathi".equals(testArea) && cwe == 89)
cwe = 643; // CWE for xpath injection
if ("ldapi".equals(testArea) && cwe == 89)
cwe = 90; // CWE for xpath injection

return cwe;
}

private static int cweLookup(String vtype) {
switch (vtype) {
case "attBlindSqlInjectionStrings":
case "attDirectoryFound" : return 22;
case "attDirOptions" : return 22;
case "attApplicationRemoteCodeExecutionAdns" : return 78; // Score worse or
case "attLDAPInjection2" : return 90;
case "attLDAPInjection" : return 90;
case "attXPathInjection" : return 643;
case "attBlindXpathInjectionSingleQuote" : return 643;
case "attFileParamPipe" : return 78;
case "attContentSecurityPolicyObjectSrc" : return 00;
case "attContentSecurityPolicyScriptSrc" : return 00;
case "attBlindLDAPInjection":
return 90;
case "attCommandInjectionAdns":
return 78;
case "attCommandInjectionUnixTws":
return 78;
case "attBlindXPathInjection":
return 643;
case "attFileUnix":
return 22;
case "GV_SQLErr": return 00;
case "passParamGET":
return 523;
case "attBlindSqlInjectionStrings":
return 89; // Score worse or better?
case "attCachedSSL":
return 00;
Expand All @@ -158,7 +253,7 @@ private static int cweLookup(String vtype) {
case "ContentTypeOptions":
return 00;

// case "GD_EmailAddress" : return 00;
case "GD_EmailAddress" : return 00;
case "GETParamOverSSL":
return 00;
// case "GV_SQLErr" : return 89; // Score worse or better with this or 00?
Expand Down