Skip to content

Commit

Permalink
Merge branch 'develop' into jpts/add-wiz-actor
Browse files Browse the repository at this point in the history
  • Loading branch information
arielkr256 authored Nov 4, 2024
2 parents 49c010e + bdc7a6c commit 41e971a
Show file tree
Hide file tree
Showing 54 changed files with 1,172 additions and 39 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/check-packs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
panther_analysis_tool check-packs || echo "errors=`cat errors.txt`" >> $GITHUB_OUTPUT
- name: Comment PR
uses: thollander/actions-comment-pull-request@e2c37e53a7d2227b61585343765f73a9ca57eda9
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b
if: ${{ steps.check-packs.outputs.errors }}
with:
mode: upsert
Expand All @@ -57,7 +57,7 @@ jobs:
```
comment-tag: check-packs
- name: Delete comment
uses: thollander/actions-comment-pull-request@e2c37e53a7d2227b61585343765f73a9ca57eda9
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b
if: ${{ !steps.check-packs.outputs.errors }}
with:
mode: delete
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ Detection:
- ID: StopInstance FOLLOWED BY StartupScriptChange
From: StopInstance
To: StartupScriptChange
WithinTimeFrameMinutes: 90
Match:
- On: p_alert_context.instance_ids
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 5
Tests:
- Name: Instance Stopped, Followed By Script Change
Expand Down
2 changes: 1 addition & 1 deletion correlation_rules/aws_console_sign-in_without_okta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Detection:
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
LookbackWindowMinutes: 1440
LookbackWindowMinutes: 2160
Tests:
- Name: AWS Console Sign-In PRECEDED BY Okta Redirect
ExpectedResult: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ Detection:
- ID: User Backdoored TO User Accessed ON IP Addr
From: User Backdoored
To: User Accessed
WithinTimeFrameMinutes: 60
Match:
- On: p_alert_context.ip_accessKeyId
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 10
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Tests:
- Name: Access Key Created and Used from Same IP
ExpectedResult: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Detection:
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
LookbackWindowMinutes: 1440
LookbackWindowMinutes: 2160
Tests:
- Name: AWS SSO Access Token Retrieved by Authenticated IP
ExpectedResult: false
Expand Down
5 changes: 3 additions & 2 deletions correlation_rules/aws_user_takeover_via_password_reset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ Detection:
- ID: Password Reset TO Login ON IP Addr
From: Password Reset
To: Login
WithinTimeFrameMinutes: 60
Match:
- On: p_alert_context.ip_and_username
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 10
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Tests:
- Name: Password Reset, Then Login From Same IP
ExpectedResult: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ Detection:
- ID: ServiceCreated FOLLOWED BY SetIAMPolicy
From: ServiceCreated
To: SetIAMPolicy
WithinTimeFrameMinutes: 90
Match:
- On: p_alert_context.caller_ip
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 5
Tests:
- Name: GCP Service Run, Followed By IAM Policy Change From Same IP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ Detection:
- ID: GHASChange NOT FOLLOWED BY RepoArchived
From: RepoArchived
To: GHASChange
WithinTimeFrameMinutes: 60
Match:
- On: p_alert_context.repo
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 10
Tests:
- Name: Security Change on Repo, Followed By Same Repo Archived
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Detection:
WithinTimeFrameMinutes: 15
Match:
- On: p_alert_context.actor_id
LookbackWindowMinutes: 1440
LookbackWindowMinutes: 2160
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
Expand Down
5 changes: 3 additions & 2 deletions correlation_rules/okta_login_without_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ Detection:
- ID: Okta to Push
From: Okta
To: Push
WithinTimeFrameMinutes: 60
Match:
- From: actor.alternateId
To: new.email
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 10
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Tests:
- Name: Okta Login, Followed By Push Authorized Login
ExpectedResult: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Detection:
WithinTimeFrameMinutes: 15
Match:
- On: user_name
LookbackWindowMinutes: 1440
LookbackWindowMinutes: 2160
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
Expand Down
5 changes: 3 additions & 2 deletions correlation_rules/potential_compromised_okta_credentials.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ Detection:
- ID: Match on user
From: Login Without Push Marker
To: Push Phishing
WithinTimeFrameMinutes: 60
Match:
- From: actor.alternateId
To: new.employee.email
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 10
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Tests:
- Name: Login Without Marker, Followed By Phishing Detection
ExpectedResult: true
Expand Down
5 changes: 3 additions & 2 deletions correlation_rules/secret_exposed_and_not_quarantined.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ Detection:
- ID: SecretFound TO SecretNotQuarantined
From: SecretFound
To: SecretNotQuarantined
WithinTimeFrameMinutes: 60
Schedule:
RateMinutes: 60
RateMinutes: 1440
TimeoutMinutes: 10
LookbackWindowMinutes: 90
LookbackWindowMinutes: 2160
Tests:
- Name: Secret Found and Quarantied
ExpectedResult: false
Expand Down
4 changes: 2 additions & 2 deletions correlation_rules/snowflake_data_exfiltration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Detection:
Match:
- On: stage
Schedule:
RateMinutes: 720
RateMinutes: 1440
TimeoutMinutes: 15
LookbackWindowMinutes: 1440
LookbackWindowMinutes: 2160
Tests:
- Name: Data Exfiltration
ExpectedResult: true
Expand Down
47 changes: 47 additions & 0 deletions correlation_rules/snowflake_potential_brute_force_success.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
AnalysisType: correlation_rule
RuleID: "Snowflake.PotentialBruteForceSuccess"
DisplayName: "Snowflake Brute Force Login Success"
Enabled: true
Severity: High
Description: Detecting brute force activity and reporting when a user has incorrectly logged in multiple times and then had a successful login.
Detection:
- Sequence:
- ID: Multiple Failed Logins
RuleID: Snowflake.Stream.BruteForceByIp
MinMatchCount: 5
- ID: Successful Login
RuleID: Snowflake.Stream.LoginSuccess
Transitions:
- ID: Multiple Failed Logins FOLLOWED BY Successful Login
From: Multiple Failed Logins
To: Successful Login
WithinTimeFrameMinutes: 30
Match:
- On: CLIENT_IP
Schedule:
RateMinutes: 720
TimeoutMinutes: 15
LookbackWindowMinutes: 1440
Tests:
- Name: Successful Bulk Login
ExpectedResult: true
RuleOutputs:
- ID: Multiple Failed Logins
Matches:
CLIENT_IP:
"1.1.1.1": [0, 2, 3, 6, 9, 10, 11, 15]
- ID: Successful Login
Matches:
CLIENT_IP:
"1.1.1.1": [16]
- Name: Successful Login With Single Failure
ExpectedResult: false
RuleOutputs:
- ID: Multiple Failed Logins
Matches:
CLIENT_IP:
"1.1.1.1": [0]
- ID: Successful Login
Matches:
CLIENT_IP:
"1.1.1.1": [1]
4 changes: 2 additions & 2 deletions global_helpers/panther_aws_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def aws_strip_role_session_id(user_identity_arn):
return user_identity_arn


def aws_rule_context(event: dict):
def aws_rule_context(event):
return {
"eventName": event.get("eventName", "<MISSING_EVENT_NAME>"),
"eventSource": event.get("eventSource", "<MISSING_ACCOUNT_ID>"),
Expand All @@ -41,7 +41,7 @@ def aws_rule_context(event: dict):
}


def aws_guardduty_context(event: dict):
def aws_guardduty_context(event):
return {
"description": event.get("description", "<MISSING DESCRIPTION>"),
"severity": event.get("severity", "<MISSING SEVERITY>"),
Expand Down
2 changes: 1 addition & 1 deletion global_helpers/panther_box_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def build_jwt_settings(response: dict) -> dict:

# 'additional_details' from box logs varies by event_type.
# This helper wraps the process of extracting those details.
def box_parse_additional_details(event: dict):
def box_parse_additional_details(event):
additional_details = event.get("additional_details", {})
if isinstance(additional_details, (str, bytes)):
try:
Expand Down
4 changes: 2 additions & 2 deletions global_helpers/panther_cloudflare_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def map_source_to_name(event: Any) -> str:
)


def cloudflare_fw_alert_context(event: dict = None):
def cloudflare_fw_alert_context(event=None):
keep_keys = [
"Action",
"ClientIP",
Expand All @@ -57,7 +57,7 @@ def cloudflare_fw_alert_context(event: dict = None):
return context_dict


def cloudflare_http_alert_context(event: dict = None):
def cloudflare_http_alert_context(event=None):
keep_keys = [
"BotScore",
"BotScoreSrc",
Expand Down
6 changes: 3 additions & 3 deletions global_helpers/panther_crowdstrike_fdr_helpers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def crowdstrike_detection_alert_context(event: dict):
def crowdstrike_detection_alert_context(event):
"""Returns common context for Crowdstrike detections"""
return {
"aid": get_crowdstrike_field(event, "aid", default=""),
Expand All @@ -13,7 +13,7 @@ def crowdstrike_detection_alert_context(event: dict):
}


def crowdstrike_process_alert_context(event: dict):
def crowdstrike_process_alert_context(event):
"""Returns common process context for Crowdstrike detections"""
return {
"aid": get_crowdstrike_field(event, "aid", default=""),
Expand All @@ -28,7 +28,7 @@ def crowdstrike_process_alert_context(event: dict):
}


def crowdstrike_network_detection_alert_context(event: dict):
def crowdstrike_network_detection_alert_context(event):
"""Returns common network context for Crowdstrike detections"""
return {
"LocalAddressIP4": get_crowdstrike_field(event, "LocalAddressIP4", default=""),
Expand Down
2 changes: 1 addition & 1 deletion global_helpers/panther_duo_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from json import JSONDecodeError


def deserialize_administrator_log_event_description(event: dict) -> dict:
def deserialize_administrator_log_event_description(event) -> dict:
"""Intelligently try and decode a field that is usually stringified json into a python dict.
This description field seems to take the form of stringified json, So this function
Expand Down
2 changes: 1 addition & 1 deletion global_helpers/panther_lookuptable_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def _lookup(self, match_field: str, *keys) -> list or str:
def p_matched(self):
return self._p_matched

def p_matches(self, event: dict, p_match: str = "") -> dict:
def p_matches(self, event, p_match: str = "") -> dict:
"""Collect enrichments by searching for a value match in the p_match field
Parameters:
Expand Down
2 changes: 1 addition & 1 deletion global_helpers/panther_okta_helpers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def okta_alert_context(event: dict):
def okta_alert_context(event):
"""Returns common context for automation of Okta alerts"""
return {
"event_type": event.get("eventtype", ""),
Expand Down
11 changes: 11 additions & 0 deletions global_helpers/panther_snowflake_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
""" Global helpers for Snowflake streaming detections. """


def query_history_alert_context(event):
return {
"user": event.get("user_name", "<UNKNOWN USER>"),
"role": event.get("role_name", "<UNKNOWN ROLE>"),
"source": event.get("p_source_label", "<UNKNOWN SOURCE>"),
# Not all queries are run in a warehouse; e.g.: getting worksheet files
"warehouse": event.get("WAREHOUSE_NAME", "<NO WAREHOUSE>"),
}
5 changes: 5 additions & 0 deletions global_helpers/panther_snowflake_helpers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
AnalysisType: global
Filename: panther_snowflake_helpers.py
GlobalID: "panther_snowflake_helpers"
Description: >
Global helpers for Snowflake streaming detections
1 change: 1 addition & 0 deletions packs/aws.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ PackDefinition:
- AWS.CMK.KeyRotation
- AWS.DynamoDB.TableTTLEnabled
- AWS.EC2.Vulnerable.XZ.Image.Launched
- Amazon.EKS.AnonymousAPIAccess
- AWS.IAM.Policy.DoesNotGrantAdminAccess
- AWS.IAM.Policy.DoesNotGrantNetworkAdminAccess
- AWS.IAM.Resource.DoesNotHaveInlinePolicy
Expand Down
23 changes: 23 additions & 0 deletions packs/snowflake_streaming.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
AnalysisType: pack
PackID: PantherManaged.SnowflakeStreaming
DisplayName: "Panther Snowflake Real-Time Rules"
Description: Group of all streaming (real-time) Snowflake detections
PackDefinition:
IDs:
# Correlation Rules
- Snowflake.PotentialBruteForceSuccess
# Helpers
- panther_snowflake_helpers
# Rules
- Snowflake.Stream.AccountAdminGranted
- Snowflake.Stream.BruteForceByIp
- Snowflake.Stream.BruteForceByUsername
- Snowflake.Stream.ExternalShares
- Snowflake.Stream.FileDownloaded
- Snowflake.Stream.LoginSuccess
- Snowflake.Stream.LoginWithoutMFA
- Snowflake.Stream.PublicRoleGrant
- Snowflake.Stream.TableCopiedIntoStage
- Snowflake.Stream.TempStageCreated
- Snowflake.Stream.UserCreated
- Snowflake.Stream.UserEnabled
Loading

0 comments on commit 41e971a

Please sign in to comment.