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.collections.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.collections.map.AbstractReferenceMap.HARD;
48 import static org.apache.commons.collections.map.AbstractReferenceMap.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
745 String cveVersion = "2.0";
746 if (rsV.getString(18) != null) {
747 cveVersion = rsV.getString(18);
748 }
749 final CvssV2Data cvssData = new CvssV2Data(cveVersion, vector, accessVector,
750 accessComplexity, authentication, confidentialityImpact,
751 integrityImpact, availabilityImpact, rsV.getDouble(11), rsV.getString(3),
752 null, null, null, null, null, null, null, null, null, null);
753 final CvssV2 cvss = new CvssV2(null, CvssV2.Type.PRIMARY, cvssData, rsV.getString(3),
754 rsV.getDouble(4), rsV.getDouble(5), rsV.getBoolean(6), rsV.getBoolean(7),
755 rsV.getBoolean(8), rsV.getBoolean(9), rsV.getBoolean(10));
756 vuln.setCvssV2(cvss);
757 }
758
759
760
761 if (rsV.getObject(21) != null) {
762
763 String cveVersion = "3.1";
764 if (rsV.getString(31) != null) {
765 cveVersion = rsV.getString(31);
766 }
767 final CvssV3Data.Version version = CvssV3Data.Version.fromValue(cveVersion);
768 final CvssV3Data.AttackVectorType attackVector = CvssV3Data.AttackVectorType.fromValue(rsV.getString(21));
769 final CvssV3Data.AttackComplexityType attackComplexity = CvssV3Data.AttackComplexityType.fromValue(rsV.getString(22));
770 final CvssV3Data.PrivilegesRequiredType privilegesRequired = CvssV3Data.PrivilegesRequiredType.fromValue(rsV.getString(23));
771 final CvssV3Data.UserInteractionType userInteraction = CvssV3Data.UserInteractionType.fromValue(rsV.getString(24));
772 final CvssV3Data.ScopeType scope = CvssV3Data.ScopeType.fromValue(rsV.getString(25));
773 final CvssV3Data.CiaType confidentialityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(26));
774 final CvssV3Data.CiaType integrityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(27));
775 final CvssV3Data.CiaType availabilityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(28));
776 final CvssV3Data.SeverityType baseSeverity = CvssV3Data.SeverityType.fromValue(rsV.getString(30));
777 final String vector = String.format("CVSS:%s/AV:%s/AC:%s/PR:%s/UI:%s/S:%s/C:%s/I:%s/A:%s",
778 version == null ? "" : version,
779 attackVector == null ? "" : attackVector.value().substring(0, 1),
780 attackComplexity == null ? "" : attackComplexity.value().substring(0, 1),
781 privilegesRequired == null ? "" : privilegesRequired.value().substring(0, 1),
782 userInteraction == null ? "" : userInteraction.value().substring(0, 1),
783 scope == null ? "" : scope.value().substring(0, 1),
784 confidentialityImpact == null ? "" : confidentialityImpact.value().substring(0, 1),
785 integrityImpact == null ? "" : integrityImpact.value().substring(0, 1),
786 availabilityImpact == null ? "" : availabilityImpact.value().substring(0, 1));
787
788 final CvssV3Data cvssData = new CvssV3Data(version, vector, attackVector, attackComplexity, privilegesRequired,
789 userInteraction, scope, confidentialityImpact, integrityImpact, availabilityImpact,
790 rsV.getDouble(29), baseSeverity, CvssV3Data.ExploitCodeMaturityType.PROOF_OF_CONCEPT,
791 CvssV3Data.RemediationLevelType.NOT_DEFINED, CvssV3Data.ConfidenceType.REASONABLE, 0.0,
792 CvssV3Data.SeverityType.MEDIUM, CvssV3Data.CiaRequirementType.NOT_DEFINED,
793 CvssV3Data.CiaRequirementType.NOT_DEFINED, CvssV3Data.CiaRequirementType.NOT_DEFINED,
794 CvssV3Data.ModifiedAttackVectorType.ADJACENT_NETWORK, CvssV3Data.ModifiedAttackComplexityType.NOT_DEFINED,
795 CvssV3Data.ModifiedPrivilegesRequiredType.NOT_DEFINED, CvssV3Data.ModifiedUserInteractionType.NOT_DEFINED,
796 CvssV3Data.ModifiedScopeType.NOT_DEFINED, CvssV3Data.ModifiedCiaType.NOT_DEFINED,
797 CvssV3Data.ModifiedCiaType.NOT_DEFINED, CvssV3Data.ModifiedCiaType.NOT_DEFINED, 1.0,
798 CvssV3Data.SeverityType.NONE);
799 final CvssV3 cvss = new CvssV3(null, null, cvssData, rsV.getDouble(19), rsV.getDouble(20));
800 vuln.setCvssV3(cvss);
801 }
802
803
804
805
806
807
808
809
810
811
812 if (rsV.getObject(33) != null) {
813 String vectorString = null;
814
815 String value = rsV.getString(32);
816 final CvssV4Data.Version version = CvssV4Data.Version.fromValue(value);
817 CvssV4Data.AttackVectorType attackVector = null;
818 value = rsV.getString(33);
819 if (value != null) {
820 attackVector = CvssV4Data.AttackVectorType.fromValue(value);
821 }
822 CvssV4Data.AttackComplexityType attackComplexity = null;
823 value = rsV.getString(34);
824 if (value != null) {
825 attackComplexity = CvssV4Data.AttackComplexityType.fromValue(value);
826 }
827 CvssV4Data.AttackRequirementsType attackRequirements = null;
828 value = rsV.getString(35);
829 if (value != null) {
830 attackRequirements = CvssV4Data.AttackRequirementsType.fromValue(value);
831 }
832 CvssV4Data.PrivilegesRequiredType privilegesRequired = null;
833 value = rsV.getString(36);
834 if (value != null) {
835 privilegesRequired = CvssV4Data.PrivilegesRequiredType.fromValue(value);
836 }
837 CvssV4Data.UserInteractionType userInteraction = null;
838 value = rsV.getString(37);
839 if (value != null) {
840 userInteraction = CvssV4Data.UserInteractionType.fromValue(value);
841 }
842 CvssV4Data.CiaType vulnConfidentialityImpact = null;
843 value = rsV.getString(38);
844 if (value != null) {
845 vulnConfidentialityImpact = CvssV4Data.CiaType.fromValue(value);
846 }
847 CvssV4Data.CiaType vulnIntegrityImpact = null;
848 value = rsV.getString(39);
849 if (value != null) {
850 vulnIntegrityImpact = CvssV4Data.CiaType.fromValue(value);
851 }
852 CvssV4Data.CiaType vulnAvailabilityImpact = null;
853 value = rsV.getString(40);
854 if (value != null) {
855 vulnAvailabilityImpact = CvssV4Data.CiaType.fromValue(value);
856 }
857 CvssV4Data.CiaType subConfidentialityImpact = null;
858 value = rsV.getString(41);
859 if (value != null) {
860 subConfidentialityImpact = CvssV4Data.CiaType.fromValue(value);
861 }
862 CvssV4Data.CiaType subIntegrityImpact = null;
863 value = rsV.getString(42);
864 if (value != null) {
865 subIntegrityImpact = CvssV4Data.CiaType.fromValue(value);
866 }
867 CvssV4Data.CiaType subAvailabilityImpact = null;
868 value = rsV.getString(43);
869 if (value != null) {
870 subAvailabilityImpact = CvssV4Data.CiaType.fromValue(value);
871 }
872 CvssV4Data.ExploitMaturityType exploitMaturity = null;
873 value = rsV.getString(44);
874 if (value != null) {
875 exploitMaturity = CvssV4Data.ExploitMaturityType.fromValue(value);
876 }
877 CvssV4Data.CiaRequirementType confidentialityRequirement = null;
878 value = rsV.getString(45);
879 if (value != null) {
880 confidentialityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
881 }
882 CvssV4Data.CiaRequirementType integrityRequirement = null;
883 value = rsV.getString(46);
884 if (value != null) {
885 integrityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
886 }
887 CvssV4Data.CiaRequirementType availabilityRequirement = null;
888 value = rsV.getString(47);
889 if (value != null) {
890 availabilityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
891 }
892 CvssV4Data.ModifiedAttackVectorType modifiedAttackVector = null;
893 value = rsV.getString(48);
894 if (value != null) {
895 modifiedAttackVector = CvssV4Data.ModifiedAttackVectorType.fromValue(value);
896 }
897 CvssV4Data.ModifiedAttackComplexityType modifiedAttackComplexity = null;
898 value = rsV.getString(49);
899 if (value != null) {
900 modifiedAttackComplexity = CvssV4Data.ModifiedAttackComplexityType.fromValue(value);
901 }
902 CvssV4Data.ModifiedAttackRequirementsType modifiedAttackRequirements = null;
903 value = rsV.getString(50);
904 if (value != null) {
905 modifiedAttackRequirements = CvssV4Data.ModifiedAttackRequirementsType.fromValue(value);
906 }
907 CvssV4Data.ModifiedPrivilegesRequiredType modifiedPrivilegesRequired = null;
908 value = rsV.getString(51);
909 if (value != null) {
910 modifiedPrivilegesRequired = CvssV4Data.ModifiedPrivilegesRequiredType.fromValue(value);
911 }
912 CvssV4Data.ModifiedUserInteractionType modifiedUserInteraction = null;
913 value = rsV.getString(52);
914 if (value != null) {
915 modifiedUserInteraction = CvssV4Data.ModifiedUserInteractionType.fromValue(value);
916 }
917 CvssV4Data.ModifiedCiaType modifiedVulnConfidentialityImpact = null;
918 value = rsV.getString(53);
919 if (value != null) {
920 modifiedVulnConfidentialityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
921 }
922 CvssV4Data.ModifiedCiaType modifiedVulnIntegrityImpact = null;
923 value = rsV.getString(54);
924 if (value != null) {
925 modifiedVulnIntegrityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
926 }
927 CvssV4Data.ModifiedCiaType modifiedVulnAvailabilityImpact = null;
928 value = rsV.getString(55);
929 if (value != null) {
930 modifiedVulnAvailabilityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
931 }
932 CvssV4Data.ModifiedCiaType modifiedSubConfidentialityImpact = null;
933 value = rsV.getString(56);
934 if (value != null) {
935 modifiedSubConfidentialityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
936 }
937 CvssV4Data.ModifiedCiaType modifiedSubIntegrityImpact = null;
938 value = rsV.getString(57);
939 if (value != null) {
940 modifiedSubIntegrityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
941 }
942 CvssV4Data.ModifiedCiaType modifiedSubAvailabilityImpact = null;
943 value = rsV.getString(58);
944 if (value != null) {
945 modifiedSubAvailabilityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
946 }
947 CvssV4Data.SafetyType safety = null;
948 value = rsV.getString(59);
949 if (value != null) {
950 safety = CvssV4Data.SafetyType.fromValue(value);
951 }
952 CvssV4Data.AutomatableType automatable = null;
953 value = rsV.getString(60);
954 if (value != null) {
955 automatable = CvssV4Data.AutomatableType.fromValue(value);
956 }
957 CvssV4Data.RecoveryType recovery = null;
958 value = rsV.getString(61);
959 if (value != null) {
960 recovery = CvssV4Data.RecoveryType.fromValue(value);
961 }
962 CvssV4Data.ValueDensityType valueDensity = null;
963 value = rsV.getString(62);
964 if (value != null) {
965 valueDensity = CvssV4Data.ValueDensityType.fromValue(value);
966 }
967 CvssV4Data.VulnerabilityResponseEffortType vulnerabilityResponseEffort = null;
968 value = rsV.getString(63);
969 if (value != null) {
970 vulnerabilityResponseEffort = CvssV4Data.VulnerabilityResponseEffortType.fromValue(value);
971 }
972 CvssV4Data.ProviderUrgencyType providerUrgency = null;
973 value = rsV.getString(64);
974 if (value != null) {
975 providerUrgency = CvssV4Data.ProviderUrgencyType.fromValue(value);
976 }
977 Double baseScore = null;
978 if (rsV.getObject(65) != null) {
979 baseScore = rsV.getDouble(65);
980 }
981 CvssV4Data.SeverityType baseSeverity = null;
982 value = rsV.getString(66);
983 if (value != null) {
984 baseSeverity = CvssV4Data.SeverityType.fromValue(value);
985 }
986 Double threatScore = null;
987 if (rsV.getObject(67) != null) {
988 threatScore = rsV.getDouble(67);
989 }
990 CvssV4Data.SeverityType threatSeverity = null;
991 value = rsV.getString(68);
992 if (value != null) {
993 threatSeverity = CvssV4Data.SeverityType.fromValue(value);
994 }
995 Double environmentalScore = null;
996 if (rsV.getObject(69) != null) {
997 environmentalScore = rsV.getDouble(69);
998 }
999 CvssV4Data.SeverityType environmentalSeverity = null;
1000 value = rsV.getString(70);
1001 if (value != null) {
1002 environmentalSeverity = CvssV4Data.SeverityType.fromValue(value);
1003 }
1004
1005 CvssV4Data data = new CvssV4Data(version, vectorString, attackVector, attackComplexity, attackRequirements, privilegesRequired,
1006 userInteraction, vulnConfidentialityImpact, vulnIntegrityImpact, vulnAvailabilityImpact, subConfidentialityImpact,
1007 subIntegrityImpact, subAvailabilityImpact, exploitMaturity, confidentialityRequirement, integrityRequirement,
1008 availabilityRequirement, modifiedAttackVector, modifiedAttackComplexity, modifiedAttackRequirements,
1009 modifiedPrivilegesRequired, modifiedUserInteraction, modifiedVulnConfidentialityImpact, modifiedVulnIntegrityImpact,
1010 modifiedVulnAvailabilityImpact, modifiedSubConfidentialityImpact, modifiedSubIntegrityImpact,
1011 modifiedSubAvailabilityImpact, safety, automatable, recovery, valueDensity, vulnerabilityResponseEffort,
1012 providerUrgency, baseScore, baseSeverity, threatScore, threatSeverity, environmentalScore, environmentalSeverity);
1013 vectorString = data.toString();
1014 data = new CvssV4Data(version, vectorString, attackVector, attackComplexity, attackRequirements, privilegesRequired,
1015 userInteraction, vulnConfidentialityImpact, vulnIntegrityImpact, vulnAvailabilityImpact, subConfidentialityImpact,
1016 subIntegrityImpact, subAvailabilityImpact, exploitMaturity, confidentialityRequirement, integrityRequirement,
1017 availabilityRequirement, modifiedAttackVector, modifiedAttackComplexity, modifiedAttackRequirements,
1018 modifiedPrivilegesRequired, modifiedUserInteraction, modifiedVulnConfidentialityImpact, modifiedVulnIntegrityImpact,
1019 modifiedVulnAvailabilityImpact, modifiedSubConfidentialityImpact, modifiedSubIntegrityImpact,
1020 modifiedSubAvailabilityImpact, safety, automatable, recovery, valueDensity, vulnerabilityResponseEffort,
1021 providerUrgency, baseScore, baseSeverity, threatScore, threatSeverity, environmentalScore, environmentalSeverity);
1022
1023 final String source = rsV.getString(71);
1024 CvssV4.Type cvssType = null;
1025 value = rsV.getString(72);
1026 if (value != null) {
1027 cvssType = CvssV4.Type.fromValue(value);
1028 }
1029 final CvssV4 cvssv4 = new CvssV4(source, cvssType, data);
1030 vuln.setCvssV4(cvssv4);
1031 }
1032 } else {
1033 LOGGER.debug(cve + " does not exist in the database");
1034 return null;
1035 }
1036 }
1037 try (PreparedStatement psCWE = getPreparedStatement(conn, SELECT_VULNERABILITY_CWE, cveId); ResultSet rsC = psCWE.executeQuery()) {
1038 while (rsC.next()) {
1039 vuln.addCwe(rsC.getString(1));
1040 }
1041 }
1042 try (PreparedStatement psR = getPreparedStatement(conn, SELECT_REFERENCES, cveId); ResultSet rsR = psR.executeQuery()) {
1043 while (rsR.next()) {
1044 vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
1045 }
1046 }
1047 try (PreparedStatement psS = getPreparedStatement(conn, SELECT_SOFTWARE, cveId); ResultSet rsS = psS.executeQuery()) {
1048
1049
1050
1051 while (rsS.next()) {
1052 vulnerableSoftwareBuilder.part(rsS.getString(1))
1053 .vendor(rsS.getString(2))
1054 .product(rsS.getString(3))
1055 .version(rsS.getString(4))
1056 .update(rsS.getString(5))
1057 .edition(rsS.getString(6))
1058 .language(rsS.getString(7))
1059 .swEdition(rsS.getString(8))
1060 .targetSw(rsS.getString(9))
1061 .targetHw(rsS.getString(10))
1062 .other(rsS.getString(11))
1063 .versionEndExcluding(rsS.getString(12))
1064 .versionEndIncluding(rsS.getString(13))
1065 .versionStartExcluding(rsS.getString(14))
1066 .versionStartIncluding(rsS.getString(15))
1067 .vulnerable(rsS.getBoolean(16));
1068 vuln.addVulnerableSoftware(vulnerableSoftwareBuilder.build());
1069 }
1070 }
1071 } catch (SQLException ex) {
1072 throw new DatabaseException("Error retrieving " + cve, ex);
1073 } catch (CpeParsingException | CpeValidationException ex) {
1074 throw new DatabaseException("The database contains an invalid Vulnerable Software Entry", ex);
1075 }
1076 return vuln;
1077 }
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 public void updateVulnerability(DefCveItem cve, String baseEcosystem) {
1090 clearCache();
1091 final String cveId = cve.getCve().getId();
1092 try {
1093 if (cve.getCve().getVulnStatus().toUpperCase().startsWith("REJECT")) {
1094 deleteVulnerability(cveId);
1095 } else {
1096 if (cveItemConverter.testCveCpeStartWithFilter(cve)) {
1097 final String description = cveItemConverter.extractDescription(cve);
1098 final int vulnerabilityId = updateOrInsertVulnerability(cve, description);
1099 updateVulnerabilityInsertCwe(vulnerabilityId, cve);
1100 updateVulnerabilityInsertReferences(vulnerabilityId, cve);
1101
1102 final List<VulnerableSoftware> software = parseCpes(cve);
1103 updateVulnerabilityInsertSoftware(vulnerabilityId, cveId, software, baseEcosystem);
1104 }
1105 }
1106 } catch (SQLException ex) {
1107 final String msg = String.format("Error updating '%s'; %s", cveId, ex.getMessage());
1108 LOGGER.debug(msg, ex);
1109 throw new DatabaseException(msg);
1110 } catch (CpeValidationException ex) {
1111 final String msg = String.format("Error parsing CPE entry from '%s'; %s", cveId, ex.getMessage());
1112 LOGGER.debug(msg, ex);
1113 throw new DatabaseException(msg);
1114 }
1115 }
1116
1117 private void loadCpeEcosystemCache() {
1118 final Map<Pair<String, String>, String> map = new HashMap<>();
1119 try (Connection conn = databaseManager.getConnection();
1120 PreparedStatement ps = getPreparedStatement(conn, SELECT_CPE_ECOSYSTEM);
1121 ResultSet rs = ps.executeQuery()) {
1122 while (rs.next()) {
1123 final Pair<String, String> key = new Pair<>(rs.getString(1), rs.getString(2));
1124 final String value = rs.getString(3);
1125 map.put(key, value);
1126 }
1127 } catch (SQLException ex) {
1128 final String msg = String.format("Error loading the Cpe Ecosystem Cache: %s", ex.getMessage());
1129 LOGGER.debug(msg, ex);
1130 throw new DatabaseException(msg, ex);
1131 }
1132 CpeEcosystemCache.setCache(map);
1133 }
1134
1135 private void saveCpeEcosystemCache() {
1136 final Map<Pair<String, String>, String> map = CpeEcosystemCache.getChanged();
1137 if (map != null && !map.isEmpty()) {
1138 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, MERGE_CPE_ECOSYSTEM)) {
1139 for (Map.Entry<Pair<String, String>, String> entry : map.entrySet()) {
1140 ps.setString(1, entry.getKey().getLeft());
1141 ps.setString(2, entry.getKey().getRight());
1142 ps.setString(3, entry.getValue());
1143 if (isBatchInsertEnabled()) {
1144 ps.addBatch();
1145 } else {
1146 ps.execute();
1147 }
1148 }
1149 if (isBatchInsertEnabled()) {
1150 ps.executeBatch();
1151 }
1152 } catch (SQLException ex) {
1153 final String msg = String.format("Error saving the Cpe Ecosystem Cache: %s", ex.getMessage());
1154 LOGGER.debug(msg, ex);
1155 throw new DatabaseException(msg, ex);
1156 }
1157 }
1158 }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 private int updateOrInsertVulnerability(DefCveItem cve, String description) {
1169 if (CpeEcosystemCache.isEmpty()) {
1170 loadCpeEcosystemCache();
1171 }
1172 final int vulnerabilityId;
1173 try (Connection conn = databaseManager.getConnection(); PreparedStatement callUpdate = getPreparedStatement(conn, UPDATE_VULNERABILITY)) {
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197 callUpdate.setString(1, cve.getCve().getId());
1198 callUpdate.setString(2, description);
1199 Optional<CvssV2> optCvssv2 = null;
1200 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV2() != null) {
1201 optCvssv2 = cve.getCve().getMetrics().getCvssMetricV2().stream().sorted(Comparator.comparing(CvssV2::getType)).findFirst();
1202 }
1203 if (optCvssv2 != null && optCvssv2.isPresent()) {
1204 final CvssV2 cvssv2 = optCvssv2.get();
1205 setUpdateColumn(callUpdate, 3, cvssv2.getBaseSeverity());
1206 setUpdateColumn(callUpdate, 4, cvssv2.getExploitabilityScore());
1207 setUpdateColumn(callUpdate, 5, cvssv2.getImpactScore());
1208 setUpdateColumn(callUpdate, 6, cvssv2.getAcInsufInfo());
1209 setUpdateColumn(callUpdate, 7, cvssv2.getObtainAllPrivilege());
1210 setUpdateColumn(callUpdate, 8, cvssv2.getObtainUserPrivilege());
1211 setUpdateColumn(callUpdate, 9, cvssv2.getObtainOtherPrivilege());
1212 setUpdateColumn(callUpdate, 10, cvssv2.getUserInteractionRequired());
1213 setUpdateColumn(callUpdate, 11, cvssv2.getCvssData().getBaseScore());
1214 setUpdateColumn(callUpdate, 12, cvssv2.getCvssData().getAccessVector());
1215 setUpdateColumn(callUpdate, 13, cvssv2.getCvssData().getAccessComplexity());
1216 setUpdateColumn(callUpdate, 14, cvssv2.getCvssData().getAuthentication());
1217 setUpdateColumn(callUpdate, 15, cvssv2.getCvssData().getConfidentialityImpact());
1218 setUpdateColumn(callUpdate, 16, cvssv2.getCvssData().getIntegrityImpact());
1219 setUpdateColumn(callUpdate, 17, cvssv2.getCvssData().getAvailabilityImpact());
1220 setUpdateColumn(callUpdate, 18, cvssv2.getCvssData().getVersion());
1221 } else {
1222 callUpdate.setNull(3, java.sql.Types.VARCHAR);
1223 callUpdate.setNull(4, java.sql.Types.DOUBLE);
1224 callUpdate.setNull(5, java.sql.Types.DOUBLE);
1225 callUpdate.setNull(6, java.sql.Types.VARCHAR);
1226
1227
1228 if (isOracle) {
1229 callUpdate.setNull(7, java.sql.Types.BIT);
1230 callUpdate.setNull(8, java.sql.Types.BIT);
1231 callUpdate.setNull(9, java.sql.Types.BIT);
1232 callUpdate.setNull(10, java.sql.Types.BIT);
1233 } else {
1234 callUpdate.setNull(7, java.sql.Types.BOOLEAN);
1235 callUpdate.setNull(8, java.sql.Types.BOOLEAN);
1236 callUpdate.setNull(9, java.sql.Types.BOOLEAN);
1237 callUpdate.setNull(10, java.sql.Types.BOOLEAN);
1238 }
1239 callUpdate.setNull(11, java.sql.Types.DOUBLE);
1240 callUpdate.setNull(12, java.sql.Types.VARCHAR);
1241 callUpdate.setNull(13, java.sql.Types.VARCHAR);
1242 callUpdate.setNull(14, java.sql.Types.VARCHAR);
1243 callUpdate.setNull(15, java.sql.Types.VARCHAR);
1244 callUpdate.setNull(16, java.sql.Types.VARCHAR);
1245 callUpdate.setNull(17, java.sql.Types.VARCHAR);
1246 callUpdate.setNull(18, java.sql.Types.VARCHAR);
1247 }
1248 Optional<CvssV3> optCvssv30 = Optional.empty();
1249 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV30() != null) {
1250 optCvssv30 = cve.getCve().getMetrics().getCvssMetricV30().stream().sorted(Comparator.comparing(CvssV3::getType)).findFirst();
1251 }
1252 Optional<CvssV3> optCvssv31 = Optional.empty();
1253 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV31() != null) {
1254 optCvssv31 = cve.getCve().getMetrics().getCvssMetricV31().stream().sorted(Comparator.comparing(CvssV3::getType)).findFirst();
1255 }
1256
1257 CvssV3 cvssv3 = null;
1258 if (optCvssv31.isPresent()) {
1259 cvssv3 = optCvssv31.get();
1260 } else if (optCvssv30.isPresent()) {
1261 cvssv3 = optCvssv30.get();
1262 }
1263 if (cvssv3 != null) {
1264 setUpdateColumn(callUpdate, 19, cvssv3.getExploitabilityScore());
1265 setUpdateColumn(callUpdate, 20, cvssv3.getImpactScore());
1266 setUpdateColumn(callUpdate, 21, cvssv3.getCvssData().getAttackVector());
1267 setUpdateColumn(callUpdate, 22, cvssv3.getCvssData().getAttackComplexity());
1268 setUpdateColumn(callUpdate, 23, cvssv3.getCvssData().getPrivilegesRequired());
1269 setUpdateColumn(callUpdate, 24, cvssv3.getCvssData().getUserInteraction());
1270 setUpdateColumn(callUpdate, 25, cvssv3.getCvssData().getScope());
1271 setUpdateColumn(callUpdate, 26, cvssv3.getCvssData().getConfidentialityImpact());
1272 setUpdateColumn(callUpdate, 27, cvssv3.getCvssData().getIntegrityImpact());
1273 setUpdateColumn(callUpdate, 28, cvssv3.getCvssData().getAvailabilityImpact());
1274 setUpdateColumn(callUpdate, 29, cvssv3.getCvssData().getBaseScore());
1275 setUpdateColumn(callUpdate, 30, cvssv3.getCvssData().getBaseSeverity());
1276 setUpdateColumn(callUpdate, 31, cvssv3.getCvssData().getVersion());
1277 } else {
1278 callUpdate.setNull(19, java.sql.Types.DOUBLE);
1279 callUpdate.setNull(20, java.sql.Types.DOUBLE);
1280 callUpdate.setNull(21, java.sql.Types.VARCHAR);
1281 callUpdate.setNull(22, java.sql.Types.VARCHAR);
1282 callUpdate.setNull(23, java.sql.Types.VARCHAR);
1283 callUpdate.setNull(24, java.sql.Types.VARCHAR);
1284 callUpdate.setNull(25, java.sql.Types.VARCHAR);
1285 callUpdate.setNull(26, java.sql.Types.VARCHAR);
1286 callUpdate.setNull(27, java.sql.Types.VARCHAR);
1287 callUpdate.setNull(28, java.sql.Types.VARCHAR);
1288 callUpdate.setNull(29, java.sql.Types.DOUBLE);
1289 callUpdate.setNull(30, java.sql.Types.VARCHAR);
1290 callUpdate.setNull(31, java.sql.Types.VARCHAR);
1291 }
1292
1293 Optional<CvssV4> optCvssv4 = null;
1294 if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV40() != null) {
1295 optCvssv4 = cve.getCve().getMetrics().getCvssMetricV40().stream().sorted(Comparator.comparing(CvssV4::getType)).findFirst();
1296 }
1297 if (optCvssv4 != null && optCvssv4.isPresent()) {
1298 final CvssV4 cvssv4 = optCvssv4.get();
1299 setUpdateColumn(callUpdate, 32, cvssv4.getCvssData().getVersion());
1300 setUpdateColumn(callUpdate, 33, cvssv4.getCvssData().getAttackVector());
1301 setUpdateColumn(callUpdate, 34, cvssv4.getCvssData().getAttackComplexity());
1302 setUpdateColumn(callUpdate, 35, cvssv4.getCvssData().getAttackRequirements());
1303 setUpdateColumn(callUpdate, 36, cvssv4.getCvssData().getPrivilegesRequired());
1304 setUpdateColumn(callUpdate, 37, cvssv4.getCvssData().getUserInteraction());
1305 setUpdateColumn(callUpdate, 38, cvssv4.getCvssData().getVulnConfidentialityImpact());
1306 setUpdateColumn(callUpdate, 39, cvssv4.getCvssData().getVulnIntegrityImpact());
1307 setUpdateColumn(callUpdate, 40, cvssv4.getCvssData().getVulnAvailabilityImpact());
1308 setUpdateColumn(callUpdate, 41, cvssv4.getCvssData().getSubConfidentialityImpact());
1309 setUpdateColumn(callUpdate, 42, cvssv4.getCvssData().getSubIntegrityImpact());
1310 setUpdateColumn(callUpdate, 43, cvssv4.getCvssData().getSubAvailabilityImpact());
1311 setUpdateColumn(callUpdate, 44, cvssv4.getCvssData().getExploitMaturity());
1312 setUpdateColumn(callUpdate, 45, cvssv4.getCvssData().getConfidentialityRequirement());
1313 setUpdateColumn(callUpdate, 46, cvssv4.getCvssData().getIntegrityRequirement());
1314 setUpdateColumn(callUpdate, 47, cvssv4.getCvssData().getAvailabilityRequirement());
1315 setUpdateColumn(callUpdate, 48, cvssv4.getCvssData().getModifiedAttackVector());
1316 setUpdateColumn(callUpdate, 49, cvssv4.getCvssData().getModifiedAttackComplexity());
1317 setUpdateColumn(callUpdate, 50, cvssv4.getCvssData().getModifiedAttackRequirements());
1318 setUpdateColumn(callUpdate, 51, cvssv4.getCvssData().getModifiedPrivilegesRequired());
1319 setUpdateColumn(callUpdate, 52, cvssv4.getCvssData().getModifiedUserInteraction());
1320 setUpdateColumn(callUpdate, 53, cvssv4.getCvssData().getModifiedVulnConfidentialityImpact());
1321 setUpdateColumn(callUpdate, 54, cvssv4.getCvssData().getModifiedVulnIntegrityImpact());
1322 setUpdateColumn(callUpdate, 55, cvssv4.getCvssData().getModifiedVulnAvailabilityImpact());
1323 setUpdateColumn(callUpdate, 56, cvssv4.getCvssData().getModifiedSubConfidentialityImpact());
1324 setUpdateColumn(callUpdate, 57, cvssv4.getCvssData().getModifiedSubIntegrityImpact());
1325 setUpdateColumn(callUpdate, 58, cvssv4.getCvssData().getModifiedSubAvailabilityImpact());
1326 setUpdateColumn(callUpdate, 59, cvssv4.getCvssData().getSafety());
1327 setUpdateColumn(callUpdate, 60, cvssv4.getCvssData().getAutomatable());
1328 setUpdateColumn(callUpdate, 61, cvssv4.getCvssData().getRecovery());
1329 setUpdateColumn(callUpdate, 62, cvssv4.getCvssData().getValueDensity());
1330 setUpdateColumn(callUpdate, 63, cvssv4.getCvssData().getVulnerabilityResponseEffort());
1331 setUpdateColumn(callUpdate, 64, cvssv4.getCvssData().getProviderUrgency());
1332 setUpdateColumn(callUpdate, 65, cvssv4.getCvssData().getBaseScore());
1333 setUpdateColumn(callUpdate, 66, cvssv4.getCvssData().getBaseSeverity());
1334 setUpdateColumn(callUpdate, 67, cvssv4.getCvssData().getThreatScore());
1335 setUpdateColumn(callUpdate, 68, cvssv4.getCvssData().getThreatSeverity());
1336 setUpdateColumn(callUpdate, 69, cvssv4.getCvssData().getEnvironmentalScore());
1337 setUpdateColumn(callUpdate, 70, cvssv4.getCvssData().getEnvironmentalSeverity());
1338 setUpdateColumn(callUpdate, 71, cvssv4.getSource());
1339 setUpdateColumn(callUpdate, 72, cvssv4.getType());
1340 } else {
1341 callUpdate.setNull(32, java.sql.Types.VARCHAR);
1342 callUpdate.setNull(33, java.sql.Types.VARCHAR);
1343 callUpdate.setNull(34, java.sql.Types.VARCHAR);
1344 callUpdate.setNull(35, java.sql.Types.VARCHAR);
1345 callUpdate.setNull(36, java.sql.Types.VARCHAR);
1346 callUpdate.setNull(37, java.sql.Types.VARCHAR);
1347 callUpdate.setNull(38, java.sql.Types.VARCHAR);
1348 callUpdate.setNull(39, java.sql.Types.VARCHAR);
1349 callUpdate.setNull(40, java.sql.Types.VARCHAR);
1350 callUpdate.setNull(41, java.sql.Types.VARCHAR);
1351 callUpdate.setNull(42, java.sql.Types.VARCHAR);
1352 callUpdate.setNull(43, java.sql.Types.VARCHAR);
1353 callUpdate.setNull(44, java.sql.Types.VARCHAR);
1354 callUpdate.setNull(45, java.sql.Types.VARCHAR);
1355 callUpdate.setNull(46, java.sql.Types.VARCHAR);
1356 callUpdate.setNull(47, java.sql.Types.VARCHAR);
1357 callUpdate.setNull(48, java.sql.Types.VARCHAR);
1358 callUpdate.setNull(49, java.sql.Types.VARCHAR);
1359 callUpdate.setNull(50, java.sql.Types.VARCHAR);
1360 callUpdate.setNull(51, java.sql.Types.VARCHAR);
1361 callUpdate.setNull(52, java.sql.Types.VARCHAR);
1362 callUpdate.setNull(53, java.sql.Types.VARCHAR);
1363 callUpdate.setNull(54, java.sql.Types.VARCHAR);
1364 callUpdate.setNull(55, java.sql.Types.VARCHAR);
1365 callUpdate.setNull(56, java.sql.Types.VARCHAR);
1366 callUpdate.setNull(57, java.sql.Types.VARCHAR);
1367 callUpdate.setNull(58, java.sql.Types.VARCHAR);
1368 callUpdate.setNull(59, java.sql.Types.VARCHAR);
1369 callUpdate.setNull(60, java.sql.Types.VARCHAR);
1370 callUpdate.setNull(61, java.sql.Types.VARCHAR);
1371 callUpdate.setNull(62, java.sql.Types.VARCHAR);
1372 callUpdate.setNull(63, java.sql.Types.VARCHAR);
1373 callUpdate.setNull(64, java.sql.Types.VARCHAR);
1374 callUpdate.setNull(65, java.sql.Types.DOUBLE);
1375 callUpdate.setNull(66, java.sql.Types.VARCHAR);
1376 callUpdate.setNull(67, java.sql.Types.DOUBLE);
1377 callUpdate.setNull(68, java.sql.Types.VARCHAR);
1378 callUpdate.setNull(69, java.sql.Types.DOUBLE);
1379 callUpdate.setNull(70, java.sql.Types.VARCHAR);
1380 callUpdate.setNull(71, java.sql.Types.VARCHAR);
1381 callUpdate.setNull(72, java.sql.Types.VARCHAR);
1382 }
1383 if (isOracle) {
1384 try {
1385 final CallableStatement cs = (CallableStatement) callUpdate;
1386 cs.registerOutParameter(73, JDBCType.INTEGER);
1387 cs.executeUpdate();
1388 vulnerabilityId = cs.getInt(73);
1389 } catch (SQLException ex) {
1390 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getId());
1391 throw new DatabaseException(msg, ex);
1392 }
1393 } else {
1394 try (ResultSet rs = callUpdate.executeQuery()) {
1395 rs.next();
1396 vulnerabilityId = rs.getInt(1);
1397 } catch (SQLException ex) {
1398 final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getId());
1399 throw new DatabaseException(msg, ex);
1400 }
1401 }
1402 } catch (SQLException ex) {
1403 throw new UnexpectedAnalysisException(ex);
1404 }
1405 return vulnerabilityId;
1406 }
1407
1408
1409
1410
1411
1412
1413
1414
1415 private void updateVulnerabilityInsertCwe(int vulnerabilityId, DefCveItem cve) throws SQLException {
1416 if (cve.getCve() != null && cve.getCve().getWeaknesses() != null) {
1417 try (Connection conn = databaseManager.getConnection();
1418 PreparedStatement insertCWE = getPreparedStatement(conn, INSERT_CWE, vulnerabilityId)) {
1419 for (Weakness weakness : cve.getCve().getWeaknesses()) {
1420 for (LangString desc : weakness.getDescription()) {
1421 if ("en".equals(desc.getLang())) {
1422 insertCWE.setString(2, desc.getValue());
1423 if (isBatchInsertEnabled()) {
1424 insertCWE.addBatch();
1425 } else {
1426 insertCWE.execute();
1427 }
1428 }
1429 }
1430 }
1431 if (isBatchInsertEnabled()) {
1432 insertCWE.executeBatch();
1433 }
1434 }
1435 }
1436 }
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446 private void deleteVulnerability(String cve) throws SQLException {
1447 try (Connection conn = databaseManager.getConnection();
1448 PreparedStatement deleteVulnerability = getPreparedStatement(conn, DELETE_VULNERABILITY, cve)) {
1449 deleteVulnerability.executeUpdate();
1450 }
1451 }
1452
1453
1454
1455
1456
1457
1458
1459
1460 public void updateKnownExploitedVulnerabilities(
1461 List<org.owasp.dependencycheck.data.knownexploited.json.Vulnerability> vulnerabilities)
1462 throws DatabaseException, SQLException {
1463 try (Connection conn = databaseManager.getConnection();
1464 PreparedStatement mergeKnownVulnerability = getPreparedStatement(conn, MERGE_KNOWN_EXPLOITED)) {
1465 int ctr = 0;
1466 for (org.owasp.dependencycheck.data.knownexploited.json.Vulnerability v : vulnerabilities) {
1467 mergeKnownVulnerability.setString(1, v.getCveID());
1468 addNullableStringParameter(mergeKnownVulnerability, 2, v.getVendorProject());
1469 addNullableStringParameter(mergeKnownVulnerability, 3, v.getProduct());
1470 addNullableStringParameter(mergeKnownVulnerability, 4, v.getVulnerabilityName());
1471 addNullableStringParameter(mergeKnownVulnerability, 5, v.getDateAdded());
1472 addNullableStringParameter(mergeKnownVulnerability, 6, v.getShortDescription());
1473 addNullableStringParameter(mergeKnownVulnerability, 7, v.getRequiredAction());
1474 addNullableStringParameter(mergeKnownVulnerability, 8, v.getDueDate());
1475 addNullableStringParameter(mergeKnownVulnerability, 9, v.getNotes());
1476 if (isBatchInsertEnabled()) {
1477 mergeKnownVulnerability.addBatch();
1478 ctr++;
1479 if (ctr >= getBatchSize()) {
1480 mergeKnownVulnerability.executeBatch();
1481 ctr = 0;
1482 }
1483 } else {
1484 try {
1485 mergeKnownVulnerability.execute();
1486 } catch (SQLException ex) {
1487 if (ex.getMessage().contains("Duplicate entry")) {
1488 final String msg = String.format("Duplicate known exploited vulnerability key identified in '%s'", v.getCveID());
1489 LOGGER.info(msg, ex);
1490 } else {
1491 throw ex;
1492 }
1493 }
1494 }
1495 }
1496 if (isBatchInsertEnabled()) {
1497 mergeKnownVulnerability.executeBatch();
1498 }
1499 }
1500 }
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514 private void updateVulnerabilityInsertSoftware(int vulnerabilityId, String cveId,
1515 List<VulnerableSoftware> software, String baseEcosystem)
1516 throws DatabaseException, SQLException {
1517 try (Connection conn = databaseManager.getConnection(); PreparedStatement insertSoftware = getPreparedStatement(conn, INSERT_SOFTWARE)) {
1518 for (VulnerableSoftware parsedCpe : software) {
1519 insertSoftware.setInt(1, vulnerabilityId);
1520 insertSoftware.setString(2, parsedCpe.getPart().getAbbreviation());
1521 insertSoftware.setString(3, parsedCpe.getVendor());
1522 insertSoftware.setString(4, parsedCpe.getProduct());
1523 insertSoftware.setString(5, parsedCpe.getVersion());
1524 insertSoftware.setString(6, parsedCpe.getUpdate());
1525 insertSoftware.setString(7, parsedCpe.getEdition());
1526 insertSoftware.setString(8, parsedCpe.getLanguage());
1527 insertSoftware.setString(9, parsedCpe.getSwEdition());
1528 insertSoftware.setString(10, parsedCpe.getTargetSw());
1529 insertSoftware.setString(11, parsedCpe.getTargetHw());
1530 insertSoftware.setString(12, parsedCpe.getOther());
1531 final String ecosystem = CpeEcosystemCache.getEcosystem(parsedCpe.getVendor(), parsedCpe.getProduct(),
1532 cveItemConverter.extractEcosystem(baseEcosystem, parsedCpe));
1533
1534 addNullableStringParameter(insertSoftware, 13, ecosystem);
1535 addNullableStringParameter(insertSoftware, 14, parsedCpe.getVersionEndExcluding());
1536 addNullableStringParameter(insertSoftware, 15, parsedCpe.getVersionEndIncluding());
1537 addNullableStringParameter(insertSoftware, 16, parsedCpe.getVersionStartExcluding());
1538 addNullableStringParameter(insertSoftware, 17, parsedCpe.getVersionStartIncluding());
1539 insertSoftware.setBoolean(18, parsedCpe.isVulnerable());
1540
1541 if (isBatchInsertEnabled()) {
1542 insertSoftware.addBatch();
1543 } else {
1544 try {
1545 insertSoftware.execute();
1546 } catch (SQLException ex) {
1547 if (ex.getMessage().contains("Duplicate entry")) {
1548 final String msg = String.format("Duplicate software key identified in '%s'", cveId);
1549 LOGGER.info(msg, ex);
1550 } else {
1551 throw ex;
1552 }
1553 }
1554 }
1555 }
1556 if (isBatchInsertEnabled()) {
1557 executeBatch(cveId, insertSoftware);
1558 }
1559 }
1560 }
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570 private void updateVulnerabilityInsertReferences(int vulnerabilityId, DefCveItem cve) throws SQLException {
1571 try (Connection conn = databaseManager.getConnection(); PreparedStatement insertReference = getPreparedStatement(conn, INSERT_REFERENCE)) {
1572 if (cve.getCve().getReferences() != null) {
1573 for (Reference r : cve.getCve().getReferences()) {
1574 insertReference.setInt(1, vulnerabilityId);
1575 String name = null;
1576 if (r.getTags() != null) {
1577 name = r.getTags().stream().sorted().collect(Collectors.joining(",")).toUpperCase().replaceAll("\\s", "_");
1578 }
1579 if (name != null) {
1580 insertReference.setString(2, name);
1581 } else {
1582 insertReference.setNull(2, java.sql.Types.VARCHAR);
1583 }
1584 if (r.getUrl() != null && !r.getUrl().isEmpty()) {
1585 insertReference.setString(3, r.getUrl());
1586 } else {
1587 insertReference.setNull(3, java.sql.Types.VARCHAR);
1588 }
1589 if (r.getSource() != null && !r.getSource().isEmpty()) {
1590 insertReference.setString(4, r.getSource());
1591 } else {
1592 insertReference.setNull(4, java.sql.Types.VARCHAR);
1593 }
1594 if (isBatchInsertEnabled()) {
1595 insertReference.addBatch();
1596 } else {
1597 insertReference.execute();
1598 }
1599 }
1600 }
1601 if (isBatchInsertEnabled()) {
1602 insertReference.executeBatch();
1603 }
1604 }
1605 }
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615 private List<VulnerableSoftware> parseCpes(DefCveItem cve) throws CpeValidationException {
1616 final List<VulnerableSoftware> software = new ArrayList<>();
1617
1618 final List<CpeMatch> cpeEntries = cve.getCve().getConfigurations().stream()
1619 .map(Config::getNodes)
1620 .flatMap(List::stream)
1621 .map(Node::getCpeMatch)
1622 .flatMap(List::stream)
1623 .filter(predicate -> predicate.getCriteria() != null)
1624 .filter(predicate -> predicate.getCriteria().startsWith(cpeStartsWithFilter))
1625
1626 .filter(entry -> !("CVE-2009-0754".equals(cve.getCve().getId())
1627 && "cpe:2.3:a:apache:apache:*:*:*:*:*:*:*:*".equals(entry.getCriteria())))
1628 .collect(Collectors.toList());
1629 final VulnerableSoftwareBuilder builder = new VulnerableSoftwareBuilder();
1630
1631 try {
1632 cpeEntries.forEach(entry -> {
1633 builder.cpe(parseCpe(entry, cve.getCve().getId()))
1634 .versionEndExcluding(entry.getVersionEndExcluding())
1635 .versionStartExcluding(entry.getVersionStartExcluding())
1636 .versionEndIncluding(entry.getVersionEndIncluding())
1637 .versionStartIncluding(entry.getVersionStartIncluding())
1638 .vulnerable(entry.getVulnerable());
1639 try {
1640 software.add(builder.build());
1641 } catch (CpeValidationException ex) {
1642 throw new LambdaExceptionWrapper(ex);
1643 }
1644 });
1645 } catch (LambdaExceptionWrapper ex) {
1646 throw (CpeValidationException) ex.getCause();
1647 }
1648 return software;
1649 }
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662 private Cpe parseCpe(CpeMatch cpe, String cveId) throws DatabaseException {
1663 final Cpe parsedCpe;
1664 try {
1665
1666 parsedCpe = CpeParser.parse(cpe.getCriteria(), true);
1667 } catch (CpeParsingException ex) {
1668 LOGGER.debug("NVD (" + cveId + ") contain an invalid 2.3 CPE: " + cpe.getCriteria());
1669 throw new DatabaseException("Unable to parse CPE: " + cpe.getCriteria(), ex);
1670 }
1671 return parsedCpe;
1672 }
1673
1674
1675
1676
1677
1678
1679 private int getBatchSize() {
1680 int max;
1681 try {
1682 max = settings.getInt(Settings.KEYS.MAX_BATCH_SIZE);
1683 } catch (InvalidSettingException pE) {
1684 max = 1000;
1685 }
1686 return max;
1687 }
1688
1689
1690
1691
1692
1693
1694
1695 private boolean isBatchInsertEnabled() {
1696 boolean batch;
1697 try {
1698 batch = settings.getBoolean(Settings.KEYS.ENABLE_BATCH_UPDATES);
1699 } catch (InvalidSettingException pE) {
1700
1701 batch = false;
1702 }
1703 return batch;
1704 }
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714 private void executeBatch(String vulnId, PreparedStatement statement)
1715 throws SQLException {
1716 try {
1717 statement.executeBatch();
1718 } catch (SQLException ex) {
1719 if (ex.getMessage().contains("Duplicate entry")) {
1720 final String msg = String.format("Duplicate software key identified in '%s'",
1721 vulnId);
1722 LOGGER.info(msg, ex);
1723 } else {
1724 throw ex;
1725 }
1726 }
1727 }
1728
1729
1730
1731
1732
1733
1734 public boolean dataExists() {
1735 try (Connection conn = databaseManager.getConnection();
1736 PreparedStatement cs = getPreparedStatement(conn, COUNT_CPE);
1737 ResultSet rs = cs.executeQuery()) {
1738 if (rs.next() && rs.getInt(1) > 0) {
1739 return true;
1740 }
1741 } catch (Exception ex) {
1742 String dd;
1743 try {
1744 dd = settings.getDataDirectory().getAbsolutePath();
1745 } catch (IOException ex1) {
1746 dd = settings.getString(Settings.KEYS.DATA_DIRECTORY);
1747 }
1748 LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. "
1749 + "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
1750 + "create a log file (see documentation at https://jeremylong.github.io/DependencyCheck/) and open a ticket at "
1751 + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
1752 dd, dd, settings.getString(Settings.KEYS.APPLICATION_NAME));
1753 LOGGER.debug("", ex);
1754 }
1755 return false;
1756 }
1757
1758
1759
1760
1761
1762
1763 public void cleanupDatabase() {
1764 LOGGER.info("Begin database maintenance");
1765 final long start = System.currentTimeMillis();
1766 try (Connection conn = databaseManager.getConnection();
1767 PreparedStatement psOrphans = getPreparedStatement(conn, CLEANUP_ORPHANS);
1768 PreparedStatement psEcosystem = getPreparedStatement(conn, UPDATE_ECOSYSTEM);
1769 PreparedStatement psEcosystem2 = getPreparedStatement(conn, UPDATE_ECOSYSTEM2)) {
1770 if (psEcosystem != null) {
1771 final int count = psEcosystem.executeUpdate();
1772 if (count > 0) {
1773 LOGGER.info("Updated the CPE ecosystem on {} NVD records", count);
1774 }
1775 }
1776 if (psEcosystem2 != null) {
1777 final int count = psEcosystem2.executeUpdate();
1778 if (count > 0) {
1779 LOGGER.info("Removed the CPE ecosystem on {} NVD records", count);
1780 }
1781 }
1782 if (psOrphans != null) {
1783 final int count = psOrphans.executeUpdate();
1784 if (count > 0) {
1785 LOGGER.info("Cleaned up {} orphaned NVD records", count);
1786 }
1787 }
1788 final long millis = System.currentTimeMillis() - start;
1789
1790 LOGGER.info("End database maintenance ({} ms)", millis);
1791 } catch (SQLException ex) {
1792 LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
1793 LOGGER.debug("", ex);
1794 throw new DatabaseException("Unexpected SQL Exception", ex);
1795 }
1796 }
1797
1798
1799
1800
1801 public void persistEcosystemCache() {
1802 saveCpeEcosystemCache();
1803 clearCache();
1804 }
1805
1806
1807
1808
1809
1810 public void defrag() {
1811 if (isH2) {
1812 final long start = System.currentTimeMillis();
1813 try (Connection conn = databaseManager.getConnection(); CallableStatement psCompaxt = conn.prepareCall("SHUTDOWN DEFRAG")) {
1814 LOGGER.info("Begin database defrag");
1815 psCompaxt.execute();
1816 final long millis = System.currentTimeMillis() - start;
1817
1818 LOGGER.info("End database defrag ({} ms)", millis);
1819 } catch (SQLException ex) {
1820 LOGGER.error("An unexpected SQL Exception occurred compacting the database; please see the verbose log for more details.");
1821 LOGGER.debug("", ex);
1822 }
1823 }
1824 }
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836 VulnerableSoftware getMatchingSoftware(Cpe cpe, Set<VulnerableSoftware> vulnerableSoftware) {
1837 VulnerableSoftware matched = null;
1838 for (VulnerableSoftware vs : vulnerableSoftware) {
1839 if (vs.matches(cpe)) {
1840 if (matched == null) {
1841 matched = vs;
1842 } else {
1843 if ("*".equals(vs.getWellFormedUpdate()) && !"*".equals(matched.getWellFormedUpdate())) {
1844 matched = vs;
1845 }
1846 }
1847 }
1848 }
1849 return matched;
1850 }
1851
1852
1853
1854
1855
1856
1857
1858 public void deleteUnusedCpe() {
1859 clearCache();
1860 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, DELETE_UNUSED_DICT_CPE)) {
1861 ps.executeUpdate();
1862 } catch (SQLException ex) {
1863 LOGGER.error("Unable to delete CPE dictionary entries", ex);
1864 }
1865 }
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 public void addCpe(String cpe, String vendor, String product) {
1879 clearCache();
1880 try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, ADD_DICT_CPE)) {
1881 ps.setString(1, cpe);
1882 ps.setString(2, vendor);
1883 ps.setString(3, product);
1884 ps.executeUpdate();
1885 } catch (SQLException ex) {
1886 LOGGER.error("Unable to add CPE dictionary entry", ex);
1887 }
1888 }
1889
1890
1891
1892
1893
1894
1895 public Map<String, org.owasp.dependencycheck.data.knownexploited.json.Vulnerability> getknownExploitedVulnerabilities() {
1896 final Map<String, org.owasp.dependencycheck.data.knownexploited.json.Vulnerability> known = new HashMap<>();
1897
1898 try (Connection conn = databaseManager.getConnection();
1899 PreparedStatement ps = getPreparedStatement(conn, SELECT_KNOWN_EXPLOITED_VULNERABILITIES);
1900 ResultSet rs = ps.executeQuery()) {
1901
1902 while (rs.next()) {
1903 final org.owasp.dependencycheck.data.knownexploited.json.Vulnerability kev =
1904 new org.owasp.dependencycheck.data.knownexploited.json.Vulnerability();
1905 kev.setCveID(rs.getString(1));
1906 kev.setVendorProject(rs.getString(2));
1907 kev.setProduct(rs.getString(3));
1908 kev.setVulnerabilityName(rs.getString(4));
1909 kev.setDateAdded(rs.getString(5));
1910 kev.setShortDescription(rs.getString(6));
1911 kev.setRequiredAction(rs.getString(7));
1912 kev.setDueDate(rs.getString(8));
1913 kev.setNotes(rs.getString(9));
1914 known.put(kev.getCveID(), kev);
1915 }
1916
1917 } catch (SQLException ex) {
1918 throw new DatabaseException(ex);
1919 }
1920 return known;
1921 }
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931 private void addNullableStringParameter(PreparedStatement ps, int pos, String value) throws SQLException {
1932 if (value == null || value.isEmpty()) {
1933 ps.setNull(pos, java.sql.Types.VARCHAR);
1934 } else {
1935 ps.setString(pos, value);
1936 }
1937 }
1938
1939 private void setUpdateColumn(PreparedStatement ps, int i, Double value) throws SQLException {
1940 if (value == null) {
1941 ps.setNull(i, java.sql.Types.DOUBLE);
1942 } else {
1943 ps.setDouble(i, value);
1944 }
1945 }
1946
1947 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AuthenticationType value) throws SQLException {
1948 if (value == null) {
1949 ps.setNull(i, java.sql.Types.VARCHAR);
1950 } else {
1951 ps.setString(i, value.value());
1952 }
1953 }
1954
1955 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.CiaType value) throws SQLException {
1956 if (value == null) {
1957 ps.setNull(i, java.sql.Types.VARCHAR);
1958 } else {
1959 ps.setString(i, value.value());
1960 }
1961 }
1962
1963 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.Version value) throws SQLException {
1964 if (value == null) {
1965 ps.setNull(i, java.sql.Types.VARCHAR);
1966 } else {
1967 ps.setString(i, value.value());
1968 }
1969 }
1970
1971 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AccessComplexityType value) throws SQLException {
1972 if (value == null) {
1973 ps.setNull(i, java.sql.Types.VARCHAR);
1974 } else {
1975 ps.setString(i, value.value());
1976 }
1977 }
1978
1979 private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AccessVectorType value) throws SQLException {
1980 if (value == null) {
1981 ps.setNull(i, java.sql.Types.VARCHAR);
1982 } else {
1983 ps.setString(i, value.value());
1984 }
1985 }
1986
1987 private void setUpdateColumn(PreparedStatement ps, int i, String value) throws SQLException {
1988 if (value == null) {
1989 ps.setNull(i, java.sql.Types.VARCHAR);
1990 } else {
1991 ps.setString(i, value);
1992 }
1993 }
1994
1995 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4.Type value) throws SQLException {
1996 if (value == null) {
1997 ps.setNull(i, java.sql.Types.VARCHAR);
1998 } else {
1999 ps.setString(i, value.value());
2000 }
2001 }
2002
2003 private void setUpdateColumn(PreparedStatement ps, int i, Boolean value) throws SQLException {
2004 if (value == null) {
2005
2006
2007 if (isOracle) {
2008 ps.setNull(i, java.sql.Types.BIT);
2009 } else {
2010 ps.setNull(i, java.sql.Types.BOOLEAN);
2011 }
2012 } else {
2013 ps.setBoolean(i, value);
2014 }
2015 }
2016
2017 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.AttackVectorType value) throws SQLException {
2018 if (value == null) {
2019 ps.setNull(i, java.sql.Types.VARCHAR);
2020 } else {
2021 ps.setString(i, value.value());
2022 }
2023 }
2024
2025 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.AttackComplexityType value) throws SQLException {
2026 if (value == null) {
2027 ps.setNull(i, java.sql.Types.VARCHAR);
2028 } else {
2029 ps.setString(i, value.value());
2030 }
2031 }
2032
2033 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.PrivilegesRequiredType value) throws SQLException {
2034 if (value == null) {
2035 ps.setNull(i, java.sql.Types.VARCHAR);
2036 } else {
2037 ps.setString(i, value.value());
2038 }
2039 }
2040
2041 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.UserInteractionType value) throws SQLException {
2042 if (value == null) {
2043 ps.setNull(i, java.sql.Types.VARCHAR);
2044 } else {
2045 ps.setString(i, value.value());
2046 }
2047 }
2048
2049 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.ScopeType value) throws SQLException {
2050 if (value == null) {
2051 ps.setNull(i, java.sql.Types.VARCHAR);
2052 } else {
2053 ps.setString(i, value.value());
2054 }
2055 }
2056
2057 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.SeverityType value) throws SQLException {
2058 if (value == null) {
2059 ps.setNull(i, java.sql.Types.VARCHAR);
2060 } else {
2061 ps.setString(i, value.value());
2062 }
2063 }
2064
2065 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.CiaType value) throws SQLException {
2066 if (value == null) {
2067 ps.setNull(i, java.sql.Types.VARCHAR);
2068 } else {
2069 ps.setString(i, value.value());
2070 }
2071 }
2072
2073 private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.Version value) throws SQLException {
2074 if (value == null) {
2075 ps.setNull(i, java.sql.Types.VARCHAR);
2076 } else {
2077 ps.setString(i, value.value());
2078 }
2079 }
2080
2081 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.Version value) throws SQLException {
2082 if (value == null) {
2083 ps.setNull(i, java.sql.Types.VARCHAR);
2084 } else {
2085 ps.setString(i, value.value());
2086 }
2087 }
2088
2089 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackVectorType value) throws SQLException {
2090 if (value == null) {
2091 ps.setNull(i, java.sql.Types.VARCHAR);
2092 } else {
2093 ps.setString(i, value.value());
2094 }
2095 }
2096
2097 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackComplexityType value) throws SQLException {
2098 if (value == null) {
2099 ps.setNull(i, java.sql.Types.VARCHAR);
2100 } else {
2101 ps.setString(i, value.value());
2102 }
2103 }
2104
2105 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackRequirementsType value) throws SQLException {
2106 if (value == null) {
2107 ps.setNull(i, java.sql.Types.VARCHAR);
2108 } else {
2109 ps.setString(i, value.value());
2110 }
2111 }
2112
2113 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.PrivilegesRequiredType value) throws SQLException {
2114 if (value == null) {
2115 ps.setNull(i, java.sql.Types.VARCHAR);
2116 } else {
2117 ps.setString(i, value.value());
2118 }
2119 }
2120
2121 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.UserInteractionType value) throws SQLException {
2122 if (value == null) {
2123 ps.setNull(i, java.sql.Types.VARCHAR);
2124 } else {
2125 ps.setString(i, value.value());
2126 }
2127 }
2128
2129 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.CiaType value) throws SQLException {
2130 if (value == null) {
2131 ps.setNull(i, java.sql.Types.VARCHAR);
2132 } else {
2133 ps.setString(i, value.value());
2134 }
2135 }
2136
2137 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ExploitMaturityType value) throws SQLException {
2138 if (value == null) {
2139 ps.setNull(i, java.sql.Types.VARCHAR);
2140 } else {
2141 ps.setString(i, value.value());
2142 }
2143 }
2144
2145 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.CiaRequirementType value) throws SQLException {
2146 if (value == null) {
2147 ps.setNull(i, java.sql.Types.VARCHAR);
2148 } else {
2149 ps.setString(i, value.value());
2150 }
2151 }
2152
2153 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackVectorType value) throws SQLException {
2154 if (value == null) {
2155 ps.setNull(i, java.sql.Types.VARCHAR);
2156 } else {
2157 ps.setString(i, value.value());
2158 }
2159 }
2160
2161 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackComplexityType value) throws SQLException {
2162 if (value == null) {
2163 ps.setNull(i, java.sql.Types.VARCHAR);
2164 } else {
2165 ps.setString(i, value.value());
2166 }
2167 }
2168
2169 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackRequirementsType value) throws SQLException {
2170 if (value == null) {
2171 ps.setNull(i, java.sql.Types.VARCHAR);
2172 } else {
2173 ps.setString(i, value.value());
2174 }
2175 }
2176
2177 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedPrivilegesRequiredType value) throws SQLException {
2178 if (value == null) {
2179 ps.setNull(i, java.sql.Types.VARCHAR);
2180 } else {
2181 ps.setString(i, value.value());
2182 }
2183 }
2184
2185 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedUserInteractionType value) throws SQLException {
2186 if (value == null) {
2187 ps.setNull(i, java.sql.Types.VARCHAR);
2188 } else {
2189 ps.setString(i, value.value());
2190 }
2191 }
2192
2193 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedCiaType value) throws SQLException {
2194 if (value == null) {
2195 ps.setNull(i, java.sql.Types.VARCHAR);
2196 } else {
2197 ps.setString(i, value.value());
2198 }
2199 }
2200
2201 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.SafetyType value) throws SQLException {
2202 if (value == null) {
2203 ps.setNull(i, java.sql.Types.VARCHAR);
2204 } else {
2205 ps.setString(i, value.value());
2206 }
2207 }
2208
2209 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AutomatableType value) throws SQLException {
2210 if (value == null) {
2211 ps.setNull(i, java.sql.Types.VARCHAR);
2212 } else {
2213 ps.setString(i, value.value());
2214 }
2215 }
2216
2217 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.RecoveryType value) throws SQLException {
2218 if (value == null) {
2219 ps.setNull(i, java.sql.Types.VARCHAR);
2220 } else {
2221 ps.setString(i, value.value());
2222 }
2223 }
2224
2225 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ValueDensityType value) throws SQLException {
2226 if (value == null) {
2227 ps.setNull(i, java.sql.Types.VARCHAR);
2228 } else {
2229 ps.setString(i, value.value());
2230 }
2231 }
2232
2233 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.VulnerabilityResponseEffortType value) throws SQLException {
2234 if (value == null) {
2235 ps.setNull(i, java.sql.Types.VARCHAR);
2236 } else {
2237 ps.setString(i, value.value());
2238 }
2239 }
2240
2241 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ProviderUrgencyType value) throws SQLException {
2242 if (value == null) {
2243 ps.setNull(i, java.sql.Types.VARCHAR);
2244 } else {
2245 ps.setString(i, value.value());
2246 }
2247 }
2248
2249 private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.SeverityType value) throws SQLException {
2250 if (value == null) {
2251 ps.setNull(i, java.sql.Types.VARCHAR);
2252 } else {
2253 ps.setString(i, value.value());
2254 }
2255 }
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266 private void setFloatValue(PreparedStatement ps, int i, Map<String, Object> props, String key) throws SQLException {
2267 if (props != null && props.containsKey(key)) {
2268 try {
2269 ps.setFloat(i, Float.parseFloat(props.get(key).toString()));
2270 } catch (NumberFormatException nfe) {
2271 ps.setNull(i, java.sql.Types.FLOAT);
2272 }
2273 } else {
2274 ps.setNull(i, java.sql.Types.FLOAT);
2275 }
2276 }
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287 private void setStringValue(PreparedStatement ps, int i, Map<String, Object> props, String key) throws SQLException {
2288 if (props != null && props.containsKey(key)) {
2289 ps.setString(i, props.get(key).toString());
2290 } else {
2291 ps.setNull(i, java.sql.Types.VARCHAR);
2292 }
2293 }
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304 private void setBooleanValue(PreparedStatement ps, int i, Map<String, Object> props, String key) throws SQLException {
2305 if (props != null && props.containsKey(key)) {
2306 ps.setBoolean(i, Boolean.parseBoolean(props.get(key).toString()));
2307 } else {
2308 ps.setNull(i, java.sql.Types.BOOLEAN);
2309 }
2310 }
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321 @SuppressFBWarnings("NP_BOOLEAN_RETURN_NULL")
2322 private Boolean getBooleanValue(ResultSet rs, int index) throws SQLException {
2323 if (rs.getObject(index) == null) {
2324 return null;
2325 }
2326 return rs.getBoolean(index);
2327 }
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338 private Float getFloatValue(ResultSet rs, int index) throws SQLException {
2339 if (rs.getObject(index) == null) {
2340 return null;
2341 }
2342 return rs.getFloat(index);
2343 }
2344 }