From 8012f1148954cbcee086995d9e3a4c6dbf4f3697 Mon Sep 17 00:00:00 2001 From: Joe Stanulis <126097374+jstanulis-push@users.noreply.github.com> Date: Tue, 21 May 2024 10:16:53 -0400 Subject: [PATCH] Push Security rules (#1207) * Deprecate GreyNoise detections (#1205) * Deprecate GreyNoise detections * Update rules/aws_cloudtrail_rules/aws_s3_activity_greynoise.yml * Update rules/cloudflare_rules/cloudflare_firewall_suspicious_event_greynoise.yml * Update cloudflare_httpreq_bot_high_volume_greynoise.yml --------- Co-authored-by: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> * fix - Notion Login From New Location - NoneType error (#1206) * fix - Notion Login From New Location - NoneType error * fix - Notion Login From New Location - NoneType error - linter fix * Push Security rules * remove codeowners (#1208) * fix - GCP rules - AttributeError (#1210) * fix - GCP rules - AttributeError * fix - GCP rules - AttributeError - linter fix * MITRE ATT&CK Mappings for MS Rules (#1209) * added MITRE mappings for microsoft rules * fixed formatting on some helper files --------- Co-authored-by: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> * traildiscover enrichment with managed schema (#1177) * traildiscover enrichment with managed schema * Add npm install in dockerfile (#1172) * add npm install in dockerfile * Remove Python optimizations; add prettier to PATH --------- Co-authored-by: egibs * schema name: TrailDiscover.CloudTrail * Fix Dockerfile; add Workflow to test image * updated data set * Add MongoDB.2FA.Disabled rule (#1190) Co-authored-by: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> * lint and fmt * fmt * add OCSF selector * additional OCSF mappings * Fix Pipfile * Rebase changes --------- Co-authored-by: Panos Sakkos Co-authored-by: egibs Co-authored-by: Oleh Melenevskyi <767472+melenevskyi@users.noreply.github.com> * Update PAT to 0.46.0 (#1216) * add file/host state to msft graph alert context (#1220) * fix timestamps (#1219) * Update PAT to 0.46.1 (#1222) * pack for traildiscover LUT (#1221) * pack, fmt lint, event.deep_get * pack update --------- Co-authored-by: Oleh Melenevskyi <767472+melenevskyi@users.noreply.github.com> Co-authored-by: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> Co-authored-by: akozlovets098 <95437895+akozlovets098@users.noreply.github.com> Co-authored-by: Panos Sakkos Co-authored-by: ben-githubs <38414634+ben-githubs@users.noreply.github.com> Co-authored-by: egibs Co-authored-by: Evan Gibler Co-authored-by: Nick Hakmiller <49166439+nhakmiller@users.noreply.github.com> Co-authored-by: Ariel Ropek --- .../push_security_app_banner_acknowledged.py | 26 +++ .../push_security_app_banner_acknowledged.yml | 98 ++++++++++ .../push_security_mfa_method_changed.py | 33 ++++ .../push_security_mfa_method_changed.yml | 167 ++++++++++++++++++ .../push_security_new_app_detected.py | 16 ++ .../push_security_new_app_detected.yml | 54 ++++++ .../push_security_new_saas_account_created.py | 17 ++ ...push_security_new_saas_account_created.yml | 115 ++++++++++++ .../push_security_open_security_finding.py | 22 +++ .../push_security_open_security_finding.yml | 86 +++++++++ .../push_security_phishable_mfa_method.py | 33 ++++ .../push_security_phishable_mfa_method.yml | 99 +++++++++++ .../push_security_phishing_attack.py | 22 +++ .../push_security_phishing_attack.yml | 63 +++++++ .../push_security_unauthorized_idp_login.py | 31 ++++ .../push_security_unauthorized_idp_login.yml | 88 +++++++++ 16 files changed, 970 insertions(+) create mode 100644 rules/push_security_rules/push_security_app_banner_acknowledged.py create mode 100644 rules/push_security_rules/push_security_app_banner_acknowledged.yml create mode 100644 rules/push_security_rules/push_security_mfa_method_changed.py create mode 100644 rules/push_security_rules/push_security_mfa_method_changed.yml create mode 100644 rules/push_security_rules/push_security_new_app_detected.py create mode 100644 rules/push_security_rules/push_security_new_app_detected.yml create mode 100644 rules/push_security_rules/push_security_new_saas_account_created.py create mode 100644 rules/push_security_rules/push_security_new_saas_account_created.yml create mode 100644 rules/push_security_rules/push_security_open_security_finding.py create mode 100644 rules/push_security_rules/push_security_open_security_finding.yml create mode 100644 rules/push_security_rules/push_security_phishable_mfa_method.py create mode 100644 rules/push_security_rules/push_security_phishable_mfa_method.yml create mode 100644 rules/push_security_rules/push_security_phishing_attack.py create mode 100644 rules/push_security_rules/push_security_phishing_attack.yml create mode 100644 rules/push_security_rules/push_security_unauthorized_idp_login.py create mode 100644 rules/push_security_rules/push_security_unauthorized_idp_login.yml diff --git a/rules/push_security_rules/push_security_app_banner_acknowledged.py b/rules/push_security_rules/push_security_app_banner_acknowledged.py new file mode 100644 index 000000000..baa13bb69 --- /dev/null +++ b/rules/push_security_rules/push_security_app_banner_acknowledged.py @@ -0,0 +1,26 @@ +from panther_base_helpers import deep_get + + +def rule(event): + if event.get("object") != "APP_BANNER": + return False + + if deep_get(event, "new", "action") == "ACKNOWLEDGED": + return True + + return False + + +def title(event): + app_type = deep_get(event, "new", "appType") + employee_email = deep_get(event, "new", "employee", "email") + return f"{app_type} accessed by {employee_email}" + + +def alert_context(event): + return { + "Push Security app banner": deep_get(event, "new", "appBanner", "mode"), + "Title": deep_get(event, "new", "appBanner", "title"), + "Subtext": deep_get(event, "new", "appBanner", "subtext"), + "Button": deep_get(event, "new", "appBanner", "buttonText"), + } diff --git a/rules/push_security_rules/push_security_app_banner_acknowledged.yml b/rules/push_security_rules/push_security_app_banner_acknowledged.yml new file mode 100644 index 000000000..7a141a067 --- /dev/null +++ b/rules/push_security_rules/push_security_app_banner_acknowledged.yml @@ -0,0 +1,98 @@ +AnalysisType: rule +Filename: push_security_app_banner_acknowledged.py +RuleID: "Push.Security.App.Banner.Acknowledged" +DisplayName: "Push Security App Banner Acknowledged" +Enabled: true +LogTypes: + - Custom.PushSecurity.Activity +Severity: Low +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: App Banner Acknowledged + ExpectedResult: true + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + action: ACKNOWLEDGED + appBanner: + buttonText: Proceed anyway + mode: ACKNOWLEDGE + subtext: This app is not approved, please use Google Drive instead. + title: This app is not approved for use + appType: DROPBOX + browser: CHROME + employee: + chatopsEnabled: true + creationTimestamp: 1.698669223e+09 + department: Security Engineering + email: john.hill@example.com + firstName: John + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + lastName: Hill + licensed: true + location: New York + os: WINDOWS + sourceIpAddress: 8.158.25.38 + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 + object: APP_BANNER + timestamp: 1.698604061e+09 + version: "1" + - Name: App Banner Displayed + ExpectedResult: false + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + action: DISPLAYED + appBanner: + buttonText: Proceed anyway + mode: ACKNOWLEDGE + subtext: This app is not approved, please use Google Drive instead. + title: This app is not approved for use + appType: DROPBOX + browser: CHROME + employee: + chatopsEnabled: true + creationTimestamp: 1.698669223e+09 + department: Security Engineering + email: john.hill@example.com + firstName: John + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + lastName: Hill + licensed: true + location: New York + os: WINDOWS + sourceIpAddress: 8.158.25.38 + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 + object: APP_BANNER + timestamp: 1.698604061e+09 + version: "1" + - Name: App Banner Inform Mode + ExpectedResult: false + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + action: DISPLAYED + appBanner: + buttonText: null + mode: INFORM + subtext: This app is not approved, please use Google Drive instead. + title: This app is not approved for use + appType: DROPBOX + browser: CHROME + employee: + chatopsEnabled: true + creationTimestamp: 1.698669223e+09 + department: Security Engineering + email: john.hill@example.com + firstName: John + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + lastName: Hill + licensed: true + location: New York + os: WINDOWS + sourceIpAddress: 8.158.25.38 + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 + object: APP_BANNER + timestamp: 1.698604061e+09 + version: "1" diff --git a/rules/push_security_rules/push_security_mfa_method_changed.py b/rules/push_security_rules/push_security_mfa_method_changed.py new file mode 100644 index 000000000..7bae8a4be --- /dev/null +++ b/rules/push_security_rules/push_security_mfa_method_changed.py @@ -0,0 +1,33 @@ +from panther_base_helpers import deep_get + + +def rule(event): + if event.get("object") != "ACCOUNT": + return False + + if event.get("old") is None: + return False + + new_mfa_methods = set(deep_get(event, "new", "mfaMethods")) + old_mfa_methods = set(deep_get(event, "old", "mfaMethods", default=[])) + + if new_mfa_methods != old_mfa_methods: + return True + + return False + + +def severity(event): + if deep_get(event, "new", "mfaMethods") == []: + return "HIGH" + return "LOW" + + +def title(event): + mfa_methods = ", ".join(deep_get(event, "new", "mfaMethods", default="No MFA")) + new_email = deep_get(event, "new", "email") + new_apptype = deep_get(event, "new", "appType") + + if mfa_methods == "": + return f"{new_email} removed all MFA methods on {new_apptype}" + return f"{new_email} changed MFA method to {mfa_methods} on {new_apptype}" diff --git a/rules/push_security_rules/push_security_mfa_method_changed.yml b/rules/push_security_rules/push_security_mfa_method_changed.yml new file mode 100644 index 000000000..892e54d9f --- /dev/null +++ b/rules/push_security_rules/push_security_mfa_method_changed.yml @@ -0,0 +1,167 @@ +AnalysisType: rule +Filename: push_security_mfa_method_changed.py +RuleID: "Push.Security.MFA.Method.Changed" +DisplayName: "Push Security SaaS App MFA Method Changed" +Enabled: true +LogTypes: + - Custom.PushSecurity.Entities +Severity: Info +Description: MFA method on SaaS app changed +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: All MFA methods removed + ExpectedResult: true + Log: + id: d1e5794f-666d-4cba-abae-c6d889ca1903 + new: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: [] + mfaRegistered: false + passwordId: null + object: ACCOUNT + old: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + mfaRegistered: false + passwordId: null + timestamp: 1.707775049e+09 + type: CREATE + version: "1" + - Name: First seen + ExpectedResult: false + Log: + id: d1e5794f-666d-4cba-abae-c6d889ca1903 + new: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + - APP_OTP + mfaRegistered: false + passwordId: null + object: ACCOUNT + old: null + timestamp: 1.707775049e+09 + type: CREATE + version: "1" + - Name: MFA method added + ExpectedResult: true + Log: + id: d1e5794f-666d-4cba-abae-c6d889ca1903 + new: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + - APP_OTP + mfaRegistered: false + passwordId: null + object: ACCOUNT + old: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + mfaRegistered: false + passwordId: null + timestamp: 1.707775049e+09 + type: CREATE + version: "1" + - Name: No MFA method change + ExpectedResult: false + Log: + id: d1e5794f-666d-4cba-abae-c6d889ca1903 + new: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + - APP_OTP + mfaRegistered: false + passwordId: null + object: ACCOUNT + old: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + - APP_OTP + mfaRegistered: false + passwordId: null + timestamp: 1.707775049e+09 + type: CREATE + version: "1" diff --git a/rules/push_security_rules/push_security_new_app_detected.py b/rules/push_security_rules/push_security_new_app_detected.py new file mode 100644 index 000000000..0388dd77e --- /dev/null +++ b/rules/push_security_rules/push_security_new_app_detected.py @@ -0,0 +1,16 @@ +from panther_base_helpers import deep_get + + +def rule(event): + if event.get("object") != "APP": + return False + + if event.get("type") == "CREATE": + return True + + return False + + +def title(event): + new_type = deep_get(event, "new", "type") + return f"New app in use: {new_type}" diff --git a/rules/push_security_rules/push_security_new_app_detected.yml b/rules/push_security_rules/push_security_new_app_detected.yml new file mode 100644 index 000000000..c06391513 --- /dev/null +++ b/rules/push_security_rules/push_security_new_app_detected.yml @@ -0,0 +1,54 @@ +AnalysisType: rule +Filename: push_security_new_app_detected.py +RuleID: "Push.Security.New.App.Detected" +DisplayName: "Push Security New App Detected" +Enabled: true +LogTypes: + - Custom.PushSecurity.Entities +Severity: Info +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: New App + ExpectedResult: true + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + approvalStatus: null + creationTimestamp: 1.698064423e+09 + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + notes: "" + ownerId: null + sensitivityLevel: null + type: ZAPIER + object: APP + old: null + timestamp: 1.698604061e+09 + type: CREATE + version: "1" + - Name: App Updated + ExpectedResult: false + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + approvalStatus: APPROVED + creationTimestamp: 1.698064423e+09 + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + notes: | + Last security audit: 16 January 2023. + ownerId: 87569da6-fb7a-4df7-8ce2-246c14044911 + sensitivityLevel: HIGH + type: ZAPIER + object: APP + old: + approvalStatus: UNDER_REVIEW + creationTimestamp: 1.698064423e+09 + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + notes: | + Initial submission for review. + ownerId: 87569da6-fb7a-4df7-8ce2-246c14044911 + sensitivityLevel: MEDIUM + type: ZAPIER + timestamp: 1.698604061e+09 + type: UPDATE + version: "1" diff --git a/rules/push_security_rules/push_security_new_saas_account_created.py b/rules/push_security_rules/push_security_new_saas_account_created.py new file mode 100644 index 000000000..942ab2581 --- /dev/null +++ b/rules/push_security_rules/push_security_new_saas_account_created.py @@ -0,0 +1,17 @@ +from panther_base_helpers import deep_get + + +def rule(event): + if event.get("object") != "ACCOUNT": + return False + + if event.get("type") == "CREATE": + return True + + return False + + +def title(event): + app_type = deep_get(event, "new", "appType") + new_email = deep_get(event, "new", "email") + return f"New account on {app_type} created by {new_email}" diff --git a/rules/push_security_rules/push_security_new_saas_account_created.yml b/rules/push_security_rules/push_security_new_saas_account_created.yml new file mode 100644 index 000000000..cf20f2705 --- /dev/null +++ b/rules/push_security_rules/push_security_new_saas_account_created.yml @@ -0,0 +1,115 @@ +AnalysisType: rule +Filename: push_security_new_saas_account_created.py +RuleID: "Push.Security.New.SaaS.Account.Created" +DisplayName: "Push Security New SaaS Account Created" +Enabled: true +LogTypes: + - Custom.PushSecurity.Entities +Severity: Info +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: Account Update + ExpectedResult: false + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: ATLASSIAN + creationTimestamp: 1.698064423e+09 + email: john.hill@example.com + employeeId: 72d0347a-2663-4ef5-b1c5-df39163f1603 + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + lastUsedTimestamp: 1.698669168e+09 + loginMethods: + oidcLogin: GOOGLE_WORKSPACE + oktaSwaLogin: true + passwordLogin: true + samlLogin: OKTA + vendorSsoLogin: GOOGLE_WORKSPACE + mfaMethods: + - APP_TOTP + - PUSH_NOTIFICATION + - EMAIL_OTP + - U2F + - HARDWARE_TOTP + - PHONE_CALL + - SMS_OTP + - APP_PASSWORD + - GRID_CARD + - EXTERNAL_PROVIDER + - BACKUP_CODES + - WEBAUTHN + mfaRegistered: true + passwordId: 4c13674f-e88a-4411-bfa2-53a70468a898 + object: ACCOUNT + old: + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: ATLASSIAN + creationTimestamp: 1.698064423e+09 + email: john.hill@example.com + employeeId: 72d0347a-2663-4ef5-b1c5-df39163f1603 + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + lastUsedTimestamp: 1.698669168e+09 + loginMethods: + oidcLogin: GOOGLE_WORKSPACE + oktaSwaLogin: true + passwordLogin: true + samlLogin: OKTA + vendorSsoLogin: GOOGLE_WORKSPACE + mfaMethods: + - APP_TOTP + - PUSH_NOTIFICATION + - EMAIL_OTP + - U2F + - HARDWARE_TOTP + - PHONE_CALL + - SMS_OTP + - APP_PASSWORD + - GRID_CARD + - EXTERNAL_PROVIDER + - BACKUP_CODES + - WEBAUTHN + mfaRegistered: true + passwordId: 4c13674f-e88a-4411-bfa2-53a70468a898 + timestamp: 1.698604061e+09 + type: UPDATE + version: "1" + - Name: New Account + ExpectedResult: true + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: ATLASSIAN + creationTimestamp: 1.698064423e+09 + email: john.hill@example.com + employeeId: 72d0347a-2663-4ef5-b1c5-df39163f1603 + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + lastUsedTimestamp: 1.698669168e+09 + loginMethods: + oidcLogin: GOOGLE_WORKSPACE + oktaSwaLogin: true + passwordLogin: true + samlLogin: OKTA + vendorSsoLogin: GOOGLE_WORKSPACE + mfaMethods: + - APP_TOTP + - PUSH_NOTIFICATION + - EMAIL_OTP + - U2F + - HARDWARE_TOTP + - PHONE_CALL + - SMS_OTP + - APP_PASSWORD + - GRID_CARD + - EXTERNAL_PROVIDER + - BACKUP_CODES + - WEBAUTHN + mfaRegistered: true + passwordId: 4c13674f-e88a-4411-bfa2-53a70468a898 + object: ACCOUNT + old: null + timestamp: 1.698604061e+09 + type: CREATE + version: "1" diff --git a/rules/push_security_rules/push_security_open_security_finding.py b/rules/push_security_rules/push_security_open_security_finding.py new file mode 100644 index 000000000..6b6d7f82d --- /dev/null +++ b/rules/push_security_rules/push_security_open_security_finding.py @@ -0,0 +1,22 @@ +from panther_base_helpers import deep_get + + +def rule(event): + if event.get("object") != "FINDING": + return False + + event_type = event.get("type") + + if event_type == "CREATE": + return True + + if event_type == "UPDATE" and deep_get(event, "new", "state") == "OPEN": + return True + + return False + + +def title(event): + new_type = deep_get(event, "new", "type") + app_type = deep_get(event, "new", "appType") + return f"Open finding {new_type} for app {app_type}" diff --git a/rules/push_security_rules/push_security_open_security_finding.yml b/rules/push_security_rules/push_security_open_security_finding.yml new file mode 100644 index 000000000..8d46a7f23 --- /dev/null +++ b/rules/push_security_rules/push_security_open_security_finding.yml @@ -0,0 +1,86 @@ +AnalysisType: rule +Filename: push_security_open_security_finding.py +RuleID: "Push.Security.Open.Security.Finding" +DisplayName: "Push Security Open Security Finding" +Enabled: true +LogTypes: + - Custom.PushSecurity.Entities +Severity: Info +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: Resolved Finding + ExpectedResult: false + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + accountId: null + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: PUSH_SECURITY + creationTimestamp: 1.698064423e+09 + employeeId: 379ac7ea-ff2a-42ef-af37-06d2020dc46a + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + passwordId: c4a045a1-5331-4714-af83-6a361e98960d + state: RESOLVED + type: WEAK_PASSWORD + object: FINDING + old: + accountId: null + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: PUSH_SECURITY + creationTimestamp: 1.698064423e+09 + employeeId: 379ac7ea-ff2a-42ef-af37-06d2020dc46a + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + passwordId: c4a045a1-5331-4714-af83-6a361e98960d + state: OPEN + type: WEAK_PASSWORD + timestamp: 1.698604061e+09 + type: UPDATE + version: "1" + - Name: New Finding + ExpectedResult: true + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + accountId: null + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: PUSH_SECURITY + creationTimestamp: 1.698064423e+09 + employeeId: 379ac7ea-ff2a-42ef-af37-06d2020dc46a + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + passwordId: c4a045a1-5331-4714-af83-6a361e98960d + state: OPEN + type: WEAK_PASSWORD + object: FINDING + old: null + timestamp: 1.698604061e+09 + type: CREATE + version: "1" + - Name: Reopened Finding + ExpectedResult: true + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + accountId: null + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: PUSH_SECURITY + creationTimestamp: 1.698064423e+09 + employeeId: 379ac7ea-ff2a-42ef-af37-06d2020dc46a + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + passwordId: c4a045a1-5331-4714-af83-6a361e98960d + state: OPEN + type: WEAK_PASSWORD + object: FINDING + old: + accountId: null + appId: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + appType: PUSH_SECURITY + creationTimestamp: 1.698064423e+09 + employeeId: 379ac7ea-ff2a-42ef-af37-06d2020dc46a + id: d6a32ba5-0532-4a66-8137-48cdf409c972 + passwordId: c4a045a1-5331-4714-af83-6a361e98960d + state: RESOLVED + type: WEAK_PASSWORD + timestamp: 1.698604061e+09 + type: UPDATE + version: "1" diff --git a/rules/push_security_rules/push_security_phishable_mfa_method.py b/rules/push_security_rules/push_security_phishable_mfa_method.py new file mode 100644 index 000000000..dac56cccd --- /dev/null +++ b/rules/push_security_rules/push_security_phishable_mfa_method.py @@ -0,0 +1,33 @@ +from panther_base_helpers import deep_get + +identity_providers = ("MICROSOFT_365", "GOOGLE_WORKSPACE", "OKTA", "JUMPCLOUD", "PING") + +phishable_mfa = ("EMAIL_OTP", "PHONE_CALL", "SMS", "APP_PASSWORD") + + +def rule(event): + if event.get("object") != "ACCOUNT": + return False + + mfa_methods = deep_get(event, "new", "mfaMethods") + + for method in mfa_methods: + if method in phishable_mfa: + return True + + return False + + +def severity(event): + if deep_get(event, "new", "appType") in identity_providers: + return "HIGH" + return "INFO" + + +def title(event): + mfa_methods = ", ".join(deep_get(event, "new", "mfaMethods", default="No MFA")) + new_email = deep_get(event, "new", "email") + app_type = deep_get(event, "new", "appType", default=[]) + + return f"{new_email} using phisbable MFA method with {app_type}. \ + MFA methods enabled: {mfa_methods}" diff --git a/rules/push_security_rules/push_security_phishable_mfa_method.yml b/rules/push_security_rules/push_security_phishable_mfa_method.yml new file mode 100644 index 000000000..be2f81530 --- /dev/null +++ b/rules/push_security_rules/push_security_phishable_mfa_method.yml @@ -0,0 +1,99 @@ +AnalysisType: rule +Filename: push_security_phishable_mfa_method.py +RuleID: "Push.Security.Phishable.MFA.Method" +DisplayName: "Push Security Phishable MFA Method" +Enabled: true +LogTypes: + - Custom.PushSecurity.Entities +Severity: Info +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: Dropbox Phishable MFA + ExpectedResult: true + Log: + id: d1e5794f-666d-4cba-abae-c6d889ca1903 + new: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: DROPBOX + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + - EMAIL_OTP + mfaRegistered: false + passwordId: null + object: ACCOUNT + old: null + - Name: Google Workspace Phishable MFA + ExpectedResult: true + Log: + id: d1e5794f-666d-4cba-abae-c6d889ca1903 + new: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: GOOGLE_WORKSPACE + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: + - SMS + - EMAIL_OTP + mfaRegistered: false + passwordId: null + object: ACCOUNT + old: null + - Name: No MFA Enabled + ExpectedResult: false + Log: + id: d1e5794f-666d-4cba-abae-c6d889ca1903 + new: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: [] + mfaRegistered: false + passwordId: null + object: ACCOUNT + old: + appId: 67ef5c13-b5e6-4945-af7b-c11ac98f630f + appType: CONTENTFUL + creationTimestamp: 1.707775048e+09 + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + id: 5e15ce4c-6b93-4fbf-aed9-1890775efa90 + lastUsedTimestamp: null + loginMethods: + oidcLogin: null + oktaSwaLogin: false + passwordLogin: false + samlLogin: null + mfaMethods: [] + mfaRegistered: false + passwordId: null + timestamp: 1.707775049e+09 + type: CREATE + version: "1" diff --git a/rules/push_security_rules/push_security_phishing_attack.py b/rules/push_security_rules/push_security_phishing_attack.py new file mode 100644 index 000000000..814fb6083 --- /dev/null +++ b/rules/push_security_rules/push_security_phishing_attack.py @@ -0,0 +1,22 @@ +from panther_base_helpers import deep_get + + +def rule(event): + if event.get("object") == "PASSWORD_PHISHING": + return True + + return False + + +def severity(event): + if deep_get(event, "new", "mode") != "BLOCK": + return "HIGH" + return "LOW" + + +def title(event): + app_type = deep_get(event, "new", "appType") + employee_email = deep_get(event, "new", "employee", "email") + new_mode = deep_get(event, "new", "mode") + return f"Phishing attack on app {app_type} user {employee_email}. \ + Attack detected in mode {new_mode}." diff --git a/rules/push_security_rules/push_security_phishing_attack.yml b/rules/push_security_rules/push_security_phishing_attack.yml new file mode 100644 index 000000000..974542099 --- /dev/null +++ b/rules/push_security_rules/push_security_phishing_attack.yml @@ -0,0 +1,63 @@ +AnalysisType: rule +Filename: push_security_phishing_attack.py +RuleID: "Push.Security.Phishing.Attack" +DisplayName: "Push Security Phishing Attack" +Enabled: true +LogTypes: + - Custom.PushSecurity.AttackDetection +Severity: High +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: Phishing Detected - Block Mode + ExpectedResult: true + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + appType: OKTA + browser: CHROME + employee: + chatopsEnabled: true + creationTimestamp: 1.698669223e+09 + department: Security Engineering + email: john.hill@example.com + firstName: John + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + lastName: Hill + licensed: true + location: New York + mode: BLOCK + os: WINDOWS + referrerUrl: https://statics.teams.cdn.office.net/ + sourceIpAddress: 8.158.25.38 + url: https://evil.com/okta.php + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 + object: PASSWORD_PHISHING + timestamp: 1.698604061e+09 + version: "1" + - Name: Phishing Detected - Monitor Mode + ExpectedResult: true + Log: + id: c478966c-f927-411c-b919-179832d3d50c + new: + appType: OKTA + browser: CHROME + employee: + chatopsEnabled: true + creationTimestamp: 1.698669223e+09 + department: Security Engineering + email: john.hill@example.com + firstName: John + id: 2a2197de-ad2c-47e4-8dcb-fb0f04cf83e0 + lastName: Hill + licensed: true + location: New York + mode: MONITOR + os: WINDOWS + referrerUrl: https://statics.teams.cdn.office.net/ + sourceIpAddress: 8.158.25.38 + url: https://evil.com/okta.php + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 + object: PASSWORD_PHISHING + timestamp: 1.698604061e+09 + version: "1" diff --git a/rules/push_security_rules/push_security_unauthorized_idp_login.py b/rules/push_security_rules/push_security_unauthorized_idp_login.py new file mode 100644 index 000000000..72af762cf --- /dev/null +++ b/rules/push_security_rules/push_security_unauthorized_idp_login.py @@ -0,0 +1,31 @@ +from panther_base_helpers import deep_get + +# Configure allowed identity provider logins to SaaS apps +allowed_idps = { + "GOOGLE_WORKSPACE": {"OIDC_LOGIN", "SAML_LOGIN"}, + "OKTA": {"PASSWORD_LOGIN"}, + None: {"PASSWORD_LOGIN"}, +} + + +def rule(event): + if event.get("object") != "LOGIN": + return False + + identity_provider = deep_get(event, "new", "identityProvider") + login_type = deep_get(event, "new", "loginType") + + if identity_provider in allowed_idps and login_type in allowed_idps[identity_provider]: + return False + + return True + + +def title(event): + identity_provider = deep_get(event, "new", "identityProvider", default="Null identityProvider") + login_type = deep_get(event, "new", "loginType", default="Null loginType") + app_type = deep_get(event, "new", "appType", default="Null appType") + new_email = deep_get(event, "new", "email") + + return f"Unauthorized identity provider in use. User: {new_email} \ + used {identity_provider} {login_type} on {app_type}" diff --git a/rules/push_security_rules/push_security_unauthorized_idp_login.yml b/rules/push_security_rules/push_security_unauthorized_idp_login.yml new file mode 100644 index 000000000..69188c856 --- /dev/null +++ b/rules/push_security_rules/push_security_unauthorized_idp_login.yml @@ -0,0 +1,88 @@ +AnalysisType: rule +Filename: push_security_unauthorized_idp_login.py +RuleID: "Push.Security.Unauthorized.IdP.Login" +DisplayName: "Push Security Unauthorized IdP Login" +Enabled: true +LogTypes: + - Custom.PushSecurity.Activity +Severity: High +Description: Login to application with unauthorized identity provider which could indicate a SAMLjacking attack. +Reference: https://github.com/pushsecurity/saas-attacks/blob/main/techniques/samljacking/description.md +DedupPeriodMinutes: 60 +Threshold: 1 +Tests: + - Name: Google Workspace Password Login + ExpectedResult: true + Log: + id: d240e3f2-3cd6-425f-a835-dad0ff237d09 + new: + accountId: a93b45a7-fdce-489e-b76d-2bd6862a62ba + appId: 8348ca36-d254-4e1b-8f31-6837d82fc5cb + appType: GOOGLE_WORKSPACE + browser: EDGE + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + identityProvider: GOOGLE_WORKSPACE + leakedPassword: false + loginTimestamp: 1.707773386e+09 + loginType: PASSWORD_LOGIN + os: WINDOWS + passwordId: 6ae9f0b2-9300-43f0-b210-c0d3c16640f8 + passwordManuallyTyped: false + sourceIpAddress: 35.90.103.134 + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.2420.81 + weakPassword: false + weakPasswordReasons: null + object: LOGIN + timestamp: 1.707774319e+09 + version: "1" + - Name: Microsoft 365 OIDC Login + ExpectedResult: true + Log: + id: d240e3f2-3cd6-425f-a835-dad0ff237d09 + new: + accountId: a93b45a7-fdce-489e-b76d-2bd6862a62ba + appId: 8348ca36-d254-4e1b-8f31-6837d82fc5cb + appType: DROPBOX + browser: EDGE + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + identityProvider: MICROSOFT_365 + leakedPassword: false + loginTimestamp: 1.707773386e+09 + loginType: OIDC_LOGIN + os: WINDOWS + passwordId: 6ae9f0b2-9300-43f0-b210-c0d3c16640f8 + passwordManuallyTyped: false + sourceIpAddress: 35.90.103.134 + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.2420.81 + weakPassword: false + weakPasswordReasons: null + object: LOGIN + timestamp: 1.707774319e+09 + version: "1" + - Name: Password Login + ExpectedResult: false + Log: + id: d240e3f2-3cd6-425f-a835-dad0ff237d09 + new: + accountId: a93b45a7-fdce-489e-b76d-2bd6862a62ba + appId: 8348ca36-d254-4e1b-8f31-6837d82fc5cb + appType: DROPBOX + browser: EDGE + email: jet.black@issp.com + employeeId: ca6cf7ce-90e6-4eb5-a262-7899bc48c39c + identityProvider: null + leakedPassword: false + loginTimestamp: 1.707773386e+09 + loginType: PASSWORD_LOGIN + os: WINDOWS + passwordId: 6ae9f0b2-9300-43f0-b210-c0d3c16640f8 + passwordManuallyTyped: false + sourceIpAddress: 35.90.103.134 + userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.2420.81 + weakPassword: false + weakPasswordReasons: null + object: LOGIN + timestamp: 1.707774319e+09 + version: "1"