From 315ebd289ce872e2e9db645411cb3af7a5e7319d Mon Sep 17 00:00:00 2001 From: Weyland <71197790+wey-chiang@users.noreply.github.com> Date: Tue, 15 Dec 2020 22:42:46 -0500 Subject: [PATCH] Global IOC Helpers (#159) * Initial commit of IOC Helpers * Removed AWS.VPCFlow and CiscoUmbrella.DNS from the SHA-256 IOC log types * Support for finding IOC matches for use in the title function. Added dynamic titles that include the matches for the Sunburst IOCs. * Added more details to the runbook for the Sunburst IOCs * Fixed linting issue (line too long) * refactored to minimize repeated code * broke out title function into two pieces * Modified Description and added Reference for sunburst indicators Co-authored-by: Nicholas Hakmiller --- global_helpers/panther_iocs.py | 56 ++++++++++++++++++++ global_helpers/panther_iocs.yml | 4 ++ okta_rules/okta_admin_role_assigned.py | 2 +- panther_ioc_rules/sunburst_fqdn_iocs.py | 12 +++++ panther_ioc_rules/sunburst_fqdn_iocs.yml | 59 ++++++++++++++++++++++ panther_ioc_rules/sunburst_ip_iocs.py | 10 ++++ panther_ioc_rules/sunburst_ip_iocs.yml | 58 +++++++++++++++++++++ panther_ioc_rules/sunburst_sha256_iocs.py | 12 +++++ panther_ioc_rules/sunburst_sha256_iocs.yml | 57 +++++++++++++++++++++ 9 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 global_helpers/panther_iocs.py create mode 100644 global_helpers/panther_iocs.yml create mode 100644 panther_ioc_rules/sunburst_fqdn_iocs.py create mode 100644 panther_ioc_rules/sunburst_fqdn_iocs.yml create mode 100644 panther_ioc_rules/sunburst_ip_iocs.py create mode 100644 panther_ioc_rules/sunburst_ip_iocs.yml create mode 100644 panther_ioc_rules/sunburst_sha256_iocs.py create mode 100644 panther_ioc_rules/sunburst_sha256_iocs.yml diff --git a/global_helpers/panther_iocs.py b/global_helpers/panther_iocs.py new file mode 100644 index 000000000..fff596b62 --- /dev/null +++ b/global_helpers/panther_iocs.py @@ -0,0 +1,56 @@ +# pylint: disable=line-too-long +# SUNBURST IOCs: https://github.com/fireeye/sunburst_countermeasures/blob/main/indicator_release/Indicator_Release_NBIs.csv +# Last accessed: 12-5-2020 +SUNBURST_FQDN_IOCS = { + 'databasegalore.com', + 'deftsecurity.com', + 'freescanonline.com', + 'highdatabase.com', + 'incomeupdate.com', + 'panhardware.com', + 'thedoccloud.com', + 'websitetheme.com', + 'zupertech.com', + '6a57jk2ba1d9keg15cbg.appsync-api.eu-west-1.avsvmcloud.com', + '7sbvaemscs0mc925tb99.appsync-api.us-west-2.avsvmcloud.com', + 'gq1h856599gqh538acqn.appsync-api.us-west-2.avsvmcloud.com', + 'ihvpgv9psvq02ffo77et.appsync-api.us-east-2.avsvmcloud.com', + 'k5kcubuassl3alrf7gm3.appsync-api.eu-west-1.avsvmcloud.com', + 'mhdosoksaccf9sni9icp.appsync-api.eu-west-1.avsvmcloud.com', +} + +SUNBURST_IP_IOCS = { + '5.252.177.21', '5.252.177.25', '13.59.205.66', '34.203.203.23', + '51.89.125.18', '54.193.127.66', '54.215.192.52', '139.99.115.204', + '167.114.213.199', '204.188.205.176' +} + +SUNBURST_SHA256_IOCS = { + '019085a76ba7126fff22770d71bd901c325fc68ac55aa743327984e89f4b0134', + '292327e5c94afa352cc5a02ca273df543f2020d0e76368ff96c84f4e90778712', + '32519b85c0b422e4656de6e6c41878e95fd95026267daab4215ee59c107d6c77', + '53f8dfc65169ccda021b72a62e0c22a4db7c4077f002fa742717d41b3c40f2c7', + 'c15abaf51e78ca56c0376522d699c978217bf041a3bd3c71d09193efa5717c71', + 'ce77d116a074dab7a22a0fd4f2c1ab475f16eec42e1ded3c0b0aa8211fe858d6', + 'd0d626deb3f9484e649294a8dfa814c5568f846d5aa02d4cdad5d041a29d5600' +} + + +def ioc_match(indicators: list, known_iocs: set) -> list: + """Matches a set of indicators against known Indicators of Compromise + + :param indicators: List of potential indicators of compromise + :param known_iocs: Set of known indicators of compromise + :return: List of any indicator matches + """ + # Check through the IP IOCs + return [ioc for ioc in (indicators or []) if ioc in known_iocs] + + +def sanitize_domain(domain: str) -> str: + """Makes a potential malicous domain not render as a domain in most systems + + :param domain: Original domain + :return: Sanitized domain + """ + return domain.replace('.', '[.]') diff --git a/global_helpers/panther_iocs.yml b/global_helpers/panther_iocs.yml new file mode 100644 index 000000000..0b5d23c03 --- /dev/null +++ b/global_helpers/panther_iocs.yml @@ -0,0 +1,4 @@ +AnalysisType: global +GlobalID: panther_iocs +Filename: panther_iocs.py +Description: Global helpers and variables used for finding matches on known indicators of compromise (IOCs) diff --git a/okta_rules/okta_admin_role_assigned.py b/okta_rules/okta_admin_role_assigned.py index b9b14bc70..c0c6ebdf6 100644 --- a/okta_rules/okta_admin_role_assigned.py +++ b/okta_rules/okta_admin_role_assigned.py @@ -1,5 +1,5 @@ -from panther_base_helpers import okta_alert_context import re +from panther_base_helpers import okta_alert_context def rule(event): diff --git a/panther_ioc_rules/sunburst_fqdn_iocs.py b/panther_ioc_rules/sunburst_fqdn_iocs.py new file mode 100644 index 000000000..ef6b4e0f1 --- /dev/null +++ b/panther_ioc_rules/sunburst_fqdn_iocs.py @@ -0,0 +1,12 @@ +from panther_iocs import ioc_match, SUNBURST_FQDN_IOCS, sanitize_domain + + +def rule(event): + return any(ioc_match(event.get('p_any_domain_names'), SUNBURST_FQDN_IOCS)) + + +def title(event): + domains = ','.join( + ioc_match(event.get('p_any_domain_names'), SUNBURST_FQDN_IOCS)) + return sanitize_domain( + f"Sunburst Indicator of Compromise Detected [Domains]: {domains}") diff --git a/panther_ioc_rules/sunburst_fqdn_iocs.yml b/panther_ioc_rules/sunburst_fqdn_iocs.yml new file mode 100644 index 000000000..210fdb54f --- /dev/null +++ b/panther_ioc_rules/sunburst_fqdn_iocs.yml @@ -0,0 +1,59 @@ +AnalysisType: rule +Filename: sunburst_fqdn_iocs.py +RuleID: IOC.SunburstFQDNIOCs +DisplayName: Sunburst Indicators of Compromise (FQDN) +Enabled: true +LogTypes: + - AWS.ALB + - AWS.CloudTrail + - AWS.GuardDuty + - AWS.S3ServerAccess + - AWS.VPCFlow + - Box.Event + - CiscoUmbrella.DNS + - GCP.AuditLog + - Gravitational.TeleportAudit + - GSuite.Reports + - Okta.SystemLog + - OneLogin.Events + - Osquery.Differential +Tags: + - AWS + - Box + - DNS + - GCP + - GSuite + - SSH + - OneLogin + - Osquery +Severity: High +Description: > + Monitors for communication to known Sunburst Backdoor FQDNs. These IOCs indicate a potential breach and have been associated with a sophisticated nation-state actor. +Reference: > + https://www.fireeye.com/blog/threat-research/2020/12/evasive-attacker-leverages-solarwinds-supply-chain-compromises-with-sunburst-backdoor.html +Runbook: > + Investigate the resources communicating with the matched IOC for signs of compromise or other malicious activity. Consider rotating credentials on any systems observed communicating with these known malicious systems. +SummaryAttributes: + - p_any_domain_names + - p_any_ip_addresses + - p_any_sha256_hashes +Tests: + - + Name: Non-matching traffic + ExpectedResult: false + Log: + { + "dstport": 53, + "dstaddr": "1.1.1.1", + "srcaddr": "10.0.0.1", + "p_any_domain_names": ["example.com"], + } + - + Name: Sunburst Indicator of Compromise (FQDN) Detected + ExpectedResult: true + Log: + { + "srcaddr": "13.59.205.66", + "dstaddr": "10.0.0.1", + "p_any_domain_names": ["incomeupdate.com"], + } diff --git a/panther_ioc_rules/sunburst_ip_iocs.py b/panther_ioc_rules/sunburst_ip_iocs.py new file mode 100644 index 000000000..f1da6a1a9 --- /dev/null +++ b/panther_ioc_rules/sunburst_ip_iocs.py @@ -0,0 +1,10 @@ +from panther_iocs import ioc_match, SUNBURST_IP_IOCS + + +def rule(event): + return any(ioc_match(event.get('p_any_ip_addresses'), SUNBURST_IP_IOCS)) + + +def title(event): + ips = ','.join(ioc_match(event.get('p_any_ip_addresses'), SUNBURST_IP_IOCS)) + return f"Sunburst Indicator of Compromise Detected [IPs]: {ips}" diff --git a/panther_ioc_rules/sunburst_ip_iocs.yml b/panther_ioc_rules/sunburst_ip_iocs.yml new file mode 100644 index 000000000..a01385895 --- /dev/null +++ b/panther_ioc_rules/sunburst_ip_iocs.yml @@ -0,0 +1,58 @@ +AnalysisType: rule +Filename: sunburst_ip_iocs.py +RuleID: IOC.SunburstIPIOCs +DisplayName: Sunburst Indicators of Compromise (IP) +Enabled: true +LogTypes: + - AWS.ALB + - AWS.CloudTrail + - AWS.GuardDuty + - AWS.S3ServerAccess + - AWS.VPCFlow + - Box.Event + - CiscoUmbrella.DNS + - GCP.AuditLog + - Gravitational.TeleportAudit + - GSuite.Reports + - Okta.SystemLog + - OneLogin.Events + - Osquery.Differential +Tags: + - AWS + - Box + - DNS + - GCP + - GSuite + - SSH + - OneLogin + - Osquery +Severity: High +Description: > + Monitors for communication to known Sunburst Backdoor IPs. These IOCs indicate a potential breach and have been associated with a sophisticated nation-state actor. +Reference: > + https://www.fireeye.com/blog/threat-research/2020/12/evasive-attacker-leverages-solarwinds-supply-chain-compromises-with-sunburst-backdoor.html +Runbook: > + Investigate the resources communicating with the matched IOC for signs of compromise or other malicious activity. Consider rotating credentials on any systems observed communicating with these known malicious systems. +SummaryAttributes: + - p_any_domain_names + - p_any_ip_addresses + - p_any_sha256_hashes +Tests: + - + Name: Non-matching traffic + ExpectedResult: false + Log: + { + "dstport": 53, + "dstaddr": "1.1.1.1", + "srcaddr": "10.0.0.1" + } + - + Name: Sunburst Indicator of Compromise (IP) Detected + ExpectedResult: true + Log: + { + "srcaddr": "13.59.205.66", + "dstaddr": "10.0.0.1", + "p_any_ip_addresses": ["13.59.205.66"], + } diff --git a/panther_ioc_rules/sunburst_sha256_iocs.py b/panther_ioc_rules/sunburst_sha256_iocs.py new file mode 100644 index 000000000..3a31b3299 --- /dev/null +++ b/panther_ioc_rules/sunburst_sha256_iocs.py @@ -0,0 +1,12 @@ +from panther_iocs import ioc_match, SUNBURST_SHA256_IOCS + + +def rule(event): + return any(ioc_match(event.get('p_any_sha256_hashes'), + SUNBURST_SHA256_IOCS)) + + +def title(event): + hashes = ','.join( + ioc_match(event.get('p_any_sha256_hashes'), SUNBURST_SHA256_IOCS)) + return f"Sunburst Indicator of Compromise Detected [SHA256 hash]: {hashes}" diff --git a/panther_ioc_rules/sunburst_sha256_iocs.yml b/panther_ioc_rules/sunburst_sha256_iocs.yml new file mode 100644 index 000000000..3ccd441a7 --- /dev/null +++ b/panther_ioc_rules/sunburst_sha256_iocs.yml @@ -0,0 +1,57 @@ +AnalysisType: rule +Filename: sunburst_sha256_iocs.py +RuleID: IOC.SunburstSHA256IOCs +DisplayName: Sunburst Indicators of Compromise (SHA-256) +Enabled: true +LogTypes: + - AWS.ALB + - AWS.CloudTrail + - AWS.GuardDuty + - AWS.S3ServerAccess + - Box.Event + - GCP.AuditLog + - Gravitational.TeleportAudit + - GSuite.Reports + - Okta.SystemLog + - OneLogin.Events + - Osquery.Differential +Tags: + - AWS + - Box + - DNS + - GCP + - GSuite + - SSH + - OneLogin + - Osquery +Severity: High +Description: > + Monitors for hashes to known Sunburst Backdoor SHA256. These IOCs indicate a potential breach and have been associated with a sophisticated nation-state actor. +Reference: > + https://www.fireeye.com/blog/threat-research/2020/12/evasive-attacker-leverages-solarwinds-supply-chain-compromises-with-sunburst-backdoor.html +Runbook: > + Investigate the resources communicating with the matched IOC for signs of compromise or other malicious activity. Consider rotating credentials on any systems observed communicating with these known malicious systems. +SummaryAttributes: + - p_any_domain_names + - p_any_ip_addresses + - p_any_sha256_hashes +Tests: + - + Name: Non-matching traffic + ExpectedResult: false + Log: + { + "dstport": 53, + "dstaddr": "1.1.1.1", + "srcaddr": "10.0.0.1", + "p_any_sha256_hashes": ["98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4"], + } + - + Name: Sunburst Indicator of Compromise (SHA-256) Detected + ExpectedResult: true + Log: + { + "srcaddr": "13.59.205.66", + "dstaddr": "10.0.0.1", + "p_any_sha256_hashes": ["019085a76ba7126fff22770d71bd901c325fc68ac55aa743327984e89f4b0134"], + }