////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009-2013 Denim Group, Ltd.
//
// The contents of this file are subject to the Mozilla Public License
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is ThreadFix.
//
// The Initial Developer of the Original Code is Denim Group, Ltd.
// Portions created by Denim Group, Ltd. are Copyright (C)
// Denim Group, Ltd. All Rights Reserved.
//
// Contributor(s): Denim Group, Ltd.
//
////////////////////////////////////////////////////////////////////////
package com.denimgroup.threadfix.service.waf;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.denimgroup.threadfix.data.dao.WafRuleDao;
import com.denimgroup.threadfix.data.dao.WafRuleDirectiveDao;
import com.denimgroup.threadfix.data.entities.GenericSeverity;
import com.denimgroup.threadfix.data.entities.GenericVulnerability;
import com.denimgroup.threadfix.data.entities.SurfaceLocation;
import com.denimgroup.threadfix.data.entities.Vulnerability;
import com.denimgroup.threadfix.data.entities.WafRule;
import com.denimgroup.threadfix.data.entities.WafRuleDirective;
/**
* @author mcollins
*
*/
public class ImpervaSecureSphereGenerator extends RealTimeProtectionGenerator {
// TODO look through CVEs in sm_schema_report_vulns.xsd
private static final Map<String, String> VULN_TYPE_MAP = new HashMap<String, String>();
static {
VULN_TYPE_MAP.put(GenericVulnerability.CWE_CROSS_SITE_REQUEST_FORGERY, "cross-site-request-forgery");
VULN_TYPE_MAP.put(GenericVulnerability.CWE_CROSS_SITE_SCRIPTING, "cross-site-scripting");
VULN_TYPE_MAP.put(GenericVulnerability.CWE_SQL_INJECTION, "sql-injection");
VULN_TYPE_MAP.put(GenericVulnerability.CWE_DIRECTORY_INDEXING, "directory-browsing");
VULN_TYPE_MAP.put(GenericVulnerability.CWE_HTTP_RESPONSE_SPLITTING, "http-response-splitting");
VULN_TYPE_MAP.put(GenericVulnerability.CWE_PATH_TRAVERSAL, "directory-traversal");
VULN_TYPE_MAP.put(GenericVulnerability.CWE_EVAL_INJECTION, "remote-command-execution-env");
VULN_TYPE_MAP.put(GenericVulnerability.CWE_OS_COMMAND_INJECTION, "remote-command-execution-env");
}
private static final Map<String, String> SEVERITIES_MAP = new HashMap<String, String>();
static {
SEVERITIES_MAP.put(GenericSeverity.CRITICAL, "high");
SEVERITIES_MAP.put(GenericSeverity.HIGH, "high");
SEVERITIES_MAP.put(GenericSeverity.MEDIUM, "medium");
SEVERITIES_MAP.put(GenericSeverity.LOW, "low");
SEVERITIES_MAP.put(GenericSeverity.INFO, "informative");
}
public ImpervaSecureSphereGenerator(WafRuleDao wafRuleDao,
WafRuleDirectiveDao wafRuleDirectiveDao) {
this.wafRuleDao = wafRuleDao;
this.wafRuleDirectiveDao = wafRuleDirectiveDao;
this.defaultDirective = "-";
}
@Override
public String[] getSupportedVulnerabilityTypes() {
return VULN_TYPE_MAP.keySet().toArray(new String[] {});
}
// TODO update for scan IDs / dates
protected String generateRuleText(String genericVulnName, String uri, String action,
String id, String parameter, Vulnerability vuln) {
String scanId = "0";
if (vuln != null && vuln.getOriginalFinding() != null &&
vuln.getOriginalFinding().getScan() != null &&
vuln.getOriginalFinding().getScan().getId() != null) {
scanId = vuln.getOriginalFinding().getScan().getId().toString();
}
String severity = "low";
if (vuln != null && vuln.getGenericSeverity() != null && vuln.getGenericSeverity().getName() != null) {
severity = SEVERITIES_MAP.get(vuln.getGenericSeverity().getName());
}
Calendar calendarToUse = Calendar.getInstance();
if (vuln != null && vuln.getOriginalFinding() != null &&
vuln.getOriginalFinding().getScan() != null &&
vuln.getOriginalFinding().getScan().getImportTime() != null) {
calendarToUse = vuln.getOriginalFinding().getScan().getImportTime();
}
String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(calendarToUse.getTime());
if (genericVulnName != null && VULN_TYPE_MAP.keySet().contains(genericVulnName)) {
StringBuilder sb = new StringBuilder();
sb.append("\n<vulnerability id=\"" + id + "\" vuln-type=\"" + VULN_TYPE_MAP.get(genericVulnName) +
"\" severity=\"" + severity + "\">" +
"\n <source src-type=\"ThreadFix\" scan-id=\"" + scanId +"\"" +
" scan-date=\"" + time + "\" src-reference=\"13\" />" +
"\n <parameters>" +
"\n <url>" + uri + "</url>");
if (parameter != null) {
sb.append("\n <param-name>" + parameter + "</param-name>");
}
sb.append("\n </parameters>" +
"\n</vulnerability>");
return sb.toString();
} else {
return null;
}
}
@Override
protected WafRule makeRule(Integer currentId, Vulnerability vulnerability, WafRuleDirective directive) {
if (currentId == null || vulnerability == null
|| vulnerability.getSurfaceLocation() == null
|| vulnerability.getGenericVulnerability() == null
|| vulnerability.getGenericVulnerability().getName() == null) {
return null;
}
SurfaceLocation surfaceLocation = vulnerability.getSurfaceLocation();
String vulnType = vulnerability.getGenericVulnerability().getName();
// Check if the vuln is supported
if (!stringInList(vulnType, getSupportedVulnerabilityTypes())) {
return null;
}
String parameter = surfaceLocation.getParameter();
String path = surfaceLocation.getPath();
WafRule rule = new WafRule();
rule.setIsNormalRule(false);
rule.setWafRuleDirective(directive);
rule.setNativeId(currentId.toString());
rule.setRule(generateRuleText(vulnerability.getGenericVulnerability().getName(),
path,null,currentId.toString(),parameter,vulnerability));
return rule;
}
public static String getEnd(List<WafRule> rules) {
return "</vulnerabilities>";
}
public static String getStart(List<WafRule> rules) {
StringBuilder builder = new StringBuilder();
builder.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
"<vulnerabilities xmlns:msxsl=\"urn:schemas-microsoft-com:xslt\" " +
"xmlns:theScript=\"urn:CustomScript\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchemainstance\">\n");
if (rules == null || rules.size() == 0) {
return builder.toString();
}
Map<String, List<WafRule>> hostRuleMap = new HashMap<String, List<WafRule>>();
for (WafRule rule : rules) {
String key = null;
if (rule != null && rule.getVulnerability() != null
&& rule.getVulnerability().getSurfaceLocation() != null
&& rule.getVulnerability().getSurfaceLocation().getHost() != null) {
key = rule.getVulnerability().getSurfaceLocation().getHost();
} else if (rule != null) {
key = "127.0.0.1";
}
if (key != null) {
if (hostRuleMap.get(key) == null) {
hostRuleMap.put(key, new ArrayList<WafRule>());
}
hostRuleMap.get(key).add(rule);
}
}
for (Entry<String, List<WafRule>> entry : hostRuleMap.entrySet()) {
if (entry != null) {
builder.append("<host host-name=\"" + entry.getKey() + "\">\n");
for (WafRule rule : entry.getValue()) {
builder.append(rule.getRule());
}
builder.append("\n</host>\n");
}
}
return builder.toString();
}
}