mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-20 08:14:44 +01:00
updated to improve CPE matching so that if a broad match occured (cpe with no version number) we use the highest confidence version when generating the CPE identifier
Former-commit-id: 6e8c87a71522b1ca7cfa9d72ca419a792d1b17e7
This commit is contained in:
@@ -182,9 +182,9 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
}
|
}
|
||||||
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
|
/* bug fix for #40 - version evidence is not showing up as "used" in the reports if there is no
|
||||||
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
|
* CPE identified. As such, we are "using" the evidence and ignoring the results. */
|
||||||
if (dependency.getVersionEvidence().contains(confidence)) {
|
// if (dependency.getVersionEvidence().contains(confidence)) {
|
||||||
addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
|
// addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), confidence);
|
||||||
}
|
// }
|
||||||
if (!vendors.isEmpty() && !products.isEmpty()) {
|
if (!vendors.isEmpty() && !products.isEmpty()) {
|
||||||
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
|
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
|
||||||
dependency.getVendorEvidence().getWeighting());
|
dependency.getVendorEvidence().getWeighting());
|
||||||
@@ -194,7 +194,7 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
if (verifyEntry(e, dependency)) {
|
if (verifyEntry(e, dependency)) {
|
||||||
final String vendor = e.getVendor();
|
final String vendor = e.getVendor();
|
||||||
final String product = e.getProduct();
|
final String product = e.getProduct();
|
||||||
identifierAdded |= determineIdentifiers(dependency, vendor, product);
|
identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (identifierAdded) {
|
if (identifierAdded) {
|
||||||
@@ -492,12 +492,16 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
* @return <code>true</code> if an identifier was added to the dependency; otherwise <code>false</code>
|
* @return <code>true</code> if an identifier was added to the dependency; otherwise <code>false</code>
|
||||||
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
|
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
|
||||||
*/
|
*/
|
||||||
private boolean determineIdentifiers(Dependency dependency, String vendor, String product) throws UnsupportedEncodingException {
|
private boolean determineIdentifiers(Dependency dependency, String vendor, String product, Confidence currentConfidence) throws UnsupportedEncodingException {
|
||||||
final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
|
final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
|
||||||
DependencyVersion bestGuess = new DependencyVersion("-");
|
DependencyVersion bestGuess = new DependencyVersion("-");
|
||||||
Confidence bestGuessConf = null;
|
Confidence bestGuessConf = null;
|
||||||
|
boolean hasBroadMatch = false;
|
||||||
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
|
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
|
||||||
for (Confidence conf : Confidence.values()) {
|
for (Confidence conf : Confidence.values()) {
|
||||||
|
// if (conf.compareTo(currentConfidence) > 0) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
|
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
|
||||||
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
|
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
|
||||||
if (evVer == null) {
|
if (evVer == null) {
|
||||||
@@ -510,9 +514,12 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
} else {
|
} else {
|
||||||
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
|
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
|
||||||
}
|
}
|
||||||
if (dbVer == null //special case, no version specified - everything is vulnerable
|
if (dbVer == null) { //special case, no version specified - everything is vulnerable
|
||||||
|| evVer.equals(dbVer)) { //yeah! exact match
|
hasBroadMatch = true;
|
||||||
|
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
|
||||||
|
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf);
|
||||||
|
collected.add(match);
|
||||||
|
} else if (evVer.equals(dbVer)) { //yeah! exact match
|
||||||
final String url = String.format(NVD_SEARCH_URL, 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);
|
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
|
||||||
collected.add(match);
|
collected.add(match);
|
||||||
@@ -538,7 +545,11 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
|
final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
|
||||||
final String url = null;
|
String url = null;
|
||||||
|
if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess.
|
||||||
|
final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
|
||||||
|
url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
|
||||||
|
}
|
||||||
if (bestGuessConf == null) {
|
if (bestGuessConf == null) {
|
||||||
bestGuessConf = Confidence.LOW;
|
bestGuessConf = Confidence.LOW;
|
||||||
}
|
}
|
||||||
@@ -577,7 +588,12 @@ public class CPEAnalyzer implements Analyzer {
|
|||||||
/**
|
/**
|
||||||
* A best guess for the CPE.
|
* A best guess for the CPE.
|
||||||
*/
|
*/
|
||||||
BEST_GUESS
|
BEST_GUESS,
|
||||||
|
/**
|
||||||
|
* The entire vendor/product group must be added (without a guess at version) because there is a CVE with a VS
|
||||||
|
* that only specifies vendor/product.
|
||||||
|
*/
|
||||||
|
BROAD_MATCH
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
|
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
callDetermineCPE_full("struts2-core-2.3.16.3.jar", "cpe:/a:apache:struts:2.3.16.3", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
callDetermineCPE_full("hazelcast-2.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
callDetermineCPE_full("hazelcast-2.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:vmware:springsource_spring_framework:2.5.5", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
|
||||||
@@ -112,13 +113,9 @@ public class CPEAnalyzerIntegrationTest extends AbstractDatabaseTestCase {
|
|||||||
Dependency dep = new Dependency(file);
|
Dependency dep = new Dependency(file);
|
||||||
|
|
||||||
fnAnalyzer.analyze(dep, null);
|
fnAnalyzer.analyze(dep, null);
|
||||||
|
|
||||||
jarAnalyzer.analyze(dep, null);
|
jarAnalyzer.analyze(dep, null);
|
||||||
|
|
||||||
hAnalyzer.analyze(dep, null);
|
hAnalyzer.analyze(dep, null);
|
||||||
|
|
||||||
instance.analyze(dep, null);
|
instance.analyze(dep, null);
|
||||||
|
|
||||||
fp.analyze(dep, null);
|
fp.analyze(dep, null);
|
||||||
|
|
||||||
if (expResult != null) {
|
if (expResult != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user