1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.data.update;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.sql.SQLException;
24 import org.owasp.dependencycheck.Engine;
25 import org.owasp.dependencycheck.data.knownexploited.json.KnownExploitedVulnerabilitiesSchema;
26 import org.owasp.dependencycheck.data.nvdcve.CveDB;
27 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
28 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
29 import org.owasp.dependencycheck.data.update.cisa.KnownExploitedVulnerabilityParser;
30 import org.owasp.dependencycheck.data.update.exception.CorruptedDatastreamException;
31 import org.owasp.dependencycheck.data.update.exception.UpdateException;
32 import org.owasp.dependencycheck.utils.DateUtil;
33 import org.owasp.dependencycheck.utils.HttpResourceConnection;
34 import org.owasp.dependencycheck.utils.ResourceNotFoundException;
35 import org.owasp.dependencycheck.utils.Settings;
36 import org.owasp.dependencycheck.utils.TooManyRequestsException;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40
41
42
43
44 public class KnownExploitedDataSource implements CachedWebDataSource {
45
46
47
48
49 private static final Logger LOGGER = LoggerFactory.getLogger(KnownExploitedDataSource.class);
50
51
52
53 private static final String DEFAULT_URL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json";
54
55
56
57 private CveDB cveDB;
58
59
60
61 private Settings settings;
62
63
64
65 private DatabaseProperties dbProperties = null;
66
67 @Override
68 public boolean update(Engine engine) throws UpdateException {
69 this.cveDB = engine.getDatabase();
70 this.settings = engine.getSettings();
71 dbProperties = cveDB.getDatabaseProperties();
72 final boolean autoUpdate = settings.getBoolean(Settings.KEYS.AUTO_UPDATE, true);
73 final boolean kevEnabled = settings.getBoolean(Settings.KEYS.ANALYZER_KNOWN_EXPLOITED_ENABLED, true);
74 if (autoUpdate && kevEnabled && shouldUpdate()) {
75 try {
76 final URL url = new URL(settings.getString(Settings.KEYS.KEV_URL, DEFAULT_URL));
77 LOGGER.info("Updating CISA Known Exploited Vulnerability list: " + url.toString());
78
79 final HttpResourceConnection conn = new HttpResourceConnection(settings);
80 try (InputStream in = conn.fetch(url)) {
81 final KnownExploitedVulnerabilityParser parser = new KnownExploitedVulnerabilityParser();
82 final KnownExploitedVulnerabilitiesSchema data = parser.parse(in);
83 final String currentVersion = dbProperties.getProperty(DatabaseProperties.KEV_VERSION, "");
84 if (!currentVersion.equals(data.getCatalogVersion())) {
85 cveDB.updateKnownExploitedVulnerabilities(data.getVulnerabilities());
86 }
87
88 dbProperties.save(DatabaseProperties.KEV_LAST_CHECKED, Long.toString(System.currentTimeMillis() / 1000));
89 return true;
90 }
91 } catch (TooManyRequestsException | ResourceNotFoundException | IOException
92 | CorruptedDatastreamException | DatabaseException | SQLException ex) {
93 throw new UpdateException(ex);
94 }
95 }
96 return false;
97 }
98
99 @Override
100 public boolean purge(Engine engine) {
101
102 return true;
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116 private boolean shouldUpdate() throws UpdateException {
117 boolean proceed = true;
118
119 final int validForHours = settings.getInt(Settings.KEYS.KEV_CHECK_VALID_FOR_HOURS, 24);
120 if (cveDB.dataExists() && 0 < validForHours) {
121
122 final long validForSeconds = validForHours * 60L * 60L;
123 final long lastChecked = dbProperties.getPropertyInSeconds(DatabaseProperties.KEV_LAST_CHECKED);
124 final long now = System.currentTimeMillis() / 1000;
125 proceed = (now - lastChecked) > validForSeconds;
126 if (!proceed) {
127 LOGGER.info("Skipping Known Exploited Vulnerabilities update check since last check was within {} hours.", validForHours);
128 }
129 }
130 return proceed;
131 }
132
133 }