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