1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.data.nvdcve;
19
20
21 import com.google.common.io.Resources;
22 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
23 import io.github.jeremylong.openvulnerability.client.nvd.Config;
24 import io.github.jeremylong.openvulnerability.client.nvd.CpeMatch;
25 import io.github.jeremylong.openvulnerability.client.nvd.CvssV2;
26 import io.github.jeremylong.openvulnerability.client.nvd.CvssV2Data;
27 import io.github.jeremylong.openvulnerability.client.nvd.CvssV3;
28 import io.github.jeremylong.openvulnerability.client.nvd.CvssV3Data;
29 import io.github.jeremylong.openvulnerability.client.nvd.CvssV4;
30 import io.github.jeremylong.openvulnerability.client.nvd.CvssV4Data;
31 import io.github.jeremylong.openvulnerability.client.nvd.DefCveItem;
32 import io.github.jeremylong.openvulnerability.client.nvd.LangString;
33 import io.github.jeremylong.openvulnerability.client.nvd.Node;
34 import io.github.jeremylong.openvulnerability.client.nvd.Reference;
35 import io.github.jeremylong.openvulnerability.client.nvd.Weakness;
36 import org.apache.commons.collections4.map.ReferenceMap;
37 import org.owasp.dependencycheck.analyzer.exception.LambdaExceptionWrapper;
38 import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
39 import org.owasp.dependencycheck.data.update.cpe.CpeEcosystemCache;
40 import org.owasp.dependencycheck.data.update.cpe.CpePlus;
41 import org.owasp.dependencycheck.dependency.Vulnerability;
42 import org.owasp.dependencycheck.dependency.VulnerableSoftware;
43 import org.owasp.dependencycheck.dependency.VulnerableSoftwareBuilder;
44 import org.owasp.dependencycheck.utils.InvalidSettingException;
45 import org.owasp.dependencycheck.utils.Pair;
46 import org.owasp.dependencycheck.utils.Settings;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import us.springett.parsers.cpe.Cpe;
50 import us.springett.parsers.cpe.CpeBuilder;
51 import us.springett.parsers.cpe.CpeParser;
52 import us.springett.parsers.cpe.exceptions.CpeParsingException;
53 import us.springett.parsers.cpe.exceptions.CpeValidationException;
54
55 import javax.annotation.concurrent.ThreadSafe;
56 import java.io.IOException;
57 import java.net.URL;
58 import java.nio.charset.StandardCharsets;
59 import java.sql.CallableStatement;
60 import java.sql.Connection;
61 import java.sql.JDBCType;
62 import java.sql.PreparedStatement;
63 import java.sql.ResultSet;
64 import java.sql.SQLException;
65 import java.sql.Statement;
66 import java.util.ArrayList;
67 import java.util.Collections;
68 import java.util.Comparator;
69 import java.util.HashMap;
70 import java.util.HashSet;
71 import java.util.List;
72 import java.util.Map;
73 import java.util.MissingResourceException;
74 import java.util.Optional;
75 import java.util.Properties;
76 import java.util.ResourceBundle;
77 import java.util.Set;
78 import java.util.stream.Collectors;
79
80 import static org.apache.commons.collections4.map.AbstractReferenceMap.ReferenceStrength.HARD;
81 import static org.apache.commons.collections4.map.AbstractReferenceMap.ReferenceStrength.SOFT;
82 import static org.owasp.dependencycheck.data.nvdcve.CveDB.PreparedStatementCveDb.*;
83
84
85
86
87
88
89
90
91 @ThreadSafe
92 public final class CveDB implements AutoCloseable {
93
94
95
96
97 private static final Logger LOGGER = LoggerFactory.getLogger(CveDB.class);
98
99
100
101
102 public static final String DB_ECOSYSTEM_CACHE = "data/dbEcosystemCacheUpdates.sql";
103
104
105
106
107 private final DatabaseManager databaseManager;
108
109
110
111
112 private ResourceBundle statementBundle;
113
114
115
116
117 private DatabaseProperties databaseProperties;
118
119
120
121
122 private final String cpeStartsWithFilter;
123
124
125
126 @SuppressWarnings("unchecked")
127 private final Map<String, List<Vulnerability>> vulnerabilitiesForCpeCache = Collections.synchronizedMap(new ReferenceMap(HARD, SOFT));
128
129
130
131 private final Settings settings;
132
133
134
135
136
137 private final CveItemOperator cveItemConverter;
138
139
140
141 private boolean isOracle = false;
142
143
144
145 private boolean isH2 = false;
146
147
148
149
150
151
152
153 public int updateEcosystemCache() {
154 LOGGER.debug("Updating the ecosystem cache");
155 int updateCount = 0;
156 try {
157 final URL url = Resources.getResource(DB_ECOSYSTEM_CACHE);
158 final List<String> sql = Resources.readLines(url, StandardCharsets.UTF_8);
159
160 try (Connection conn = databaseManager.getConnection(); Statement statement = conn.createStatement()) {
161 for (String single : sql) {
162 updateCount += statement.executeUpdate(single);
163 }
164 } catch (SQLException ex) {
165 LOGGER.debug("", ex);
166 throw new DatabaseException("Unable to update the ecosystem cache", ex);
167 }
168 } catch (IOException ex) {
169 throw new DatabaseException("Unable to update the ecosystem cache", ex);
170 }
171 return updateCount;
172 }
173
174
175
176
177
178 enum PreparedStatementCveDb {
179
180
181
182 CLEANUP_ORPHANS,
183
184
185
186 UPDATE_ECOSYSTEM,
187
188
189
190 UPDATE_ECOSYSTEM2,
191
192
193
194 COUNT_CPE,
195
196
197
198 DELETE_VULNERABILITY,
199
200
201
202 INSERT_PROPERTY,
203
204
205
206 INSERT_CWE,
207
208
209
210 INSERT_REFERENCE,
211
212
213
214 INSERT_SOFTWARE,
215
216
217
218 MERGE_PROPERTY,
219
220
221
222 SELECT_CPE_ENTRIES,
223
224
225
226 SELECT_CVE_FROM_SOFTWARE,
227
228
229
230 SELECT_PROPERTIES,
231
232
233
234 SELECT_VULNERABILITY_CWE,
235
236
237
238 SELECT_REFERENCES,
239
240
241
242 SELECT_SOFTWARE,
243
244
245
246 SELECT_VENDOR_PRODUCT_LIST,
247
248
249
250 SELECT_VENDOR_PRODUCT_LIST_FOR_NODE,
251
252
253
254 SELECT_VULNERABILITY,
255
256
257
258 UPDATE_PROPERTY,
259
260
261
262 UPDATE_VULNERABILITY,
263
264
265
266 SELECT_CPE_ECOSYSTEM,
267
268
269
270 MERGE_CPE_ECOSYSTEM,
271
272
273
274 DELETE_UNUSED_DICT_CPE,
275
276
277
278 ADD_DICT_CPE,
279
280
281
282 SELECT_KNOWN_EXPLOITED_VULNERABILITIES,
283
284
285
286 MERGE_KNOWN_EXPLOITED
287 }
288
289
290
291
292
293
294
295
296
297 public CveDB(Settings settings) throws DatabaseException {
298 this.settings = settings;
299 this.cpeStartsWithFilter = settings.getString(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER, "cpe:2.3:a:");
300 this.cveItemConverter = new CveItemOperator(cpeStartsWithFilter);
301 databaseManager = new DatabaseManager(settings);
302 statementBundle = databaseManager.getSqlStatements();
303 isOracle = databaseManager.isOracle();
304 isH2 = databaseManager.isH2Connection();
305 }
306
307
308
309
310 public void open() {
311 databaseManager.open();
312 databaseProperties = new DatabaseProperties(this);
313 }
314
315
316
317
318
319 @Override
320 public void close() {
321 if (isOpen()) {
322 LOGGER.debug("Closing database");
323 clearCache();
324 LOGGER.debug("Cache cleared");
325 try {
326 databaseManager.close();
327 LOGGER.debug("Connection closed");
328 } catch (Throwable ex) {
329 LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details.");
330 LOGGER.debug("", ex);
331 }
332 releaseResources();
333 LOGGER.debug("Resources released");
334 databaseManager.cleanup();
335 }
336 }
337
338
339
340
341 private void releaseResources() {
342 statementBundle = null;
343 databaseProperties = null;
344 }
345
346
347
348
349
350
351 public boolean isOpen() {
352 return databaseManager.isOpen();
353 }
354
355
356
357
358
359
360
361
362
363
364
365
366
367 private PreparedStatement getPreparedStatement(Connection connection, PreparedStatementCveDb key, String parameter)
368 throws DatabaseException, SQLException {
369 final PreparedStatement preparedStatement = getPreparedStatement(connection, key);
370 preparedStatement.setString(1, parameter);
371 return preparedStatement;
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385
386 private PreparedStatement getPreparedStatement(Connection connection, PreparedStatementCveDb key, int parameter)
387 throws DatabaseException, SQLException {
388 final PreparedStatement preparedStatement = getPreparedStatement(connection, key);
389 preparedStatement.setInt(1, parameter);
390 return preparedStatement;
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404 private PreparedStatement getPreparedStatement(Connection connection, PreparedStatementCveDb key) throws DatabaseException {
405 PreparedStatement preparedStatement = null;
406 try {
407 final String statementString = statementBundle.getString(key.name());
408 if (isOracle && key == UPDATE_VULNERABILITY) {
409 preparedStatement = connection.prepareCall(statementString);
410
411
412
413 } else {
414 preparedStatement = connection.prepareStatement(statementString);
415 }
416 if (isOracle) {
417
418
419 preparedStatement.setFetchSize(10_000);
420 }
421 } catch (SQLException ex) {
422 throw new DatabaseException(ex);
423 } catch (MissingResourceException ex) {
424 if (!ex.getMessage().contains("key MERGE_PROPERTY")) {
425 throw new DatabaseException(ex);
426 }
427 }
428 return preparedStatement;
429 }
430
431
432
433
434
435
436 @Override
437 @SuppressWarnings("FinalizeDeclaration")
438 protected void finalize() throws Throwable {
439 LOGGER.debug("Entering finalize");
440 close();
441 super.finalize();
442 }
443
444
445
446
447
448
449 public DatabaseProperties getDatabaseProperties() {
450 return databaseProperties;
451 }
452
453
454
455
456
457
458 DatabaseProperties reloadProperties() {
459 databaseProperties = new DatabaseProperties(this);
460 return databaseProperties;
461 }
462
463
464
465
466
467
468
469
470
471
472
473 public Set<CpePlus> getCPEs(String vendor, String product) {
474 final Set<CpePlus> cpe = new HashSet<>();
475 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, SELECT_CPE_ENTRIES)) {
476
477
478 ps.setString(1, vendor);
479 ps.setString(2, product);
480 try (ResultSet rs = ps.executeQuery()) {
481 final CpeBuilder builder = new CpeBuilder();
482 while (rs.next()) {
483 final Cpe entry = builder
484 .part(rs.getString(1))
485 .vendor(rs.getString(2))
486 .product(rs.getString(3))
487 .version(rs.getString(4))
488 .update(rs.getString(5))
489 .edition(rs.getString(6))
490 .language(rs.getString(7))
491 .swEdition(rs.getString(8))
492 .targetSw(rs.getString(9))
493 .targetHw(rs.getString(10))
494 .other(rs.getString(11)).build();
495 final CpePlus plus = new CpePlus(entry, rs.getString(12));
496 cpe.add(plus);
497 }
498 }
499 } catch (SQLException | CpeParsingException | CpeValidationException ex) {
500 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
501 LOGGER.debug("", ex);
502 }
503 return cpe;
504 }
505
506
507
508
509
510
511
512
513 public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
514 final Set<Pair<String, String>> data = new HashSet<>();
515 try (Connection conn = databaseManager.getConnection();
516 PreparedStatement ps = getPreparedStatement(conn, SELECT_VENDOR_PRODUCT_LIST);
517 ResultSet rs = ps.executeQuery()) {
518 while (rs.next()) {
519 data.add(new Pair<>(rs.getString(1), rs.getString(2)));
520 }
521 } catch (SQLException ex) {
522 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
523 throw new DatabaseException(msg, ex);
524 }
525 return data;
526 }
527
528
529
530
531
532
533
534
535
536
537 public Set<Pair<String, String>> getVendorProductListForNode() throws DatabaseException {
538 final Set<Pair<String, String>> data = new HashSet<>();
539 try (Connection conn = databaseManager.getConnection();
540 PreparedStatement ps = getPreparedStatement(conn, SELECT_VENDOR_PRODUCT_LIST_FOR_NODE);
541 ResultSet rs = ps.executeQuery()) {
542 while (rs.next()) {
543 data.add(new Pair<>(rs.getString(1), rs.getString(2)));
544 }
545 } catch (SQLException ex) {
546 final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
547 throw new DatabaseException(msg, ex);
548 }
549 return data;
550 }
551
552
553
554
555
556
557 public Properties getProperties() {
558 final Properties prop = new Properties();
559 try (Connection conn = databaseManager.getConnection();
560 PreparedStatement ps = getPreparedStatement(conn, SELECT_PROPERTIES);
561 ResultSet rs = ps.executeQuery()) {
562 while (rs.next()) {
563 prop.setProperty(rs.getString(1), rs.getString(2));
564 }
565 } catch (SQLException ex) {
566 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
567 LOGGER.debug("", ex);
568 }
569 return prop;
570 }
571
572
573
574
575
576
577
578 public void saveProperty(String key, String value) {
579 clearCache();
580 try (Connection conn = databaseManager.getConnection(); PreparedStatement mergeProperty = getPreparedStatement(conn, MERGE_PROPERTY)) {
581 if (mergeProperty != null) {
582 mergeProperty.setString(1, key);
583 mergeProperty.setString(2, value);
584 mergeProperty.execute();
585 } else {
586
587 try (PreparedStatement updateProperty = getPreparedStatement(conn, UPDATE_PROPERTY)) {
588 updateProperty.setString(1, value);
589 updateProperty.setString(2, key);
590 if (updateProperty.executeUpdate() == 0) {
591 try (PreparedStatement insertProperty = getPreparedStatement(conn, INSERT_PROPERTY)) {
592 insertProperty.setString(1, key);
593 insertProperty.setString(2, value);
594 insertProperty.executeUpdate();
595 }
596 }
597 }
598 }
599 } catch (SQLException ex) {
600 LOGGER.warn("Unable to save property '{}' with a value of '{}' to the database", key, value);
601 LOGGER.debug("", ex);
602 }
603 }
604
605
606
607
608
609
610
611
612
613
614 private void clearCache() {
615 vulnerabilitiesForCpeCache.clear();
616 }
617
618
619
620
621
622
623
624
625 public List<Vulnerability> getVulnerabilities(Cpe cpe) throws DatabaseException {
626 final List<Vulnerability> cachedVulnerabilities = vulnerabilitiesForCpeCache.get(cpe.toCpe23FS());
627 if (cachedVulnerabilities != null) {
628 LOGGER.debug("Cache hit for {}", cpe.toCpe23FS());
629 return cachedVulnerabilities;
630 } else {
631 LOGGER.debug("Cache miss for {}", cpe.toCpe23FS());
632 }
633
634 final List<Vulnerability> vulnerabilities = new ArrayList<>();
635 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, SELECT_CVE_FROM_SOFTWARE)) {
636 ps.setString(1, cpe.getVendor());
637 ps.setString(2, cpe.getProduct());
638 try (ResultSet rs = ps.executeQuery()) {
639 String currentCVE = "";
640 final Set<VulnerableSoftware> vulnSoftware = new HashSet<>();
641 final VulnerableSoftwareBuilder vulnerableSoftwareBuilder = new VulnerableSoftwareBuilder();
642 while (rs.next()) {
643 final String cveId = rs.getString(1);
644 if (currentCVE.isEmpty()) {
645
646 currentCVE = cveId;
647 }
648 if (!vulnSoftware.isEmpty() && !currentCVE.equals(cveId)) {
649 final VulnerableSoftware matchedCPE = getMatchingSoftware(cpe, vulnSoftware);
650 if (matchedCPE != null) {
651 final Vulnerability v = getVulnerability(currentCVE, conn);
652 if (v != null) {
653 v.setMatchedVulnerableSoftware(matchedCPE);
654 v.setSource(Vulnerability.Source.NVD);
655 vulnerabilities.add(v);
656 }
657 }
658 vulnSoftware.clear();
659 currentCVE = cveId;
660 }
661
662
663
664 final VulnerableSoftware vs;
665 try {
666 vs = vulnerableSoftwareBuilder.part(rs.getString(2)).vendor(rs.getString(3))
667 .product(rs.getString(4)).version(rs.getString(5)).update(rs.getString(6))
668 .edition(rs.getString(7)).language(rs.getString(8)).swEdition(rs.getString(9))
669 .targetSw(rs.getString(10)).targetHw(rs.getString(11)).other(rs.getString(12))
670 .versionEndExcluding(rs.getString(13)).versionEndIncluding(rs.getString(14))
671 .versionStartExcluding(rs.getString(15)).versionStartIncluding(rs.getString(16))
672 .vulnerable(rs.getBoolean(17)).build();
673 } catch (CpeParsingException | CpeValidationException ex) {
674 throw new DatabaseException("Database contains an invalid Vulnerable Software Entry", ex);
675 }
676 vulnSoftware.add(vs);
677 }
678
679
680 final VulnerableSoftware matchedCPE = getMatchingSoftware(cpe, vulnSoftware);
681 if (matchedCPE != null) {
682 final Vulnerability v = getVulnerability(currentCVE, conn);
683 if (v != null) {
684 v.setMatchedVulnerableSoftware(matchedCPE);
685 v.setSource(Vulnerability.Source.NVD);
686 vulnerabilities.add(v);
687 }
688 }
689 }
690 } catch (SQLException ex) {
691 throw new DatabaseException("Exception retrieving vulnerability for " + cpe.toCpe23FS(), ex);
692 }
693 vulnerabilitiesForCpeCache.put(cpe.toCpe23FS(), vulnerabilities);
694 return vulnerabilities;
695 }
696
697
698
699
700
701
702
703
704 public Vulnerability getVulnerability(String cve) throws DatabaseException {
705 try (Connection conn = databaseManager.getConnection()) {
706 return getVulnerability(cve, conn);
707 } catch (SQLException ex) {
708 throw new DatabaseException("Error retrieving " + cve, ex);
709 }
710 }
711
712
713
714
715
716
717
718
719
720 public Vulnerability getVulnerability(String cve, Connection conn) throws DatabaseException {
721 final int cveId;
722 final VulnerableSoftwareBuilder vulnerableSoftwareBuilder = new VulnerableSoftwareBuilder();
723 Vulnerability vuln = null;
724 try {
725 try (PreparedStatement psV = getPreparedStatement(conn, SELECT_VULNERABILITY, cve); ResultSet rsV = psV.executeQuery()) {
726 if (rsV.next()) {
727
728 cveId = rsV.getInt(1);
729 vuln = new Vulnerability();
730 vuln.setSource(Vulnerability.Source.NVD);
731 vuln.setName(cve);
732 vuln.setDescription(rsV.getString(2));
733
734
735
736
737
738 if (rsV.getObject(11) != null) {
739
740 final CvssV2Data.AccessVectorType accessVector = CvssV2Data.AccessVectorType.fromValue(rsV.getString(12));
741 final CvssV2Data.AccessComplexityType accessComplexity = CvssV2Data.AccessComplexityType.fromValue(rsV.getString(13));
742 final CvssV2Data.AuthenticationType authentication = CvssV2Data.AuthenticationType.fromValue(rsV.getString(14));
743 final CvssV2Data.CiaType confidentialityImpact = CvssV2Data.CiaType.fromValue(rsV.getString(15));
744 final CvssV2Data.CiaType integrityImpact = CvssV2Data.CiaType.fromValue(rsV.getString(16));
745 final CvssV2Data.CiaType availabilityImpact = CvssV2Data.CiaType.fromValue(rsV.getString(17));
746 final String vector = String.format("/AV:%s/AC:%s/Au:%s/C:%s/I:%s/A:%s",
747 accessVector == null ? "" : accessVector.value().substring(0, 1),
748 accessComplexity == null ? "" : accessComplexity.value().substring(0, 1),
749 authentication == null ? "" : authentication.value().substring(0, 1),
750 confidentialityImpact == null ? "" : confidentialityImpact.value().substring(0, 1),
751 integrityImpact == null ? "" : integrityImpact.value().substring(0, 1),
752 availabilityImpact == null ? "" : availabilityImpact.value().substring(0, 1));
753
754 final CvssV2Data cvssData = new CvssV2Data(CvssV2Data.Version._2_0, vector, accessVector,
755 accessComplexity, authentication, confidentialityImpact,
756 integrityImpact, availabilityImpact, rsV.getDouble(11), rsV.getString(3),
757 null, null, null, null, null, null, null, null, null, null);
758 final CvssV2 cvss = new CvssV2(null, CvssV2.Type.PRIMARY, cvssData, rsV.getString(3),
759 rsV.getDouble(4), rsV.getDouble(5), rsV.getBoolean(6), rsV.getBoolean(7),
760 rsV.getBoolean(8), rsV.getBoolean(9), rsV.getBoolean(10));
761 vuln.setCvssV2(cvss);
762 }
763
764
765
766 if (rsV.getObject(21) != null) {
767
768 String cveVersion = "3.1";
769 if (rsV.getString(31) != null) {
770 cveVersion = rsV.getString(31);
771 }
772 final CvssV3Data.Version version = CvssV3Data.Version.fromValue(cveVersion);
773 final CvssV3Data.AttackVectorType attackVector = CvssV3Data.AttackVectorType.fromValue(rsV.getString(21));
774 final CvssV3Data.AttackComplexityType attackComplexity = CvssV3Data.AttackComplexityType.fromValue(rsV.getString(22));
775 final CvssV3Data.PrivilegesRequiredType privilegesRequired = CvssV3Data.PrivilegesRequiredType.fromValue(rsV.getString(23));
776 final CvssV3Data.UserInteractionType userInteraction = CvssV3Data.UserInteractionType.fromValue(rsV.getString(24));
777 final CvssV3Data.ScopeType scope = CvssV3Data.ScopeType.fromValue(rsV.getString(25));
778 final CvssV3Data.CiaType confidentialityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(26));
779 final CvssV3Data.CiaType integrityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(27));
780 final CvssV3Data.CiaType availabilityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(28));
781 final CvssV3Data.SeverityType baseSeverity = CvssV3Data.SeverityType.fromValue(rsV.getString(30));
782 final String vector = String.format("CVSS:%s/AV:%s/AC:%s/PR:%s/UI:%s/S:%s/C:%s/I:%s/A:%s",
783 version == null ? "" : version,
784 attackVector == null ? "" : attackVector.value().substring(0, 1),
785 attackComplexity == null ? "" : attackComplexity.value().substring(0, 1),
786 privilegesRequired == null ? "" : privilegesRequired.value().substring(0, 1),
787 userInteraction == null ? "" : userInteraction.value().substring(0, 1),
788 scope == null ? "" : scope.value().substring(0, 1),
789 confidentialityImpact == null ? "" : confidentialityImpact.value().substring(0, 1),
790 integrityImpact == null ? "" : integrityImpact.value().substring(0, 1),
791 availabilityImpact == null ? "" : availabilityImpact.value().substring(0, 1));
792
793 final CvssV3Data cvssData = new CvssV3Data(version, vector, attackVector, attackComplexity, privilegesRequired,
794 userInteraction, scope, confidentialityImpact, integrityImpact, availabilityImpact,
795 rsV.getDouble(29), baseSeverity, CvssV3Data.ExploitCodeMaturityType.PROOF_OF_CONCEPT,
796 CvssV3Data.RemediationLevelType.NOT_DEFINED, CvssV3Data.ConfidenceType.REASONABLE, 0.0,
797 CvssV3Data.SeverityType.MEDIUM, CvssV3Data.CiaRequirementType.NOT_DEFINED,
798 CvssV3Data.CiaRequirementType.NOT_DEFINED, CvssV3Data.CiaRequirementType.NOT_DEFINED,
799 CvssV3Data.ModifiedAttackVectorType.ADJACENT_NETWORK, CvssV3Data.ModifiedAttackComplexityType.NOT_DEFINED,
800 CvssV3Data.ModifiedPrivilegesRequiredType.NOT_DEFINED, CvssV3Data.ModifiedUserInteractionType.NOT_DEFINED,
801 CvssV3Data.ModifiedScopeType.NOT_DEFINED, CvssV3Data.ModifiedCiaType.NOT_DEFINED,
802 CvssV3Data.ModifiedCiaType.NOT_DEFINED, CvssV3Data.ModifiedCiaType.NOT_DEFINED, 1.0,
803 CvssV3Data.SeverityType.NONE);
804 final CvssV3 cvss = new CvssV3(null, null, cvssData, rsV.getDouble(19), rsV.getDouble(20));
805 vuln.setCvssV3(cvss);
806 }
807
808
809
810
811
812
813
814
815
816
817 if (rsV.getObject(33) != null) {
818 String vectorString = null;
819
820 String value = rsV.getString(32);
821 final CvssV4Data.Version version = CvssV4Data.Version.fromValue(value);
822 CvssV4Data.AttackVectorType attackVector = null;
823 value = rsV.getString(33);
824 if (value != null) {
825 attackVector = CvssV4Data.AttackVectorType.fromValue(value);
826 }
827 CvssV4Data.AttackComplexityType attackComplexity = null;
828 value = rsV.getString(34);
829 if (value != null) {
830 attackComplexity = CvssV4Data.AttackComplexityType.fromValue(value);
831 }
832 CvssV4Data.AttackRequirementsType attackRequirements = null;
833 value = rsV.getString(35);
834 if (value != null) {
835 attackRequirements = CvssV4Data.AttackRequirementsType.fromValue(value);
836 }
837 CvssV4Data.PrivilegesRequiredType privilegesRequired = null;
838 value = rsV.getString(36);
839 if (value != null) {
840 privilegesRequired = CvssV4Data.PrivilegesRequiredType.fromValue(value);
841 }
842 CvssV4Data.UserInteractionType userInteraction = null;
843 value = rsV.getString(37);
844 if (value != null) {
845 userInteraction = CvssV4Data.UserInteractionType.fromValue(value);
846 }
847 CvssV4Data.CiaType vulnConfidentialityImpact = null;
848 value = rsV.getString(38);
849 if (value != null) {
850 vulnConfidentialityImpact = CvssV4Data.CiaType.fromValue(value);
851 }
852 CvssV4Data.CiaType vulnIntegrityImpact = null;
853 value = rsV.getString(39);
854 if (value != null) {
855 vulnIntegrityImpact = CvssV4Data.CiaType.fromValue(value);
856 }
857 CvssV4Data.CiaType vulnAvailabilityImpact = null;
858 value = rsV.getString(40);
859 if (value != null) {
860 vulnAvailabilityImpact = CvssV4Data.CiaType.fromValue(value);
861 }
862 CvssV4Data.CiaType subConfidentialityImpact = null;
863 value = rsV.getString(41);
864 if (value != null) {
865 subConfidentialityImpact = CvssV4Data.CiaType.fromValue(value);
866 }
867 CvssV4Data.CiaType subIntegrityImpact = null;
868 value = rsV.getString(42);
869 if (value != null) {
870 subIntegrityImpact = CvssV4Data.CiaType.fromValue(value);
871 }
872 CvssV4Data.CiaType subAvailabilityImpact = null;
873 value = rsV.getString(43);
874 if (value != null) {
875 subAvailabilityImpact = CvssV4Data.CiaType.fromValue(value);
876 }
877 CvssV4Data.ExploitMaturityType exploitMaturity = null;
878 value = rsV.getString(44);
879 if (value != null) {
880 exploitMaturity = CvssV4Data.ExploitMaturityType.fromValue(value);
881 }
882 CvssV4Data.CiaRequirementType confidentialityRequirement = null;
883 value = rsV.getString(45);
884 if (value != null) {
885 confidentialityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
886 }
887 CvssV4Data.CiaRequirementType integrityRequirement = null;
888 value = rsV.getString(46);
889 if (value != null) {
890 integrityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
891 }
892 CvssV4Data.CiaRequirementType availabilityRequirement = null;
893 value = rsV.getString(47);
894 if (value != null) {
895 availabilityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
896 }
897 CvssV4Data.ModifiedAttackVectorType modifiedAttackVector = null;
898 value = rsV.getString(48);
899 if (value != null) {
900 modifiedAttackVector = CvssV4Data.ModifiedAttackVectorType.fromValue(value);
901 }
902 CvssV4Data.ModifiedAttackComplexityType modifiedAttackComplexity = null;
903 value = rsV.getString(49);
904 if (value != null) {
905 modifiedAttackComplexity = CvssV4Data.ModifiedAttackComplexityType.fromValue(value);
906 }
907 CvssV4Data.ModifiedAttackRequirementsType modifiedAttackRequirements = null;
908 value = rsV.getString(50);
909 if (value != null) {
910 modifiedAttackRequirements = CvssV4Data.ModifiedAttackRequirementsType.fromValue(value);
911 }
912 CvssV4Data.ModifiedPrivilegesRequiredType modifiedPrivilegesRequired = null;
913 value = rsV.getString(51);
914 if (value != null) {
915 modifiedPrivilegesRequired = CvssV4Data.ModifiedPrivilegesRequiredType.fromValue(value);
916 }
917 CvssV4Data.ModifiedUserInteractionType modifiedUserInteraction = null;
918 value = rsV.getString(52);
919 if (value != null) {
920 modifiedUserInteraction = CvssV4Data.ModifiedUserInteractionType.fromValue(value);
921 }
922 CvssV4Data.ModifiedCiaType modifiedVulnConfidentialityImpact = null;
923 value = rsV.getString(53);
924 if (value != null) {
925 modifiedVulnConfidentialityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
926 }
927 CvssV4Data.ModifiedCiaType modifiedVulnIntegrityImpact = null;
928 value = rsV.getString(54);
929 if (value != null) {
930 modifiedVulnIntegrityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
931 }
932 CvssV4Data.ModifiedCiaType modifiedVulnAvailabilityImpact = null;
933 value = rsV.getString(55);
934 if (value != null) {
935 modifiedVulnAvailabilityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
936 }
937 CvssV4Data.ModifiedSubCType modifiedSubConfidentialityImpact = null;
938 value = rsV.getString(56);
939 if (value != null) {
940 modifiedSubConfidentialityImpact = CvssV4Data.ModifiedSubCType.fromValue(value);
941 }
942 CvssV4Data.ModifiedSubIaType modifiedSubIntegrityImpact = null;
943 value = rsV.getString(57);
944 if (value != null) {
945 modifiedSubIntegrityImpact = CvssV4Data.ModifiedSubIaType.fromValue(value);
946 }
947 CvssV4Data.ModifiedSubIaType modifiedSubAvailabilityImpact = null;
948 value = rsV.getString(58);
949 if (value != null) {
950 modifiedSubAvailabilityImpact = CvssV4Data.ModifiedSubIaType.fromValue(value);
951 }
952 CvssV4Data.SafetyType safety = null;
953 value = rsV.getString(59);
954 if (value != null) {
955 safety = CvssV4Data.SafetyType.fromValue(value);
956 }
957 CvssV4Data.AutomatableType automatable = null;
958 value = rsV.getString(60);
959 if (value != null) {
960 automatable = CvssV4Data.AutomatableType.fromValue(value);
961 }
962 CvssV4Data.RecoveryType recovery = null;
963 value = rsV.getString(61);
964 if (value != null) {
965 recovery = CvssV4Data.RecoveryType.fromValue(value);
966 }
967 CvssV4Data.ValueDensityType valueDensity = null;
968 value = rsV.getString(62);
969 if (value != null) {
970 valueDensity = CvssV4Data.ValueDensityType.fromValue(value);
971 }
972 CvssV4Data.VulnerabilityResponseEffortType vulnerabilityResponseEffort = null;
973 value = rsV.getString(63);
974 if (value != null) {
975 vulnerabilityResponseEffort = CvssV4Data.VulnerabilityResponseEffortType.fromValue(value);
976 }
977 CvssV4Data.ProviderUrgencyType providerUrgency = null;
978 value = rsV.getString(64);
979 if (value != null) {
980 providerUrgency = CvssV4Data.ProviderUrgencyType.fromValue(value);
981 }
982 Double baseScore = null;
983 if (rsV.getObject(65) != null) {
984 baseScore = rsV.getDouble(65);
985 }
986 CvssV4Data.SeverityType baseSeverity = null;
987 value = rsV.getString(66);
988 if (value != null) {
989 baseSeverity = CvssV4Data.SeverityType.fromValue(value);
990 }
991 Double threatScore = null;
992 if (rsV.getObject(67) != null) {
993 threatScore = rsV.getDouble(67);
994 }
995 CvssV4Data.SeverityType threatSeverity = null;
996 value = rsV.getString(68);
997 if (value != null) {
998 threatSeverity = CvssV4Data.SeverityType.fromValue(value);
999 }
1000 Double environmentalScore = null;
1001 if (rsV.getObject(69) != null) {
1002 environmentalScore = rsV.getDouble(69);
1003 }
1004 CvssV4Data.SeverityType environmentalSeverity = null;
1005 value = rsV.getString(70);
1006 if (value != null) {
1007 environmentalSeverity = CvssV4Data.SeverityType.fromValue(value);
1008 }
1009
1010 CvssV4Data data = new CvssV4Data(version, vectorString, attackVector, attackComplexity, attackRequirements, privilegesRequired,
1011 userInteraction, vulnConfidentialityImpact, vulnIntegrityImpact, vulnAvailabilityImpact, subConfidentialityImpact,
1012 subIntegrityImpact, subAvailabilityImpact, exploitMaturity, confidentialityRequirement, integrityRequirement,
1013 availabilityRequirement, modifiedAttackVector, modifiedAttackComplexity, modifiedAttackRequirements,
1014 modifiedPrivilegesRequired, modifiedUserInteraction, modifiedVulnConfidentialityImpact, modifiedVulnIntegrityImpact,
1015 modifiedVulnAvailabilityImpact, modifiedSubConfidentialityImpact, modifiedSubIntegrityImpact,
1016 modifiedSubAvailabilityImpact, safety, automatable, recovery, valueDensity, vulnerabilityResponseEffort,
1017 providerUrgency, baseScore, baseSeverity, threatScore, threatSeverity, environmentalScore, environmentalSeverity);
1018 vectorString = data.toString();
1019 data = new CvssV4Data(version, vectorString, attackVector, attackComplexity, attackRequirements, privilegesRequired,
1020 userInteraction, vulnConfidentialityImpact, vulnIntegrityImpact, vulnAvailabilityImpact, subConfidentialityImpact,
1021 subIntegrityImpact, subAvailabilityImpact, exploitMaturity, confidentialityRequirement, integrityRequirement,
1022 availabilityRequirement, modifiedAttackVector, modifiedAttackComplexity, modifiedAttackRequirements,
1023 modifiedPrivilegesRequired, modifiedUserInteraction, modifiedVulnConfidentialityImpact, modifiedVulnIntegrityImpact,
1024 modifiedVulnAvailabilityImpact, modifiedSubConfidentialityImpact, modifiedSubIntegrityImpact,
1025 modifiedSubAvailabilityImpact, safety, automatable, recovery, valueDensity, vulnerabilityResponseEffort,
1026 providerUrgency, baseScore, baseSeverity, threatScore, threatSeverity, environmentalScore, environmentalSeverity);
1027
1028 final String source = rsV.getString(71);
1029 CvssV4.Type cvssType = null;
1030 value = rsV.getString(72);
1031 if (value != null) {
1032 cvssType = CvssV4.Type.fromValue(value);
1033 }
1034 final CvssV4 cvssv4 = new CvssV4(source, cvssType, data);
1035 vuln.setCvssV4(cvssv4);
1036 }
1037 } else {
1038 LOGGER.debug(cve + " does not exist in the database");
1039 return null;
1040 }
1041 }
1042 try (PreparedStatement psCWE = getPreparedStatement(conn, SELECT_VULNERABILITY_CWE, cveId); ResultSet rsC = psCWE.executeQuery()) {
1043 while (rsC.next()) {
1044 vuln.addCwe(rsC.getString(1));
1045 }
1046 }
1047 try (PreparedStatement psR = getPreparedStatement(conn, SELECT_REFERENCES, cveId); ResultSet rsR = psR.executeQuery()) {
1048 while (rsR.next()) {
1049 vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
1050 }
1051 }
1052 try (PreparedStatement psS = getPreparedStatement(conn, SELECT_SOFTWARE, cveId); ResultSet rsS = psS.executeQuery()) {
1053
1054
1055
1056 while (rsS.next()) {
1057 vulnerableSoftwareBuilder.part(rsS.getString(1))
1058 .vendor(rsS.getString(2))
1059 .product(rsS.getString(3))
1060 .version(rsS.getString(4))
1061 .update(rsS.getString(5))
1062 .edition(rsS.getString(6))
1063 .language(rsS.getString(7))
1064 .swEdition(rsS.getString(8))
1065 .targetSw(rsS.getString(9))
1066 .targetHw(rsS.getString(10))
1067 .other(rsS.getString(11))
1068 .versionEndExcluding(rsS.getString(12))
1069 .versionEndIncluding(rsS.getString(13))
1070 .versionStartExcluding(rsS.getString(14))
1071 .versionStartIncluding(rsS.getString(15))
1072 .vulnerable(rsS.getBoolean(16));
1073 vuln.addVulnerableSoftware(vulnerableSoftwareBuilder.build());
1074 }
1075 }
1076 } catch (SQLException ex) {
1077 throw new DatabaseException("Error retrieving " + cve, ex);
1078 } catch (CpeParsingException | CpeValidationException ex) {
1079 throw new DatabaseException("The database contains an invalid Vulnerable Software Entry", ex);
1080 }
1081 return vuln;
1082 }
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 public void updateVulnerability(DefCveItem cve, String baseEcosystem) {
1095 clearCache();
1096 final String cveId = cve.getCve().getId();
1097 try {
1098 if (cve.getCve().getVulnStatus() != null && cve.getCve().getVulnStatus().toUpperCase().startsWith("REJECT")) {
1099 deleteVulnerability(cveId);
1100 } else {
1101 if (cveItemConverter.testCveCpeStartWithFilter(cve)) {
1102 final String description = cveItemConverter.extractDescription(cve);
1103 final int vulnerabilityId = updateOrInsertVulnerability(cve, description);
1104 updateVulnerabilityInsertCwe(vulnerabilityId, cve);
1105 updateVulnerabilityInsertReferences(vulnerabilityId, cve);
1106
1107 final List<VulnerableSoftware> software = parseCpes(cve);
1108 updateVulnerabilityInsertSoftware(vulnerabilityId, cveId, software, baseEcosystem);
1109 }
1110 }
1111 } catch (SQLException ex) {
1112 final String msg = String.format("Error updating '%s'; %s", cveId, ex.getMessage());
1113 LOGGER.debug(msg, ex);
1114 throw new DatabaseException(msg);
1115 } catch (CpeValidationException ex) {
1116 final String msg = String.format("Error parsing CPE entry from '%s'; %s", cveId, ex.getMessage());
1117 LOGGER.debug(msg, ex);
1118 throw new DatabaseException(msg);
1119 }
1120 }
1121
1122 private void loadCpeEcosystemCache() {
1123 final Map<Pair<String, String>, String> map = new HashMap<>();
1124 try (Connection conn = databaseManager.getConnection();
1125 PreparedStatement ps = getPreparedStatement(conn, SELECT_CPE_ECOSYSTEM);
1126 ResultSet rs = ps.executeQuery()) {
1127 while (rs.next()) {
1128 final Pair<String, String> key = new Pair<>(rs.getString(1), rs.getString(2));
1129 final String value = rs.getString(3);
1130 map.put(key, value);
1131 }
1132 } catch (SQLException ex) {
1133 final String msg = String.format("Error loading the Cpe Ecosystem Cache: %s", ex.getMessage());
1134 LOGGER.debug(msg, ex);
1135 throw new DatabaseException(msg, ex);
1136 }
1137 CpeEcosystemCache.setCache(map);
1138 }
1139
1140 private void saveCpeEcosystemCache() {
1141 final Map<Pair<String, String>, String> map = CpeEcosystemCache.getChanged();
1142 if (map != null && !map.isEmpty()) {
1143 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, MERGE_CPE_ECOSYSTEM)) {
1144 for (Map.Entry<Pair<String, String>, String> entry : map.entrySet()) {
1145 ps.setString(1, entry.getKey().getLeft());
1146 ps.setString(2, entry.getKey().getRight());
1147 ps.setString(3, entry.getValue());
1148 if (isBatchInsertEnabled()) {
1149 ps.addBatch();
1150 } else {
1151 ps.execute();
1152 }
1153 }
1154 if (isBatchInsertEnabled()) {
1155 ps.executeBatch();
1156 }
1157 } catch (SQLException ex) {
1158 final String msg = String.format("Error saving the Cpe Ecosystem Cache: %s", ex.getMessage());
1159 LOGGER.debug(msg, ex);
1160 throw new DatabaseException(msg, ex);
1161 }
1162 }
1163 }
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173 private int updateOrInsertVulnerability(DefCveItem cve, String description) {
1174 if (CpeEcosystemCache.isEmpty()) {
1175 loadCpeEcosystemCache();
1176 }
1177 final int vulnerabilityId;
1178 try (Connection conn = databaseManager.getConnection(); PreparedStatement callUpdate = getPreparedStatement(conn, UPDATE_VULNERABILITY)) {
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202 callUpdate.setString(1, cve.getCve().getId());
1203 callUpdate.setString(2, description);
1204 Optional<CvssV2> optCvssv2 = null;
1205 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV2() != null) {
1206 optCvssv2 = cve.getCve().getMetrics().getCvssMetricV2().stream().sorted(Comparator.comparing(CvssV2::getType)).findFirst();
1207 }
1208 if (optCvssv2 != null && optCvssv2.isPresent()) {
1209 final CvssV2 cvssv2 = optCvssv2.get();
1210 setUpdateColumn(callUpdate, 3, cvssv2.getBaseSeverity());
1211 setUpdateColumn(callUpdate, 4, cvssv2.getExploitabilityScore());
1212 setUpdateColumn(callUpdate, 5, cvssv2.getImpactScore());
1213 setUpdateColumn(callUpdate, 6, cvssv2.getAcInsufInfo());
1214 setUpdateColumn(callUpdate, 7, cvssv2.getObtainAllPrivilege());
1215 setUpdateColumn(callUpdate, 8, cvssv2.getObtainUserPrivilege());
1216 setUpdateColumn(callUpdate, 9, cvssv2.getObtainOtherPrivilege());
1217 setUpdateColumn(callUpdate, 10, cvssv2.getUserInteractionRequired());
1218 setUpdateColumn(callUpdate, 11, cvssv2.getCvssData().getBaseScore());
1219 setUpdateColumn(callUpdate, 12, cvssv2.getCvssData().getAccessVector());
1220 setUpdateColumn(callUpdate, 13, cvssv2.getCvssData().getAccessComplexity());
1221 setUpdateColumn(callUpdate, 14, cvssv2.getCvssData().getAuthentication());
1222 setUpdateColumn(callUpdate, 15, cvssv2.getCvssData().getConfidentialityImpact());
1223 setUpdateColumn(callUpdate, 16, cvssv2.getCvssData().getIntegrityImpact());
1224 setUpdateColumn(callUpdate, 17, cvssv2.getCvssData().getAvailabilityImpact());
1225 setUpdateColumn(callUpdate, 18, cvssv2.getCvssData().getVersion());
1226 } else {
1227 callUpdate.setNull(3, java.sql.Types.VARCHAR);
1228 callUpdate.setNull(4, java.sql.Types.DOUBLE);
1229 callUpdate.setNull(5, java.sql.Types.DOUBLE);
1230 callUpdate.setNull(6, java.sql.Types.VARCHAR);
1231
1232
1233 if (isOracle) {
1234 callUpdate.setNull(7, java.sql.Types.BIT);
1235 callUpdate.setNull(8, java.sql.Types.BIT);
1236 callUpdate.setNull(9, java.sql.Types.BIT);
1237 callUpdate.setNull(10, java.sql.Types.BIT);
1238 } else {
1239 callUpdate.setNull(7, java.sql.Types.BOOLEAN);
1240 callUpdate.setNull(8, java.sql.Types.BOOLEAN);
1241 callUpdate.setNull(9, java.sql.Types.BOOLEAN);
1242 callUpdate.setNull(10, java.sql.Types.BOOLEAN);
1243 }
1244 callUpdate.setNull(11, java.sql.Types.DOUBLE);
1245 callUpdate.setNull(12, java.sql.Types.VARCHAR);
1246 callUpdate.setNull(13, java.sql.Types.VARCHAR);
1247 callUpdate.setNull(14, java.sql.Types.VARCHAR);
1248 callUpdate.setNull(15, java.sql.Types.VARCHAR);
1249 callUpdate.setNull(16, java.sql.Types.VARCHAR);
1250 callUpdate.setNull(17, java.sql.Types.VARCHAR);
1251 callUpdate.setNull(18, java.sql.Types.VARCHAR);
1252 }
1253 Optional<CvssV3> optCvssv30 = Optional.empty();
1254 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV30() != null) {
1255 optCvssv30 = cve.getCve().getMetrics().getCvssMetricV30().stream().sorted(Comparator.comparing(CvssV3::getType)).findFirst();
1256 }
1257 Optional<CvssV3> optCvssv31 = Optional.empty();
1258 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV31() != null) {
1259 optCvssv31 = cve.getCve().getMetrics().getCvssMetricV31().stream().sorted(Comparator.comparing(CvssV3::getType)).findFirst();
1260 }
1261
1262 CvssV3 cvssv3 = null;
1263 if (optCvssv31.isPresent()) {
1264 cvssv3 = optCvssv31.get();
1265 } else if (optCvssv30.isPresent()) {
1266 cvssv3 = optCvssv30.get();
1267 }
1268 if (cvssv3 != null) {
1269 setUpdateColumn(callUpdate, 19, cvssv3.getExploitabilityScore());
1270 setUpdateColumn(callUpdate, 20, cvssv3.getImpactScore());
1271 setUpdateColumn(callUpdate, 21, cvssv3.getCvssData().getAttackVector());
1272 setUpdateColumn(callUpdate, 22, cvssv3.getCvssData().getAttackComplexity());
1273 setUpdateColumn(callUpdate, 23, cvssv3.getCvssData().getPrivilegesRequired());
1274 setUpdateColumn(callUpdate, 24, cvssv3.getCvssData().getUserInteraction());
1275 setUpdateColumn(callUpdate, 25, cvssv3.getCvssData().getScope());
1276 setUpdateColumn(callUpdate, 26, cvssv3.getCvssData().getConfidentialityImpact());
1277 setUpdateColumn(callUpdate, 27, cvssv3.getCvssData().getIntegrityImpact());
1278 setUpdateColumn(callUpdate, 28, cvssv3.getCvssData().getAvailabilityImpact());
1279 setUpdateColumn(callUpdate, 29, cvssv3.getCvssData().getBaseScore());
1280 setUpdateColumn(callUpdate, 30, cvssv3.getCvssData().getBaseSeverity());
1281 setUpdateColumn(callUpdate, 31, cvssv3.getCvssData().getVersion());
1282 } else {
1283 callUpdate.setNull(19, java.sql.Types.DOUBLE);
1284 callUpdate.setNull(20, java.sql.Types.DOUBLE);
1285 callUpdate.setNull(21, java.sql.Types.VARCHAR);
1286 callUpdate.setNull(22, java.sql.Types.VARCHAR);
1287 callUpdate.setNull(23, java.sql.Types.VARCHAR);
1288 callUpdate.setNull(24, java.sql.Types.VARCHAR);
1289 callUpdate.setNull(25, java.sql.Types.VARCHAR);
1290 callUpdate.setNull(26, java.sql.Types.VARCHAR);
1291 callUpdate.setNull(27, java.sql.Types.VARCHAR);
1292 callUpdate.setNull(28, java.sql.Types.VARCHAR);
1293 callUpdate.setNull(29, java.sql.Types.DOUBLE);
1294 callUpdate.setNull(30, java.sql.Types.VARCHAR);
1295 callUpdate.setNull(31, java.sql.Types.VARCHAR);
1296 }
1297
1298 Optional<CvssV4> optCvssv4 = null;
1299 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV40() != null) {
1300 optCvssv4 = cve.getCve().getMetrics().getCvssMetricV40().stream().sorted(Comparator.comparing(CvssV4::getType)).findFirst();
1301 }
1302 if (optCvssv4 != null && optCvssv4.isPresent()) {
1303 final CvssV4 cvssv4 = optCvssv4.get();
1304 setUpdateColumn(callUpdate, 32, cvssv4.getCvssData().getVersion());
1305 setUpdateColumn(callUpdate, 33, cvssv4.getCvssData().getAttackVector());
1306 setUpdateColumn(callUpdate, 34, cvssv4.getCvssData().getAttackComplexity());
1307 setUpdateColumn(callUpdate, 35, cvssv4.getCvssData().getAttackRequirements());
1308 setUpdateColumn(callUpdate, 36, cvssv4.getCvssData().getPrivilegesRequired());
1309 setUpdateColumn(callUpdate, 37, cvssv4.getCvssData().getUserInteraction());
1310 setUpdateColumn(callUpdate, 38, cvssv4.getCvssData().getVulnConfidentialityImpact());
1311 setUpdateColumn(callUpdate, 39, cvssv4.getCvssData().getVulnIntegrityImpact());
1312 setUpdateColumn(callUpdate, 40, cvssv4.getCvssData().getVulnAvailabilityImpact());
1313 setUpdateColumn(callUpdate, 41, cvssv4.getCvssData().getSubConfidentialityImpact());
1314 setUpdateColumn(callUpdate, 42, cvssv4.getCvssData().getSubIntegrityImpact());
1315 setUpdateColumn(callUpdate, 43, cvssv4.getCvssData().getSubAvailabilityImpact());
1316 setUpdateColumn(callUpdate, 44, cvssv4.getCvssData().getExploitMaturity());
1317 setUpdateColumn(callUpdate, 45, cvssv4.getCvssData().getConfidentialityRequirement());
1318 setUpdateColumn(callUpdate, 46, cvssv4.getCvssData().getIntegrityRequirement());
1319 setUpdateColumn(callUpdate, 47, cvssv4.getCvssData().getAvailabilityRequirement());
1320 setUpdateColumn(callUpdate, 48, cvssv4.getCvssData().getModifiedAttackVector());
1321 setUpdateColumn(callUpdate, 49, cvssv4.getCvssData().getModifiedAttackComplexity());
1322 setUpdateColumn(callUpdate, 50, cvssv4.getCvssData().getModifiedAttackRequirements());
1323 setUpdateColumn(callUpdate, 51, cvssv4.getCvssData().getModifiedPrivilegesRequired());
1324 setUpdateColumn(callUpdate, 52, cvssv4.getCvssData().getModifiedUserInteraction());
1325 setUpdateColumn(callUpdate, 53, cvssv4.getCvssData().getModifiedVulnConfidentialityImpact());
1326 setUpdateColumn(callUpdate, 54, cvssv4.getCvssData().getModifiedVulnIntegrityImpact());
1327 setUpdateColumn(callUpdate, 55, cvssv4.getCvssData().getModifiedVulnAvailabilityImpact());
1328 setUpdateColumn(callUpdate, 56, cvssv4.getCvssData().getModifiedSubConfidentialityImpact());
1329 setUpdateColumn(callUpdate, 57, cvssv4.getCvssData().getModifiedSubIntegrityImpact());
1330 setUpdateColumn(callUpdate, 58, cvssv4.getCvssData().getModifiedSubAvailabilityImpact());
1331 setUpdateColumn(callUpdate, 59, cvssv4.getCvssData().getSafety());
1332 setUpdateColumn(callUpdate, 60, cvssv4.getCvssData().getAutomatable());
1333 setUpdateColumn(callUpdate, 61, cvssv4.getCvssData().getRecovery());
1334 setUpdateColumn(callUpdate, 62, cvssv4.getCvssData().getValueDensity());
1335 setUpdateColumn(callUpdate, 63, cvssv4.getCvssData().getVulnerabilityResponseEffort());
1336 setUpdateColumn(callUpdate, 64, cvssv4.getCvssData().getProviderUrgency());
1337 setUpdateColumn(callUpdate, 65, cvssv4.getCvssData().getBaseScore());
1338 setUpdateColumn(callUpdate, 66, cvssv4.getCvssData().getBaseSeverity());
1339 setUpdateColumn(callUpdate, 67, cvssv4.getCvssData().getThreatScore());
1340 setUpdateColumn(callUpdate, 68, cvssv4.getCvssData().getThreatSeverity());
1341 setUpdateColumn(callUpdate, 69, cvssv4.getCvssData().getEnvironmentalScore());
1342 setUpdateColumn(callUpdate, 70, cvssv4.getCvssData().getEnvironmentalSeverity());
1343 setUpdateColumn(callUpdate, 71, cvssv4.getSource());
1344 setUpdateColumn(callUpdate, 72, cvssv4.getType());
1345 } else {
1346 callUpdate.setNull(32, java.sql.Types.VARCHAR);
1347 callUpdate.setNull(33, java.sql.Types.VARCHAR);
1348 callUpdate.setNull(34, java.sql.Types.VARCHAR);
1349 callUpdate.setNull(35, java.sql.Types.VARCHAR);
1350 callUpdate.setNull(36, java.sql.Types.VARCHAR);
1351 callUpdate.setNull(37, java.sql.Types.VARCHAR);
1352 callUpdate.setNull(38, java.sql.Types.VARCHAR);
1353 callUpdate.setNull(39, java.sql.Types.VARCHAR);
1354 callUpdate.setNull(40, java.sql.Types.VARCHAR);
1355 callUpdate.setNull(41, java.sql.Types.VARCHAR);
1356 callUpdate.setNull(42, java.sql.Types.VARCHAR);
1357 callUpdate.setNull(43, java.sql.Types.VARCHAR);
1358 callUpdate.setNull(44, java.sql.Types.VARCHAR);
1359 callUpdate.setNull(45, java.sql.Types.VARCHAR);
1360 callUpdate.setNull(46, java.sql.Types.VARCHAR);
1361 callUpdate.setNull(47, java.sql.Types.VARCHAR);
1362 callUpdate.setNull(48, java.sql.Types.VARCHAR);
1363 callUpdate.setNull(49, java.sql.Types.VARCHAR);
1364 callUpdate.setNull(50, java.sql.Types.VARCHAR);
1365 callUpdate.setNull(51, java.sql.Types.VARCHAR);
1366 callUpdate.setNull(52, java.sql.Types.VARCHAR);
1367 callUpdate.setNull(53, java.sql.Types.VARCHAR);
1368 callUpdate.setNull(54, java.sql.Types.VARCHAR);
1369 callUpdate.setNull(55, java.sql.Types.VARCHAR);
1370 callUpdate.setNull(56, java.sql.Types.VARCHAR);
1371 callUpdate.setNull(57, java.sql.Types.VARCHAR);
1372 callUpdate.setNull(58, java.sql.Types.VARCHAR);
1373 callUpdate.setNull(59, java.sql.Types.VARCHAR);
1374 callUpdate.setNull(60, java.sql.Types.VARCHAR);
1375 callUpdate.setNull(61, java.sql.Types.VARCHAR);
1376 callUpdate.setNull(62, java.sql.Types.VARCHAR);
1377 callUpdate.setNull(63, java.sql.Types.VARCHAR);
1378 callUpdate.setNull(64, java.sql.Types.VARCHAR);
1379 callUpdate.setNull(65, java.sql.Types.DOUBLE);
1380 callUpdate.setNull(66, java.sql.Types.VARCHAR);
1381 callUpdate.setNull(67, java.sql.Types.DOUBLE);
1382 callUpdate.setNull(68, java.sql.Types.VARCHAR);
1383 callUpdate.setNull(69, java.sql.Types.DOUBLE);
1384 callUpdate.setNull(70, java.sql.Types.VARCHAR);
1385 callUpdate.setNull(71, java.sql.Types.VARCHAR);
1386 callUpdate.setNull(72, java.sql.Types.VARCHAR);
1387 }
1388 if (isOracle) {
1389 try {
1390 final CallableStatement cs = (CallableStatement) callUpdate;
1391 cs.registerOutParameter(73, JDBCType.INTEGER);
1392 cs.executeUpdate();
1393 vulnerabilityId = cs.getInt(73);
1394 } catch (SQLException ex) {
1395 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getId());
1396 throw new DatabaseException(msg, ex);
1397 }
1398 } else {
1399 try (ResultSet rs = callUpdate.executeQuery()) {
1400 rs.next();
1401 vulnerabilityId = rs.getInt(1);
1402 } catch (SQLException ex) {
1403 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getId());
1404 throw new DatabaseException(msg, ex);
1405 }
1406 }
1407 } catch (SQLException ex) {
1408 throw new UnexpectedAnalysisException(ex);
1409 }
1410 return vulnerabilityId;
1411 }
1412
1413
1414
1415
1416
1417
1418
1419
1420 private void updateVulnerabilityInsertCwe(int vulnerabilityId, DefCveItem cve) throws SQLException {
1421 if (cve.getCve() != null && cve.getCve().getWeaknesses() != null) {
1422 try (Connection conn = databaseManager.getConnection();
1423 PreparedStatement insertCWE = getPreparedStatement(conn, INSERT_CWE, vulnerabilityId)) {
1424 for (Weakness weakness : cve.getCve().getWeaknesses()) {
1425 for (LangString desc : weakness.getDescription()) {
1426 if ("en".equals(desc.getLang())) {
1427 insertCWE.setString(2, desc.getValue());
1428 if (isBatchInsertEnabled()) {
1429 insertCWE.addBatch();
1430 } else {
1431 insertCWE.execute();
1432 }
1433 }
1434 }
1435 }
1436 if (isBatchInsertEnabled()) {
1437 insertCWE.executeBatch();
1438 }
1439 }
1440 }
1441 }
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451 private void deleteVulnerability(String cve) throws SQLException {
1452 try (Connection conn = databaseManager.getConnection();
1453 PreparedStatement deleteVulnerability = getPreparedStatement(conn, DELETE_VULNERABILITY, cve)) {
1454 deleteVulnerability.executeUpdate();
1455 }
1456 }
1457
1458
1459
1460
1461
1462
1463
1464
1465 public void updateKnownExploitedVulnerabilities(
1466 List<org.owasp.dependencycheck.data.knownexploited.json.Vulnerability> vulnerabilities)
1467 throws DatabaseException, SQLException {
1468 try (Connection conn = databaseManager.getConnection();
1469 PreparedStatement mergeKnownVulnerability = getPreparedStatement(conn, MERGE_KNOWN_EXPLOITED)) {
1470 int ctr = 0;
1471 for (org.owasp.dependencycheck.data.knownexploited.json.Vulnerability v : vulnerabilities) {
1472 mergeKnownVulnerability.setString(1, v.getCveID());
1473 addNullableStringParameter(mergeKnownVulnerability, 2, v.getVendorProject());
1474 addNullableStringParameter(mergeKnownVulnerability, 3, v.getProduct());
1475 addNullableStringParameter(mergeKnownVulnerability, 4, v.getVulnerabilityName());
1476 addNullableStringParameter(mergeKnownVulnerability, 5, v.getDateAdded());
1477 addNullableStringParameter(mergeKnownVulnerability, 6, v.getShortDescription());
1478 addNullableStringParameter(mergeKnownVulnerability, 7, v.getRequiredAction());
1479 addNullableStringParameter(mergeKnownVulnerability, 8, v.getDueDate());
1480 addNullableStringParameter(mergeKnownVulnerability, 9, v.getNotes());
1481 if (isBatchInsertEnabled()) {
1482 mergeKnownVulnerability.addBatch();
1483 ctr++;
1484 if (ctr >= getBatchSize()) {
1485 mergeKnownVulnerability.executeBatch();
1486 ctr = 0;
1487 }
1488 } else {
1489 try {
1490 mergeKnownVulnerability.execute();
1491 } catch (SQLException ex) {
1492 if (ex.getMessage().contains("Duplicate entry")) {
1493 final String msg = String.format("Duplicate known exploited vulnerability key identified in '%s'", v.getCveID());
1494 LOGGER.info(msg, ex);
1495 } else {
1496 throw ex;
1497 }
1498 }
1499 }
1500 }
1501 if (isBatchInsertEnabled()) {
1502 mergeKnownVulnerability.executeBatch();
1503 }
1504 }
1505 }
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519 private void updateVulnerabilityInsertSoftware(int vulnerabilityId, String cveId,
1520 List<VulnerableSoftware> software, String baseEcosystem)
1521 throws DatabaseException, SQLException {
1522 try (Connection conn = databaseManager.getConnection(); PreparedStatement insertSoftware = getPreparedStatement(conn, INSERT_SOFTWARE)) {
1523 for (VulnerableSoftware parsedCpe : software) {
1524 insertSoftware.setInt(1, vulnerabilityId);
1525 insertSoftware.setString(2, parsedCpe.getPart().getAbbreviation());
1526 insertSoftware.setString(3, parsedCpe.getVendor());
1527 insertSoftware.setString(4, parsedCpe.getProduct());
1528 insertSoftware.setString(5, parsedCpe.getVersion());
1529 insertSoftware.setString(6, parsedCpe.getUpdate());
1530 insertSoftware.setString(7, parsedCpe.getEdition());
1531 insertSoftware.setString(8, parsedCpe.getLanguage());
1532 insertSoftware.setString(9, parsedCpe.getSwEdition());
1533 insertSoftware.setString(10, parsedCpe.getTargetSw());
1534 insertSoftware.setString(11, parsedCpe.getTargetHw());
1535 insertSoftware.setString(12, parsedCpe.getOther());
1536 final String ecosystem = CpeEcosystemCache.getEcosystem(parsedCpe.getVendor(), parsedCpe.getProduct(),
1537 cveItemConverter.extractEcosystem(baseEcosystem, parsedCpe));
1538
1539 addNullableStringParameter(insertSoftware, 13, ecosystem);
1540 addNullableStringParameter(insertSoftware, 14, parsedCpe.getVersionEndExcluding());
1541 addNullableStringParameter(insertSoftware, 15, parsedCpe.getVersionEndIncluding());
1542 addNullableStringParameter(insertSoftware, 16, parsedCpe.getVersionStartExcluding());
1543 addNullableStringParameter(insertSoftware, 17, parsedCpe.getVersionStartIncluding());
1544 insertSoftware.setBoolean(18, parsedCpe.isVulnerable());
1545
1546 if (isBatchInsertEnabled()) {
1547 insertSoftware.addBatch();
1548 } else {
1549 try {
1550 insertSoftware.execute();
1551 } catch (SQLException ex) {
1552 if (ex.getMessage().contains("Duplicate entry")) {
1553 final String msg = String.format("Duplicate software key identified in '%s'", cveId);
1554 LOGGER.info(msg, ex);
1555 } else {
1556 throw ex;
1557 }
1558 }
1559 }
1560 }
1561 if (isBatchInsertEnabled()) {
1562 executeBatch(cveId, insertSoftware);
1563 }
1564 }
1565 }
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575 private void updateVulnerabilityInsertReferences(int vulnerabilityId, DefCveItem cve) throws SQLException {
1576 try (Connection conn = databaseManager.getConnection(); PreparedStatement insertReference = getPreparedStatement(conn, INSERT_REFERENCE)) {
1577 if (cve.getCve().getReferences() != null) {
1578 for (Reference r : cve.getCve().getReferences()) {
1579 insertReference.setInt(1, vulnerabilityId);
1580 String name = null;
1581 if (r.getTags() != null) {
1582 name = r.getTags().stream().sorted().collect(Collectors.joining(",")).toUpperCase().replaceAll("\\s", "_");
1583 }
1584 if (name != null) {
1585 insertReference.setString(2, name);
1586 } else {
1587 insertReference.setNull(2, java.sql.Types.VARCHAR);
1588 }
1589 if (r.getUrl() != null && !r.getUrl().isEmpty()) {
1590 insertReference.setString(3, r.getUrl());
1591 } else {
1592 insertReference.setNull(3, java.sql.Types.VARCHAR);
1593 }
1594 if (r.getSource() != null && !r.getSource().isEmpty()) {
1595 insertReference.setString(4, r.getSource());
1596 } else {
1597 insertReference.setNull(4, java.sql.Types.VARCHAR);
1598 }
1599 if (isBatchInsertEnabled()) {
1600 insertReference.addBatch();
1601 } else {
1602 insertReference.execute();
1603 }
1604 }
1605 }
1606 if (isBatchInsertEnabled()) {
1607 insertReference.executeBatch();
1608 }
1609 }
1610 }
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620 private List<VulnerableSoftware> parseCpes(DefCveItem cve) throws CpeValidationException {
1621 final List<VulnerableSoftware> software = new ArrayList<>();
1622
1623 final List<CpeMatch> cpeEntries = cve.getCve().getConfigurations().stream()
1624 .filter(config -> config.getNodes() != null)
1625 .map(Config::getNodes)
1626 .flatMap(List::stream)
1627 .map(Node::getCpeMatch)
1628 .flatMap(List::stream)
1629 .filter(predicate -> predicate.getCriteria() != null)
1630 .filter(predicate -> predicate.getCriteria().startsWith(cpeStartsWithFilter))
1631
1632 .filter(entry -> !("CVE-2009-0754".equals(cve.getCve().getId())
1633 && "cpe:2.3:a:apache:apache:*:*:*:*:*:*:*:*".equals(entry.getCriteria())))
1634 .collect(Collectors.toList());
1635 final VulnerableSoftwareBuilder builder = new VulnerableSoftwareBuilder();
1636
1637 try {
1638 cpeEntries.forEach(entry -> {
1639 builder.cpe(parseCpe(entry, cve.getCve().getId()))
1640 .versionEndExcluding(entry.getVersionEndExcluding())
1641 .versionStartExcluding(entry.getVersionStartExcluding())
1642 .versionEndIncluding(entry.getVersionEndIncluding())
1643 .versionStartIncluding(entry.getVersionStartIncluding())
1644 .vulnerable(entry.getVulnerable());
1645 try {
1646 software.add(builder.build());
1647 } catch (CpeValidationException ex) {
1648 throw new LambdaExceptionWrapper(ex);
1649 }
1650 });
1651 } catch (LambdaExceptionWrapper ex) {
1652 throw (CpeValidationException) ex.getCause();
1653 }
1654 return software;
1655 }
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668 private Cpe parseCpe(CpeMatch cpe, String cveId) throws DatabaseException {
1669 final Cpe parsedCpe;
1670 try {
1671
1672 parsedCpe = CpeParser.parse(cpe.getCriteria(), true);
1673 } catch (CpeParsingException ex) {
1674 LOGGER.debug("NVD (" + cveId + ") contain an invalid 2.3 CPE: " + cpe.getCriteria());
1675 throw new DatabaseException("Unable to parse CPE: " + cpe.getCriteria(), ex);
1676 }
1677 return parsedCpe;
1678 }
1679
1680
1681
1682
1683
1684
1685 private int getBatchSize() {
1686 int max;
1687 try {
1688 max = settings.getInt(Settings.KEYS.MAX_BATCH_SIZE);
1689 } catch (InvalidSettingException pE) {
1690 max = 1000;
1691 }
1692 return max;
1693 }
1694
1695
1696
1697
1698
1699
1700
1701 private boolean isBatchInsertEnabled() {
1702 boolean batch;
1703 try {
1704 batch = settings.getBoolean(Settings.KEYS.ENABLE_BATCH_UPDATES);
1705 } catch (InvalidSettingException pE) {
1706
1707 batch = false;
1708 }
1709 return batch;
1710 }
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720 private void executeBatch(String vulnId, PreparedStatement statement)
1721 throws SQLException {
1722 try {
1723 statement.executeBatch();
1724 } catch (SQLException ex) {
1725 if (ex.getMessage().contains("Duplicate entry")) {
1726 final String msg = String.format("Duplicate software key identified in '%s'",
1727 vulnId);
1728 LOGGER.info(msg, ex);
1729 } else {
1730 throw ex;
1731 }
1732 }
1733 }
1734
1735
1736
1737
1738
1739
1740 public boolean dataExists() {
1741 try (Connection conn = databaseManager.getConnection();
1742 PreparedStatement cs = getPreparedStatement(conn, COUNT_CPE);
1743 ResultSet rs = cs.executeQuery()) {
1744 if (rs.next() && rs.getInt(1) > 0) {
1745 return true;
1746 }
1747 } catch (Exception ex) {
1748 String dd;
1749 try {
1750 dd = settings.getDataDirectory().getAbsolutePath();
1751 } catch (IOException ex1) {
1752 dd = settings.getString(Settings.KEYS.DATA_DIRECTORY);
1753 }
1754 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. "
1755 + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
1756 + "create a log file (see documentation at https://dependency-check.github.io/DependencyCheck/) and open a ticket at "
1757 + "https://github.com/dependency-check/DependencyCheck/issues and include the log file.\n\n",
1758 dd, dd, settings.getString(Settings.KEYS.APPLICATION_NAME));
1759 LOGGER.debug("", ex);
1760 }
1761 return false;
1762 }
1763
1764
1765
1766
1767
1768
1769 public void cleanupDatabase() {
1770 LOGGER.info("Begin database maintenance");
1771 final long start = System.currentTimeMillis();
1772 try (Connection conn = databaseManager.getConnection();
1773 PreparedStatement psOrphans = getPreparedStatement(conn, CLEANUP_ORPHANS);
1774 PreparedStatement psEcosystem = getPreparedStatement(conn, UPDATE_ECOSYSTEM);
1775 PreparedStatement psEcosystem2 = getPreparedStatement(conn, UPDATE_ECOSYSTEM2)) {
1776 if (psEcosystem != null) {
1777 final int count = psEcosystem.executeUpdate();
1778 if (count > 0) {
1779 LOGGER.info("Updated the CPE ecosystem on {} NVD records", count);
1780 }
1781 }
1782 if (psEcosystem2 != null) {
1783 final int count = psEcosystem2.executeUpdate();
1784 if (count > 0) {
1785 LOGGER.info("Removed the CPE ecosystem on {} NVD records", count);
1786 }
1787 }
1788 if (psOrphans != null) {
1789 final int count = psOrphans.executeUpdate();
1790 if (count > 0) {
1791 LOGGER.info("Cleaned up {} orphaned NVD records", count);
1792 }
1793 }
1794 final long millis = System.currentTimeMillis() - start;
1795
1796 LOGGER.info("End database maintenance ({} ms)", millis);
1797 } catch (SQLException ex) {
1798 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
1799 LOGGER.debug("", ex);
1800 throw new DatabaseException("Unexpected SQL Exception", ex);
1801 }
1802 }
1803
1804
1805
1806
1807 public void persistEcosystemCache() {
1808 saveCpeEcosystemCache();
1809 clearCache();
1810 }
1811
1812
1813
1814
1815
1816 public void defrag() {
1817 if (isH2) {
1818 final long start = System.currentTimeMillis();
1819 try (Connection conn = databaseManager.getConnection(); CallableStatement psCompaxt = conn.prepareCall("SHUTDOWN DEFRAG")) {
1820 LOGGER.info("Begin database defrag");
1821 psCompaxt.execute();
1822 final long millis = System.currentTimeMillis() - start;
1823
1824 LOGGER.info("End database defrag ({} ms)", millis);
1825 } catch (SQLException ex) {
1826 LOGGER.error("An unexpected SQL Exception occurred compacting the database; please see the verbose log for more details.");
1827 LOGGER.debug("", ex);
1828 }
1829 }
1830 }
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842 VulnerableSoftware getMatchingSoftware(Cpe cpe, Set<VulnerableSoftware> vulnerableSoftware) {
1843 VulnerableSoftware matched = null;
1844 for (VulnerableSoftware vs : vulnerableSoftware) {
1845 if (vs.matches(cpe)) {
1846 if (matched == null) {
1847 matched = vs;
1848 } else {
1849 if ("*".equals(vs.getWellFormedUpdate()) && !"*".equals(matched.getWellFormedUpdate())) {
1850 matched = vs;
1851 }
1852 }
1853 }
1854 }
1855 return matched;
1856 }
1857
1858
1859
1860
1861
1862
1863
1864 public void deleteUnusedCpe() {
1865 clearCache();
1866 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, DELETE_UNUSED_DICT_CPE)) {
1867 ps.executeUpdate();
1868 } catch (SQLException ex) {
1869 LOGGER.error("Unable to delete CPE dictionary entries", ex);
1870 }
1871 }
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884 public void addCpe(String cpe, String vendor, String product) {
1885 clearCache();
1886 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, ADD_DICT_CPE)) {
1887 ps.setString(1, cpe);
1888 ps.setString(2, vendor);
1889 ps.setString(3, product);
1890 ps.executeUpdate();
1891 } catch (SQLException ex) {
1892 LOGGER.error("Unable to add CPE dictionary entry", ex);
1893 }
1894 }
1895
1896
1897
1898
1899
1900
1901 public Map<String, org.owasp.dependencycheck.data.knownexploited.json.Vulnerability> getknownExploitedVulnerabilities() {
1902 final Map<String, org.owasp.dependencycheck.data.knownexploited.json.Vulnerability> known = new HashMap<>();
1903
1904 try (Connection conn = databaseManager.getConnection();
1905 PreparedStatement ps = getPreparedStatement(conn, SELECT_KNOWN_EXPLOITED_VULNERABILITIES);
1906 ResultSet rs = ps.executeQuery()) {
1907
1908 while (rs.next()) {
1909 final org.owasp.dependencycheck.data.knownexploited.json.Vulnerability kev =
1910 new org.owasp.dependencycheck.data.knownexploited.json.Vulnerability();
1911 kev.setCveID(rs.getString(1));
1912 kev.setVendorProject(rs.getString(2));
1913 kev.setProduct(rs.getString(3));
1914 kev.setVulnerabilityName(rs.getString(4));
1915 kev.setDateAdded(rs.getString(5));
1916 kev.setShortDescription(rs.getString(6));
1917 kev.setRequiredAction(rs.getString(7));
1918 kev.setDueDate(rs.getString(8));
1919 kev.setNotes(rs.getString(9));
1920 known.put(kev.getCveID(), kev);
1921 }
1922
1923 } catch (SQLException ex) {
1924 throw new DatabaseException(ex);
1925 }
1926 return known;
1927 }
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937 private void addNullableStringParameter(PreparedStatement ps, int pos, String value) throws SQLException {
1938 if (value == null || value.isEmpty()) {
1939 ps.setNull(pos, java.sql.Types.VARCHAR);
1940 } else {
1941 ps.setString(pos, value);
1942 }
1943 }
1944
1945 private void setUpdateColumn(PreparedStatement ps, int i, Double value) throws SQLException {
1946 if (value == null) {
1947 ps.setNull(i, java.sql.Types.DOUBLE);
1948 } else {
1949 ps.setDouble(i, value);
1950 }
1951 }
1952
1953 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AuthenticationType value) throws SQLException {
1954 if (value == null) {
1955 ps.setNull(i, java.sql.Types.VARCHAR);
1956 } else {
1957 ps.setString(i, value.value());
1958 }
1959 }
1960
1961 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.CiaType value) throws SQLException {
1962 if (value == null) {
1963 ps.setNull(i, java.sql.Types.VARCHAR);
1964 } else {
1965 ps.setString(i, value.value());
1966 }
1967 }
1968
1969 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.Version value) throws SQLException {
1970 if (value == null) {
1971 ps.setNull(i, java.sql.Types.VARCHAR);
1972 } else {
1973 ps.setString(i, value.value());
1974 }
1975 }
1976
1977 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AccessComplexityType value) throws SQLException {
1978 if (value == null) {
1979 ps.setNull(i, java.sql.Types.VARCHAR);
1980 } else {
1981 ps.setString(i, value.value());
1982 }
1983 }
1984
1985 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AccessVectorType value) throws SQLException {
1986 if (value == null) {
1987 ps.setNull(i, java.sql.Types.VARCHAR);
1988 } else {
1989 ps.setString(i, value.value());
1990 }
1991 }
1992
1993 private void setUpdateColumn(PreparedStatement ps, int i, String value) throws SQLException {
1994 if (value == null) {
1995 ps.setNull(i, java.sql.Types.VARCHAR);
1996 } else {
1997 ps.setString(i, value);
1998 }
1999 }
2000
2001 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4.Type value) throws SQLException {
2002 if (value == null) {
2003 ps.setNull(i, java.sql.Types.VARCHAR);
2004 } else {
2005 ps.setString(i, value.value());
2006 }
2007 }
2008
2009 private void setUpdateColumn(PreparedStatement ps, int i, Boolean value) throws SQLException {
2010 if (value == null) {
2011
2012
2013 if (isOracle) {
2014 ps.setNull(i, java.sql.Types.BIT);
2015 } else {
2016 ps.setNull(i, java.sql.Types.BOOLEAN);
2017 }
2018 } else {
2019 ps.setBoolean(i, value);
2020 }
2021 }
2022
2023 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.AttackVectorType value) throws SQLException {
2024 if (value == null) {
2025 ps.setNull(i, java.sql.Types.VARCHAR);
2026 } else {
2027 ps.setString(i, value.value());
2028 }
2029 }
2030
2031 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.AttackComplexityType value) throws SQLException {
2032 if (value == null) {
2033 ps.setNull(i, java.sql.Types.VARCHAR);
2034 } else {
2035 ps.setString(i, value.value());
2036 }
2037 }
2038
2039 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.PrivilegesRequiredType value) throws SQLException {
2040 if (value == null) {
2041 ps.setNull(i, java.sql.Types.VARCHAR);
2042 } else {
2043 ps.setString(i, value.value());
2044 }
2045 }
2046
2047 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.UserInteractionType value) throws SQLException {
2048 if (value == null) {
2049 ps.setNull(i, java.sql.Types.VARCHAR);
2050 } else {
2051 ps.setString(i, value.value());
2052 }
2053 }
2054
2055 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.ScopeType value) throws SQLException {
2056 if (value == null) {
2057 ps.setNull(i, java.sql.Types.VARCHAR);
2058 } else {
2059 ps.setString(i, value.value());
2060 }
2061 }
2062
2063 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.SeverityType value) throws SQLException {
2064 if (value == null) {
2065 ps.setNull(i, java.sql.Types.VARCHAR);
2066 } else {
2067 ps.setString(i, value.value());
2068 }
2069 }
2070
2071 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.CiaType value) throws SQLException {
2072 if (value == null) {
2073 ps.setNull(i, java.sql.Types.VARCHAR);
2074 } else {
2075 ps.setString(i, value.value());
2076 }
2077 }
2078
2079 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.Version value) throws SQLException {
2080 if (value == null) {
2081 ps.setNull(i, java.sql.Types.VARCHAR);
2082 } else {
2083 ps.setString(i, value.value());
2084 }
2085 }
2086
2087 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.Version value) throws SQLException {
2088 if (value == null) {
2089 ps.setNull(i, java.sql.Types.VARCHAR);
2090 } else {
2091 ps.setString(i, value.value());
2092 }
2093 }
2094
2095 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackVectorType value) throws SQLException {
2096 if (value == null) {
2097 ps.setNull(i, java.sql.Types.VARCHAR);
2098 } else {
2099 ps.setString(i, value.value());
2100 }
2101 }
2102
2103 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackComplexityType value) throws SQLException {
2104 if (value == null) {
2105 ps.setNull(i, java.sql.Types.VARCHAR);
2106 } else {
2107 ps.setString(i, value.value());
2108 }
2109 }
2110
2111 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackRequirementsType value) throws SQLException {
2112 if (value == null) {
2113 ps.setNull(i, java.sql.Types.VARCHAR);
2114 } else {
2115 ps.setString(i, value.value());
2116 }
2117 }
2118
2119 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.PrivilegesRequiredType value) throws SQLException {
2120 if (value == null) {
2121 ps.setNull(i, java.sql.Types.VARCHAR);
2122 } else {
2123 ps.setString(i, value.value());
2124 }
2125 }
2126
2127 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.UserInteractionType value) throws SQLException {
2128 if (value == null) {
2129 ps.setNull(i, java.sql.Types.VARCHAR);
2130 } else {
2131 ps.setString(i, value.value());
2132 }
2133 }
2134
2135 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.CiaType value) throws SQLException {
2136 if (value == null) {
2137 ps.setNull(i, java.sql.Types.VARCHAR);
2138 } else {
2139 ps.setString(i, value.value());
2140 }
2141 }
2142
2143 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ExploitMaturityType value) throws SQLException {
2144 if (value == null) {
2145 ps.setNull(i, java.sql.Types.VARCHAR);
2146 } else {
2147 ps.setString(i, value.value());
2148 }
2149 }
2150
2151 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.CiaRequirementType value) throws SQLException {
2152 if (value == null) {
2153 ps.setNull(i, java.sql.Types.VARCHAR);
2154 } else {
2155 ps.setString(i, value.value());
2156 }
2157 }
2158
2159 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackVectorType value) throws SQLException {
2160 if (value == null) {
2161 ps.setNull(i, java.sql.Types.VARCHAR);
2162 } else {
2163 ps.setString(i, value.value());
2164 }
2165 }
2166
2167 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackComplexityType value) throws SQLException {
2168 if (value == null) {
2169 ps.setNull(i, java.sql.Types.VARCHAR);
2170 } else {
2171 ps.setString(i, value.value());
2172 }
2173 }
2174
2175 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackRequirementsType value) throws SQLException {
2176 if (value == null) {
2177 ps.setNull(i, java.sql.Types.VARCHAR);
2178 } else {
2179 ps.setString(i, value.value());
2180 }
2181 }
2182
2183 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedPrivilegesRequiredType value) throws SQLException {
2184 if (value == null) {
2185 ps.setNull(i, java.sql.Types.VARCHAR);
2186 } else {
2187 ps.setString(i, value.value());
2188 }
2189 }
2190
2191 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedUserInteractionType value) throws SQLException {
2192 if (value == null) {
2193 ps.setNull(i, java.sql.Types.VARCHAR);
2194 } else {
2195 ps.setString(i, value.value());
2196 }
2197 }
2198
2199 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedCiaType value) throws SQLException {
2200 if (value == null) {
2201 ps.setNull(i, java.sql.Types.VARCHAR);
2202 } else {
2203 ps.setString(i, value.value());
2204 }
2205 }
2206
2207 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedSubCType value) throws SQLException {
2208 if (value == null) {
2209 ps.setNull(i, java.sql.Types.VARCHAR);
2210 } else {
2211 ps.setString(i, value.value());
2212 }
2213 }
2214
2215 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedSubIaType value) throws SQLException {
2216 if (value == null) {
2217 ps.setNull(i, java.sql.Types.VARCHAR);
2218 } else {
2219 ps.setString(i, value.value());
2220 }
2221 }
2222
2223 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.SafetyType value) throws SQLException {
2224 if (value == null) {
2225 ps.setNull(i, java.sql.Types.VARCHAR);
2226 } else {
2227 ps.setString(i, value.value());
2228 }
2229 }
2230
2231 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AutomatableType value) throws SQLException {
2232 if (value == null) {
2233 ps.setNull(i, java.sql.Types.VARCHAR);
2234 } else {
2235 ps.setString(i, value.value());
2236 }
2237 }
2238
2239 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.RecoveryType value) throws SQLException {
2240 if (value == null) {
2241 ps.setNull(i, java.sql.Types.VARCHAR);
2242 } else {
2243 ps.setString(i, value.value());
2244 }
2245 }
2246
2247 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ValueDensityType value) throws SQLException {
2248 if (value == null) {
2249 ps.setNull(i, java.sql.Types.VARCHAR);
2250 } else {
2251 ps.setString(i, value.value());
2252 }
2253 }
2254
2255 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.VulnerabilityResponseEffortType value) throws SQLException {
2256 if (value == null) {
2257 ps.setNull(i, java.sql.Types.VARCHAR);
2258 } else {
2259 ps.setString(i, value.value());
2260 }
2261 }
2262
2263 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ProviderUrgencyType value) throws SQLException {
2264 if (value == null) {
2265 ps.setNull(i, java.sql.Types.VARCHAR);
2266 } else {
2267 ps.setString(i, value.value());
2268 }
2269 }
2270
2271 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.SeverityType value) throws SQLException {
2272 if (value == null) {
2273 ps.setNull(i, java.sql.Types.VARCHAR);
2274 } else {
2275 ps.setString(i, value.value());
2276 }
2277 }
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288 private void setFloatValue(PreparedStatement ps, int i, Map<String, Object> props, String key) throws SQLException {
2289 if (props != null && props.containsKey(key)) {
2290 try {
2291 ps.setFloat(i, Float.parseFloat(props.get(key).toString()));
2292 } catch (NumberFormatException nfe) {
2293 ps.setNull(i, java.sql.Types.FLOAT);
2294 }
2295 } else {
2296 ps.setNull(i, java.sql.Types.FLOAT);
2297 }
2298 }
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309 private void setStringValue(PreparedStatement ps, int i, Map<String, Object> props, String key) throws SQLException {
2310 if (props != null && props.containsKey(key)) {
2311 ps.setString(i, props.get(key).toString());
2312 } else {
2313 ps.setNull(i, java.sql.Types.VARCHAR);
2314 }
2315 }
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326 private void setBooleanValue(PreparedStatement ps, int i, Map<String, Object> props, String key) throws SQLException {
2327 if (props != null && props.containsKey(key)) {
2328 ps.setBoolean(i, Boolean.parseBoolean(props.get(key).toString()));
2329 } else {
2330 ps.setNull(i, java.sql.Types.BOOLEAN);
2331 }
2332 }
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343 @SuppressFBWarnings("NP_BOOLEAN_RETURN_NULL")
2344 private Boolean getBooleanValue(ResultSet rs, int index) throws SQLException {
2345 if (rs.getObject(index) == null) {
2346 return null;
2347 }
2348 return rs.getBoolean(index);
2349 }
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360 private Float getFloatValue(ResultSet rs, int index) throws SQLException {
2361 if (rs.getObject(index) == null) {
2362 return null;
2363 }
2364 return rs.getFloat(index);
2365 }
2366 }