From c2b757ad6f0a700291c5da34f7a587b9f370e56f Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Wed, 28 Jan 2015 18:50:51 -0500 Subject: [PATCH] re-added the struts1/2 fix and fixed other bugs in patch for issue #180 Former-commit-id: 93d45b91a46171788ac1a6c703055e5f196dcc0d --- .../dependencycheck/data/nvdcve/CveDB.java | 53 ++++++++++++++----- .../data/nvdcve/CveDBIntegrationTest.java | 16 +++--- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index b25eff594..6ab4bd1de 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -215,7 +215,7 @@ public class CveDB { + "FROM software INNER JOIN vulnerability ON vulnerability.id = software.cveId " + "INNER JOIN cpeEntry ON cpeEntry.id = software.cpeEntryId " + "WHERE vendor = ? AND product = ? " - + "ORDER BY cve, cpe DESC, previousVersion"; + + "ORDER BY cve, cpe"; //, previousVersion //unfortunately, the version info is too complicated to do in a select. Need to filter this afterwards // + " AND (version = '-' OR previousVersion IS NOT NULL OR version=?)"; // @@ -466,11 +466,12 @@ public class CveDB { ps.setString(2, cpe.getProduct()); rs = ps.executeQuery(); String currentCVE = ""; + final HashMap vulnSoftware = new HashMap(); while (rs.next()) { final String cveId = rs.getString(1); if (!currentCVE.equals(cveId)) { //check for match and add - final Entry matchedCPE = getMatchingSoftware(vulnSoftware, detectedVersion); + final Entry matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); if (matchedCPE != null) { cveEntries.add(currentCVE); final Vulnerability v = getVulnerability(currentCVE); @@ -487,7 +488,7 @@ public class CveDB { vulnSoftware.put(cpeId, p); } //remember to process the last set of CVE/CPE entries - final Entry matchedCPE = getMatchingSoftware(vulnSoftware, detectedVersion); + final Entry matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); if (matchedCPE != null) { cveEntries.add(currentCVE); final Vulnerability v = getVulnerability(currentCVE); @@ -781,11 +782,16 @@ public class CveDB { * Determines if the given identifiedVersion is affected by the given cpeId and previous version flag. A non-null, non-empty * string passed to the previous version argument indicates that all previous versions are affected. * + * @param vendor the vendor of the dependency being analyzed + * @param product the product name of the dependency being analyzed * @param vulnerableSoftware a map of the vulnerable software with a boolean indicating if all previous versions are affected * @param identifiedVersion the identified version of the dependency being analyzed * @return true if the identified version is affected, otherwise false */ - protected Entry getMatchingSoftware(HashMap vulnerableSoftware, DependencyVersion identifiedVersion) { + protected Entry getMatchingSoftware(HashMap vulnerableSoftware, String vendor, String product, DependencyVersion identifiedVersion) { + + final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product); + HashSet majorVersionsAffectingAllPrevious = new HashSet(); boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString()); String majorVersionMatch = null; @@ -809,17 +815,36 @@ public class CveDB { } boolean canSkipVersions = majorVersionMatch != null && majorVersionsAffectingAllPrevious.size() > 1; - for (Iterator> it = vulnerableSoftware.entrySet().iterator(); it.hasNext();) { - Entry entry = it.next(); - final DependencyVersion v = parseDependencyVersion(entry.getKey()); - //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. - if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { - continue; + //yes, we are iterating over this twice. The first time we are skipping versions those that affect all versions + //then later we process those that affect all versions. This could be done with sorting... + for (Entry entry : vulnerableSoftware.entrySet()) { + if (!entry.getValue()) { + final DependencyVersion v = parseDependencyVersion(entry.getKey()); + //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. + if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { + continue; + } + //this can't dereference a null 'identifiedVersion' because if it was null we would have exited + //in the above loop or just after loop (if matchesAnyPrevious return null). + if (identifiedVersion.equals(v)) { + return entry; + } } - //this can't dereference a null 'identifiedVersion' because if it was null we would have exited - //in the above loop or just after loop (if matchesAnyPrevious return null). - if (identifiedVersion.equals(v) || (entry.getValue() && identifiedVersion.compareTo(v) < 0)) { - return entry; + } + for (Entry entry : vulnerableSoftware.entrySet()) { + if (entry.getValue()) { + final DependencyVersion v = parseDependencyVersion(entry.getKey()); + //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this. + if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) { + continue; + } + //this can't dereference a null 'identifiedVersion' because if it was null we would have exited + //in the above loop or just after loop (if matchesAnyPrevious return null). + if (entry.getValue() && identifiedVersion.compareTo(v) <= 0) { + if (!(isVersionTwoADifferentProduct && !identifiedVersion.getVersionParts().get(0).equals(v.getVersionParts().get(0)))) { + return entry; + } + } } } return null; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java index 52731bf53..39ae50614 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/CveDBIntegrationTest.java @@ -113,14 +113,14 @@ public class CveDBIntegrationTest extends BaseDBTestCase { versions.put("cpe:/a:openssl:openssl:1.0.1e", Boolean.FALSE); CveDB instance = new CveDB(); - Entry results = instance.getMatchingSoftware(versions, identifiedVersion); + Entry results = instance.getMatchingSoftware(versions, "openssl", "openssl", identifiedVersion); Assert.assertNull(results); versions.put("cpe:/a:openssl:openssl:1.0.1p", Boolean.FALSE); - results = instance.getMatchingSoftware(versions, identifiedVersion); + results = instance.getMatchingSoftware(versions, "openssl", "openssl", identifiedVersion); Assert.assertNull(results); versions.put("cpe:/a:openssl:openssl:1.0.1q", Boolean.TRUE); - results = instance.getMatchingSoftware(versions, identifiedVersion); + results = instance.getMatchingSoftware(versions, "openssl", "openssl", identifiedVersion); Assert.assertNotNull(results); Assert.assertEquals("cpe:/a:openssl:openssl:1.0.1q", results.getKey()); @@ -136,26 +136,26 @@ public class CveDBIntegrationTest extends BaseDBTestCase { versions.put("cpe:/a:springsource:spring_framework:4.0.0:rc1", Boolean.FALSE); identifiedVersion = new DependencyVersion("3.2.2"); - results = instance.getMatchingSoftware(versions, identifiedVersion); + results = instance.getMatchingSoftware(versions, "springsource", "spring_framework", identifiedVersion); Assert.assertEquals("cpe:/a:springsource:spring_framework:3.2.7", results.getKey()); Assert.assertTrue(results.getValue()); identifiedVersion = new DependencyVersion("3.2.12"); - results = instance.getMatchingSoftware(versions, identifiedVersion); + results = instance.getMatchingSoftware(versions, "springsource", "spring_framework", identifiedVersion); Assert.assertNull(results); identifiedVersion = new DependencyVersion("4.0.0"); - results = instance.getMatchingSoftware(versions, identifiedVersion); + results = instance.getMatchingSoftware(versions, "springsource", "spring_framework", identifiedVersion); Assert.assertEquals("cpe:/a:springsource:spring_framework:4.0.1", results.getKey()); Assert.assertTrue(results.getValue()); identifiedVersion = new DependencyVersion("4.1.0"); - results = instance.getMatchingSoftware(versions, identifiedVersion); + results = instance.getMatchingSoftware(versions, "springsource", "spring_framework", identifiedVersion); Assert.assertNull(results); versions.clear(); versions.put("cpe:/a:jruby:jruby:-", Boolean.FALSE); identifiedVersion = new DependencyVersion("1.6.3"); - results = instance.getMatchingSoftware(versions, identifiedVersion); + results = instance.getMatchingSoftware(versions, "springsource", "spring_framework", identifiedVersion); Assert.assertNotNull(results); }