mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-13 23:33:37 +01:00
Merge remote-tracking branch 'origin/master'
Former-commit-id: 1ed0b6e8621fb68a823b8127775fc5f86932cc00
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class ScanAgentException extends IOException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new NoDataException.
|
||||
* Creates a new ScanAgentException.
|
||||
*
|
||||
* @param ex the cause of the exception.
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
BIN
dependency-check-core/src/main/resources/GrokAssembly.exe
Executable file → Normal file
Binary file not shown.
@@ -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>
|
||||
@@ -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.
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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 <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: <a href="#" onclick="toggleDisplay(this,'.notvulnerable'); return false;">show all</a><br/><br/>
|
||||
<ul class="indent">
|
||||
Display: <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"># 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 Impact</th>
|
||||
<th title="The number of Common Vulnerability and Exposure (CVE) entries">CVE Count</th>
|
||||
<th title="The confidence rating dependency-check has for the identified CPE">CPE Confidence</th>
|
||||
<th title="The count of evidence used to identify the CPE">Evidence 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)
|
||||
|
||||
#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
|
||||
<button class="copybutton" onclick="copyText('$enc.html($dependency.FileNameForJavaScript)', '$enc.html($dependency.Sha1sum)', 'cpe', '$enc.html($id.value)')">suppress</button>
|
||||
<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> <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> <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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
30
dependency-check-utils/src/site/site.xml
Normal file
30
dependency-check-utils/src/site/site.xml
Normal 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>
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
16
pom.xml
@@ -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>
|
||||
|
||||
16
src/site/markdown/archive-analyzer.md
Normal file
16
src/site/markdown/archive-analyzer.md
Normal 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.
|
||||
10
src/site/markdown/assembly-analyzer.md
Normal file
10
src/site/markdown/assembly-analyzer.md
Normal 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
|
||||
@@ -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
|
||||
|
||||
35
src/site/markdown/internals.md
Normal file
35
src/site/markdown/internals.md
Normal 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.).
|
||||
11
src/site/markdown/jar-analyzer.md
Normal file
11
src/site/markdown/jar-analyzer.md
Normal 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
|
||||
@@ -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
|
||||
|
||||
13
src/site/markdown/nuspec-analyzer.md
Normal file
13
src/site/markdown/nuspec-analyzer.md
Normal 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
|
||||
@@ -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>
|
||||
```
|
||||
|
||||
|
||||
26
src/site/markdown/thereport.md
Normal file
26
src/site/markdown/thereport.md
Normal 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
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user