Merge remote-tracking branch 'origin/master'

Former-commit-id: 1ed0b6e8621fb68a823b8127775fc5f86932cc00
This commit is contained in:
Steve Springett
2014-08-05 14:25:20 -05:00
58 changed files with 11522 additions and 12612 deletions

View File

@@ -40,7 +40,6 @@ The plugin can be configured using the following:
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<goals>
@@ -59,7 +58,7 @@ The plugin can be configured using the following:
### Ant Task
For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-maven/installation.html).
For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-ant/installation.html).
Development Usage
-------------
@@ -106,4 +105,4 @@ Dependency-Check makes use of several other open source libraries. Please see th
[wiki]: https://github.com/jeremylong/DependencyCheck/wiki
[subscribe]: mailto:dependency-check+subscribe@googlegroups.com
[post]: mailto:dependency-check@googlegroups.com
[notices]: https://github.com/jeremylong/DependencyCheck/blob/master/NOTICES.txt
[notices]: https://github.com/jeremylong/DependencyCheck/blob/master/NOTICES.txt

View File

@@ -21,14 +21,14 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.4-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-ant</artifactId>
<packaging>jar</packaging>
<name>Dependency-Check Ant Task</name>
<description>Dependency-check is a utility that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries.</description>
<description>dependency-check-ant is an Ant Task that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the project's dependencies. The task will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
@@ -324,6 +324,9 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>

View File

@@ -3,7 +3,20 @@ Installation
Download dependency-check-ant from [bintray here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-${project.version}.jar).
To install dependency-check-ant place the dependency-check-ant-${project.version}.jar into
the lib directory of your Ant instalation directory. Once installed you can add
the taskdef to you build.xml and add the task to a new or existing target.
the taskdef to you build.xml and add the task to a new or existing target:
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask"/>
```
If you do not want to install dependency-check-ant into your ant's lib directory when you define the task def you
must add the classpath to the taskdef:
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask">
<classpath path="[path]/[to]/dependency-check-ant-${project.version}.jar"/>
</taskdef>
```
It is important to understand that the first time this task is executed it may
take 20 minutes or more as it downloads and processes the data from the National

View File

@@ -1,11 +1,19 @@
Usage
====================
First, add the dependency-check-ant taskdef to your build.xml:
First, add the dependency-check-ant taskdef to your build.xml (see the [installation guide](installation.html):
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask"/>
```
Or
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask">
<classpath path="[path]/[to]/dependency-check-ant-${project.version}.jar"/>
</taskdef>
```
Next, add the task to a target of your choosing:
```xml

View File

@@ -21,14 +21,14 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.4-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-cli</artifactId>
<packaging>jar</packaging>
<name>Dependency-Check Command Line</name>
<description>Dependency-Check-Maven is a Maven Plugin that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries.</description>
<description>dependency-check-cli is an command line tool that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the scanned project dependencies. The tool will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
@@ -174,6 +174,9 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>

View File

@@ -15,19 +15,19 @@ limitations under the License.
Copyright (c) 2012 Jeremy Long. All Rights Reserved.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.4-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-core</artifactId>
<packaging>jar</packaging>
<name>Dependency-Check Core</name>
<description>dependency-check-core is the engine and reporting tool used to identify and report if there are any known, publicly disclosed vulnerabilities in the scanned project's dependencies. The engine extracts meta-data from the dependencies and uses this to do fuzzy key-word matching against the Common Platfrom Enumeration (CPE), if any CPE identifiers are found the associated Common Vulnerability and Exposure (CVE) entries are added to the generated report.</description>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
@@ -272,6 +272,9 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>
@@ -429,7 +432,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.8</version>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
@@ -531,6 +534,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.0.0.RELEASE</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
* Copyright (c) 2014 Steve Springett. All Rights Reserved.
*/
package org.owasp.dependencycheck.agent;

View File

@@ -98,11 +98,17 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
* @throws SuppressionParseException thrown if the XML cannot be parsed.
*/
private void loadSuppressionData() throws SuppressionParseException {
final SuppressionParser parser = new SuppressionParser();
File file = null;
try {
rules = parser.parseSuppressionRules(this.getClass().getClassLoader().getResourceAsStream("dependencycheck-base-suppression.xml"));
} catch (SuppressionParseException ex) {
LOGGER.log(Level.FINE, "Unable to parse the base suppression data file", ex);
}
final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
if (suppressionFilePath == null) {
return;
}
File file = null;
boolean deleteTempFile = false;
try {
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
@@ -132,9 +138,9 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
}
if (file != null) {
final SuppressionParser parser = new SuppressionParser();
try {
rules = parser.parseSuppressionRules(file);
//rules = parser.parseSuppressionRules(file);
rules.addAll(parser.parseSuppressionRules(file));
LOGGER.log(Level.FINE, rules.size() + " suppression rules were loaded.");
} catch (SuppressionParseException ex) {
final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());

View File

@@ -242,7 +242,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
final File tdir = getNextTempDirectory();
final String fileName = dependency.getFileName();
LOGGER.info(String.format("The zip file '%s' appears to be a JAR file, making a deep copy and analyzing it as a JAR.", fileName));
LOGGER.info(String.format("The zip file '%s' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName));
final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar");
try {

View File

@@ -531,7 +531,6 @@ public class CPEAnalyzer implements Analyzer {
if (dbVer == null //special case, no version specified - everything is vulnerable
|| evVer.equals(dbVer)) { //yeah! exact match
//final String url = String.format("http://web.nvd.nist.gov/view/vuln/search?cpe=%s", URLEncoder.encode(vs.getName(), "UTF-8"));
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
collected.add(match);

View File

@@ -161,11 +161,20 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
*/
public static final Pattern CORE_JAVA = Pattern.compile("^cpe:/a:(sun|oracle|ibm):(j2[ems]e|"
+ "java(_platform_micro_edition|_runtime_environment|_se|virtual_machine|se_development_kit|fx)?|"
+ "jdk|jre|jsf|jsse)($|:.*)");
+ "jdk|jre|jsse)($|:.*)");
/**
* Regex to identify core jsf libraries.
*/
public static final Pattern CORE_JAVA_JSF = Pattern.compile("^cpe:/a:(sun|oracle|ibm):jsf($|:.*)");
/**
* Regex to identify core java library files. This is currently incomplete.
*/
public static final Pattern CORE_FILES = Pattern.compile("^((alt[-])?rt|jsf[-].*|jsse|jfxrt|jfr|jce|javaws|deploy|charsets)\\.jar$");
public static final Pattern CORE_FILES = Pattern.compile("(^|/)((alt[-])?rt|jsse|jfxrt|jfr|jce|javaws|deploy|charsets)\\.jar$");
/**
* Regex to identify core jsf java library files. This is currently incomplete.
*/
public static final Pattern CORE_JSF_FILES = Pattern.compile("(^|/)jsf[-][^/]*\\.jar$");
/**
* Removes any CPE entries for the JDK/JRE unless the filename ends with rt.jar
@@ -182,6 +191,11 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
if (coreCPE.matches() && !coreFiles.matches()) {
itr.remove();
}
final Matcher coreJsfCPE = CORE_JAVA_JSF.matcher(i.getValue());
final Matcher coreJsfFiles = CORE_JSF_FILES.matcher(dependency.getFileName());
if (coreJsfCPE.matches() && !coreJsfFiles.matches()) {
itr.remove();
}
}
}

View File

@@ -73,7 +73,6 @@ import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
/**
*
* Used to load a JAR file and collect information that can be used to determine the associated CPE.
*
* @author Jeremy Long <jeremy.long@owasp.org>
@@ -170,7 +169,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*/
public JarAnalyzer() {
try {
final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
//final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
final JAXBContext jaxbContext = JAXBContext.newInstance(Model.class);
pomUnmarshaller = jaxbContext.createUnmarshaller();
} catch (JAXBException ex) { //guess we will just have a null pointer exception later...
LOGGER.log(Level.SEVERE, "Unable to load parser. See the log for more details.");
@@ -345,16 +345,25 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @return a Properties object or null if no pom.properties was found
* @throws IOException thrown if there is an exception reading the pom.properties
*/
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "OS_OPEN_STREAM",
justification = "The reader is closed by closing the zipEntry")
private Properties retrievePomProperties(String path, final JarFile jar) throws IOException {
Properties pomProperties = null;
final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
final ZipEntry propEntry = jar.getEntry(propPath);
if (propEntry != null) {
final Reader reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
pomProperties = new Properties();
pomProperties.load(reader);
Reader reader = null;
try {
reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
pomProperties = new Properties();
pomProperties.load(reader);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, "close error", ex);
}
}
}
}
return pomProperties;
}
@@ -571,7 +580,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
groupid = parentGroupId;
}
}
String originalGroupID = groupid;
final String originalGroupID = groupid;
if (groupid != null && !groupid.isEmpty()) {
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
@@ -601,7 +610,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
artifactid = parentArtifactId;
}
}
String originalArtifactID = artifactid;
final String originalArtifactID = artifactid;
if (artifactid != null && !artifactid.isEmpty()) {
if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
artifactid = artifactid.substring(4);

View File

@@ -22,7 +22,7 @@ package org.owasp.dependencycheck.data.cpe;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public abstract class Fields {
public final class Fields {
/**
* The key for the name document id.
@@ -36,7 +36,10 @@ public abstract class Fields {
* The key for the product field.
*/
public static final String PRODUCT = "product";
/**
* The key for the version field.
* Private constructor as this is more of an enumeration rather then a full class.
*/
private Fields() {
}
}

View File

@@ -42,6 +42,7 @@ import org.owasp.dependencycheck.utils.Settings;
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public final class ConnectionFactory {
/**
* The Logger.
*/
@@ -49,7 +50,7 @@ public final class ConnectionFactory {
/**
* The version of the current DB Schema.
*/
public static final String DB_SCHEMA_VERSION = "2.9";
public static final String DB_SCHEMA_VERSION = Settings.getString(Settings.KEYS.DB_VERSION);
/**
* Resource location for SQL file used to create the database schema.
*/
@@ -111,7 +112,10 @@ public final class ConnectionFactory {
//yes, yes - hard-coded password - only if there isn't one in the properties file.
password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
try {
connectionString = getConnectionString();
connectionString = Settings.getConnectionString(
Settings.KEYS.DB_CONNECTION_STRING,
Settings.KEYS.DB_FILE_NAME,
Settings.KEYS.DB_VERSION);
} catch (IOException ex) {
LOGGER.log(Level.FINE,
"Unable to retrieve the database connection string", ex);
@@ -120,7 +124,7 @@ public final class ConnectionFactory {
boolean shouldCreateSchema = false;
try {
if (connectionString.startsWith("jdbc:h2:file:")) { //H2
shouldCreateSchema = !dbSchemaExists();
shouldCreateSchema = !h2DataFileExists();
LOGGER.log(Level.FINE, "Need to create DB Structure: {0}", shouldCreateSchema);
}
} catch (IOException ioex) {
@@ -217,51 +221,17 @@ public final class ConnectionFactory {
return conn;
}
/**
* Returns the configured connection string. If using the embedded H2 database this function will also ensure the
* data directory exists and if not create it.
*
* @return the connection string
* @throws IOException thrown the data directory cannot be created
*/
private static String getConnectionString() throws IOException {
final String connStr = Settings.getString(Settings.KEYS.DB_CONNECTION_STRING, "jdbc:h2:file:%s;AUTO_SERVER=TRUE");
if (connStr.contains("%s")) {
final String directory = getDataDirectory().getCanonicalPath();
final File dataFile = new File(directory, "cve." + DB_SCHEMA_VERSION);
LOGGER.log(Level.FINE, String.format("File path for H2 file: '%s'", dataFile.toString()));
return String.format(connStr, dataFile.getAbsolutePath());
}
return connStr;
}
/**
* Retrieves the directory that the JAR file exists in so that we can ensure we always use a common data directory
* for the embedded H2 database. This is public solely for some unit tests; otherwise this should be private.
*
* @return the data directory to store data files
* @throws IOException is thrown if an IOException occurs of course...
*/
public static File getDataDirectory() throws IOException {
final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
if (!path.exists()) {
if (!path.mkdirs()) {
throw new IOException("Unable to create NVD CVE Data directory");
}
}
return path;
}
/**
* Determines if the H2 database file exists. If it does not exist then the data structure will need to be created.
*
* @return true if the H2 database file does not exist; otherwise false
* @throws IOException thrown if the data directory does not exist and cannot be created
*/
private static boolean dbSchemaExists() throws IOException {
final File dir = getDataDirectory();
final String name = String.format("cve.%s.h2.db", DB_SCHEMA_VERSION);
final File file = new File(dir, name);
private static boolean h2DataFileExists() throws IOException {
final File dir = Settings.getDataDirectory();
final String name = Settings.getString(Settings.KEYS.DB_FILE_NAME);
final String fileName = String.format(name, DB_SCHEMA_VERSION);
final File file = new File(dir, fileName);
return file.exists();
}

View File

@@ -248,6 +248,7 @@ public class CveDB {
/**
* SQL Statement to retrieve a property from the database.
*/
@SuppressWarnings("unused")
private static final String SELECT_PROPERTY = "SELECT id, value FROM properties WHERE id = ?";
/**
* SQL Statement to insert a new property.
@@ -260,6 +261,7 @@ public class CveDB {
/**
* SQL Statement to delete a property.
*/
@SuppressWarnings("unused")
private static final String DELETE_PROPERTY = "DELETE FROM properties WHERE id = ?";
//</editor-fold>

View File

@@ -22,6 +22,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Settings;
/**
* Class responsible for updating the NVD CVE and CPE data stores.
@@ -54,7 +55,11 @@ public class NvdCveUpdater implements CachedWebDataSource {
LOGGER.log(Level.FINE, null, ex);
} catch (DownloadFailedException ex) {
LOGGER.log(Level.WARNING,
"Unable to download the NVD CVE data, unable to update the data to use the most current data.");
"Unable to download the NVD CVE data; the results may not include the most recent CPE/CVEs from the NVD.");
if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) {
LOGGER.log(Level.INFO,
"If you are behind a proxy you may need to configure dependency-check to use the proxy.");
}
LOGGER.log(Level.FINE, null, ex);
}
}

View File

@@ -188,6 +188,10 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
} catch (DownloadFailedException ex) {
msg = String.format("Download Failed for NVD CVE - %s%nSome CVEs may not be reported.", nvdCveInfo.getId());
LOGGER.log(Level.WARNING, msg);
if (Settings.getString(Settings.KEYS.PROXY_SERVER) == null) {
LOGGER.log(Level.INFO,
"If you are behind a proxy you may need to configure dependency-check to use the proxy.");
}
LOGGER.log(Level.FINE, null, ex);
return null;
}

View File

@@ -48,7 +48,7 @@ public class ScanAgentException extends IOException {
}
/**
* Creates a new NoDataException.
* Creates a new ScanAgentException.
*
* @param ex the cause of the exception.
*/

View File

@@ -54,6 +54,10 @@ public class SuppressionHandler extends DefaultHandler {
* The CWE element name.
*/
public static final String CWE = "cwe";
/**
* The GAV element name.
*/
public static final String GAV = "gav";
/**
* The cvssBelow element name.
*/
@@ -95,13 +99,10 @@ public class SuppressionHandler extends DefaultHandler {
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentAttributes = null;
currentAttributes = attributes;
currentText = new StringBuffer();
if (SUPPRESS.equals(qName)) {
rule = new SuppressionRule();
} else if (FILE_PATH.equals(qName)) {
currentAttributes = attributes;
}
}
@@ -123,6 +124,9 @@ public class SuppressionHandler extends DefaultHandler {
rule.setFilePath(pt);
} else if (SHA1.equals(qName)) {
rule.setSha1(currentText.toString());
} else if (GAV.equals(qName)) {
final PropertyType pt = processPropertyType();
rule.setGav(pt);
} else if (CPE.equals(qName)) {
final PropertyType pt = processPropertyType();
rule.addCpe(pt);

View File

@@ -66,10 +66,35 @@ public class SuppressionParser {
* @throws SuppressionParseException thrown if the xml file cannot be parsed
*/
public List<SuppressionRule> parseSuppressionRules(File file) throws SuppressionParseException {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
return parseSuppressionRules(fis);
} catch (IOException ex) {
LOGGER.log(Level.FINE, null, ex);
throw new SuppressionParseException(ex);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
LOGGER.log(Level.FINE, "Unable to close stream", ex);
}
}
}
}
/**
* Parses the given xml stream and returns a list of the suppression rules contained.
*
* @param inputStream an InputStream containing suppression rues
* @return a list of suppression rules
* @throws SuppressionParseException if the xml cannot be parsed
*/
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException {
try {
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream("schema/suppression.xsd");
final SuppressionHandler handler = new SuppressionHandler();
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
@@ -80,7 +105,6 @@ public class SuppressionParser {
xmlReader.setErrorHandler(new SuppressionErrorHandler());
xmlReader.setContentHandler(handler);
final InputStream inputStream = new FileInputStream(file);
final Reader reader = new InputStreamReader(inputStream, "UTF-8");
final InputSource in = new InputSource(reader);
//in.setEncoding("UTF-8");

View File

@@ -234,6 +234,37 @@ public class SuppressionRule {
public boolean hasCve() {
return cve.size() > 0;
}
/**
* A Maven GAV to suppression.
*/
private PropertyType gav = null;
/**
* Get the value of Maven GAV.
*
* @return the value of gav
*/
public PropertyType getGav() {
return gav;
}
/**
* Set the value of Maven GAV.
*
* @param gav new value of Maven gav
*/
public void setGav(PropertyType gav) {
this.gav = gav;
}
/**
* Returns whether or not this suppression rule as GAV entries.
*
* @return whether or not this suppression rule as GAV entries
*/
public boolean hasGav() {
return gav != null;
}
/**
* Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any
@@ -248,12 +279,27 @@ public class SuppressionRule {
if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
return;
}
if (gav != null) {
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
boolean gavFound = false;
while (itr.hasNext()) {
final Identifier i = itr.next();
if (identifierMatches("maven", this.gav, i)) {
gavFound = true;
break;
}
}
if (!gavFound) {
return;
}
}
if (this.hasCpe()) {
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
final Identifier i = itr.next();
for (PropertyType c : this.cpe) {
if (cpeMatches(c, i)) {
if (identifierMatches("cpe", c, i)) {
dependency.addSuppressedIdentifier(i);
itr.remove();
break;
@@ -309,7 +355,7 @@ public class SuppressionRule {
boolean cpeHasNoVersion(PropertyType c) {
if (c.isRegex()) {
return false;
} // cpe:/a:jboss:jboss:1.0.0:
}
if (countCharacter(c.getValue(), ':') == 3) {
return true;
}
@@ -336,26 +382,75 @@ public class SuppressionRule {
/**
* Determines if the cpeEntry specified as a PropertyType matches the given Identifier.
*
* @param cpeEntry a suppression rule entry
* @param identifierType the type of identifier ("cpe", "maven", etc.)
* @param suppressionEntry a suppression rule entry
* @param identifier a CPE identifier to check
* @return true if the entry matches; otherwise false
*/
boolean cpeMatches(PropertyType cpeEntry, Identifier identifier) {
if (cpeEntry.matches(identifier.getValue())) {
return true;
} else if (cpeHasNoVersion(cpeEntry)) {
if (cpeEntry.isCaseSensitive()) {
if (identifier.getValue().startsWith(cpeEntry.getValue())) {
return true;
}
} else {
final String id = identifier.getValue().toLowerCase();
final String check = cpeEntry.getValue().toLowerCase();
if (id.startsWith(check)) {
return true;
boolean identifierMatches(String identifierType, PropertyType suppressionEntry, Identifier identifier) {
if (identifierType.equals(identifier.getType())) {
if (suppressionEntry.matches(identifier.getValue())) {
return true;
} else if ("cpe".equals(identifierType) && cpeHasNoVersion(suppressionEntry)) {
if (suppressionEntry.isCaseSensitive()) {
return identifier.getValue().startsWith(suppressionEntry.getValue());
} else {
final String id = identifier.getValue().toLowerCase();
final String check = suppressionEntry.getValue().toLowerCase();
return id.startsWith(check);
}
}
}
return false;
}
/**
* Standard toString implementation.
*
* @return a string representation of this object
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SuppressionRule{");
if (filePath != null) {
sb.append("filePath=").append(filePath).append(",");
}
if (sha1 != null) {
sb.append("sha1=").append(sha1).append(",");
}
if (gav != null) {
sb.append("gav=").append(gav).append(",");
}
if (cpe != null && cpe.size() > 0) {
sb.append("cpe={");
for (PropertyType pt : cpe) {
sb.append(pt).append(",");
}
sb.append("}");
}
if (cwe != null && cwe.size() > 0) {
sb.append("cwe={");
for (String s : cwe) {
sb.append(s).append(",");
}
sb.append("}");
}
if (cve != null && cve.size() > 0) {
sb.append("cve={");
for (String s : cve) {
sb.append(s).append(",");
}
sb.append("}");
}
if (cvssBelow != null && cvssBelow.size() > 0) {
sb.append("cvssBelow={");
for (Float s : cvssBelow) {
sb.append(s).append(",");
}
sb.append("}");
}
sb.append("}");
return sb.toString();
}
}

View File

@@ -1,17 +1,19 @@
/*
* Copyright 2014 OWASP.
* This file is part of dependency-check-core.
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
@@ -33,7 +35,7 @@ import static org.owasp.dependencycheck.utils.FileUtils.getFileExtension;
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class ExtractionUtil {
public final class ExtractionUtil {
/**
* The logger.

BIN
dependency-check-core/src/main/resources/GrokAssembly.exe Executable file → Normal file

Binary file not shown.

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress>
<notes><![CDATA[
This suppresses false positives identified on spring security.
]]></notes>
<gav regex="true">org\.springframework\.security:spring.*</gav>
<cpe>cpe:/a:mod_security:mod_security</cpe>
<cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
</suppress>
<suppress>
<notes><![CDATA[
This suppreses additional false positives for the xstream library that occur because spring has a copy of this library.
com.springsource.com.thoughtworks.xstream-1.3.1.jar
]]></notes>
<gav regex="true">com\.thoughtworks\.xstream:xstream:.*</gav>
<cpe>cpe:/a:springsource:spring_framework</cpe>
</suppress>
</suppressions>

View File

@@ -13,8 +13,10 @@ max.download.threads=3
# will not be used. The data.directory will be resolved and if the connection string
# below contains a %s then the data.directory will replace the %s.
data.directory=[JAR]/data
#if the filename has a %s it will be replaced with the current expected version
data.file_name=cve.%s.h2.db
data.version=2.9
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
# user name and password for the database connection. The inherent case is to use H2.

View File

@@ -41,6 +41,7 @@
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="filePath" type="dc:regexStringType"/>
<xs:element name="sha1" type="dc:sha1Type"/>
<xs:element name="gav" type="dc:regexStringType"/>
</xs:choice>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="cpe" type="dc:regexStringType"/>

View File

@@ -84,13 +84,14 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
$('#modal-text').focus();
$('#modal-text').select();
}
function toggleDisplay(el, clzName) {
function toggleDisplay(el, clzName, all, some) {
$(clzName).toggle();
if (el.innerHTML == 'show all') {
el.innerHTML = 'less';
if (el.innerHTML == all) {
el.innerHTML = some;
} else {
el.innerHTML = 'show all';
el.innerHTML = all;
}
return false;
}
</script>
<style type="text/css">
@@ -427,15 +428,24 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
.indent {
margin-left:20px;
}
td, th {
td{
vertical-align:text-top;
padding:6px;
margin:0px;
}
th {
text-align:left
vertical-align:text-top;
padding:6px;
margin:0px;
border-bottom:1px;
border-color: black;
}
table {
border: 0px;
}
table.lined tr:nth-child(even) {
background-color: #fbfbfb;
background-color: #f3f3f3;
}
.fullwidth {
width:100%;
@@ -448,10 +458,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
margin-bottom:3px;
}
.vulnerable {
color: #f00;
}
.vulnerable li {
color: #000;
color: #000;
}
.notvulnerable {
display:none;
@@ -481,7 +488,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<div id="modal-content">
<div>Press CTR-C to copy XML&nbsp;<a href="http://jeremylong.github.io/DependencyCheck/suppression.html" class="infolink" target="_blank" title="Help with suppressing false positives">[help]</a></div>
<textarea id="modal-text" cols="50" rows="10"></textarea><br/>
<button id="modal-add-header" class="modal-button">Complete XML Doc</button><button id="modal-close" class="modal-button-right">Close</button>
<button id="modal-add-header" title="Add the parent XML nodes to create the complete XML file that can be used to suppress this finding" class="modal-button">Complete XML Doc</button><button id="modal-close" class="modal-button-right">Close</button>
</div>
<div class="wrapper">
<h1>Dependency-Check Report</h1>
@@ -513,7 +520,7 @@ arising out of or in connection with the use of this tool, the analysis performe
#set($vulnSuppressedCount=$vulnSuppressedCount+$dependency.getSuppressedVulnerabilities().size())
#end
#end
Scan Information (<a href="#" onclick="toggleDisplay(this, '.scaninfo'); return false;">show all</a>):<br/>
Scan Information (<a href="#" title="Click to toggle display" onclick="return toggleDisplay(this, '.scaninfo', 'show all', 'show less'); return false;">show all</a>):<br/>
<ul class="indent">
<li><i>dependency-check version</i>: $version</li>
<li><i>Report Generated On</i>: $scanDate</li>
@@ -526,23 +533,96 @@ arising out of or in connection with the use of this tool, the analysis performe
<li class="scaninfo hidden"><i>$enc.html($prop.key)</i>: $enc.html($prop.value)</li>
#end
</ul><br/>
Dependency Display:&nbsp;<a href="#" onclick="toggleDisplay(this,'.notvulnerable'); return false;">show all</a><br/><br/>
<ul class="indent">
Display:&nbsp;<a href="#" title="Click to toggle display" onclick="return toggleDisplay(this,'.notvulnerable', 'Showing Vulnerable Dependencies', 'Showing All Dependencies'); return false;">Showing Vulnerable Dependencies</a><br/><br/>
#set($lnkcnt=0)
#foreach($dependency in $dependencies)
<table class="lined">
<tr style="text-align:left">
<th title="The name of the dependency">Dependency</th>
<th title="The number of related dependencies">#&nbsp;Related</th>
<th title="The Common Platform Enumeration">CPE</th>
<th title="The Maven GAV Coordinates">GAV</th>
<th title="The highest CVE Impact">CVE&nbsp;Impact</th>
<th title="The number of Common Vulnerability and Exposure (CVE) entries">CVE&nbsp;Count</th>
<th title="The confidence rating dependency-check has for the identified CPE">CPE&nbsp;Confidence</th>
<th title="The count of evidence used to identify the CPE">Evidence&nbsp;Count</th>
</tr>
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<li class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
<a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a>
#if($dependency.getRelatedDependencies().size()>0)
<ul>
#foreach($related in $dependency.getRelatedDependencies())
<li>$enc.html($related.DisplayFileName)</li>
<tr class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
<td><a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a></td>
<td>$dependency.getRelatedDependencies().size()</td>
#set($mavenlink="")
#set($cpeIdCount=0)
#set($cpeIdConf="")
<td>
#foreach($id in $dependency.getIdentifiers())
#if ($id.type=="maven")
#if ($mavenlink=="" || !$mavenlink.url)
#set($mavenlink=$id)
#end
#else
#if ($cpeIdCount>=1)
<br/>
#end
#if( $id.url )
<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>
#else
$enc.html($id.value)
#end
#if ($cpeIdConf == "")
#set($cpeIdConf=$id.confidence)
#elseif ($cpeIdConf.compareTo($id.confidence)>0)
#set($cpeIdConf=$id.confidence)
#end
#set($cpeIdCount=$cpeIdCount+1)
#end
#end
</ul>
</td>
<td>#if( $mavenlink.url )
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
<a href="$enc.html($mavenlink.url)" target="_blank">$enc.html($mavenlink.value)</a>
#elseif ($mavenlink.value)
$enc.html($mavenlink.value)
#end</td>
#set($cveImpact=-1)
#foreach($vuln in $dependency.getVulnerabilities())
#if ($cveImpact<$vuln.cvssScore)
#set($cveImpact=$vuln.cvssScore)
#end
#end
<td>
#if ($cveImpact<0)
&nbsp;
#elseif ($cveImpact<4.0)
Low
#elseif ($cveImpact>=7.0)
High
#else
Medium
#end
</td>
<td>$dependency.getVulnerabilities().size()</td>
<td>$cpeIdConf</td>
<td>$dependency.getEvidenceForDisplay().size()</td>
</tr>
#end
</li>
#end
</ul>
</table>
## <ul class="indent">
## #set($lnkcnt=0)
## #foreach($dependency in $dependencies)
## #set($lnkcnt=$lnkcnt+1)
## <li class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
## <a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a>
## #if($dependency.getRelatedDependencies().size()>0)
## <ul>
## #foreach($related in $dependency.getRelatedDependencies())
## <li>$enc.html($related.DisplayFileName)</li>
## #end
## </ul>
## #end
## </li>
## #end
## </ul>
<h2>Dependencies</h2>
#set($lnkcnt=0)
#set($cnt=0)
@@ -630,7 +710,7 @@ arising out of or in connection with the use of this tool, the analysis performe
#end
#if ($id.type=="cpe")
##yes, we are HTML Encoding into JavaScript... the escape utils don't have a JS Encode and I haven't written one yet
&nbsp;&nbsp;<button class="copybutton" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cpe', '$enc.html($id.value)')">suppress</button>
&nbsp;&nbsp;<button class="copybutton" title="Generate Suppression XML for this CPE for this file" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cpe', '$enc.html($id.value)')">suppress</button>
#end
#if ($id.description)
<br/>$enc.html($id.description)
@@ -646,7 +726,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<div id="content$cnt" class="subsectioncontent standardsubsection">
#foreach($vuln in $dependency.getVulnerabilities())
#set($vsctr=$vsctr+1)
<p><b><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$enc.url($vuln.name)">$enc.html($vuln.name)</a></b>&nbsp;&nbsp;<button class="copybutton" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cve', '$enc.html($vuln.name)')">suppress</button></p>
<p><b><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$enc.url($vuln.name)">$enc.html($vuln.name)</a></b>&nbsp;&nbsp;<button class="copybutton" title="Generate Suppression XML for this CCE for this file" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cve', '$enc.html($vuln.name)')">suppress</button></p>
<p>Severity:
#if ($vuln.cvssScore<4.0)
Low

View File

@@ -34,8 +34,8 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* @author Jeremy Long <jeremy.long@owasp.org>
@@ -67,7 +67,7 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest {
instance.initialize();
int expCount = 5;
List<SuppressionRule> result = instance.getRules();
assertEquals(expCount, result.size());
assertTrue(expCount <= result.size());
}
/**
@@ -79,7 +79,7 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest {
instance.initialize();
int expCount = 5;
List<SuppressionRule> result = instance.getRules();
assertEquals(expCount, result.size());
assertTrue(expCount <= result.size());
}
@Test(expected = SuppressionParseException.class)

View File

@@ -85,7 +85,7 @@ public class HintAnalyzerTest extends BaseTest {
for (Dependency d : engine.getDependencies()) {
if (d.getActualFile().equals(guice)) {
gdep = d;
} else {
} else if (d.getActualFile().equals(spring)) {
sdep = d;
}
}

View File

@@ -45,8 +45,10 @@ public abstract class BaseDBTestCase extends BaseTest {
public static void ensureDBExists() throws Exception {
java.io.File dataPath = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
if (!dataPath.exists() || (dataPath.isDirectory() && dataPath.listFiles().length < 3)) {
java.io.File dataPath = Settings.getDataDirectory();
String fileName = String.format(Settings.getString(Settings.KEYS.DB_FILE_NAME), Settings.getString(Settings.KEYS.DB_VERSION));
java.io.File dataFile = new File(dataPath, fileName);
if (!dataPath.exists() || !dataFile.exists()) {
dataPath.mkdirs();
FileInputStream fis = null;
ZipInputStream zin = null;

View File

@@ -339,55 +339,70 @@ public class SuppressionRuleTest {
}
/**
* Test of cpeMatches method, of class SuppressionRule.
* Test of identifierMatches method, of class SuppressionRule.
*/
@Test
public void testCpeMatches() {
Identifier identifier = new Identifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
Identifier identifier = new Identifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
PropertyType cpe = new PropertyType();
cpe.setValue("cpe:/a:microsoft:.net_framework:4.5");
SuppressionRule instance = new SuppressionRule();
boolean expResult = true;
boolean result = instance.cpeMatches(cpe, identifier);
boolean result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:microsoft:.net_framework:4.0");
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("CPE:/a:microsoft:.net_framework:4.5");
cpe.setCaseSensitive(true);
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:microsoft:.net_framework");
cpe.setCaseSensitive(false);
expResult = true;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:microsoft:.*");
cpe.setRegex(true);
expResult = true;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("CPE:/a:microsoft:.*");
cpe.setRegex(true);
cpe.setCaseSensitive(true);
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("cpe:/a:apache:.*");
cpe.setRegex(true);
cpe.setCaseSensitive(false);
expResult = false;
result = instance.cpeMatches(cpe, identifier);
result = instance.identifierMatches("cpe", cpe, identifier);
assertEquals(expResult, result);
identifier = new Identifier("maven", "org.springframework:spring-core:2.5.5", "https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.springframework&a=spring-core&v=2.5.5&e=jar");
cpe.setValue("org.springframework:spring-core:2.5.5");
cpe.setRegex(false);
cpe.setCaseSensitive(false);
expResult = true;
result = instance.identifierMatches("maven", cpe, identifier);
assertEquals(expResult, result);
cpe.setValue("org\\.springframework\\.security:spring.*");
cpe.setRegex(true);
cpe.setCaseSensitive(false);
expResult = false;
result = instance.identifierMatches("maven", cpe, identifier);
assertEquals(expResult, result);
}
@@ -398,7 +413,7 @@ public class SuppressionRuleTest {
public void testProcess() {
File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
Dependency dependency = new Dependency(struts);
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
String sha1 = dependency.getSha1sum();
dependency.setSha1sum("384FAA82E193D4E4B0546059CA09572654BC3970");
Vulnerability v = createVulnerability();
@@ -455,9 +470,9 @@ public class SuppressionRuleTest {
assertTrue(dependency.getIdentifiers().isEmpty());
assertTrue(dependency.getSuppressedIdentifiers().size() == 1);
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
pt = new PropertyType();
pt.setValue("cpe:/a:microsoft:.net_framework");
instance.addCpe(pt);
@@ -467,6 +482,43 @@ public class SuppressionRuleTest {
assertTrue(dependency.getSuppressedIdentifiers().size() == 3);
}
/**
* Test of process method, of class SuppressionRule.
*/
@Test
public void testProcessGAV() {
File spring = new File(this.getClass().getClassLoader().getResource("spring-security-web-3.0.0.RELEASE.jar").getPath());
Dependency dependency = new Dependency(spring);
dependency.addIdentifier("cpe", "cpe:/a:vmware:springsource_spring_framework:3.0.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:springsource:spring_framework:3.0.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:mod_security:mod_security:3.0.0", "some url not needed for this test");
dependency.addIdentifier("cpe", "cpe:/a:vmware:springsource_spring_security:3.0.0", "some url not needed for this test");
dependency.addIdentifier("maven", "org.springframework.security:spring-security-web:3.0.0.RELEASE", "some url not needed for this test");
//cpe
SuppressionRule instance = new SuppressionRule();
PropertyType pt = new PropertyType();
pt.setValue("org\\.springframework\\.security:spring.*");
pt.setRegex(true);
pt.setCaseSensitive(false);
instance.setGav(pt);
pt = new PropertyType();
pt.setValue("cpe:/a:mod_security:mod_security");
instance.addCpe(pt);
pt = new PropertyType();
pt.setValue("cpe:/a:springsource:spring_framework");
instance.addCpe(pt);
pt = new PropertyType();
pt.setValue("cpe:/a:vmware:springsource_spring_framework");
instance.addCpe(pt);
instance.process(dependency);
assertEquals(2, dependency.getIdentifiers().size());
}
private Vulnerability createVulnerability() {
Vulnerability v = new Vulnerability();
v.setCwe("CWE-287 Improper Authentication");

View File

@@ -13,8 +13,12 @@ max.download.threads=3
# will not be used. The data.directory will be resolved and if the connection string
# below contains a %s then the data.directory will replace the %s.
data.directory=[JAR]/data
# if the filename has a %s it will be replaced with the current expected version. For file
# based databases the below filename will be added to the data directory above and then
# if the connection string has a %s it will be replaced by the directory/filename path.
data.file_name=cve.%s.h2.db
data.version=2.9
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck
# user name and password for the database connection. The inherent case is to use H2.

View File

@@ -1,17 +1,25 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<description>This plug-in can independently execute a Dependency-Check analysis and visualize the results.</description>
<url>http://wiki.jenkins-ci.org/display/JENKINS/OWASP+Dependency-Check+Plugin</url>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.4-SNAPSHOT</version>
</parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-jenkins</artifactId>
<name>Dependency-Check Jenkins Plugin</name>
<url>http://wiki.jenkins-ci.org/display/JENKINS/OWASP+Dependency-Check+Plugin</url>
<description>dependency-check-jenkins is a Jenkins plugin that runs dependency-check-core on a project to detect publicly disclosed vulnerabilities associated with the project's dependencies. The plugin will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries. This module is simply a placeholder and does not contain the actual plugin source code. The source code and distribution of the plugin is handled via https://github.com/jenkinsci/dependency-check-jenkins and Jenkin's plugin management.</description>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
<id>github-pages-site</id>
<name>Deployment through GitHub's site deployment plugin</name>
<url>${basedir}/../target/site/${project.version}/dependency-check-jenkins</url>
</site>
</distributionManagement>
<!-- end copy -->
<packaging>pom</packaging>
<inceptionYear>2012</inceptionYear>
<organization>
@@ -31,15 +39,6 @@
</roles>
</developer>
</developers>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
<id>github-pages-site</id>
<name>Deployment through GitHub's site deployment plugin</name>
<url>${basedir}/../target/site/${project.version}/dependency-check-maven</url>
</site>
</distributionManagement>
<!-- end copy -->
<scm>
<connection>scm:git:git@github.com:jenkinsci/dependency-check-jenkins.git</connection>
<url>https://github.com/jenkinsci/dependency-check-jenkins</url>

View File

@@ -15,7 +15,6 @@ limitations under the License.
Copyright (c) 2013 Jeremy Long. All Rights Reserved.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<url>http://maven.apache.org</url>
@@ -23,14 +22,14 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.4-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-maven</artifactId>
<packaging>maven-plugin</packaging>
<name>Dependency-Check Maven Plugin</name>
<description>Dependency-Check-Maven is a Maven Plugin that attempts to detect publicly disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries.</description>
<description>dependency-check-maven is a Maven Plugin that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the project's dependencies. The plugin will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.</description>
<inceptionYear>2013</inceptionYear>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
@@ -150,6 +149,9 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>
@@ -239,7 +241,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<linkXref>true</linkXref>
<sourceEncoding>utf-8</sourceEncoding>
<excludes>
<exclude>**/generated/*.java</exclude>
<exclude>**/generated/**/*.java</exclude>
<exclude>**/HelpMojo.java</exclude>
</excludes>
<rulesets>

View File

@@ -21,18 +21,18 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.4-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-utils</artifactId>
<name>Dependency-Check Utils</name>
<description>Dependency-check-utils a collection of common utlity classs used within dependency-check.</description>
<description>dependency-check-utils is a collection of common utlity classes used within dependency-check that might be useful in other projects.</description>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
<id>github-pages-site</id>
<name>Deployment through GitHub's site deployment plugin</name>
<url>${basedir}/../target/site/${project.version}/dependency-check-ant</url>
<url>${basedir}/../target/site/${project.version}/dependency-check-utils</url>
</site>
</distributionManagement>
<!-- end copy -->
@@ -158,6 +158,9 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<bottom>Copyright© 2012-14 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>

View File

@@ -1,9 +1,27 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
@@ -12,19 +30,16 @@ import java.util.logging.Logger;
/**
* Includes methods to generate the MD5 and SHA1 checksum.
*
* This code was copied from Real's How To. It has been slightly modified.
*
* Written and compiled by Réal Gagnon ©1998-2012
*
* @author Real's How To: http://www.rgagnon.com/javadetails/java-0416.html
* @author Jeremy Long <jeremy.long@owasp.org>
*
*/
public final class Checksum {
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(Checksum.class.getName());
/**
* Private constructor for a utility class.
*/
@@ -32,30 +47,29 @@ public final class Checksum {
}
/**
* <p>Creates the cryptographic checksum of a given file using the specified
* algorithm.</p> <p>This algorithm was copied and heavily modified from
* Real's How To: http://www.rgagnon.com/javadetails/java-0416.html</p>
* <p>
* Creates the cryptographic checksum of a given file using the specified algorithm.</p>
*
* @param algorithm the algorithm to use to calculate the checksum
* @param file the file to calculate the checksum for
* @return the checksum
* @throws IOException when the file does not exist
* @throws NoSuchAlgorithmException when an algorithm is specified that does
* not exist
* @throws NoSuchAlgorithmException when an algorithm is specified that does not exist
*/
@SuppressWarnings("empty-statement")
public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
InputStream fis = null;
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance(algorithm);
int numRead;
MessageDigest digest = MessageDigest.getInstance(algorithm);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
FileChannel ch = fis.getChannel();
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
digest.update(byteBuffer);
// BufferedInputStream bis = new BufferedInputStream(fis);
// DigestInputStream dis = new DigestInputStream(bis, digest);
// //yes, we are reading in a buffer for performance reasons - 1 byte at a time is SLOW
// byte[] buffer = new byte[8192];
// while (dis.read(buffer) != -1);
} finally {
if (fis != null) {
try {
@@ -65,7 +79,7 @@ public final class Checksum {
}
}
}
return complete.digest();
return digest.digest();
}
/**
@@ -93,12 +107,17 @@ public final class Checksum {
byte[] b = getChecksum("SHA1", file);
return getHex(b);
}
/**
* Hex code characters used in getHex.
*/
private static final String HEXES = "0123456789ABCDEF";
/**
* <p>Converts a byte array into a hex string.</p>
* <p>
* Converts a byte array into a hex string.</p>
*
* <p>This method was copied from <a
* <p>
* This method was copied from <a
* href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p>
*
* @param raw a byte array
@@ -110,7 +129,7 @@ public final class Checksum {
}
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F));
}
return hex.toString();
}

View File

@@ -176,7 +176,7 @@ public final class Downloader {
conn = URLConnectionFactory.createHttpURLConnection(url);
conn.setRequestMethod("HEAD");
conn.connect();
int t = conn.getResponseCode();
final int t = conn.getResponseCode();
if (t >= 200 && t < 300) {
timestamp = conn.getLastModified();
} else {

View File

@@ -53,20 +53,24 @@ public final class LogUtils {
try {
LogManager.getLogManager().reset();
LogManager.getLogManager().readConfiguration(in);
if (verboseLogFile != null && !verboseLogFile.isEmpty()) {
verboseLoggingEnabled = true;
final Logger logger = Logger.getLogger("");
final FileHandler handler = new FileHandler(verboseLogFile, true);
handler.setFormatter(new SimpleFormatter());
handler.setLevel(Level.FINE);
handler.setFilter(new LogFilter());
logger.addHandler(handler);
final FileHandler fileHandler = new FileHandler(verboseLogFile, true);
fileHandler.setFormatter(new SimpleFormatter());
fileHandler.setLevel(Level.FINE);
fileHandler.setFilter(new LogFilter());
logger.addHandler(fileHandler);
logger.setLevel(Level.FINE);
}
} catch (IOException ex) {
LOGGER.log(Level.FINE, "IO Error preparing the logger", ex);
LOGGER.log(Level.WARNING, "IO Error preparing the logger", ex);
} catch (SecurityException ex) {
LOGGER.log(Level.FINE, "Error preparing the logger", ex);
LOGGER.log(Level.WARNING, "Error preparing the logger", ex);
} catch (Throwable ex) {
LOGGER.log(Level.WARNING, "Error preparing the logger", ex);
} finally {
if (in != null) {
try {

View File

@@ -78,6 +78,14 @@ public final class Settings {
* The base path to use for the data directory (for embedded db).
*/
public static final String DATA_DIRECTORY = "data.directory";
/**
* The database file name.
*/
public static final String DB_FILE_NAME = "data.file_name";
/**
* The database schema version.
*/
public static final String DB_VERSION = "data.version";
/**
* The properties key for the URL to retrieve the "meta" data from about the CVE entries.
*/
@@ -97,7 +105,7 @@ public final class Settings {
*/
public static final String CVE_MODIFIED_VALID_FOR_DAYS = "cve.url.modified.validfordays";
/**
* The properties key for the telling us how many cvr.url.* URLs exists. This is used in combination with
* The properties key for the telling us how many cve.url.* URLs exists. This is used in combination with
* CVE_BASE_URL to be able to retrieve the URLs for all of the files that make up the NVD CVE listing.
*/
public static final String CVE_START_YEAR = "cve.startyear";
@@ -200,6 +208,28 @@ public final class Settings {
* The properties key for whether Provided Scope dependencies should be skipped.
*/
public static final String SKIP_PROVIDED_SCOPE = "skip.provided.scope";
/**
* The key to obtain the path to the VFEED data file.
*/
public static final String VFEED_DATA_FILE = "vfeed.data_file";
/**
* The key to obtain the VFEED connection string.
*/
public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string";
/**
* The key to obtain the base download URL for the VFeed data file.
*/
public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url";
/**
* The key to obtain the download file name for the VFeed data.
*/
public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file";
/**
* The key to obtain the VFeed update status.
*/
public static final String VFEED_UPDATE_STATUS = "vfeed.update_status";
}
//</editor-fold>
@@ -382,8 +412,19 @@ public final class Settings {
* @throws IOException is thrown when there is an exception loading/merging the properties
*/
public static void mergeProperties(File filePath) throws FileNotFoundException, IOException {
final FileInputStream fis = new FileInputStream(filePath);
mergeProperties(fis);
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
mergeProperties(fis);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, "close error", ex);
}
}
}
}
/**
@@ -396,8 +437,19 @@ public final class Settings {
* @throws IOException is thrown when there is an exception loading/merging the properties
*/
public static void mergeProperties(String filePath) throws FileNotFoundException, IOException {
final FileInputStream fis = new FileInputStream(filePath);
mergeProperties(fis);
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
mergeProperties(fis);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
LOGGER.log(Level.FINEST, "close error", ex);
}
}
}
}
/**
@@ -441,7 +493,7 @@ public final class Settings {
* @param key the key to lookup within the properties file
* @return the property from the properties file converted to a File object
*/
public static File getDataFile(String key) {
protected static File getDataFile(String key) {
final String file = getString(key);
LOGGER.log(Level.FINE, String.format("Settings.getDataFile() - file: '%s'", file));
if (file == null) {
@@ -641,4 +693,74 @@ public final class Settings {
}
return value;
}
/**
* Returns a connection string from the configured properties. If the connection string contains a %s, this method
* will determine the 'data' directory and replace the %s with the path to the data directory. If the data directory
* does not exists it will be created.
*
* @param connectionStringKey the property file key for the connection string
* @param dbFileNameKey the settings key for the db filename
* @param dbVersionKey the settings key for the dbVersion
* @return the connection string
* @throws IOException thrown the data directory cannot be created
* @throws InvalidSettingException thrown if there is an invalid setting
*/
public static String getConnectionString(String connectionStringKey, String dbFileNameKey, String dbVersionKey)
throws IOException, InvalidSettingException {
final String connStr = Settings.getString(connectionStringKey);
if (connStr == null) {
final String msg = String.format("Invalid properties file to get the connection string; '%s' must be defined.",
connectionStringKey);
throw new InvalidSettingException(msg);
}
if (connStr.contains("%s")) {
final File directory = getDataDirectory();
String fileName = null;
if (dbFileNameKey != null) {
fileName = Settings.getString(dbFileNameKey);
}
if (fileName == null) {
final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.",
dbFileNameKey);
throw new InvalidSettingException(msg);
}
if (fileName.contains("%s")) {
String version = null;
if (dbVersionKey != null) {
version = Settings.getString(dbVersionKey);
}
if (version == null) {
final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.",
dbFileNameKey);
throw new InvalidSettingException(msg);
}
fileName = String.format(fileName, version);
}
if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) {
fileName = fileName.substring(0, fileName.length() - 6);
}
// yes, for H2 this path won't actually exists - but this is sufficient to get the value needed
final File dbFile = new File(directory, fileName);
final String cString = String.format(connStr, dbFile.getCanonicalPath());
LOGGER.log(Level.FINE, String.format("Connection String: '%s'", cString));
return cString;
}
return connStr;
}
/**
* Retrieves the directory that the JAR file exists in so that we can ensure we always use a common data directory
* for the embedded H2 database. This is public solely for some unit tests; otherwise this should be private.
*
* @return the data directory to store data files
* @throws IOException is thrown if an IOException occurs of course...
*/
public static File getDataDirectory() throws IOException {
final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
if (path.exists() || path.mkdirs()) {
return path;
}
throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath()));
}
}

View File

@@ -50,7 +50,7 @@ public final class URLConnectionFactory {
*/
public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
HttpURLConnection conn = null;
Proxy proxy = null;
Proxy proxy;
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER);
try {
if (proxyUrl != null) {
@@ -96,7 +96,7 @@ public final class URLConnectionFactory {
* Utility method to create an HttpURLConnection. The use of a proxy here is optional as there may be cases where a
* proxy is configured but we don't want to use it (for example, if there's an internal repository configured)
*
* @param url the url to connect to
* @param url the URL to connect to
* @param proxy whether to use the proxy (if configured)
* @return a newly constructed HttpURLConnection
* @throws URLConnectionFailureException thrown if there is an exception

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
This file is part of dependency-check-ant.
Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright (c) 2014 Jeremy Long. All Rights Reserved.
-->
<project name="dependency-check-ant">
<bannerLeft>
<name>dependency-check-utils</name>
</bannerLeft>
<body>
<breadcrumbs>
<item name="dependency-check" href="../index.html"/>
</breadcrumbs>
<menu ref="Project Documentation" />
<menu ref="reports" />
</body>
</project>

View File

@@ -26,6 +26,8 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Checksum;
import org.owasp.dependencycheck.utils.Checksum;
/**
*

View File

@@ -157,4 +157,35 @@ public class SettingsTest extends BaseTest {
ret = Settings.getString(key, dfault);
Assert.assertEquals(dfault, ret);
}
/**
* Test of getConnectionString.
*/
@Test
public void testGetConnectionString() throws Exception {
String value = Settings.getConnectionString(Settings.KEYS.DB_CONNECTION_STRING, Settings.KEYS.DB_FILE_NAME, Settings.KEYS.DB_VERSION);
Assert.assertNotNull(value);
String msg = null;
try {
value = Settings.getConnectionString(Settings.KEYS.DB_CONNECTION_STRING, Settings.KEYS.DB_FILE_NAME, null);
} catch (InvalidSettingException e) {
msg = e.getMessage();
}
Assert.assertNotNull(msg, msg);
try {
value = Settings.getConnectionString("invalidKey", null, null);
} catch (InvalidSettingException e) {
msg = e.getMessage();
}
Assert.assertNotNull(msg, msg);
}
/**
* Test of getTempDirectory.
*/
@Test
public void testGetTempDirectory() throws Exception {
File tmp = Settings.getTempDirectory();
Assert.assertTrue(tmp.exists());
}
}

View File

@@ -13,6 +13,8 @@ max.download.threads=3
# will not be used. The data.directory will be resolved and if the connection string
# below contains a %s then the data.directory will replace the %s.
data.directory=[JAR]/data
data.file_name=cve.%s.h2.db
data.version=2.9
data.connection_string=jdbc:h2:file:%s;FILE_LOCK=SERIALIZED;AUTOCOMMIT=ON;
#data.connection_string=jdbc:h2:file:%s;AUTO_SERVER=TRUE;AUTOCOMMIT=ON;
#data.connection_string=jdbc:mysql://localhost:3306/dependencycheck

16
pom.xml
View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.4-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
@@ -29,11 +29,11 @@ Copyright (c) 2012 - Jeremy Long
<module>dependency-check-ant</module>
<module>dependency-check-maven</module>
<module>dependency-check-jenkins</module>
<module>dependency-check-utils</module>
</modules>
<module>dependency-check-utils</module>
</modules>
<name>Dependency-Check</name>
<url>https://github.com/jeremylong/DependencyCheck.git</url>
<description>dependency-check is a utility that identifies project dependencies and checks if there are any known, publicly disclosed, vulnerabilities. This tool can be part of the solution to the OWASP Top 10 2013: A9 - Using Components with Known Vulnerabilities.</description>
<description>dependency-check is a utility that identifies project dependencies and checks if there are any known, publicly disclosed vulnerabilities. This tool can be part of the solution to the OWASP Top 10 2013: A9 - Using Components with Known Vulnerabilities.</description>
<inceptionYear>2012</inceptionYear>
<organization>
@@ -141,14 +141,6 @@ Copyright (c) 2012 - Jeremy Long
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<bottom>Copyright© 2012-13 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
</plugin>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@@ -0,0 +1,16 @@
Archive Analyzer
==============
Dependency-check includes an analyzer an archive analyzer that will attempt
to extract files from the archive that are supported by the other file type
analyzers.
Files Types Scanned: ZIP, EAR, WAR, JAR, SAR, APK, NUPKG, TAR, GZ, TGZ
Additional file extensions for ZIP archives can be added, see the configuration
section in the Maven, Ant, or CLI interfaces for more information on configuration.
Note, since this analyzer does examine the contents of a JAR file there are times
that you may see additional entries in the report and/or warnings in the log file (if used)
for DLL or EXE files contained within the JAR file. In almost all cases these can
be ignored as it is fairly rare to have a .NET dll or exe within a JAR file.

View File

@@ -0,0 +1,10 @@
Assembly Analyzer
==============
Dependency-check includes an analyzer that scans .NET dll and exe files and collect as
much information it can about the files as it can. The information collected
is internally referred to as evidence and is grouped into vendor, product, and version
buckets. Other analyzers later use this evidence to identify any Common Platform
Enumeration (CPE) identifiers that apply.
Files Types Scanned: EXE, DLL

View File

@@ -12,11 +12,10 @@ The gist of the paper is that we as a development community include third party
libraries in our applications that contain well known published vulnerabilities
\(such as those at the [National Vulnerability Database](http://web.nvd.nist.gov/view/vuln/search)\).
Dependency-check scans directories and files and if it contains an Analyzer that
can scan a particular file type then information from the file is collected. This
information is then used to identify the [Common Platform Enumeration](http://nvd.nist.gov/cpe.cfm) \(CPE\). If a
CPE is identified a listing of associated [Common Vulnerability and Exposure](http://cve.mitre.org/) \(CVE\)
entries are listed in a report.
More information about dependency-check can be found here:
* (How does dependency-check work)[internals.html]
* (How to read the report)[thereport.html]
**IMPORTANT NOTE**: Dependency-check automatically updates itself using the NVD Data Feeds hosted by
NIST. **The initial download of the data may take fifteen minutes

View File

@@ -0,0 +1,35 @@
How does dependency-check work?
===========
Dependency-check works by collecting information about the files it scans (using Analyzers). The information collected
is called Evidence; there are three types of evidence collected: vendor, product, and version. For instance, the
JarAnalyzer will collect information from the Manifest, pom.xml, and the package names within the JAR files scanned and
it has heuristics to place the information from the various sources into one or more buckets of evidence.
Within the NVD CVE Data (schema can be found [here](http://nvd.nist.gov/schema/nvd-cve-feed_2.0.xsd)) each CVE Entry has a list of vulnerable software:
```xml
<entry id="CVE-2012-5055">
...
<vuln:vulnerable-software-list>
<vuln:product>cpe:/a:vmware:springsource_spring_security:3.1.2</vuln:product>
<vuln:product>cpe:/a:vmware:springsource_spring_security:2.0.4</vuln:product>
<vuln:product>cpe:/a:vmware:springsource_spring_security:3.0.1</vuln:product>
```
These CPE entries are read "cpe:/[Entry Type]:[Vendor]:[Product]:[Version]:[Revision]:...". The CPE data is collected
and stored in a [Lucene Index](http://lucene.apache.org/). Dependency-check then use the Evidence collected and attempt
to match an entry from the Lucene CPE Index. If found, the CPEAnalyzer will add an Identifier to the Dependency and
subsequently to the report. Once a CPE has been identified the associated CVE entries are added to the report.
One important point about the evidence is that it is rated using different confidence levels - low, medium, high, and
highest. These confidence levels are applied to each item of evidence. When the CPE is determined it is given a confidence
level that is equal to the lowest level confidence level of evidence used during identification. If only highest confidence
evidence was used in determining the CPE then the CPE would have a highest confidence level.
Because of the way dependency-check works both false positives and false negatives may exist. Please read
(How to read the report)[thereport.html] to get a better understanding of sorting through the false positives and false
negatives.
Dependency-check does not currently use file hashes for identification. If the dependency was built from source the hash
likely will not match the "published" hash. While the evidence based mechanism currently used can also be unreliable the
design decision was to avoid maintaining a hash database of known vulnerable libraries. A future enhancement may add some
hash matching for very common well known libraries (Spring, Struts, etc.).

View File

@@ -0,0 +1,11 @@
Jar Analyzer
==============
Dependency-check includes an analyzer that scans JAR files and collect as
much information it can about the file as it can. The information collected
is internally referred to as evidence and is grouped into vendor, product, and version
buckets. Other analyzers later use this evidence to identify any Common Platform
Enumeration (CPE) identifiers that apply. Additionally, if a POM is present
the analyzer will add the Maven group, artifact, and version (GAV).
Files Types Scanned: JAR, WAR

View File

@@ -1,7 +1,7 @@
Nexus Analyzer
==============
Dependency Check includes an analyzer which will check for the Maven GAV
Dependency-check includes an analyzer that will check for the Maven GAV
(Group/Artifact/Version) information for artifacts in the scanned area. By
default the information comes from [Maven Central][1], but can be configured to
use a local repository if necessary. If the artifact's hash is found in the

View File

@@ -0,0 +1,13 @@
Nuspec Analyzer
==============
Dependency-check includes an analyzer that will scan NuGet's Nuspec file to
collect information about the component being used. The evidence collected
is used by other analyzers to determine if there are any known vulnerabilities
associated with the component.
Note, the Nuspec Analyzer does not scan dependencies defined. However, if
the dependencies have been downloaded and may be included in the scan depending
on configuration.
Files Types Scanned: NUSPEC

View File

@@ -64,6 +64,15 @@ HTML version of the report. The other common scenario would be to ignore all CVE
]]></notes>
<cvssBelow>7</cvssBelow>
</suppress>
<suppress>
<notes><![CDATA[
This suppresses false positives identified on spring security.
]]></notes>
<gav regex="true">org\.springframework\.security:spring.*</gav>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
<cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:mod_security:mod_security</cpe>
</suppress>
</suppressions>
```

View File

@@ -0,0 +1,26 @@
How To Read The Report
========
There is a lot of information contained in the HTML version of the report. When analyzing the results, the first thing one should do is determine if the CPE looks
appropriate. Due to the way dependency-check works (see above) the report may contain false positives; these false positives are primarily on the CPE values. If the CPE value
is wrong, this is usually obvious and one should use the suppression feature in the report to generate a suppression XML file that can be used on future scans. In addition
to just looking at the CPE values in comparison to the name of the dependency - one may also consider the confidence of the CPE (as discussed in (How does dependency-check
work)[internals.html]). See the (Suppression False Positives)[suppression.html] page for more information on how to generate and use the suppression file.
Once you have weeded out any obvious false positives one can then look at the remaining entries and determine if any of the identified CVE entries are actually
exploitable in your environment. Determining if a CVE is exploitable in your environment can be tricky - for this I do not currently have any tips other then
upgrade the library if you can just to be safe. Note, some CVE entries can be fixed by either upgrading the library or changing configuration options.
One item that dependency-check flags that many may think is a false positive are old database drivers. One thing to consider about an old database driver is that the
CPE/CVEs identified are usually for the server rather then the driver. However, the presence of an old driver may indicate that you have an older version of the server
running in your environment and that server may need to be patched or upgraded. However, in some cases the old database drivers are actually unused, transitive dependencies
from other dependencies.
Regarding False Negatives
=======
As stated above, due to the nature of dependency-check there may be publicly disclosed vulnerabilities in the project dependencies scanned by dependency-check that
are not identified. With the current version of dependency-check the HTML report has a table at the top that initially displays just the dependencies with identified
vulnerabilities. This can be toggled to show all dependencies. If you examine the rows that do not have identified CPE/CVE entries you will see an "evidence count".
If the evidence count is extremely low (0-5 entries) then there may not have been enough information contained in the dependency to identify a CPE and associated CVEs.
It should be noted that while the false positives described above are bad, more concerning is that there may be vulnerabilities within the project dependencies that
have yet to be publicly known. If one has the resources consider performing security assessments on the project dependencies.

File diff suppressed because one or more lines are too long

View File

@@ -72,6 +72,12 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<menu ref="reports" />
<menu name="General">
<item name="How it Works" href="./internals.html">
<description>How does dependency-check work?</description>
</item>
<item name="Reading the Report" href="./thereport.html">
<description>How to read the report</description>
</item>
<item name="False Positives" href="./suppression.html">
<description>Suppressing False Positives</description>
</item>
@@ -84,14 +90,25 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<item name="Sample Report" href="./SampleReport.html">
<description>Sample Report</description>
</item>
</menu>
<menu name="File Type Analyzers">
<item name="Archive Analyzer" href="./archive-analyzer.html">
<description>Archive Analyzer</description>
</item>
<item name="Jar Analyzer" href="./jar-analyzer.html">
<description>Jar Analyzer</description>
</item>
<item name="Nexus Analyzer" href="./nexus-analyzer.html">
<description>Nexus Analyzer</description>
</item>
<item name="Assembly Analyzer" href="./assembly-analyzer.html">
<description>Assembly Analyzer</description>
</item>
<item name="Nuspec Analyzer" href="./nuspec-analyzer.html">
<description>Nuspec Analyzer</description>
</item>
</menu>
<menu name="Modules">
<item name="dependency-check-core" href="./dependency-check-core/index.html">
<description>The core dependency-check library</description>
</item>
<item name="dependency-check-cli" href="./dependency-check-cli/installation.html">
<description>The command line interface for dependency-check.</description>
</item>
@@ -104,6 +121,12 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<item name="dependency-check-jenkins" href="./dependency-check-jenkins/index.html">
<description>A Jenkins plugin for dependency-check.</description>
</item>
<item name="dependency-check-core" href="./dependency-check-core/index.html">
<description>The core dependency-check engine and reporting tool.</description>
</item>
<item name="dependency-check-utils" href="./dependency-check-utils/index.html">
<description>A set of utility classes used by dependency-check.</description>
</item>
</menu>
<footer>Copyright © 2012-2014 Jeremy Long. All Rights Reserved.</footer>
</body>