Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare for v3.62.0 #1338

Merged
merged 49 commits into from
Aug 27, 2024
Merged
Changes from 19 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
944da69
add: new user created, password changed
ben-githubs Jul 22, 2024
4cae76b
add: Crowdstrike.UserDeleted
ben-githubs Jul 22, 2024
5caa1be
add: Crowdstrike.EphemeralUserAccount
ben-githubs Jul 22, 2024
f5b63ff
abstract "turn audit keys to dictionary" away from "alert context"
ben-githubs Jul 22, 2024
5f930be
add: Crowdstrike.AdminRoleAssigned
ben-githubs Jul 22, 2024
d4381b7
chore: formatting updates to python code
ben-githubs Jul 24, 2024
6b6cb06
add: Crowdstrike.SingleIpAllowlisted
ben-githubs Jul 26, 2024
349a077
add: Crowdstrike.AllowlistRemoved
ben-githubs Jul 26, 2024
b3a70a6
edit: Crowdstrike.SingleIpAllowlisted detects updated allow lists as …
ben-githubs Jul 26, 2024
a9498ba
Improve github webhook modified rule
geoffg-sentry Aug 9, 2024
7bcec48
remove deprecated iocs and helper references
arielkr256 Aug 9, 2024
c06b89f
remove deprecated ioc rules
arielkr256 Aug 13, 2024
9f207a6
remove failing tests
arielkr256 Aug 13, 2024
a12ba46
lint
arielkr256 Aug 13, 2024
b2eb2af
edit: update Crowdstrike.UserPasswordChange with dynamic severity
ben-githubs Aug 13, 2024
0d0d4db
edit: minor fixes and suggestions raised by Ariel
ben-githubs Aug 13, 2024
dc3d432
add: Crowdstrike.IpAllowlistChanged
ben-githubs Aug 13, 2024
a66a12f
fix: minor changes to str_to_list and Crowdstrike.IpAllowlistChanged
ben-githubs Aug 14, 2024
4299b50
Merge pull request #1325 from panther-labs/remove-deprecated
arielkr256 Aug 14, 2024
901901f
add: Crowdstrike.NewAdminUserCreated
ben-githubs Aug 15, 2024
a060b68
chore: make yaml formatting consistent
ben-githubs Aug 15, 2024
594556e
Info Alerts are Signals, Nonrouted
arielkr256 Aug 15, 2024
e3cb9a2
Merge pull request #1328 from panther-labs/info-alerts-are-signals-no…
arielkr256 Aug 16, 2024
fcb3433
edit: update pack manifest
ben-githubs Aug 16, 2024
896e4ac
fix: mispelled rule id in pack manifest
ben-githubs Aug 16, 2024
d1f1ce3
Merge branch 'release' into ben/new/cs_eventstreams_audit_rules
arielkr256 Aug 16, 2024
98c4c4a
Merge pull request #1307 from panther-labs/ben/new/cs_eventstreams_au…
arielkr256 Aug 16, 2024
790b4e5
Okta rate limit tuning (#1329)
arielkr256 Aug 19, 2024
1e0fbf5
traffic mirroring tuning (#1330)
arielkr256 Aug 19, 2024
3e6592f
better deduplication of alerts (#1331)
arielkr256 Aug 19, 2024
14aec5e
add dynamic severity to AWS.CloudTrail.SnapshotMadePublic
ben-githubs Aug 21, 2024
155d4c2
initial commit
ben-githubs Aug 21, 2024
64703f6
Missing MITRE ATT&CK tactics (#1322)
arielkr256 Aug 21, 2024
3ee6ad2
tuning Wiz Alert Passthrough rule (#1326)
arielkr256 Aug 21, 2024
38cf297
Merge branch 'release' into improve-github-webhook-modified-rule
arielkr256 Aug 22, 2024
14932ca
Merge pull request #1324 from geoffg-sentry/improve-github-webhook-mo…
arielkr256 Aug 22, 2024
704b750
Merge branch 'release' into THREAT-325-Tweak-AWS.CloudTrail.SnapshotM…
arielkr256 Aug 22, 2024
77f83ed
Merge pull request #1333 from panther-labs/THREAT-325-Tweak-AWS.Cloud…
arielkr256 Aug 22, 2024
254fa34
fixed unit tests that were failing in pypanther
ben-githubs Aug 22, 2024
04187a0
Merge pull request #1335 from panther-labs/THREAT-378/fix-failing-pyp…
arielkr256 Aug 22, 2024
4ba7f33
Convert to Signals
arielkr256 Aug 26, 2024
4532e1b
Merge pull request #1336 from panther-labs/signals-for-noisy-alerts
arielkr256 Aug 26, 2024
9d38712
update slack passthrough anomaly rules
arielkr256 Aug 27, 2024
51efb76
Merge branch 'release' into THREAT-371/slack-anomaly-detection-tuning
arielkr256 Aug 27, 2024
d5a2b43
Merge pull request #1334 from panther-labs/THREAT-371/slack-anomaly-d…
arielkr256 Aug 27, 2024
2ba9384
PAT update v0.52.1
arielkr256 Aug 27, 2024
8341a04
Merge branch 'release' into pat-version-bump
le4ker Aug 27, 2024
7833588
Merge pull request #1337 from panther-labs/pat-version-bump
arielkr256 Aug 27, 2024
a4aed26
Merge branch 'main' into release
arielkr256 Aug 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions global_helpers/crowdstrike_event_streams_helpers.py
Original file line number Diff line number Diff line change
@@ -2,6 +2,19 @@


def cs_alert_context(event):
return audit_keys_dict(event)


def audit_keys_dict(event):
return key_value_list_to_dict(
event.deep_get("event", "AuditKeyValues", default=[]), "Key", "ValueString"
)


def str_to_list(liststr: str) -> list[str]:
"""Several crowdstrike values are returned as a list like "[x y z]". This function convetrs
such entries to Python list of strings, like: ["x", "y", "z"]."""
# Validate
if liststr[0] != "[" or liststr[-1] != "]":
raise ValueError(f"Invalid list string: {liststr}")
return [x.strip() for x in liststr[1:-1].split(" ")]
14 changes: 12 additions & 2 deletions packs/crowdstrike_event_streams.yml
Original file line number Diff line number Diff line change
@@ -3,7 +3,17 @@ PackID: PantherManaged.CrowdstrikeEventStreams
Description: Group of all Crowdstrike Event Stream detections
PackDefinition:
IDs:
- crowdstrike_event_streams_helpers
- panther_base_helpers

- Crowdstrike.AdminRoleAssigned
- Crowdstrike.AllowlistRemoved
- Crowdstrike.API.Key.Created
- Crowdstrike.API.Key.Deleted
- panther_base_helpers
- crowdstrike_event_streams_helpers
- Crowdstrike.EphemeralUserAccount
- Crowdstrike.IpAllowlistChanged
- Crowdstrike.NewAdminUserCreated
- Crowdstrike.NewUserCreated
- Crowdstrike.SingleIpAllowlisted
- Crowdstrike.UserDeleted
- Crowdstrike.UserPasswordChange
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from crowdstrike_event_streams_helpers import audit_keys_dict, cs_alert_context

# List of priviledged roles.
# IMPORTANT: YOU MUST ADD ANY CUSTOM ADMIN ROLES YOURSELF
ADMIN_ROLES = {
"billing_dashboard_admin",
"falconhost_admin",
"firewall_manager",
"xdr_admin", # NG SIEM Admin
"remote_responder_three", # Remote Responder Admin
}


def get_roles_assigned(event):
"""Returns a list of the roles assigned in this event."""
# Extract the AuditKeyValues construct
audit_keys = audit_keys_dict(event)
# Return Roles
return audit_keys.get("roles", "").split(",")


def rule(event):
# Ignore non role-granting events
if not all(
[
event.deep_get("event", "OperationName") == "grantUserRoles",
event.deep_get("event", "Success"),
]
):
return False

# Raise alert if any of the admin roles were assigned
roles_assigned = get_roles_assigned(event)
return bool(ADMIN_ROLES & set(roles_assigned))


def title(event):
audit_keys = audit_keys_dict(event)
actor = audit_keys["actor_user"]
target = audit_keys["target_name"]
admin_roles = set(get_roles_assigned(event)) & ADMIN_ROLES
return f"{actor} assigned admin roles to {target}: {', '.join(list(admin_roles))}"


def dedup(event):
# The title includes the role names, but if the actor assigned more roles to the user, we
# dedup those alerts as well.
audit_keys = audit_keys_dict(event)
actor = audit_keys["actor_user"]
target = audit_keys["target_name"]
return f"{actor}-{target}"


def alert_context(event):
context = cs_alert_context(event)
actor = context.get("actor_user", "UNKNWON_ACTOR")
target = context.get("target_name", "UNKNOWN_TARGET")
context["actor_target"] = f"{actor}-{target}"
return context
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
AnalysisType: rule
Filename: crowdstrike_admin_role_assigned.py
RuleID: "Crowdstrike.AdminRoleAssigned"
DisplayName: "Crowdstrike Admin Role Assigned"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Medium
Reports:
MITRE ATT&CK:
- T1093.003 # Additional Cloud Roles
Description: A user was assigned a priviledged role
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Confirm the role assignment is justified.
Tests:
- Name: Admin Role Assigned (Single)
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "merry.brandybuck@hobbiton.co"
},
{
"Key": "target_user_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "roles",
"ValueString": "billing_dashboard_admin"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "897d300ad09137b362ee6a62846a9277"
},
{
"Key": "actor_user",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "actor_user_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
}
],
"OperationName": "grantUserRoles",
"ServiceName": "Crowdstrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 21:32:49.000000000",
"UserId": "peregrin.took@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 21:32:49.531000000",
"eventType": "AuthActivityAuditEvent",
"offset": 342905,
"version": "1.0"
}
}
- Name: Admin Role Assigned (Multiple)
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "merry.brandybuck@hobbiton.co"
},
{
"Key": "target_user_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "roles",
"ValueString": "custom_non_admin_role,billing_dashboard_admin,falconhost_admin"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "897d300ad09137b362ee6a62846a9277"
},
{
"Key": "actor_user",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "actor_user_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
}
],
"OperationName": "grantUserRoles",
"ServiceName": "Crowdstrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 21:32:49.000000000",
"UserId": "peregrin.took@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 21:32:49.531000000",
"eventType": "AuthActivityAuditEvent",
"offset": 342905,
"version": "1.0"
}
}
- Name: Non-Admin Role Assigned
ExpectedResult: false
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "merry.brandybuck@hobbiton.co"
},
{
"Key": "target_user_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "roles",
"ValueString": "custom_non_admin_role"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "897d300ad09137b362ee6a62846a9277"
},
{
"Key": "actor_user",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "actor_user_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
}
],
"OperationName": "grantUserRoles",
"ServiceName": "Crowdstrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 21:32:49.000000000",
"UserId": "peregrin.took@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 21:32:49.531000000",
"eventType": "AuthActivityAuditEvent",
"offset": 342905,
"version": "1.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from crowdstrike_event_streams_helpers import audit_keys_dict, cs_alert_context


def rule(event):
# Return True if allowlist is deleted
if event.deep_get("event", "OperationName") == "DeleteAllowlistGroup":
return True

# Return True if allowlist is disabled
if event.deep_get("event", "OperationName") == "UpdateAllowlistGroup":
audit_keys = audit_keys_dict(event)
return audit_keys.get("active") == "false" and audit_keys.get("old_active") == "true"

return False


def title(event):
actor = event.deep_get("event", "UserId")
audit_keys = audit_keys_dict(event)
list_name = audit_keys.get("group_name", "UNKNOWN_GROUP")

verb = {"DeleteAllowlistGroup": "deleted", "UpdateAllowlistGroup": "disabled"}.get(
event.deep_get("event", "OperationName"), "removed"
)

return f'{actor} {verb} IP allowlist "{list_name}"'


def dedup(event):
# We wanna group alerts if a user disables, then deletes the same allowlist
actor = event.deep_get("event", "UserId")
audit_keys = audit_keys_dict(event)
list_name = audit_keys.get("group_name", "UNKNOWN_GROUP")
return f"{actor}-{list_name}"


def alert_context(event):
return cs_alert_context(event)


def severity(event):
# Downgrade severity if a disabled allowlist was deleted
if all(
[
event.deep_get("event", "OperationName") == "DeleteAllowlistGroup",
audit_keys_dict(event).get("enabled") == "false",
]
):
return "INFO"
return "DEFAULT"
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
AnalysisType: rule
Filename: crowdstrike_allowlist_removed.py
RuleID: "Crowdstrike.AllowlistRemoved"
DisplayName: "Crowdstrike Allowlist Removed"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Medium
Reports:
MITRE ATT&CK:
- T1531 # Account Access removal
Description: A user deleted an allowlist
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Confirm if the deleted allowlist is needed.
Tests:
- Name: Enabled Allow List Deleted
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "cidrs",
"ValueString": "[0.0.0.0/8]"
},
{
"Key": "contexts",
"ValueString": "[API]"
},
{
"Key": "active",
"ValueString": "true"
},
{
"Key": "allowlist_group_id",
"ValueString": "782f842e-98dd-4ee7-9793-33abf8647656"
},
{
"Key": "group_name",
"ValueString": "my_allow_list"
},
{
"Key": "description",
"ValueString": ""
}
],
"OperationName": "DeleteAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 19:43:35.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-26 19:43:35.082000000",
"eventType": "AuthActivityAuditEvent",
"offset": 366125,
"version": "1.0"
}
}
- Name: Disabled Allow List Deleted
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "cidrs",
"ValueString": "[0.0.0.0/8]"
},
{
"Key": "contexts",
"ValueString": "[API]"
},
{
"Key": "active",
"ValueString": "false"
},
{
"Key": "allowlist_group_id",
"ValueString": "782f842e-98dd-4ee7-9793-33abf8647656"
},
{
"Key": "group_name",
"ValueString": "my_allow_list"
},
{
"Key": "description",
"ValueString": ""
}
],
"OperationName": "DeleteAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 19:43:35.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-26 19:43:35.082000000",
"eventType": "AuthActivityAuditEvent",
"offset": 366125,
"version": "1.0"
}
}
- Name: Allowlist Disabled
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "old_active",
"ValueString": "true"
},
{
"Key": "group_name",
"ValueString": "my_allow_list"
},
{
"Key": "old_group_name",
"ValueString": "b"
},
{
"Key": "cidrs",
"ValueString": "[1.2.3.4/8]"
},
{
"Key": "contexts",
"ValueString": "[API UI]"
},
{
"Key": "active",
"ValueString": "false"
},
{
"Key": "old_allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "old_description",
"ValueString": ""
},
{
"Key": "old_cidrs",
"ValueString": "[1.2.3.4/8]"
},
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "old_contexts",
"ValueString": "[API UI]"
}
],
"OperationName": "UpdateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 19:52:14.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-26 19:52:14.438000000",
"eventType": "AuthActivityAuditEvent",
"offset": 366171,
"version": "1.0"
}
}
- Name: Unrelated Event
ExpectedResult: false
Log:
{
"metadata": {
"customerIDString": "face_customer_id",
"offset": 1238741,
"eventType": "AuthActivityAuditEvent",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"version": "1.0"
},
"event": {
"UserId": "bilbo.baggins@hobbiton.co",
"UserIp": "1.1.1.1",
"OperationName": "createUser",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -2,48 +2,48 @@ AnalysisType: rule
Filename: crowdstrike_api_key_created.py
RuleID: "Crowdstrike.API.Key.Created"
DisplayName: "Crowdstrike API Key Created"
Reports:
MITRE ATT&CK:
- T1098.001 # Additional Cloud Credentials
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
- Crowdstrike.EventStreams
Severity: Medium
Reports:
MITRE ATT&CK:
- T1098.001 # Additional Cloud Credentials
Description: A user created an API Key in CrowdStrike
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Reach out to the user if needed to validate the activity.
Tests:
- Name: API Key Created
ExpectedResult: true
Log:
event:
AuditKeyValues:
- Key: scope(s)
ValueString: alerts:read,api-integrations:read
- Key: actor_user
ValueString: tester@panther.com
- Key: actor_user_uuid
ValueString: a11a1111-1a11-1a1a-1a11-a11a111a111a
- Key: actor_cid
ValueString: aaa111111111111111aaaaaa11a11a11
- Key: trace_id
ValueString: 1a111111-a1a1-111a-11aa-a111111a1a1a
- Key: APIClientID
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: id
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: name
ValueString: key name
OperationName: CreateAPIClient
ServiceName: Crowdstrike API Client
Success: true
UTCTimestamp: "2024-07-08 14:01:54.000000000"
UserId: tester@panther.com
UserIp: 11.1.111.11
metadata:
customerIDString: aaa111111111111111aaaaaa11a11a11
eventCreationTime: "2024-07-08 14:01:54.451000000"
eventType: AuthActivityAuditEvent
offset: 111111
version: "1.0"
- Name: API Key Created
ExpectedResult: true
Log:
event:
AuditKeyValues:
- Key: scope(s)
ValueString: alerts:read,api-integrations:read
- Key: actor_user
ValueString: tester@panther.com
- Key: actor_user_uuid
ValueString: a11a1111-1a11-1a1a-1a11-a11a111a111a
- Key: actor_cid
ValueString: aaa111111111111111aaaaaa11a11a11
- Key: trace_id
ValueString: 1a111111-a1a1-111a-11aa-a111111a1a1a
- Key: APIClientID
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: id
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: name
ValueString: key name
OperationName: CreateAPIClient
ServiceName: Crowdstrike API Client
Success: true
UTCTimestamp: "2024-07-08 14:01:54.000000000"
UserId: tester@panther.com
UserIp: 11.1.111.11
metadata:
customerIDString: aaa111111111111111aaaaaa11a11a11
eventCreationTime: "2024-07-08 14:01:54.451000000"
eventType: AuthActivityAuditEvent
offset: 111111
version: "1.0"
Original file line number Diff line number Diff line change
@@ -2,82 +2,82 @@ AnalysisType: rule
Filename: crowdstrike_api_key_deleted.py
RuleID: "Crowdstrike.API.Key.Deleted"
DisplayName: "Crowdstrike API Key Deleted"
Reports:
MITRE ATT&CK:
- T1531 # Account Access Removal
- T1070 # Indicator Removal
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
- Crowdstrike.EventStreams
Severity: Medium
Reports:
MITRE ATT&CK:
- T1531 # Account Access Removal
- T1070 # Indicator Removal
Description: A user deleted an API Key in CrowdStrike
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Validate this action was authorized.
Tests:
- Name: API Key Deleted
ExpectedResult: true
Log:
event:
AuditKeyValues:
- Key: scope(s)
ValueString: alerts:read,api-integrations:read
- Key: actor_user
ValueString: tester@panther.com
- Key: actor_user_uuid
ValueString: a11a1111-1a11-1a1a-1a11-a11a111a111a
- Key: actor_cid
ValueString: aaa111111111111111aaaaaa11a11a11
- Key: trace_id
ValueString: 1a111111-a1a1-111a-11aa-a111111a1a1a
- Key: APIClientID
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: id
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: name
ValueString: key name
OperationName: DeleteAPIClients
ServiceName: Crowdstrike API Client
Success: true
UTCTimestamp: "2024-07-08 14:01:54.000000000"
UserId: tester@panther.com
UserIp: 11.1.111.11
metadata:
customerIDString: aaa111111111111111aaaaaa11a11a11
eventCreationTime: "2024-07-08 14:01:54.451000000"
eventType: AuthActivityAuditEvent
offset: 111111
version: "1.0"
- Name: API Key Delete failed
ExpectedResult: false
Log:
event:
AuditKeyValues:
- Key: scope(s)
ValueString: alerts:read,api-integrations:read
- Key: actor_user
ValueString: tester@panther.com
- Key: actor_user_uuid
ValueString: a11a1111-1a11-1a1a-1a11-a11a111a111a
- Key: actor_cid
ValueString: aaa111111111111111aaaaaa11a11a11
- Key: trace_id
ValueString: 1a111111-a1a1-111a-11aa-a111111a1a1a
- Key: APIClientID
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: id
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: name
ValueString: key name
OperationName: DeleteAPIClients
ServiceName: Crowdstrike API Client
Success: false
UTCTimestamp: "2024-07-08 14:01:54.000000000"
UserId: tester@panther.com
UserIp: 11.1.111.11
metadata:
customerIDString: aaa111111111111111aaaaaa11a11a11
eventCreationTime: "2024-07-08 14:01:54.451000000"
eventType: AuthActivityAuditEvent
offset: 111111
version: "1.0"
- Name: API Key Deleted
ExpectedResult: true
Log:
event:
AuditKeyValues:
- Key: scope(s)
ValueString: alerts:read,api-integrations:read
- Key: actor_user
ValueString: tester@panther.com
- Key: actor_user_uuid
ValueString: a11a1111-1a11-1a1a-1a11-a11a111a111a
- Key: actor_cid
ValueString: aaa111111111111111aaaaaa11a11a11
- Key: trace_id
ValueString: 1a111111-a1a1-111a-11aa-a111111a1a1a
- Key: APIClientID
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: id
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: name
ValueString: key name
OperationName: DeleteAPIClients
ServiceName: Crowdstrike API Client
Success: true
UTCTimestamp: "2024-07-08 14:01:54.000000000"
UserId: tester@panther.com
UserIp: 11.1.111.11
metadata:
customerIDString: aaa111111111111111aaaaaa11a11a11
eventCreationTime: "2024-07-08 14:01:54.451000000"
eventType: AuthActivityAuditEvent
offset: 111111
version: "1.0"
- Name: API Key Delete failed
ExpectedResult: false
Log:
event:
AuditKeyValues:
- Key: scope(s)
ValueString: alerts:read,api-integrations:read
- Key: actor_user
ValueString: tester@panther.com
- Key: actor_user_uuid
ValueString: a11a1111-1a11-1a1a-1a11-a11a111a111a
- Key: actor_cid
ValueString: aaa111111111111111aaaaaa11a11a11
- Key: trace_id
ValueString: 1a111111-a1a1-111a-11aa-a111111a1a1a
- Key: APIClientID
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: id
ValueString: aaa1a11aaa111a1a11a11aaaa1aa1a11
- Key: name
ValueString: key name
OperationName: DeleteAPIClients
ServiceName: Crowdstrike API Client
Success: false
UTCTimestamp: "2024-07-08 14:01:54.000000000"
UserId: tester@panther.com
UserIp: 11.1.111.11
metadata:
customerIDString: aaa111111111111111aaaaaa11a11a11
eventCreationTime: "2024-07-08 14:01:54.451000000"
eventType: AuthActivityAuditEvent
offset: 111111
version: "1.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
AnalysisType: correlation_rule
RuleID: "Crowdstrike.EphemeralUserAccount"
DisplayName: "Crowdstrike Ephemeral User Account"
Enabled: true
Severity: High
Description: Detects when a user account is created and deleted within 12 hours. This aims to detect ephemeral user accounts infiltrators might use to avoid suspicion.
Reference: ""
Reports:
MITRE ATT&CK:
- T1136.003 # Create Cloud Account
- T1070 # Indicator Removal
Detection:
- Sequence:
- ID: AccountCreated
RuleID: Crowdstrike.NewUserCreated
- ID: AccountDeleted
RuleID: Crowdstrike.UserDeleted
Transitions:
- ID: User Created FOLLOWED BY User Deleted
From: AccountCreated
To: AccountDeleted
Match:
- On: p_alert_context.target_name
LookbackWindowMinutes: 720 # 12 hours
Schedule:
RateMinutes: 480 # 8 hours
TimeoutMinutes: 1
Tests:
- Name: User Creation, Followed By Deletion
ExpectedResult: true
RuleOutputs:
- ID: AccountCreated
Matches:
p_alert_context.target_name:
'non.chalant@legitbiz.com':
- 0
- ID: AccountDeleted
Matches:
p_alert_context.target_name:
'non.chalant@legitbiz.com':
- 640 # 9 hours
- Name: User Creation, Not Followed By Deletion
ExpectedResult: false
RuleOutputs:
- ID: AccountCreated
Matches:
p_alert_context.target_name:
'non.chalant@legitbiz.com':
- 0
- Name: User Deletion, Not Preceded By Creation
ExpectedResult: false
RuleOutputs:
- ID: AccountDeleted
Matches:
p_alert_context.target_name:
'non.chalant@legitbiz.com':
- 120 # 2 hours
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from crowdstrike_event_streams_helpers import audit_keys_dict, cs_alert_context, str_to_list


def rule(event):
# Only alert if an allow list is created or edited
op_name = event.deep_get("event", "OperationName")
if op_name not in ("CreateAllowlistGroup", "UpdateAllowlistGroup"):
return False

return True


def title(event):
actor = event.deep_get("event", "UserId")
action = {
"CreateAllowlistGroup": "created a new",
"UpdateAllowlistGroup": "made changes to",
}.get(event.deep_get("event", "OperationName"))
group = audit_keys_dict(event).get("group_name", "UNKNWOWN GROUP")
return f"{actor} {action} Crowdstrike IP allowlist group: {group}"


def alert_context(event):
context = cs_alert_context(event)

# Be nice and concert the "lists" into actual lists so customers can easily process the alert
# context
for key in ("cidrs", "old_cidrs", "contexts", "old_contexts"):
if context.get(key):
try:
context[key] = str_to_list(context[key])
except ValueError:
pass # Just ignore if we can't unmarshal it

# Find out what entries were removed, and which were added
op_name = event.deep_get("event", "OperationName")
audit_keys = audit_keys_dict(event)
added_cidrs = []
removed_cidrs = []
added_contexts = []
removed_contexts = []

def getlist(key: str):
return str_to_list(audit_keys.get(key))

match op_name:
case "UpdateAllowlistGroup":
new_cidrs = getlist("cidrs")
old_cidrs = getlist("old_cidrs")
new_ctx = getlist("contexts")
old_ctx = getlist("old_contexts")
added_cidrs = get_unique_entries(new_cidrs, old_cidrs)
removed_cidrs = get_unique_entries(old_cidrs, new_cidrs)
added_contexts = get_unique_entries(new_ctx, old_ctx)
removed_contexts = get_unique_entries(old_ctx, new_ctx)
case "CreateAllowlistGroup":
added_cidrs = str_to_list(audit_keys.get("cidrs", []))
added_contexts = str_to_list(audit_keys.get("contexts", []))
case _:
# Raise error if there's another operationname
# This is in case we update the rule logic but forget to update this logic too
raise ValueError(f"Unepected Operation Name: {op_name}")

context.update(
{
"changes": {
"cidr_added": added_cidrs,
"cidr_removed": removed_cidrs,
"context_added": added_contexts,
"context_removed": removed_contexts,
}
}
)

return context


def get_unique_entries(list1: list, list2: list) -> list:
"""Returns items in l1 that are not in l2."""
return list(set(list1) - set(list2))
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
AnalysisType: rule
Filename: crowdstrike_ip_allowlist_changed.py
RuleID: "Crowdstrike.IpAllowlistChanged"
DisplayName: "Crowdstrike IP Allowlist Changed"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Info
CreateAlert: false
Reports:
MITRE ATT&CK:
- T1556.009 # Modify Authentication Process: Conditional Access Policies
Description: Updates were made to Falcon console's allowlist. This could indicate a bad actor permitting access from another machine, or could be attackers preventing legitimate actors from accessing the console.
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Validate this action was authorized.
Tests:
- Name: A Single IP In Created Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "example_group"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.1.1.1]"
},
{
"Key": "contexts",
"ValueString": "[API]"
},
{
"Key": "active",
"ValueString": "false"
}
],
"OperationName": "CreateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 16:13:13.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_cust_id",
"eventCreationTime": "2024-07-26 16:13:13.579000000",
"eventType": "AuthActivityAuditEvent",
"offset": 365164,
"version": "1.0"
}
}
- Name: Multiple Single IPs In Created Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "example_group"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.1.1.1 2.2.2.2 3.3.3.3/32]"
},
{
"Key": "contexts",
"ValueString": "[API UI OTHER]"
},
{
"Key": "active",
"ValueString": "false"
}
],
"OperationName": "CreateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 16:13:13.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_cust_id",
"eventCreationTime": "2024-07-26 16:13:13.579000000",
"eventType": "AuthActivityAuditEvent",
"offset": 365164,
"version": "1.0"
}
}
- Name: Single IP Added to existing Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "old_group_name",
"ValueString": "my_allowlist"
},
{
"Key": "old_cidrs",
"ValueString": "[1.2.3.4/8]"
},
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "my_allowlist"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.2.3.4/8 32.32.32.32]"
},
{
"Key": "contexts",
"ValueString": "[API]"
},
{
"Key": "active",
"ValueString": "false"
},
{
"Key": "old_allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "old_description",
"ValueString": ""
},
{
"Key": "old_contexts",
"ValueString": "[API]"
},
{
"Key": "old_active",
"ValueString": "false"
}
],
"OperationName": "UpdateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 19:47:16.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-26 19:47:16.428000000",
"eventType": "AuthActivityAuditEvent",
"offset": 366148,
"version": "1.0"
}
}
- Name: CIDR Removed from existing Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "old_group_name",
"ValueString": "my_allowlist"
},
{
"Key": "old_cidrs",
"ValueString": "[1.2.3.4/8 8.8.8.8/12]"
},
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "my_allowlist"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.2.3.4/8]"
},
{
"Key": "contexts",
"ValueString": "[API]"
},
{
"Key": "active",
"ValueString": "false"
},
{
"Key": "old_allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "old_description",
"ValueString": ""
},
{
"Key": "old_contexts",
"ValueString": "[API]"
},
{
"Key": "old_active",
"ValueString": "false"
}
],
"OperationName": "UpdateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 19:47:16.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-26 19:47:16.428000000",
"eventType": "AuthActivityAuditEvent",
"offset": 366148,
"version": "1.0"
}
}
- Name: Only CIDR Ranges In Created Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "example_group"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.1.1.1/12 2.2.2.2/8 3.3.3.3/4]"
},
{
"Key": "contexts",
"ValueString": "[API UI OTHER]"
},
{
"Key": "active",
"ValueString": "false"
}
],
"OperationName": "CreateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 16:13:13.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_cust_id",
"eventCreationTime": "2024-07-26 16:13:13.579000000",
"eventType": "AuthActivityAuditEvent",
"offset": 365164,
"version": "1.0"
}
}
- Name: Unrelated Event
ExpectedResult: false
Log:
{
"metadata": {
"customerIDString": "fake_customer_id",
"offset": 341329,
"eventType": "AuthActivityAuditEvent",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"version": "1.0"
},
"event": {
"UserId": "sharkey@hobbiton.co",
"UserIp": "192.0.2.100",
"OperationName": "deleteUser",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
AnalysisType: correlation_rule
RuleID: "Crowdstrike.NewAdminUserCreated"
DisplayName: "Crowdstrike New Admin User Created"
Enabled: true
Severity: High
Description: Detects when a user account is created and assigned admin permissions
Reports:
MITRE ATT&CK:
- T1136.003 # Create Cloud Account
- T1093.003 # Additional Cloud Roles
Detection:
- Sequence:
- ID: AccountCreated
RuleID: Crowdstrike.NewUserCreated
- ID: AdminRoleAssigned
RuleID: Crowdstrike.AdminRoleAssigned
Transitions:
- ID: AcountCreated FOLLOWED BY AdminRoleAssigned ON target AND actor
From: AccountCreated
To: AdminRoleAssigned
Match:
- On: p_alert_context.actor_target
LookbackWindowMinutes: 45
Schedule:
RateMinutes: 30
TimeoutMinutes: 1
Tests:
- Name: User Creation, Followed By Role Assignment
ExpectedResult: true
RuleOutputs:
- ID: AccountCreated
Matches:
p_alert_context.actor_target:
'newuser@biz.co-hackerman@biz.co':
- 0
- ID: AdminRoleAssigned
Matches:
p_alert_context.actor_target:
'newuser@biz.co-hackerman@biz.co':
- 15
- Name: User Creation, Not Followed By Role Assignment
ExpectedResult: false
RuleOutputs:
- ID: AccountCreated
Matches:
p_alert_context.actor_target:
'newuser@biz.co-hackerman@biz.co':
- 0
- Name: Role Assignment Not Preceded By User Creation
ExpectedResult: false
RuleOutputs:
- ID: AdminRoleAssigned
Matches:
p_alert_context.actor_target:
'newuser@biz.co-hackerman@biz.co':
- 20
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from crowdstrike_event_streams_helpers import cs_alert_context
from panther_base_helpers import key_value_list_to_dict


def rule(event):
return all(
[
event.deep_get("event", "OperationName") == "createUser",
event.deep_get("event", "Success"),
]
)


def title(event):
audit_keys = key_value_list_to_dict(
event.deep_get("event", "AuditKeyValues"), "Key", "ValueString"
)

actor = event.deep_get("event", "UserId", "UNKNOWN USER")
target = audit_keys.get("target_name")

return f"[{actor}] created a new user: [{target}]"


def alert_context(event):
context = cs_alert_context(event)
actor = context.get("actor_user", "UNKNWON_ACTOR")
target = context.get("target_name", "UNKNOWN_TARGET")
context["actor_target"] = f"{actor}-{target}"
return context
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
AnalysisType: rule
Filename: crowdstrike_new_user_created.py
RuleID: "Crowdstrike.NewUserCreated"
DisplayName: "Crowdstrike New User Created"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Info
CreateAlert: false
Reports:
MITRE ATT&CK:
- T1136.003 # Create Cloud Account
Description: A new Crowdstrike user was created
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Confirm the new user is valid.
Tests:
- Name: New User Created
ExpectedResult: true
Log:
{
"metadata": {
"customerIDString": "face_customer_id",
"offset": 1238741,
"eventType": "AuthActivityAuditEvent",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"version": "1.0"
},
"event": {
"UserId": "bilbo.baggins@hobbiton.co",
"UserIp": "1.1.1.1",
"OperationName": "createUser",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
]
}
}
- Name: Unrelated Event
ExpectedResult: false
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "652fc606f369ef3105925197b34f2c54"
},
{
"Key": "target_name",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "action_target_name",
"ValueString": "peregrin.took@hobbiton.co"
}
],
"OperationName": "userAuthenticate",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"UserId": "peregrin.took@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"eventType": "AuthActivityAuditEvent",
"offset": 341329,
"version": "1.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from crowdstrike_event_streams_helpers import cs_alert_context
from panther_base_helpers import key_value_list_to_dict


def rule(event):
return all(
[
event.deep_get("event", "OperationName") == "changePassword",
event.deep_get("event", "Success"),
]
)


def title(event):
audit_keys = key_value_list_to_dict(
event.deep_get("event", "AuditKeyValues"), "Key", "ValueString"
)
target = audit_keys.get("target_name", "UNKNOWN USER")
actor = event.deep_get("event", "UserId")

if target == actor:
return f"[{actor}] changed their password."

return f"[{actor}] changed the password of [{target}]"


def severity(event):
# Downgrade sev if password changed by same uer

audit_keys = key_value_list_to_dict(
event.deep_get("event", "AuditKeyValues"), "Key", "ValueString"
)
target = audit_keys.get("target_name", "UNKNOWN USER")
actor = event.deep_get("event", "UserId")

if target == actor:
return "INFO"

return "DEFAULT"


def alert_context(event):
return cs_alert_context(event)
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
AnalysisType: rule
Filename: crowdstrike_password_change.py
RuleID: "Crowdstrike.UserPasswordChange"
DisplayName: "Crowdstrike User Password Changed"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Medium
Reports:
MITRE ATT&CK:
- T1098.001 # Additional Cloud Credentials
Description: A user's password was changed
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Validate this action was authorized.
Tests:
- Name: Own Password Changed
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "f4f8b3233619bdf49ea2a2d108ce39d8"
},
{
"Key": "target_name",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "action_target_name",
"ValueString": "peregrin.took@hobbiton.co"
}
],
"OperationName": "changePassword",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 16:15:36.535000000",
"UserId": "peregrin.took@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 16:15:36.535000000",
"eventType": "AuthActivityAuditEvent",
"offset": 341447,
"version": "1.0"
}
}
- Name: Password Changed for Different User
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "f4f8b3233619bdf49ea2a2d108ce39d8"
},
{
"Key": "target_name",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "action_target_name",
"ValueString": "peregrin.took@hobbiton.co"
}
],
"OperationName": "changePassword",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 16:15:36.535000000",
"UserId": "bilbo.baggins@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 16:15:36.535000000",
"eventType": "AuthActivityAuditEvent",
"offset": 341447,
"version": "1.0"
}
}
- Name: Unsuccessful Password Change Attempt
ExpectedResult: false
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "f4f8b3233619bdf49ea2a2d108ce39d8"
},
{
"Key": "target_name",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "action_target_name",
"ValueString": "peregrin.took@hobbiton.co"
}
],
"OperationName": "changePassword",
"ServiceName": "CrowdStrike Authentication",
"Success": false,
"UTCTimestamp": "2024-07-22 16:15:36.535000000",
"UserId": "bilbo.baggins@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 16:15:36.535000000",
"eventType": "AuthActivityAuditEvent",
"offset": 341447,
"version": "1.0"
}
}
- Name: Unrelated Event
ExpectedResult: false
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "652fc606f369ef3105925197b34f2c54"
},
{
"Key": "target_name",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "action_target_name",
"ValueString": "peregrin.took@hobbiton.co"
}
],
"OperationName": "userAuthenticate",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"UserId": "peregrin.took@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"eventType": "AuthActivityAuditEvent",
"offset": 341329,
"version": "1.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from crowdstrike_event_streams_helpers import audit_keys_dict, cs_alert_context, str_to_list


def get_single_ips(event, fieldname="cidrs") -> list[str]:
"""Searches the "cidrs" field of the event audit keys, and returns any cidr entries which
are actually just single IP addresses."""
single_ips = []
audit_keys = audit_keys_dict(event)
cidrs = str_to_list(audit_keys.get(fieldname, []))
for entry in cidrs:
if "/" not in entry:
single_ips.append(entry)
elif entry.endswith("/32"):
# A 32-bit CIDR range is the same as a single IP address
single_ips.append(entry[:-3])
return single_ips


def rule(event):
# Only alert if an allow list is created or edited
op_name = event.deep_get("event", "OperationName")
if op_name not in ("CreateAllowlistGroup", "UpdateAllowlistGroup"):
return False

# Only alert if there's a single IP address allowed by the allowlist
single_ips = get_single_ips(event)

if op_name == "UpdateAllowlistGroup":
# Remove IPs from single_ips if the weren't recently added
old_single_ips = set(get_single_ips(event, "old_cidrs"))
single_ips = [ip for ip in single_ips if ip not in old_single_ips]

# Return true if there were any single IPs
return len(single_ips) > 0


def title(event):
# Title format: {actor} granted {contexts_str} access to {a, X} single ip{s}
single_ips = get_single_ips(event)
actor = event.deep_get("event", "UserId")

# contexts_str: one of API, UI, or API & UI
# Also a more general case: API, UI, and XX (for if they add extra contexts in the future)
contexts = str_to_list(audit_keys_dict(event)["contexts"])
if len(contexts) == 1:
contexts_str = contexts[0]
else:
contexts_str = ", ".join(contexts[:-1]) + " & " + contexts[-1]

num_ips_str = "a single ip" if len(contexts) == 1 else f"{len(single_ips)} single ips"

return f"{actor} granted {contexts_str} access to {num_ips_str}"


def alert_context(event):
context = cs_alert_context(event)
context.update({"single_ips": get_single_ips(event)})
return context
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
AnalysisType: rule
Filename: crowdstrike_single_ip_allowlisted.py
RuleID: "Crowdstrike.SingleIpAllowlisted"
DisplayName: "Crowdstrike Single IP Allowlisted"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Medium
Reports:
MITRE ATT&CK:
- T1556.009 # Modify Authentication Process: Conditional Access Policies
Description: A single IP (instead of a CIDR range) was allowlisted. This could indicate a bad actor permitting access from another machine.
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Validate this action was authorized, and determine the client to which the IP belongs to.
Tests:
- Name: A Single IP In Created Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "example_group"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.1.1.1]"
},
{
"Key": "contexts",
"ValueString": "[API]"
},
{
"Key": "active",
"ValueString": "false"
}
],
"OperationName": "CreateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 16:13:13.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_cust_id",
"eventCreationTime": "2024-07-26 16:13:13.579000000",
"eventType": "AuthActivityAuditEvent",
"offset": 365164,
"version": "1.0"
}
}
- Name: Multiple Single IPs In Created Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "example_group"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.1.1.1 2.2.2.2 3.3.3.3/32]"
},
{
"Key": "contexts",
"ValueString": "[API UI OTHER]"
},
{
"Key": "active",
"ValueString": "false"
}
],
"OperationName": "CreateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 16:13:13.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_cust_id",
"eventCreationTime": "2024-07-26 16:13:13.579000000",
"eventType": "AuthActivityAuditEvent",
"offset": 365164,
"version": "1.0"
}
}
- Name: Single IP Added to existing Allowlist
ExpectedResult: true
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "old_group_name",
"ValueString": "my_allowlist"
},
{
"Key": "old_cidrs",
"ValueString": "[1.2.3.4/8]"
},
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "my_allowlist"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.2.3.4/8 32.32.32.32]"
},
{
"Key": "contexts",
"ValueString": "[API]"
},
{
"Key": "active",
"ValueString": "false"
},
{
"Key": "old_allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "old_description",
"ValueString": ""
},
{
"Key": "old_contexts",
"ValueString": "[API]"
},
{
"Key": "old_active",
"ValueString": "false"
}
],
"OperationName": "UpdateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 19:47:16.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-26 19:47:16.428000000",
"eventType": "AuthActivityAuditEvent",
"offset": 366148,
"version": "1.0"
}
}
- Name: Only CIDR Ranges In Created Allowlist
ExpectedResult: false
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "allowlist_group_id",
"ValueString": "24821376-7e77-431e-9469-74846978fe64"
},
{
"Key": "group_name",
"ValueString": "example_group"
},
{
"Key": "description",
"ValueString": ""
},
{
"Key": "cidrs",
"ValueString": "[1.1.1.1/12 2.2.2.2/8 3.3.3.3/4]"
},
{
"Key": "contexts",
"ValueString": "[API UI OTHER]"
},
{
"Key": "active",
"ValueString": "false"
}
],
"OperationName": "CreateAllowlistGroup",
"ServiceName": "Crowdstrike Allowlist Management",
"Success": true,
"UTCTimestamp": "2024-07-26 16:13:13.000000000",
"UserId": "wormtongue@isengard.org",
"UserIp": "1.2.3.4"
},
"metadata": {
"customerIDString": "fake_cust_id",
"eventCreationTime": "2024-07-26 16:13:13.579000000",
"eventType": "AuthActivityAuditEvent",
"offset": 365164,
"version": "1.0"
}
}
- Name: Unrelated Event
ExpectedResult: false
Log:
{
"metadata": {
"customerIDString": "fake_customer_id",
"offset": 341329,
"eventType": "AuthActivityAuditEvent",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"version": "1.0"
},
"event": {
"UserId": "sharkey@hobbiton.co",
"UserIp": "192.0.2.100",
"OperationName": "deleteUser",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from crowdstrike_event_streams_helpers import cs_alert_context


def rule(event):
return all(
[
event.deep_get("event", "OperationName") == "deleteUser",
event.deep_get("event", "Success"),
]
)


def title(event):
actor = event.deep_get("event", "UserId", default="UNKNOWN USER")
return f"[{actor}] has deleted multiple Crowdstrike users within the past hour."


def alert_context(event):
return cs_alert_context(event)
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
AnalysisType: rule
Filename: crowdstrike_user_deleted.py
RuleID: "Crowdstrike.UserDeleted"
DisplayName: "Crowdstrike User Deleted"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: High
Reports:
MITRE ATT&CK:
- T1070 # Indicator Removal
Description: Someone has deleted multiple users.
DedupPeriodMinutes: 60
Threshold: 3
Runbook: Validate this action was authorized.
Tests:
- Name: Successful User Deletion
ExpectedResult: true
Log:
{
"metadata": {
"customerIDString": "fake_customer_id",
"offset": 341329,
"eventType": "AuthActivityAuditEvent",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"version": "1.0"
},
"event": {
"UserId": "sharkey@hobbiton.co",
"UserIp": "192.0.2.100",
"OperationName": "deleteUser",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
]
}
}
- Name: Unsuccessful User Deletion Attempt
ExpectedResult: false
Log:
{
"metadata": {
"customerIDString": "fake_customer_id",
"offset": 341329,
"eventType": "AuthActivityAuditEvent",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"version": "1.0"
},
"event": {
"UserId": "sharkey@hobbiton.co",
"UserIp": "192.0.2.100",
"OperationName": "deleteUser",
"ServiceName": "CrowdStrike Authentication",
"Success": false,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
]
}
}
- Name: Unrelated Event
ExpectedResult: false
Log:
{
"event": {
"AuditKeyValues": [
{
"Key": "target_uuid",
"ValueString": "e70e5306-4a83-4a9f-9b59-a78c304c438b"
},
{
"Key": "target_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "actor_cid",
"ValueString": "fake_customer_id"
},
{
"Key": "trace_id",
"ValueString": "652fc606f369ef3105925197b34f2c54"
},
{
"Key": "target_name",
"ValueString": "peregrin.took@hobbiton.co"
},
{
"Key": "action_target_name",
"ValueString": "peregrin.took@hobbiton.co"
}
],
"OperationName": "userAuthenticate",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"UserId": "peregrin.took@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"eventType": "AuthActivityAuditEvent",
"offset": 341329,
"version": "1.0"
}
}