Compare commits

..

15 Commits

Author SHA1 Message Date
Jeremy Long
4dba00ad38 [maven-release-plugin] prepare release dependency-check-0.2.6.0
Former-commit-id: 72f4e6be540edb2a8fd5ea3700a244e4aa0d9fbd
2013-02-02 17:12:48 -05:00
Jeremy Long
283acc5e30 updated version
Former-commit-id: f7ad88caa8ae9064d66c1bdff4d98c2dd0778d8b
2013-02-02 16:50:29 -05:00
Jeremy Long
cfece9499b updated usage
Former-commit-id: 807dd804fac2be34fb4a5c938e3e6bbdf694613e
2013-02-02 16:49:11 -05:00
Jeremy Long
276078a2e3 bug fixes and additions
Former-commit-id: 1eddb332f6dba5732284eda1ed1fa62cb196f7f9
2013-02-02 16:44:46 -05:00
Jeremy Long
9e4b39988f bug fixes and additions
Former-commit-id: 82130e779f30550ce08c7c90503c1cfce21e9b53
2013-02-02 16:44:06 -05:00
Jeremy Long
9a9f03e730 added CWE Names
Former-commit-id: e1d0daf70d7ba49b4667ecc9437c1b8f4efe036b
2013-01-14 22:14:45 -05:00
Jeremy Long
d37ea348bf minor update
Former-commit-id: abf23f47d2bf07f96200cf990a3c3a48179aedf9
2013-01-13 17:05:19 -05:00
Jeremy Long
9478d5aea3 added CWE
Former-commit-id: f47818f88a5fbbd883eb60709dab768f80e20c18
2013-01-13 17:01:46 -05:00
Jeremy Long
c2dbe4c821 fixed analysis phase
Former-commit-id: e28068852192aeba7912e434cde2ec207a679baa
2013-01-13 16:53:28 -05:00
Jeremy Long
41f631d1c0 Added CVSS Scores
Former-commit-id: 2feda15c4f42461b87a2a4e5941a32eb98a918de
2013-01-13 16:48:27 -05:00
Jeremy Long
0080b916ce version 0.2.5.1
Former-commit-id: 7ced778f0f8a749ffca1efd7d3416c4a16c1da26
2013-01-09 22:51:06 -05:00
Jeremy Long
73782493b0 additional spring jar files for testing
Former-commit-id: 95f8858a0b75ff74b4e039948c1848bcd3c1be22
2013-01-09 22:50:11 -05:00
Jeremy Long
bb1e47ae43 fixed analyzer method signature, added SpringCleaningAnalyzer, and removed ArchiveAnalyzer interface
Former-commit-id: 789fcd7a7c463ee2528c9a325a8536f2cc9278c5
2013-01-09 22:49:41 -05:00
Jeremy Long
d1194f23d7 added 2013 NVD CVE file
Former-commit-id: 049b7e8d493d722fb61896fd46067f625e56d79e
2013-01-08 15:40:58 -05:00
Jeremy Long
b9eda7984f added mailing list
Former-commit-id: a4ff51a95343a893e7565814a4a3ce21f19d6a75
2013-01-06 12:38:56 -05:00
40 changed files with 177784 additions and 159 deletions

View File

@@ -7,8 +7,8 @@ If found, it will generate a report linking to the associated CVE entries.
Usage:
$ mvn package
$ cd target
$ java -jar DependencyCheck-0.2.5.0.jar -h
$ java -jar DependencyCheck-0.2.5.0.jar -a Testing -out . -scan ./test-classes/org.mortbay.jetty.jar -scan ./test-classes/struts2-core-2.1.2.jar -scan ./lib
$ java -jar dependency-check-0.2.6.0.jar -h
$ java -jar dependency-check-0.2.6.0.jar -a Testing -out . -scan ./test-classes/org.mortbay.jetty.jar -scan ./test-classes/struts2-core-2.1.2.jar -scan ./lib
Then load the resulting 'DependencyCheck-Report.html' into your favorite browser.

27
pom.xml
View File

@@ -14,16 +14,15 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
along with DependencyCheck. If not, see <http://www.gnu.org/licenses />.
-->
<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">
<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>
<groupId>org.codesecure</groupId>
<artifactId>DependencyCheck</artifactId>
<version>0.2.5.0</version>
<artifactId>dependency-check</artifactId>
<version>0.2.6.0</version>
<packaging>jar</packaging>
<name>DependencyCheck</name>
@@ -50,11 +49,21 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
<connection>scm:git:git@github.com:jeremylong/DependencyCheck.git</connection>
<url>https://github.com/jeremylong/DependencyCheck.git</url>
<developerConnection>scm:git:git@github.com:jeremylong/DependencyCheck.git</developerConnection>
</scm>
<tag>dependency-check-0.2.6.0</tag>
</scm>
<issueManagement>
<system>github</system>
<url>https://github.com/jeremylong/DependencyCheck/issues</url>
</issueManagement>
<mailingLists>
<mailingList>
<name>Dependency Check</name>
<subscribe>dependency-check+subscribe@googlegroups.com</subscribe>
<unsubscribe>dependency-check+unsubscribe@googlegroups.com</unsubscribe>
<post>dependency-check@googlegroups.com</post>
<archive>https://groups.google.com/forum/?fromgroups#!forum/dependency-check</archive>
</mailingList>
</mailingLists>
<licenses>
<license>
<name>GNU General Public License version 3</name>
@@ -101,7 +110,7 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8.1</version>
<configuration>
<bottom>Copyright&#169; 2012 Jeremy Long. All Rights Reserved.</bottom>
<bottom>Copyright© 2012 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
</plugin>
<plugin>
@@ -257,7 +266,7 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
<reportSets>
<reportSet>
<reports>
<!--<report>mailing-list</report>-->
<report>mailing-list</report>
<!--<report>cim</report>-->
<report>index</report>
<report>summary</report>
@@ -463,7 +472,7 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
<!-- The following dependencies are only scanned during integration testing -->
<!--<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<artifactId>spring-webmvc</artifactId>
<version>2.5.5</version>
<scope>test</scope>
</dependency>-->

View File

@@ -19,9 +19,7 @@
package org.codesecure.dependencycheck;
import java.util.EnumMap;
import org.codesecure.dependencycheck.dependency.Dependency;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
@@ -33,10 +31,10 @@ import org.codesecure.dependencycheck.analyzer.AnalysisException;
import org.codesecure.dependencycheck.analyzer.AnalysisPhase;
import org.codesecure.dependencycheck.analyzer.Analyzer;
import org.codesecure.dependencycheck.analyzer.AnalyzerService;
import org.codesecure.dependencycheck.analyzer.ArchiveAnalyzer;
import org.codesecure.dependencycheck.data.CachedWebDataSource;
import org.codesecure.dependencycheck.data.UpdateException;
import org.codesecure.dependencycheck.data.UpdateService;
import org.codesecure.dependencycheck.dependency.Dependency;
import org.codesecure.dependencycheck.utils.FileUtils;
/**
@@ -188,9 +186,9 @@ public class Engine {
* Runs the analyzers against all of the dependencies.
*/
public void analyzeDependencies() {
//phase one initilize
for (AnalysisPhase phase : AnalysisPhase.values()) {
List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
try {
a.initialize();
@@ -204,41 +202,34 @@ public class Engine {
}
continue;
}
}
}
// analysis phases
for (AnalysisPhase phase : AnalysisPhase.values()) {
List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
for (Dependency d : dependencies) {
if (a.supportsExtension(d.getFileExtension())) {
try {
if (a instanceof ArchiveAnalyzer) {
ArchiveAnalyzer aa = (ArchiveAnalyzer) a;
aa.analyze(d, this);
} else {
a.analyze(d);
}
a.analyze(d, this);
} catch (AnalysisException ex) {
d.addAnalysisException(ex);
} catch (IOException ex) {
String msg = String.format("IOException occured while analyzing the file '%s'.",
d.getActualFilePath());
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, msg, ex);
}
}
}
try {
a.close();
} catch (Exception ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//Now cycle through all of the analyzers one last time to call
// cleanup on any archiveanalyzers. These should only exist in the
// initial phase, but we are going to be thourough just in case.
//close/cleanup
for (AnalysisPhase phase : AnalysisPhase.values()) {
List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
if (a instanceof ArchiveAnalyzer) {
ArchiveAnalyzer aa = (ArchiveAnalyzer) a;
aa.cleanup();
try {
a.close();
} catch (Exception ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

View File

@@ -19,6 +19,7 @@
package org.codesecure.dependencycheck.analyzer;
import java.util.Set;
import org.codesecure.dependencycheck.Engine;
import org.codesecure.dependencycheck.dependency.Dependency;
/**
@@ -37,10 +38,12 @@ public interface Analyzer {
* description or license information for the dependency it should be added.
*
* @param dependency a dependency to analyze.
* @param engine the engine that is scanning the dependencies - this is useful
* if we need to check other dependencies
* @throws AnalysisException is thrown if there is an error analyzing the
* dependency file
*/
void analyze(Dependency dependency) throws AnalysisException;
void analyze(Dependency dependency, Engine engine) throws AnalysisException;
/**
* <p>Returns a list of supported file extensions. An example would be an

View File

@@ -1,48 +0,0 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.codesecure.dependencycheck.analyzer;
import org.codesecure.dependencycheck.dependency.Dependency;
import java.io.IOException;
import org.codesecure.dependencycheck.Engine;
/**
* An interface that defines an Analyzer that is used to expand archives and
* allow the engine to scan the contents.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public interface ArchiveAnalyzer {
/**
* An ArchiveAnalyzer expands an archive and calls the scan method of the
* engine on the exploded contents.
*
* @param dependency a dependency to analyze.
* @param engine the engine that is scanning the dependencies.
* @throws IOException is thrown if there is an error reading the dependency
* file
*/
void analyze(Dependency dependency, Engine engine) throws IOException;
/**
* Cleans any temporary files generated when analyzing the archive.
*/
void cleanup();
}

View File

@@ -21,6 +21,7 @@ package org.codesecure.dependencycheck.analyzer;
import org.codesecure.dependencycheck.dependency.Dependency;
import org.codesecure.dependencycheck.dependency.Evidence;
import java.util.Set;
import org.codesecure.dependencycheck.Engine;
/**
*
@@ -85,15 +86,16 @@ public class FileNameAnalyzer implements Analyzer {
* Collects information about the file name.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
public void analyze(Dependency dependency) throws AnalysisException {
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
String fileName = dependency.getFileName();
int pos = fileName.lastIndexOf(".");
if (pos > 0) {
fileName = fileName.substring(0, pos - 1);
fileName = fileName.substring(0, pos);
}
dependency.getProductEvidence().addEvidence("file", "name",

View File

@@ -23,6 +23,7 @@ import java.io.FileInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBException;
import org.codesecure.dependencycheck.Engine;
import org.codesecure.dependencycheck.dependency.Dependency;
import org.codesecure.dependencycheck.dependency.Evidence;
import org.codesecure.dependencycheck.dependency.EvidenceCollection;
@@ -54,7 +55,7 @@ import org.codesecure.dependencycheck.utils.NonClosingStream;
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class JarAnalyzer extends AbstractAnalyzer {
public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
/**
* The system independent newline character.
@@ -67,7 +68,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* A list of elements in the manifest to ignore.
*/
@@ -178,10 +179,11 @@ public class JarAnalyzer extends AbstractAnalyzer {
* checksums to identify the correct CPE information.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
public void analyze(Dependency dependency) throws AnalysisException {
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
try {
parseManifest(dependency);
analyzePackageNames(dependency);
@@ -646,13 +648,21 @@ public class JarAnalyzer extends AbstractAnalyzer {
}
private void addPredefinedData(Dependency dependency) {
Evidence spring = new Evidence("Manifest",
Evidence springTest1 = new Evidence("Manifest",
"Implementation-Title",
"Spring Framework",
Evidence.Confidence.HIGH);
if (dependency.getProductEvidence().getEvidence().contains(spring)) {
Evidence springTest2 = new Evidence("Manifest",
"Implementation-Title",
"org.springframework.core",
Evidence.Confidence.HIGH);
Set<Evidence> evidence = dependency.getProductEvidence().getEvidence();
if (evidence.contains(springTest1) || evidence.contains(springTest2)) {
dependency.getProductEvidence().addEvidence("a priori", "product", "springsource_spring_framework", Evidence.Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("a priori", "vendor", "SpringSource", Evidence.Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("a priori", "vendor", "vmware", Evidence.Confidence.HIGH);
}
}
}

View File

@@ -0,0 +1,159 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.codesecure.dependencycheck.analyzer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.codesecure.dependencycheck.Engine;
import org.codesecure.dependencycheck.dependency.Dependency;
import org.codesecure.dependencycheck.dependency.Identifier;
/**
* This analyzer ensures that the Spring Framework Core CPE identifiers are only associated
* with the "core" jar files. If there are other Spring JARs, such as spring-beans, and
* spring-core is in the scanned dependencies then only the spring-core will have a reference
* to the CPE values (if there are any for the version of spring being used).
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class SpringCleaningAnalyzer extends AbstractAnalyzer {
/**
* The set of file extensions supported by this analyzer.
*/
private static final Set<String> EXTENSIONS = newHashSet("jar");
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Jar Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
/**
* Returns a list of file EXTENSIONS supported by this analyzer.
*
* @return a list of file EXTENSIONS supported by this analyzer.
*/
public Set<String> getSupportedExtensions() {
return EXTENSIONS;
}
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns whether or not this analyzer can process the given extension.
*
* @param extension the file extension to test for support.
* @return whether or not the specified file extension is supported by tihs
* analyzer.
*/
public boolean supportsExtension(String extension) {
return EXTENSIONS.contains(extension);
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* The initialize method does nothing for this Analyzer
* @throws Exception never thrown by this analyzer
*/
public void initialize() throws Exception {
//do nothing
}
/**
* The close method does nothing for this Analyzer
* @throws Exception never thrown by this analyzer
*/
public void close() throws Exception {
//do nothing
}
private List<Identifier> springVersions = null;
/**
* Determines if several "spring" libraries were scanned and trimes the
* cpe:/a:springsource:spring_framework:[version] from the none "core" framework
* if the core framework was part of the scan.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
collectSpringFrameworkIdentifiers(engine);
List<Identifier> identifiersToRemove = new ArrayList<Identifier>();
for (Identifier identifier : dependency.getIdentifiers()) {
if (springVersions.contains(identifier) && !isCoreFramework(dependency.getFileName())) {
identifiersToRemove.add(identifier);
}
}
for (Identifier i : identifiersToRemove) {
dependency.getIdentifiers().remove(i);
}
}
private void collectSpringFrameworkIdentifiers(Engine engine) {
//check to see if any of the libs are the core framework
if (springVersions == null) {
springVersions = new ArrayList<Identifier>();
for (Dependency d : engine.getDependencies()) {
if (supportsExtension(d.getFileExtension())) {
for (Identifier i : d.getIdentifiers()) {
if (isSpringFrameworkCpe(i)) {
if (isCoreFramework(d.getFileName())) {
springVersions.add(i);
}
}
}
}
}
}
}
private boolean isSpringFrameworkCpe(Identifier identifier) {
return "cpe".equals(identifier.getType())
&& (identifier.getValue().startsWith("cpe:/a:springsource:spring_framework:")
|| identifier.getValue().startsWith("cpe:/a:vmware:springsource_spring_framework"));
}
private boolean isCoreFramework(String filename) {
return filename.toLowerCase().matches("^spring([ _-]?core)?[ _-]?\\d.*");
}
}

View File

@@ -29,6 +29,7 @@ import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.codesecure.dependencycheck.Engine;
import org.codesecure.dependencycheck.analyzer.AnalysisException;
import org.codesecure.dependencycheck.analyzer.AnalysisPhase;
import org.codesecure.dependencycheck.data.lucene.LuceneUtils;
@@ -143,7 +144,6 @@ public class CPEAnalyzer implements org.codesecure.dependencycheck.analyzer.Anal
for (Entry e : entries) {
if (verifyEntry(e, dependency)) {
found = true;
dependency.addIdentifier(
"cpe",
e.getName(),
@@ -420,26 +420,34 @@ public class CPEAnalyzer implements org.codesecure.dependencycheck.analyzer.Anal
*/
private boolean verifyEntry(final Entry entry, final Dependency dependency) {
boolean isValid = false;
if (dependency.getProductEvidence().containsUsedString(entry.getProduct())
&& dependency.getVendorEvidence().containsUsedString(entry.getVendor())) {
//TODO - determine if this is right? Should we be carrying too much about the
// version at this point? Likely need to implement the versionAnalyzer....
if (dependency.getVersionEvidence().containsUsedString(entry.getVersion())) {
isValid = true;
}
if (collectionContainsStrings(dependency.getProductEvidence(), entry.getProduct())
&& collectionContainsStrings(dependency.getVendorEvidence(), entry.getVendor())
&& collectionContainsStrings(dependency.getVersionEvidence(), entry.getVersion())) {
isValid = true;
}
return isValid;
}
private boolean collectionContainsStrings(EvidenceCollection ec, String text) {
String[] words = text.split("[\\s_-]");
boolean contains = true;
for (String word : words) {
contains &= ec.containsUsedString(word);
}
return contains;
}
/**
* Analyzes a dependency and attempts to determine if there are any CPE
* identifiers for this dependency.
*
* @param dependency The Dependency to analyze.
* @param engine The analysis engine
* @throws AnalysisException is thrown if there is an issue analyzing the
* dependency.
*/
public void analyze(Dependency dependency) throws AnalysisException {
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
try {
determineCPE(dependency);
} catch (CorruptIndexException ex) {

View File

@@ -40,6 +40,8 @@ import org.codesecure.dependencycheck.data.lucene.AbstractIndex;
import org.codesecure.dependencycheck.utils.Settings;
import org.codesecure.dependencycheck.data.lucene.FieldAnalyzer;
import org.codesecure.dependencycheck.data.lucene.SearchFieldAnalyzer;
import org.codesecure.dependencycheck.data.lucene.SearchVersionAnalyzer;
import org.codesecure.dependencycheck.data.lucene.VersionAnalyzer;
/**
* The Index class is used to utilize and maintain the CPE Index.
@@ -97,7 +99,8 @@ public class Index extends AbstractIndex {
public Analyzer createIndexingAnalyzer() {
Map fieldAnalyzers = new HashMap();
fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
//fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
fieldAnalyzers.put(Fields.VERSION, new VersionAnalyzer(Version.LUCENE_40));
fieldAnalyzers.put(Fields.NAME, new KeywordAnalyzer());
PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(
@@ -117,8 +120,9 @@ public class Index extends AbstractIndex {
public Analyzer createSearchingAnalyzer() {
Map fieldAnalyzers = new HashMap();
fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
fieldAnalyzers.put(Fields.NAME, new KeywordAnalyzer());
//fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
fieldAnalyzers.put(Fields.VERSION, new SearchVersionAnalyzer(Version.LUCENE_40));
productSearchFieldAnalyzer = new SearchFieldAnalyzer(Version.LUCENE_40);
vendorSearchFieldAnalyzer = new SearchFieldAnalyzer(Version.LUCENE_40);
fieldAnalyzers.put(Fields.PRODUCT, productSearchFieldAnalyzer);

View File

@@ -0,0 +1,75 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.codesecure.dependencycheck.data.cwe;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class CweDB {
private CweDB() {
//empty contructor for utility class
}
private static final HashMap<String, String> CWE = loadData();
private static HashMap<String, String> loadData() {
ObjectInputStream oin = null;
try {
String filePath = "data/cwe.hashmap.serialized";
InputStream input = CweDB.class.getClassLoader().getResourceAsStream(filePath);
oin = new ObjectInputStream(input);
@SuppressWarnings("unchecked")
HashMap<String, String> data = (HashMap<String, String>) oin.readObject();
return data;
} catch (ClassNotFoundException ex) {
Logger.getLogger(CweDB.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(CweDB.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (oin != null) {
try {
oin.close();
} catch (IOException ex) {
Logger.getLogger(CweDB.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
return null;
}
/**
* <p>Returns the full CWE name from the CWE ID.</p>
* @param cweId te CWE ID
* @return the full name of the CWE
*/
public static String getCweName(String cweId) {
if (cweId != null) {
return CWE.get(cweId);
}
return null;
}
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.codesecure.dependencycheck.data.cwe;
import java.util.HashMap;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* A SAX Handler that will parse the CWE XML.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class CweHandler extends DefaultHandler {
private HashMap<String, String> cwe = new HashMap<String, String>();
/**
* Returns the HashMap of CWE entries (CWE-ID, Full CWE Name).
* @return a HashMap of CWE entries <String, String>
*/
public HashMap<String, String> getCwe() {
return cwe;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("Weakness".equals(qName) || "Category".equals(qName)) {
String id = "CWE-" + attributes.getValue("ID");
String name = attributes.getValue("Name");
cwe.put(id, name);
}
}
}

View File

@@ -0,0 +1,12 @@
/**
* <html>
* <head>
* <title>org.codesecure.dependencycheck.data.cwe</title>
* </head>
* <body>
* Contains classes for working with the CWE Database.
* </body>
* </html>
*/
package org.codesecure.dependencycheck.data.cwe;

View File

@@ -0,0 +1,70 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.codesecure.dependencycheck.data.lucene;
import java.io.Reader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.core.LowerCaseFilter;
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
import org.apache.lucene.util.Version;
/**
* SearchVersionAnalyzer is a Lucene Analyzer used to analyze version information.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class SearchVersionAnalyzer extends Analyzer {
//TODO consider implementing payloads/custom attributes...
// use custom attributes for major, minor, x, x, x, rcx
// these can then be used to weight the score for searches on the version.
// see http://lucene.apache.org/core/3_6_1/api/core/org/apache/lucene/analysis/package-summary.html#package_description
// look at this article to implement
// http://www.codewrecks.com/blog/index.php/2012/08/25/index-your-blog-using-tags-and-lucene-net/
/**
* The Lucene Version used
*/
private Version version = null;
/**
* Creates a new SearchVersionAnalyzer
* @param version the Lucene version
*/
public SearchVersionAnalyzer(Version version) {
this.version = version;
}
/**
* Creates the TokenStreamComponents
*
* @param fieldName the field name being analyzed
* @param reader the reader containing the input
* @return the TokenStreamComponents
*/
@Override
protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
Tokenizer source = new WhitespaceTokenizer(version, reader);
TokenStream stream = source;
stream = new LowerCaseFilter(version, stream);
stream = new VersionTokenizingFilter(stream);
return new TokenStreamComponents(source, stream);
}
}

View File

@@ -18,16 +18,52 @@
*/
package org.codesecure.dependencycheck.data.lucene;
import java.io.Reader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.core.LowerCaseFilter;
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
import org.apache.lucene.util.Version;
/**
* VersionAnalyzer is a Lucene Analyzer used to analyze version information.
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class VersionAnalyzer {
//TODO Implement this...
public class VersionAnalyzer extends Analyzer {
//TODO consider implementing payloads/custom attributes...
// use custom attributes for major, minor, x, x, x, rcx
// these can then be used to weight the score for searches on the version.
// see http://lucene.apache.org/core/3_6_1/api/core/org/apache/lucene/analysis/package-summary.html#package_description
// look at this article to implement
// http://www.codewrecks.com/blog/index.php/2012/08/25/index-your-blog-using-tags-and-lucene-net/
/**
* The Lucene Version used
*/
private Version version = null;
/**
* Creates a new VersionAnalyzer
* @param version the Lucene version
*/
public VersionAnalyzer(Version version) {
this.version = version;
}
/**
* Creates the TokenStreamComponents
*
* @param fieldName the field name being analyzed
* @param reader the reader containing the input
* @return the TokenStreamComponents
*/
@Override
protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
Tokenizer source = new WhitespaceTokenizer(version, reader);
TokenStream stream = source;
stream = new LowerCaseFilter(version, stream);
return new TokenStreamComponents(source, stream);
}
}

View File

@@ -0,0 +1,100 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.codesecure.dependencycheck.data.lucene;
import java.io.IOException;
import java.util.LinkedList;
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
/**
* <p>Takes a TokenStream and splits or adds tokens to correctly index version numbers.</p>
* <p><b>Example:</b> "3.0.0.RELEASE" -> "3 3.0 3.0.0 RELEASE 3.0.0.RELEASE".</p>
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public final class VersionTokenizingFilter extends TokenFilter {
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
/**
* A collection of tokens to add to the stream.
*/
protected LinkedList<String> tokens = null;
/**
* Consructs a new VersionTokenizingFilter
* @param stream the TokenStream that this filter will process
*/
public VersionTokenizingFilter(TokenStream stream) {
super(stream);
tokens = new LinkedList<String>();
}
/**
* Increments the underlying TokenStream and sets CharTermAtttributes to
* construct an expanded set of tokens by concatenting tokens with the
* previous token.
*
* @return whether or not we have hit the end of the TokenStream
* @throws IOException is thrown when an IOException occurs
*/
@Override
public boolean incrementToken() throws IOException {
if (tokens.size() == 0 && input.incrementToken()) {
String version = new String(termAtt.buffer(), 0, termAtt.length());
analyzeVersion(version);
}
return addTerm();
}
/**
* Adds a term, if one exists, from the tokens collection..
* @return
*/
private boolean addTerm() {
boolean termAdded = tokens.size() > 0;
if (termAdded) {
String version = tokens.pop();
clearAttributes();
termAtt.append(version);
}
return termAdded;
}
//major.minor[.maintenance[.build]]
private void analyzeVersion(String version) {
//todo should we also be splitting on dash or underscore? we would need
// to incorporate the dash or underscore back in...
String[] versionParts = version.split("\\.");
String dottedVersion = null;
for (int x = 0; x < versionParts.length; x++) {
String current = versionParts[x];
if (!current.matches("^/d+$")) {
tokens.add(current);
}
if (dottedVersion == null) {
dottedVersion = current;
} else {
dottedVersion = dottedVersion + "." + current;
}
tokens.add(dottedVersion);
}
}
}

View File

@@ -33,6 +33,7 @@ import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codesecure.dependencycheck.data.cpe.Entry;
import org.codesecure.dependencycheck.data.cwe.CweDB;
import org.codesecure.dependencycheck.dependency.Reference;
import org.codesecure.dependencycheck.dependency.Vulnerability;
import org.codesecure.dependencycheck.dependency.VulnerableSoftware;
@@ -46,7 +47,6 @@ import org.codesecure.dependencycheck.utils.Settings;
public class CveDB {
//<editor-fold defaultstate="collapsed" desc="Constants to create, maintain, and retrieve data from the CVE Database">
/**
* SQL Statement to create an index on the reference table
*/
@@ -76,8 +76,10 @@ public class CveDB {
/**
* SQL Statement to create the vulnerability table
*/
public static final String CREATE_TABLE_VULNERABILITY = "CREATE TABLE IF NOT EXISTS vulnerability "
+ "(cveid CHAR(13) PRIMARY KEY, description varchar(8000))";
public static final String CREATE_TABLE_VULNERABILITY = "CREATE TABLE IF NOT EXISTS vulnerability (cveid CHAR(13) PRIMARY KEY, "
+ "description varchar(8000), cwe varchar(10), cvssScore DECIMAL(3,1), cvssAccessVector varchar(20), "
+ "cvssAccessComplexity varchar(20), cvssAuthentication varchar(20), cvssConfidentialityImpact varchar(20), "
+ "cvssIntegrityImpact varchar(20), cvssAvailabilityImpact varchar(20))";
/**
* SQL Statement to delete references by CVEID
*/
@@ -102,7 +104,9 @@ public class CveDB {
/**
* SQL Statement to insert a new vulnerability
*/
public static final String INSERT_VULNERABILITY = "INSERT INTO vulnerability (cveid, description) VALUES (?, ?)";
public static final String INSERT_VULNERABILITY = "INSERT INTO vulnerability (cveid, description, cwe, cvssScore, cvssAccessVector, "
+ "cvssAccessComplexity, cvssAuthentication, cvssConfidentialityImpact, cvssIntegrityImpact, cvssAvailabilityImpact) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
/**
* SQL Statement to find CVE entries based on CPE data
*/
@@ -119,9 +123,9 @@ public class CveDB {
/**
* SQL Statement to select a vulnerability by CVEID
*/
public static final String SELECT_VULNERABILITY = "SELECT cveid, description FROM vulnerability WHERE cveid = ?";
public static final String SELECT_VULNERABILITY = "SELECT cveid, description, cwe, cvssScore, cvssAccessVector, cvssAccessComplexity, "
+ "cvssAuthentication, cvssConfidentialityImpact, cvssIntegrityImpact, cvssAvailabilityImpact FROM vulnerability WHERE cveid = ?";
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Collection of CallableStatements to work with the DB">
/**
* delete reference - parameters (cveid)
@@ -144,7 +148,8 @@ public class CveDB {
*/
private CallableStatement insertSoftware = null;
/**
* insert vulnerability - parameters (cveid, description)
* insert vulnerability - parameters (cveid, description, cwe, cvssScore, cvssAccessVector,
* cvssAccessComplexity, cvssAuthentication, cvssConfidentialityImpact, cvssIntegrityImpact, cvssAvailabilityImpact)
*/
private CallableStatement insertVulnerability = null;
/**
@@ -164,7 +169,6 @@ public class CveDB {
*/
private CallableStatement selectSoftware = null;
//</editor-fold>
/**
* Database connection
*/
@@ -269,6 +273,22 @@ public class CveDB {
vuln = new Vulnerability();
vuln.setName(cve);
vuln.setDescription(rsV.getString(2));
String cwe = rsV.getString(3);
if (cwe != null) {
String name = CweDB.getCweName(cwe);
if (name != null) {
cwe += " " + name;
}
}
vuln.setCwe(cwe);
vuln.setCvssScore(rsV.getFloat(4));
vuln.setCvssAccessVector(rsV.getString(5));
vuln.setCvssAccessComplexity(rsV.getString(6));
vuln.setCvssAuthentication(rsV.getString(7));
vuln.setCvssConfidentialityImpact(rsV.getString(8));
vuln.setCvssIntegrityImpact(rsV.getString(9));
vuln.setCvssAvailabilityImpact(rsV.getString(10));
selectReferences.setString(1, cve);
rsR = selectReferences.executeQuery();
while (rsR.next()) {
@@ -333,6 +353,14 @@ public class CveDB {
insertVulnerability.setString(1, vuln.getName());
insertVulnerability.setString(2, vuln.getDescription());
insertVulnerability.setString(3, vuln.getCwe());
insertVulnerability.setFloat(4, vuln.getCvssScore());
insertVulnerability.setString(5, vuln.getCvssAccessVector());
insertVulnerability.setString(6, vuln.getCvssAccessComplexity());
insertVulnerability.setString(7, vuln.getCvssAuthentication());
insertVulnerability.setString(8, vuln.getCvssConfidentialityImpact());
insertVulnerability.setString(9, vuln.getCvssIntegrityImpact());
insertVulnerability.setString(10, vuln.getCvssAvailabilityImpact());
insertVulnerability.execute();
insertReference.setString(1, vuln.getName());

View File

@@ -22,6 +22,7 @@ import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.codesecure.dependencycheck.Engine;
import org.codesecure.dependencycheck.analyzer.AnalysisException;
import org.codesecure.dependencycheck.analyzer.AnalysisPhase;
import org.codesecure.dependencycheck.dependency.Dependency;
@@ -92,11 +93,12 @@ public class NvdCveAnalyzer implements org.codesecure.dependencycheck.analyzer.A
* Analyzes a dependency and attempts to determine if there are any CPE
* identifiers for this dependency.
*
* @param dependency The Dependency to analyze.
* @param dependency The Dependency to analyze
* @param engine The analysis engine
* @throws AnalysisException is thrown if there is an issue analyzing the
* dependency.
* dependency
*/
public void analyze(Dependency dependency) throws AnalysisException {
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
for (Identifier id : dependency.getIdentifiers()) {
if ("cpe".equals(id.getType())) {
try {

View File

@@ -77,7 +77,7 @@ public class DatabaseUpdater implements CachedWebDataSource {
/**
* The current version of the database
*/
public static final String DATABASE_VERSION = "2.0";
public static final String DATABASE_VERSION = "2.2";
/**
* <p>Downloads the latest NVD CVE XML file from the web and imports it into

View File

@@ -21,6 +21,8 @@ package org.codesecure.dependencycheck.data.nvdcve.xml;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.lucene.index.CorruptIndexException;
import org.codesecure.dependencycheck.data.cpe.Index;
import org.codesecure.dependencycheck.data.nvdcve.CveDB;
@@ -75,6 +77,22 @@ public class NvdCve20Handler extends DefaultHandler {
if (!CURRENT_SCHEMA_VERSION.equals(nvdVer)) {
throw new SAXNotSupportedException("Schema version " + nvdVer + " is not supported");
}
} else if (current.isVulnCWENode()) {
vulnerability.setCwe(attributes.getValue("id"));
} else if (current.isCVSSScoreNode()) {
nodeText = new StringBuilder(5);
} else if (current.isCVSSAccessVectorNode()) {
nodeText = new StringBuilder(20);
} else if (current.isCVSSAccessComplexityNode()) {
nodeText = new StringBuilder(20);
} else if (current.isCVSSAuthenticationNode()) {
nodeText = new StringBuilder(20);
} else if (current.isCVSSAvailabilityImpactNode()) {
nodeText = new StringBuilder(20);
} else if (current.isCVSSConfidentialityImpactNode()) {
nodeText = new StringBuilder(20);
} else if (current.isCVSSIntegrityImpactNode()) {
nodeText = new StringBuilder(20);
}
}
@@ -101,6 +119,32 @@ public class NvdCve20Handler extends DefaultHandler {
}
}
vulnerability = null;
} else if (current.isCVSSScoreNode()) {
try {
float score = Float.parseFloat(nodeText.toString());
vulnerability.setCvssScore(score);
} catch (NumberFormatException ex) {
Logger.getLogger(NvdCve20Handler.class.getName()).log(Level.SEVERE, null, ex);
}
nodeText = null;
} else if (current.isCVSSAccessVectorNode()) {
vulnerability.setCvssAccessVector(nodeText.toString());
nodeText = null;
} else if (current.isCVSSAccessComplexityNode()) {
vulnerability.setCvssAccessComplexity(nodeText.toString());
nodeText = null;
} else if (current.isCVSSAuthenticationNode()) {
vulnerability.setCvssAuthentication(nodeText.toString());
nodeText = null;
} else if (current.isCVSSAvailabilityImpactNode()) {
vulnerability.setCvssAvailabilityImpact(nodeText.toString());
nodeText = null;
} else if (current.isCVSSConfidentialityImpactNode()) {
vulnerability.setCvssConfidentialityImpact(nodeText.toString());
nodeText = null;
} else if (current.isCVSSIntegrityImpactNode()) {
vulnerability.setCvssIntegrityImpact(nodeText.toString());
nodeText = null;
} else if (current.isVulnProductNode()) {
String cpe = nodeText.toString();
if (cpe.startsWith("cpe:/a:")) {
@@ -217,6 +261,40 @@ public class NvdCve20Handler extends DefaultHandler {
* A node type in the NVD CVE Schema 2.0
*/
public static final String VULN_SUMMARY = "vuln:summary";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String VULN_CWE = "vuln:cwe";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String CVSS_SCORE = "cvss:score";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String CVSS_ACCESS_VECTOR = "cvss:access-vector";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String CVSS_ACCESS_COMPLEXITY = "cvss:access-complexity";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String CVSS_AUTHENTICATION = "cvss:authentication";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String CVSS_CONFIDENTIALITY_IMPACT = "cvss:confidentiality-impact";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String CVSS_INTEGRITY_IMPACT = "cvss:integrity-impact";
/**
* A node type in the NVD CVE Schema 2.0
*/
public static final String CVSS_AVAILABILITY_IMPACT = "cvss:availability-impact";
private String node = null;
/**
@@ -299,6 +377,72 @@ public class NvdCve20Handler extends DefaultHandler {
public boolean isVulnSummaryNode() {
return VULN_SUMMARY.equals(node);
}
/**
* Checks if the handler is at the VULN_CWE node
*
* @return true or false
*/
public boolean isVulnCWENode() {
return VULN_CWE.equals(node);
}
/**
* Checks if the handler is at the CVSS_SCORE node
*
* @return true or false
*/
public boolean isCVSSScoreNode() {
return CVSS_SCORE.equals(node);
}
/**
* Checks if the handler is at the CVSS_ACCESS_VECTOR node
*
* @return true or false
*/
public boolean isCVSSAccessVectorNode() {
return CVSS_ACCESS_VECTOR.equals(node);
}
/**
* Checks if the handler is at the CVSS_ACCESS_COMPLEXITY node
*
* @return true or false
*/
public boolean isCVSSAccessComplexityNode() {
return CVSS_ACCESS_COMPLEXITY.equals(node);
}
/**
* Checks if the handler is at the CVSS_AUTHENTICATION node
*
* @return true or false
*/
public boolean isCVSSAuthenticationNode() {
return CVSS_AUTHENTICATION.equals(node);
}
/**
* Checks if the handler is at the CVSS_CONFIDENTIALITY_IMPACT node
*
* @return true or false
*/
public boolean isCVSSConfidentialityImpactNode() {
return CVSS_CONFIDENTIALITY_IMPACT.equals(node);
}
/**
* Checks if the handler is at the CVSS_INTEGRITY_IMPACT node
*
* @return true or false
*/
public boolean isCVSSIntegrityImpactNode() {
return CVSS_INTEGRITY_IMPACT.equals(node);
}
/**
* Checks if the handler is at the CVSS_AVAILABILITY_IMPACT node
*
* @return true or false
*/
public boolean isCVSSAvailabilityImpactNode() {
return CVSS_AVAILABILITY_IMPACT.equals(node);
}
}
// </editor-fold>
}

View File

@@ -23,6 +23,9 @@ import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codesecure.dependencycheck.utils.Checksum;
@@ -87,7 +90,7 @@ public class Dependency {
productEvidence = new EvidenceCollection();
versionEvidence = new EvidenceCollection();
identifiers = new ArrayList<Identifier>();
vulnerabilities = new ArrayList<Vulnerability>();
vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
}
/**
@@ -366,7 +369,8 @@ public class Dependency {
}
/**
* Determines if the specified string was used when searching.
* Determines if the specified string was used when searching. This is
* currently only used in test.
*
* @param str is the string that is being checked if it was used.
* @return true or false.
@@ -390,14 +394,14 @@ public class Dependency {
/**
* A list of vulnerabilities for this dependency
*/
private List<Vulnerability> vulnerabilities;
private SortedSet<Vulnerability> vulnerabilities;
/**
* Get the list of vulnerabilities
*
* @return the list of vulnerabilities
*/
public List<Vulnerability> getVulnerabilities() {
public Set<Vulnerability> getVulnerabilities() {
return vulnerabilities;
}
@@ -406,7 +410,7 @@ public class Dependency {
*
* @param vulnerabilities new value of vulnerabilities
*/
public void setVulnerabilities(List<Vulnerability> vulnerabilities) {
public void setVulnerabilities(SortedSet<Vulnerability> vulnerabilities) {
this.vulnerabilities = vulnerabilities;
}

View File

@@ -138,4 +138,31 @@ public class Identifier {
public void setDescription(String description) {
this.description = description;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Identifier other = (Identifier) obj;
if ((this.value == null) ? (other.value != null) : !this.value.equals(other.value)) {
return false;
}
if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 53 * hash + (this.value != null ? this.value.hashCode() : 0);
hash = 53 * hash + (this.type != null ? this.type.hashCode() : 0);
return hash;
}
}

View File

@@ -27,7 +27,7 @@ import java.util.Set;
*
* @author Jeremy
*/
public class Vulnerability implements Serializable {
public class Vulnerability implements Serializable, Comparable<Vulnerability> {
private static final long serialVersionUID = 307319490326651052L;
/**
@@ -142,7 +142,6 @@ public class Vulnerability implements Serializable {
this.vulnerableSoftware = vulnerableSoftware;
}
/**
* Adds an entry for vulnerable software
* @param cpe string representation of a CPE entry
@@ -178,6 +177,182 @@ public class Vulnerability implements Serializable {
}
return vulnerableSoftware.add(vulnSoftware);
}
/**
* The CWE for the vulnerability
*/
protected String cwe;
/**
* Get the value of cwe
*
* @return the value of cwe
*/
public String getCwe() {
return cwe;
}
/**
* Set the value of cwe
*
* @param cwe new value of cwe
*/
public void setCwe(String cwe) {
this.cwe = cwe;
}
/**
* CVSS Score
*/
protected float cvssScore;
/**
* Get the value of cvssScore
*
* @return the value of cvssScore
*/
public float getCvssScore() {
return cvssScore;
}
/**
* Set the value of cvssScore
*
* @param cvssScore new value of cvssScore
*/
public void setCvssScore(float cvssScore) {
this.cvssScore = cvssScore;
}
/**
* CVSS Access Vector
*/
protected String cvssAccessVector;
/**
* Get the value of cvssAccessVector
*
* @return the value of cvssAccessVector
*/
public String getCvssAccessVector() {
return cvssAccessVector;
}
/**
* Set the value of cvssAccessVector
*
* @param cvssAccessVector new value of cvssAccessVector
*/
public void setCvssAccessVector(String cvssAccessVector) {
this.cvssAccessVector = cvssAccessVector;
}
/**
* CVSS Access Complexity
*/
protected String cvssAccessComplexity;
/**
* Get the value of cvssAccessComplexity
*
* @return the value of cvssAccessComplexity
*/
public String getCvssAccessComplexity() {
return cvssAccessComplexity;
}
/**
* Set the value of cvssAccessComplexity
*
* @param cvssAccessComplexity new value of cvssAccessComplexity
*/
public void setCvssAccessComplexity(String cvssAccessComplexity) {
this.cvssAccessComplexity = cvssAccessComplexity;
}
/**
* CVSS Authentication
*/
protected String cvssAuthentication;
/**
* Get the value of cvssAuthentication
*
* @return the value of cvssAuthentication
*/
public String getCvssAuthentication() {
return cvssAuthentication;
}
/**
* Set the value of cvssAuthentication
*
* @param cvssAuthentication new value of cvssAuthentication
*/
public void setCvssAuthentication(String cvssAuthentication) {
this.cvssAuthentication = cvssAuthentication;
}
/**
* CVSS Confidentiality Impact
*/
protected String cvssConfidentialityImpact;
/**
* Get the value of cvssConfidentialityImpact
*
* @return the value of cvssConfidentialityImpact
*/
public String getCvssConfidentialityImpact() {
return cvssConfidentialityImpact;
}
/**
* Set the value of cvssConfidentialityImpact
*
* @param cvssConfidentialityImpact new value of cvssConfidentialityImpact
*/
public void setCvssConfidentialityImpact(String cvssConfidentialityImpact) {
this.cvssConfidentialityImpact = cvssConfidentialityImpact;
}
/**
* CVSS Integrity Impact
*/
protected String cvssIntegrityImpact;
/**
* Get the value of cvssIntegrityImpact
*
* @return the value of cvssIntegrityImpact
*/
public String getCvssIntegrityImpact() {
return cvssIntegrityImpact;
}
/**
* Set the value of cvssIntegrityImpact
*
* @param cvssIntegrityImpact new value of cvssIntegrityImpact
*/
public void setCvssIntegrityImpact(String cvssIntegrityImpact) {
this.cvssIntegrityImpact = cvssIntegrityImpact;
}
/**
* CVSS Availability Impact
*/
protected String cvssAvailabilityImpact;
/**
* Get the value of cvssAvailabilityImpact
*
* @return the value of cvssAvailabilityImpact
*/
public String getCvssAvailabilityImpact() {
return cvssAvailabilityImpact;
}
/**
* Set the value of cvssAvailabilityImpact
*
* @param cvssAvailabilityImpact new value of cvssAvailabilityImpact
*/
public void setCvssAvailabilityImpact(String cvssAvailabilityImpact) {
this.cvssAvailabilityImpact = cvssAvailabilityImpact;
}
@Override
public boolean equals(Object obj) {
@@ -200,4 +375,13 @@ public class Vulnerability implements Serializable {
hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0);
return hash;
}
/**
* Compares two vulnerabilities
*
* @param v a vulnerabilitiy to be compared
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified vulnerability
*/
public int compareTo(Vulnerability v) {
return v.getName().compareTo(this.getName());
}
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of DependencyCheck.
*
* DependencyCheck is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* DependencyCheck is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* DependencyCheck. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.codesecure.dependencycheck.dependency;
import java.io.Serializable;
import java.util.Comparator;
/**
* Comparator for Vulnerability objects.
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class VulnerabilityComparator implements Comparator<Vulnerability>, Serializable {
private static final long serialVersionUID = 1L;
/**
* Implements the comparison of vulnerabilities.
* @param o1 a vulnerability
* @param o2 a second vulnerability
* @return the comparison
*/
public int compare(Vulnerability o1, Vulnerability o2) {
return o2.getName().compareTo(o1.getName());
}
}

View File

@@ -1,4 +1,5 @@
org.codesecure.dependencycheck.analyzer.JarAnalyzer
org.codesecure.dependencycheck.analyzer.FileNameAnalyzer
org.codesecure.dependencycheck.analyzer.SpringCleaningAnalyzer
org.codesecure.dependencycheck.data.cpe.CPEAnalyzer
org.codesecure.dependencycheck.data.nvdcve.NvdCveAnalyzer

View File

@@ -22,7 +22,7 @@ cve.url-2.0.modified=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modifie
# holds 8 days of updates, we are using 7 just to be safe.
cve.url.modified.validfordays=7
# the number of cve.urls
cve.url.count=11
cve.url.count=12
# the paths to the various nvd cve files (schema version 2.0)
cve.url-2.0.1=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2002.xml
cve.url-2.0.2=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2003.xml
@@ -35,6 +35,7 @@ cve.url-2.0.8=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2009.xml
cve.url-2.0.9=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2010.xml
cve.url-2.0.10=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2011.xml
cve.url-2.0.11=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2012.xml
cve.url-2.0.12=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2013.xml
# the paths to the various nvd cve files (schema version 1.2).
cve.url-1.2.modified=http://nvd.nist.gov/download/nvdcve-modified.xml
@@ -48,4 +49,5 @@ cve.url-1.2.7=http://nvd.nist.gov/download/nvdcve-2008.xml
cve.url-1.2.8=http://nvd.nist.gov/download/nvdcve-2009.xml
cve.url-1.2.9=http://nvd.nist.gov/download/nvdcve-2010.xml
cve.url-1.2.10=http://nvd.nist.gov/download/nvdcve-2011.xml
cve.url-1.2.11=http://nvd.nist.gov/download/nvdcve-2012.xml
cve.url-1.2.11=http://nvd.nist.gov/download/nvdcve-2012.xml
cve.url-1.2.12=http://nvd.nist.gov/download/nvdcve-2013.xml

Binary file not shown.

View File

@@ -48,12 +48,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
$(header).addClass("expandablesubsection");
$(header).removeClass("collaspablesubsection");
}
});
});
</script>
<style type="text/css">
.rounded-corners {
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
@@ -81,7 +81,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
/*background-image: url(img/minus.gif);*/
background-image: url(data:image/gif;base64,R0lGODlhDAAMAIABAICAgP///yH5BAEAAAEALAAAAAAMAAwAAAIajI8Hy22Q1IszQHphW3ZuXUUZ1ZXi8zFkUgAAOw==);
background-repeat: no-repeat;
background-position: 98% 50%;
background-position: 98% 50%;
-moz-border-radius-bottomleft:0px; /* bottom left corner */
-webkit-border-bottom-left-radius:0px; /* bottom left corner */
border-bottom-left-radius: 0px;
@@ -93,7 +93,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
border-bottom-left-radius: 0px;
border-bottom: 0px solid #ffffff;
}
.content {
margin-top:0px;
margin-left:20px;
@@ -102,7 +102,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
background: #ffffff;
padding: 20px;
}
.sectionheader {
background-color: #cccccc;
margin-top: 20px;
@@ -148,12 +148,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
margin-right:20px;
margin-bottom:10px;
background: #ffffff;
padding-top: 10px;
padding-bottom: 20px;
padding-left:20px;
padding-right:20px;
border-top: 0px;
border-right: 1px solid #ccc;
border-left: 1px solid #ccc;
@@ -175,7 +175,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
border-bottom-right-radius: 15px;
border-bottom-left-radius: 15px;
}
.subsectionheader {
background-color: #cccccc;
margin-top: 20px;
@@ -285,20 +285,24 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<div class="sectioncontent">Report Generated On: $date<br/><br/>
Dependencies Scanned:&nbsp;$dependencies.size()<br/><br/>
<div class="indent">
#set($lnkcnt=0)
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
#if($dependency.getVulnerabilities().size()>0)
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a>&nbsp;<b style="color:#ff0000;">&#8226;</b><br/>
<a href="#l${lnkcnt}_$esc.html($esc.url($dependency.Sha1sum))">$esc.html($dependency.FileName)</a>&nbsp;<b style="color:#ff0000;">&#8226;</b><br/>
#else
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a><br/>
<a href="#l${lnkcnt}_$esc.html($esc.url($dependency.Sha1sum))">$esc.html($dependency.FileName)</a><br/>
#end
#end
</div>
<h2>Dependencies</h2>
#set($lnkcnt=0)
#set($cnt=0)
#foreach($dependency in $dependencies)
<h3 class="subsectionheader standardsubsection"><a name="$esc.html($dependency.FilePath)"></a>$esc.html($dependency.FileName)</h3>
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<h3 class="subsectionheader standardsubsection"><a name="l${lnkcnt}_$esc.html($dependency.Sha1sum)"></a>$esc.html($dependency.FileName)</h3>
<div class="subsectioncontent">
#if ($dependency.description)
#if ($dependency.description)
<p><b>Description:</b>&nbsp;$esc.html($dependency.description)<br/></p>
#end
<p>
@@ -359,14 +363,9 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<h4 id="header$cnt" class="subsectionheader white">Identifiers</h4>
##:&nbsp;<a href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$esc.url($cpevalue)" target="_blank">$esc.html($cpevalue)</a></h4>
<div id="content$cnt" class="subsectioncontent standardsubsection">
#if($cpeCount>1)
Several possible CPEs where identified. If one of the following are correct please update the configuration
to set the hash code for this file to the CPE entry below.<br/><br/>
#end
#if($dependency.getIdentifiers().size()==0)
#if ($dependency.getIdentifiers().size()==0)
<ul><li><b>None</b></li></ul>
#end
#if($dependency.getIdentifiers().size()>0)
#else ## ($dependency.getIdentifiers().size()>0)
<ul>
#foreach($id in $dependency.getIdentifiers())
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
@@ -385,6 +384,18 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<div id="content$cnt" class="subsectioncontent standardsubsection">
#foreach($vuln in $dependency.getVulnerabilities())
<p><b><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$esc.url($vuln.name)">$esc.html($vuln.name)</a></b></p>
<p>Severity:
#if ($vuln.cvssScore<4.0)
Low
#elseif ($vuln.cvssScore>=7.0)
High
#else
Medium
#end
<br/>CVSS Score: $vuln.cvssScore
#if ($vuln.cwe)
<br/>CWE: $vuln.cwe
#end</p>
<p>$esc.html($vuln.description)
#if ($vuln.getReferences().size()>0)
<ul>
@@ -400,6 +411,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</div>
#end
</div>
</div>
</div>
</body>
</html>

View File

@@ -19,7 +19,7 @@ import static org.junit.Assert.*;
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class FileNameAnalyzerTest {
public FileNameAnalyzerTest() {
}
@@ -30,11 +30,11 @@ public class FileNameAnalyzerTest {
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@@ -97,7 +97,7 @@ public class FileNameAnalyzerTest {
File file = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
Dependency result = new Dependency(file);
FileNameAnalyzer instance = new FileNameAnalyzer();
instance.analyze(result);
instance.analyze(result, null);
assertTrue(result.getVendorEvidence().toString().toLowerCase().contains("struts"));
}
@@ -119,7 +119,7 @@ public class FileNameAnalyzerTest {
public void testClose() {
System.out.println("close");
FileNameAnalyzer instance = new FileNameAnalyzer();
instance.close();
instance.close();
assertTrue(true); //close does nothing.
}
}

View File

@@ -53,14 +53,14 @@ public class JarAnalyzerTest {
File file = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
Dependency result = new Dependency(file);
JarAnalyzer instance = new JarAnalyzer();
instance.analyze(result);
instance.analyze(result, null);
assertTrue(result.getVendorEvidence().toString().toLowerCase().contains("apache"));
assertTrue(result.getVendorEvidence().getWeighting().contains("apache"));
file = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath());
result = new Dependency(file);
instance.analyze(result);
instance.analyze(result, null);
boolean found = false;
for (Evidence e : result.getProductEvidence()) {
if (e.getName().equalsIgnoreCase("package-title")
@@ -93,7 +93,7 @@ public class JarAnalyzerTest {
file = new File(this.getClass().getClassLoader().getResource("org.mortbay.jmx.jar").getPath());
result = new Dependency(file);
instance.analyze(result);
instance.analyze(result, null);
assertEquals("org.mortbar,jmx.jar has version evidence?", result.getVersionEvidence().size(), 0);
}

View File

@@ -97,20 +97,31 @@ public class CPEAnalyzerTest extends BaseIndexTestCase {
File file = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
JarAnalyzer jarAnalyzer = new JarAnalyzer();
Dependency depends = new Dependency(file);
jarAnalyzer.analyze(depends);
jarAnalyzer.analyze(depends, null);
File fileSpring = new File(this.getClass().getClassLoader().getResource("spring-core-2.5.5.jar").getPath());
Dependency spring = new Dependency(fileSpring);
jarAnalyzer.analyze(spring);
jarAnalyzer.analyze(spring, null);
File fileSpring3 = new File(this.getClass().getClassLoader().getResource("spring-core-3.0.0.RELEASE.jar").getPath());
Dependency spring3 = new Dependency(fileSpring3);
jarAnalyzer.analyze(spring3, null);
CPEAnalyzer instance = new CPEAnalyzer();
instance.open();
String expResult = "cpe:/a:apache:struts:2.1.2";
String expResultSpring = "cpe:/a:springsource:spring_framework:2.5.5";
String expResultSpring3 = "cpe:/a:vmware:springsource_spring_framework:3.0.0";
instance.determineCPE(depends);
instance.determineCPE(spring);
instance.determineCPE(spring3);
instance.close();
assertTrue("Incorrect match", depends.getIdentifiers().size() == 1);
assertTrue("Incorrect match", depends.getIdentifiers().get(0).getValue().equals(expResult));
assertTrue("Incorrect match size - struts", depends.getIdentifiers().size() == 1);
assertTrue("Incorrect match - struts", depends.getIdentifiers().get(0).getValue().equals(expResult));
assertTrue("Incorrect match size - spring", spring.getIdentifiers().size() == 1);
assertTrue("Incorrect match - spring", spring.getIdentifiers().get(0).getValue().equals(expResultSpring));
assertTrue("Incorrect match size - spring3 - " + spring3.getIdentifiers().size(), spring3.getIdentifiers().size() >= 9);
//assertTrue("Incorrect match - spring3", spring3.getIdentifiers().get(0).getValue().equals(expResultSpring3));
}

View File

@@ -0,0 +1,78 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.codesecure.dependencycheck.data.cwe;
import java.io.ObjectOutputStream;
import java.io.FileOutputStream;
import java.util.Map;
import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* @author Jeremy Long (jeremy.long@gmail.com)
*/
public class CweDBTest {
public CweDBTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Method to serlize the CWE HashMap. This is not used in
* production; this is only used once during dev to create
* the serialized hashmap.
*/
// @Test
// public void testUpdate() throws Exception {
// SAXParserFactory factory = SAXParserFactory.newInstance();
// SAXParser saxParser = factory.newSAXParser();
//
// CweHandler handler = new CweHandler();
// File file = new File(this.getClass().getClassLoader().getResource("cwe.2000.xml").getPath());
//
// saxParser.parse(file, handler);
// System.out.println("Found " + handler.getCwe().size() + " cwe entries.");
// Map<String,String> cwe = handler.getCwe();
// FileOutputStream fout = new FileOutputStream("src/main/resources/data/cwe.hashmap.serialized");
// ObjectOutputStream objOut = new ObjectOutputStream(fout);
// objOut.writeObject(cwe);
// objOut.close();
// }
/**
* Test of getCweName method, of class CweDB.
*/
@Test
public void testGetCweName() {
System.out.println("getCweName");
String cweId = "CWE-16";
String expResult = "Configuration";
String result = CweDB.getCweName(cweId);
assertEquals(expResult, result);
}
}

Binary file not shown.

176610
src/test/resources/cwe.2000.xml Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.