From 0a65f85365fd7b8b6c92aeea8a7f431b651098a6 Mon Sep 17 00:00:00 2001 From: Simon Lukasik Date: Thu, 14 Oct 2021 19:41:36 +0200 Subject: [PATCH 1/4] Provide valid RuleTypes as constants in gofalcon --- falcon/client/intel/constants.go | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 falcon/client/intel/constants.go diff --git a/falcon/client/intel/constants.go b/falcon/client/intel/constants.go new file mode 100644 index 00000000..f0e8266e --- /dev/null +++ b/falcon/client/intel/constants.go @@ -0,0 +1,34 @@ +package intel + +type RuleType string + +const ( + RuleTypeSnortSuricataMaster RuleType = "snort-suricata-master" + RuleTypeSnortSuricataUpdate RuleType = "snort-suricata-update" + RuleTypeSnortSuricataChangelog RuleType = "snort-suricata-changelog" + RuleTypeYaraMaster RuleType = "yara-master" + RuleTypeYaraUpdate RuleType = "yara-update" + RuleTypeYaraChangelog RuleType = "yara-changelog" + RuleTypeCommonEventFormat RuleType = "common-event-format" + RuleTypeNetwitness RuleType = "netwitness" +) + +var RuleTypeValidValues = []RuleType{ + RuleTypeSnortSuricataMaster, + RuleTypeSnortSuricataUpdate, + RuleTypeSnortSuricataChangelog, + RuleTypeYaraMaster, + RuleTypeYaraUpdate, + RuleTypeYaraChangelog, + RuleTypeCommonEventFormat, + RuleTypeNetwitness, +} + +func (rt RuleType) Valid() bool { + for _, item := range RuleTypeValidValues { + if rt == item { + return true + } + } + return false +} From 34130991e885e78d08e411db6d8467f93ae766ae Mon Sep 17 00:00:00 2001 From: Simon Lukasik Date: Thu, 14 Oct 2021 19:49:51 +0200 Subject: [PATCH 2/4] Example: Download CrowdStrike Falcon Intelligence Rule files --- README.md | 1 + .../falcon_intel_rules_download/README.md | 19 +++++ examples/falcon_intel_rules_download/main.go | 82 +++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 examples/falcon_intel_rules_download/README.md create mode 100644 examples/falcon_intel_rules_download/main.go diff --git a/README.md b/README.md index ed4e3986..ca4753d2 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Detailed API documentation is available on [pkg.go.dev](https://pkg.go.dev/githu | [falcon_event_stream](examples/falcon_event_stream) | stand-alone tool that can be used to stream events as they happen in CrowdStrike Falcon Console | | [falcon_cleanup_pods](examples/falcon_cleanup_pods) | stand-alone tool that can be used to clean-up inactive pods from CrowdStrike Falcon Console | | [falcon_iocs](examples/falcon_iocs) | stand-alone tool that can be used to add, delete or list Custom IOCs in the CrowdStrike Falcon Console | +| [falcon_intel_rules_download](examples/falcon_intel_rules_download) stand-alone tool that downloads CrowdStrike Falcon Intelligence Rule files | | [falcon_host_details](examples/falcon_host_details) | stand-alone tool that outputs inventory of hosts registered to CrowdStrike Falcon platform | | [falcon_registry_token](examples/falcon_registry_token) | helper to generate container registry logic information for `docker login` | diff --git a/examples/falcon_intel_rules_download/README.md b/examples/falcon_intel_rules_download/README.md new file mode 100644 index 00000000..17b50383 --- /dev/null +++ b/examples/falcon_intel_rules_download/README.md @@ -0,0 +1,19 @@ +# Falcon Intelligence Rules Download + +Minimalist example to show download CrowdStrike Falcon Intelligence Rules through API. This example can be run interactively or in script when all information is passed in through command-line. + +## Installation + +``` +go get github.com/crowdstrike/gofalcon/examples/falcon_intel_rules_download +``` + +## Example Run + +Download rules file interactively +``` +$ FALCON_CLIENT_ID="abc" FALCON_CLIENT_SECRET="XYZ" FALCON_CLOUD=us-1 falcon_intel_rules_download +Missing--rule-type argument. Valid options are [snort-suricata-master snort-suricata-update snort-suricata-changelog yara-master yara-update yara-changelog common-event-format netwitness]. +Requested Rule type: snort-suricata-master +Downloading file snort-suricata-master.tar.gz +``` diff --git a/examples/falcon_intel_rules_download/main.go b/examples/falcon_intel_rules_download/main.go new file mode 100644 index 00000000..4fdfdace --- /dev/null +++ b/examples/falcon_intel_rules_download/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/crowdstrike/gofalcon/falcon" + "github.com/crowdstrike/gofalcon/falcon/client" + "github.com/crowdstrike/gofalcon/falcon/client/intel" + "github.com/crowdstrike/gofalcon/pkg/falcon_util" +) + +func main() { + clientId := flag.String("client-id", os.Getenv("FALCON_CLIENT_ID"), "Client ID for accessing CrowdStrike Falcon Platform (default taken from FALCON_CLIENT_ID env)") + clientSecret := flag.String("client-secret", os.Getenv("FALCON_CLIENT_SECRET"), "Client Secret for accessing CrowdStrike Falcon Platform (default taken from FALCON_CLIENT_SECRET)") + memberCID := flag.String("member-cid", os.Getenv("FALCON_MEMBER_CID"), "Member CID for MSSP (for cases when OAuth2 authenticates multiple CIDs)") + clientCloud := flag.String("cloud", os.Getenv("FALCON_CLOUD"), "Falcon cloud abbreviation (us-1, us-2, eu-1, us-gov-1)") + intelRuleType := flag.String("rule-type", "", fmt.Sprintf("Falcon Intelligence Rule Type: available types: %s", intel.RuleTypeValidValues)) + flag.Parse() + + if *clientId == "" { + *clientId = falcon_util.PromptUser(`Missing FALCON_CLIENT_ID environment variable. Please provide your OAuth2 API Client ID for authentication with CrowdStrike Falcon platform. Establishing and retrieving OAuth2 API credentials can be performed at https://falcon.crowdstrike.com/support/api-clients-and-keys. +Falcon Client ID`) + } + if *clientSecret == "" { + *clientSecret = falcon_util.PromptUser(`Missing FALCON_CLIENT_SECRET environment variable. Please provide your OAuth2 API Client Secret for authentication with CrowdStrike Falcon platform. Establishing and retrieving OAuth2 API credentials can be performed at https://falcon.crowdstrike.com/support/api-clients-and-keys. +Falcon Client Secret`) + } + + if !intel.RuleType(*intelRuleType).Valid() { + *intelRuleType = falcon_util.PromptUser(fmt.Sprintf("Missing--rule-type argument. Valid options are %s. \nRequested Rule type", intel.RuleTypeValidValues)) + } + + client, err := falcon.NewClient(&falcon.ApiConfig{ + ClientId: *clientId, + ClientSecret: *clientSecret, + MemberCID: *memberCID, + Cloud: falcon.Cloud(*clientCloud), + Context: context.Background(), + Debug: false, + }) + if err != nil { + panic(err) + } + + intelType := *intelRuleType + filepath := fmt.Sprintf("%s.tar.gz", intelType) + fmt.Printf("Downloading file %s\n", filepath) + err = DownloadLatestRuleFile(client, filepath, intelType) + if err != nil { + panic(err) + + } +} + +func DownloadLatestRuleFile(client *client.CrowdStrikeAPISpecification, filepath, intelType string) error { + file, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + return err + } + + /* #nosec */ + defer func() { + // (ignore possibly false positive https://github.com/securego/gosec/issues/714) + if err := file.Close(); err != nil { + fmt.Fprintf(os.Stderr, "Error closing file: %s\n", err) + } + }() + + gzip := "gzip" + _, err = client.Intel.GetLatestIntelRuleFile(&intel.GetLatestIntelRuleFileParams{ + Context: context.Background(), + Type: intelType, + Format: &gzip, + }, file) + if err != nil { + return err + } + return nil +} From cda03b479b99f05c07974cbb5b42882d3505880c Mon Sep 17 00:00:00 2001 From: Simon Lukasik Date: Thu, 14 Oct 2021 20:24:14 +0200 Subject: [PATCH 3/4] Fix spell checking CI --- .github/wordlist.txt | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/wordlist.txt b/.github/wordlist.txt index 3423dafc..5b34dabf 100644 --- a/.github/wordlist.txt +++ b/.github/wordlist.txt @@ -17,6 +17,7 @@ gofalcon gosec hostnames initialisation +intel iocs oauth pre diff --git a/README.md b/README.md index ca4753d2..ae28eb32 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Detailed API documentation is available on [pkg.go.dev](https://pkg.go.dev/githu | [falcon_event_stream](examples/falcon_event_stream) | stand-alone tool that can be used to stream events as they happen in CrowdStrike Falcon Console | | [falcon_cleanup_pods](examples/falcon_cleanup_pods) | stand-alone tool that can be used to clean-up inactive pods from CrowdStrike Falcon Console | | [falcon_iocs](examples/falcon_iocs) | stand-alone tool that can be used to add, delete or list Custom IOCs in the CrowdStrike Falcon Console | -| [falcon_intel_rules_download](examples/falcon_intel_rules_download) stand-alone tool that downloads CrowdStrike Falcon Intelligence Rule files | +| [falcon_intel_rules_download](examples/falcon_intel_rules_download) | stand-alone tool that downloads CrowdStrike Falcon Intelligence Rule files | | [falcon_host_details](examples/falcon_host_details) | stand-alone tool that outputs inventory of hosts registered to CrowdStrike Falcon platform | | [falcon_registry_token](examples/falcon_registry_token) | helper to generate container registry logic information for `docker login` | From 7271837993e56bff2ec4ff4f4023e0ff6eaac971 Mon Sep 17 00:00:00 2001 From: Simon Lukasik Date: Thu, 14 Oct 2021 20:31:10 +0200 Subject: [PATCH 4/4] Fix gosec assertion G304 (CWE-22): sanitize filename --- examples/falcon_intel_rules_download/main.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/falcon_intel_rules_download/main.go b/examples/falcon_intel_rules_download/main.go index 4fdfdace..bfc96acd 100644 --- a/examples/falcon_intel_rules_download/main.go +++ b/examples/falcon_intel_rules_download/main.go @@ -5,6 +5,8 @@ import ( "flag" "fmt" "os" + "path/filepath" + "strings" "github.com/crowdstrike/gofalcon/falcon" "github.com/crowdstrike/gofalcon/falcon/client" @@ -55,8 +57,13 @@ Falcon Client Secret`) } } -func DownloadLatestRuleFile(client *client.CrowdStrikeAPISpecification, filepath, intelType string) error { - file, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0600) +func DownloadLatestRuleFile(client *client.CrowdStrikeAPISpecification, filename, intelType string) error { + safeLocation := filepath.Clean(filename) + if strings.Contains(safeLocation, "/") || strings.Contains(safeLocation, "\\") || strings.Contains(safeLocation, "..") { + panic("Suspicious file location: " + safeLocation) + } + + file, err := os.OpenFile(safeLocation, os.O_CREATE|os.O_WRONLY, 0600) if err != nil { return err }