diff --git a/cmd/fleet/cron.go b/cmd/fleet/cron.go index 1832c2c390..ea7db205b3 100644 --- a/cmd/fleet/cron.go +++ b/cmd/fleet/cron.go @@ -455,10 +455,11 @@ func checkNVDVulnerabilities( ) []fleet.SoftwareVulnerability { if !config.DisableDataSync { opts := nvd.SyncOptions{ - VulnPath: config.DatabasesPath, - CPEDBURL: config.CPEDatabaseURL, - CPETranslationsURL: config.CPETranslationsURL, - CVEFeedPrefixURL: config.CVEFeedPrefixURL, + VulnPath: config.DatabasesPath, + CPEDBURL: config.CPEDatabaseURL, + CPETranslationsURL: config.CPETranslationsURL, + CVEFeedPrefixURL: config.CVEFeedPrefixURL, + CISAKnownExploitsURL: config.CISAKnownExploitsURL, } err := nvd.Sync(opts, logger) if err != nil { diff --git a/cmd/fleetctl/fleetctl/vulnerability_data_stream.go b/cmd/fleetctl/fleetctl/vulnerability_data_stream.go index 3730362390..9c3e640c56 100644 --- a/cmd/fleetctl/fleetctl/vulnerability_data_stream.go +++ b/cmd/fleetctl/fleetctl/vulnerability_data_stream.go @@ -74,7 +74,7 @@ Downloads (if needed) the data streams that can be used by the Fleet server to p log(c, " Done\n") log(c, "[-] Downloading CISA known exploits feed...") - err = nvd.DownloadCISAKnownExploitsFeed(dir) + err = nvd.DownloadCISAKnownExploitsFeed(dir, "") if err != nil { return fmt.Errorf("Error downloading CISA known exploits feed: %v", err) } diff --git a/docs/Configuration/fleet-server-configuration.md b/docs/Configuration/fleet-server-configuration.md index 7f7e014d88..9e68114dad 100644 --- a/docs/Configuration/fleet-server-configuration.md +++ b/docs/Configuration/fleet-server-configuration.md @@ -2393,6 +2393,22 @@ When not defined, Fleet downloads CVE information from the nvd.nist.gov host usi cve_feed_prefix_url: "" ``` +### cisa_known_exploits_url + +The CISA known exploited vulnerabilities catalog is downloaded from this URL. This catalog contains +vulnerabilities that are known to be actively exploited in the wild and is used to enhance vulnerability +reporting with exploit status information. When this value is defined, it will download the file from +the specified URL. If this value is not defined, Fleet uses the default CISA catalog URL. Fleet expects this +path to be a JSON file. For a specification on the catalog you can view https://www.cisa.gov/known-exploited-vulnerabilities-catalog. + +- Default value: `https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json` +- Environment variable: `FLEET_VULNERABILITIES_CISA_KNOWN_EXPLOITS_URL` +- Config file format: + ```yaml + vulnerabilities: + cisa_known_exploits_url: https://custom-cisa-path.gov/main/known_exploited_vulnerabilities.json + ``` + ### disable_schedule When running multiple instances of the Fleet server, by default, one of them dynamically takes the lead in vulnerability processing. This lead can change over time. Some Fleet users want to be able to define which deployment is doing this checking. If you wish to do this, you'll need to deploy your Fleet instances with this set explicitly to `true` and one of them set to `false`. diff --git a/server/config/config.go b/server/config/config.go index bffba77058..6254761569 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -541,6 +541,7 @@ type VulnerabilitiesConfig struct { CPEDatabaseURL string `json:"cpe_database_url" yaml:"cpe_database_url"` CPETranslationsURL string `json:"cpe_translations_url" yaml:"cpe_translations_url"` CVEFeedPrefixURL string `json:"cve_feed_prefix_url" yaml:"cve_feed_prefix_url"` + CISAKnownExploitsURL string `json:"cisa_known_exploits_url" yaml:"cisa_known_exploits_url"` CurrentInstanceChecks string `json:"current_instance_checks" yaml:"current_instance_checks"` DisableSchedule bool `json:"disable_schedule" yaml:"disable_schedule"` DisableDataSync bool `json:"disable_data_sync" yaml:"disable_data_sync"` @@ -1366,6 +1367,8 @@ func (man Manager) addConfigs() { "URL from which to get the latest CPE translations. If empty, it will be downloaded from the latest release available at https://github.com/fleetdm/nvd/releases.") man.addConfigString("vulnerabilities.cve_feed_prefix_url", "", "Prefix URL for the CVE data feed. If empty, default to https://nvd.nist.gov/") + man.addConfigString("vulnerabilities.cisa_known_exploits_url", "", + "URL from which to get the latest CISA (Known exploited vulnerabilities) database. If empty, it will be downloaded from https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json") man.addConfigString("vulnerabilities.current_instance_checks", "auto", "Allows to manually select an instance to do the vulnerability processing.") man.addConfigBool("vulnerabilities.disable_schedule", false, @@ -1671,6 +1674,7 @@ func (man Manager) LoadConfig() FleetConfig { CPEDatabaseURL: man.getConfigString("vulnerabilities.cpe_database_url"), CPETranslationsURL: man.getConfigString("vulnerabilities.cpe_translations_url"), CVEFeedPrefixURL: man.getConfigString("vulnerabilities.cve_feed_prefix_url"), + CISAKnownExploitsURL: man.getConfigString("vulnerabilities.cisa_known_exploits_url"), CurrentInstanceChecks: man.getConfigString("vulnerabilities.current_instance_checks"), DisableSchedule: man.getConfigBool("vulnerabilities.disable_schedule"), DisableDataSync: man.getConfigBool("vulnerabilities.disable_data_sync"), diff --git a/server/vulnerabilities/nvd/sync.go b/server/vulnerabilities/nvd/sync.go index d5dbb9e5fe..05dc9a9054 100644 --- a/server/vulnerabilities/nvd/sync.go +++ b/server/vulnerabilities/nvd/sync.go @@ -26,11 +26,12 @@ import ( ) type SyncOptions struct { - VulnPath string - CPEDBURL string - CPETranslationsURL string - CVEFeedPrefixURL string - Debug bool + VulnPath string + CPEDBURL string + CPETranslationsURL string + CVEFeedPrefixURL string + CISAKnownExploitsURL string + Debug bool } // Sync downloads all the vulnerability data sources. @@ -58,7 +59,7 @@ func Sync(opts SyncOptions, logger log.Logger) error { return fmt.Errorf("sync EPSS CVE feed: %w", err) } - if err := DownloadCISAKnownExploitsFeed(opts.VulnPath); err != nil { + if err := DownloadCISAKnownExploitsFeed(opts.VulnPath, opts.CISAKnownExploitsURL); err != nil { return fmt.Errorf("sync CISA known exploits feed: %w", err) } @@ -141,8 +142,8 @@ func parseEPSSScoresFile(path string) ([]epssScore, error) { } const ( - cisaKnownExploitsURL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json" - cisaKnownExploitsFilename = "known_exploited_vulnerabilities.json" + defaultCisaKnownExploitsURL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json" + cisaKnownExploitsFilename = "known_exploited_vulnerabilities.json" ) // knownExploitedVulnerabilitiesCatalog represents the CISA Catalog of Known Exploited Vulnerabilities. @@ -168,9 +169,13 @@ type knownExploitedVulnerability struct { } // DownloadCISAKnownExploitsFeed downloads the CISA known exploited vulnerabilities feed. -func DownloadCISAKnownExploitsFeed(vulnPath string) error { +func DownloadCISAKnownExploitsFeed(vulnPath string, cisaKnownExploitsURL string) error { path := filepath.Join(vulnPath, cisaKnownExploitsFilename) + if cisaKnownExploitsURL == "" { + cisaKnownExploitsURL = defaultCisaKnownExploitsURL + } + u, err := url.Parse(cisaKnownExploitsURL) if err != nil { return err diff --git a/server/vulnerabilities/nvd/sync_test.go b/server/vulnerabilities/nvd/sync_test.go index c1117b2f15..a1e165f119 100644 --- a/server/vulnerabilities/nvd/sync_test.go +++ b/server/vulnerabilities/nvd/sync_test.go @@ -32,7 +32,18 @@ func TestDownloadCISAKnownExploitsFeed(t *testing.T) { tempDir := t.TempDir() - err := DownloadCISAKnownExploitsFeed(tempDir) + err := DownloadCISAKnownExploitsFeed(tempDir, "") + require.NoError(t, err) + + assert.FileExists(t, filepath.Join(tempDir, cisaKnownExploitsFilename)) +} + +func TestDownloadCISAKnownExploitsFeedMirror(t *testing.T) { + nettest.Run(t) + + tempDir := t.TempDir() + + err := DownloadCISAKnownExploitsFeed(tempDir, "https://raw.githubusercontent.com/EugenMayer/cisa-known-exploited-mirror/main/known_exploited_vulnerabilities.json") require.NoError(t, err) assert.FileExists(t, filepath.Join(tempDir, cisaKnownExploitsFilename))