Detection rules › Elastic

Elastic rules: 0q

AWS EC2 LOLBin Execution via SSM SendCommand

#
Status
production
Severity
medium
Time window
9m
Group by
Esql.aws_ssm_command_id
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies the execution of Living Off the Land Binaries (LOLBins) or GTFOBins on EC2 instances via AWS Systems Manager (SSM) SendCommand API. This detection correlates AWS CloudTrail SendCommand events with endpoint process execution by matching SSM command IDs. While AWS redacts command parameters in CloudTrail logs, this correlation technique reveals the actual commands executed on EC2 instances. Adversaries may abuse SSM to execute malicious commands remotely without requiring SSH or RDP access, using legitimate system utilities for data exfiltration, establishing reverse shells, or lateral movement.

Known False Positives

  • Legitimate administrative tasks using SSM to run system utilities may trigger this rule. Review the command context, user identity, and timing to determine if the activity is authorized.
  • Automated configuration management or monitoring scripts that use LOLBins via SSM for legitimate purposes. Consider excluding known automation accounts or specific command patterns.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2025/11/23"
integration = ["aws", "endpoint"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Identifies the execution of Living Off the Land Binaries (LOLBins) or GTFOBins on EC2 instances via AWS Systems Manager
(SSM) `SendCommand` API. This detection correlates AWS CloudTrail `SendCommand` events with endpoint process execution
by matching SSM command IDs. While AWS redacts command parameters in CloudTrail logs, this correlation technique reveals
the actual commands executed on EC2 instances. Adversaries may abuse SSM to execute malicious commands remotely without
requiring SSH or RDP access, using legitimate system utilities for data exfiltration, establishing reverse shells, or
lateral movement.
"""
false_positives = [
    """
    Legitimate administrative tasks using SSM to run system utilities may trigger this rule. Review the command context,
    user identity, and timing to determine if the activity is authorized.
    """,
    """
    Automated configuration management or monitoring scripts that use LOLBins via SSM for legitimate purposes. Consider
    excluding known automation accounts or specific command patterns.
    """,
]
from = "now-9m"
interval = "8m"
language = "esql"
license = "Elastic License v2"
name = "AWS EC2 LOLBin Execution via SSM SendCommand"
note = """## Triage and analysis

### Investigating AWS EC2 LOLBin Execution via SSM SendCommand

AWS Systems Manager (SSM) enables remote command execution on EC2 instances without SSH/RDP access. While legitimate for administration, adversaries exploit this by running LOLBins—system utilities abused for malicious purposes like data theft or backdoors. This detection correlates CloudTrail API logs with endpoint telemetry using SSM command IDs, bypassing AWS's parameter redaction to reveal actual executed commands and identify suspicious activity.

This is an ESQL aggregation-based rule, thus all original event fields and detail may not be present in the alert. It is recommended to pivot into the raw events from both data sources for full context during investigation.

### Possible investigation steps

- Review the SSM command ID in the alert to track the full lifecycle of the command from initiation to execution across both CloudTrail and endpoint data
- Examine the CloudTrail user identity, including the ARN and access key ID, to determine who initiated the SSM command and verify if the activity is authorized
- Analyze the command lines of the executed LOLBins to understand what commands were run and assess their intent, looking for indicators of data exfiltration, reverse shells, or reconnaissance
- Check the source IP address and user agent from the CloudTrail event to identify if the request came from an expected location or tool
- Investigate the affected EC2 instances for other suspicious activities or signs of compromise during the same timeframe, including network connections and file modifications
- Review the SSM shell process details to see the full context of what the SSM agent executed and identify the parent-child process relationships
- Correlate the timing between the CloudTrail event and endpoint execution to ensure they occurred within the detection window and represent the same activity
- Check if the same user identity or source IP has executed similar SSM commands on other EC2 instances in your environment

### False positive analysis

- Routine administrative scripts that use utilities like curl, wget, or python for legitimate configuration management should be documented and excluded by user identity or source IP
- Automated monitoring tools that execute commands via SSM for health checks or data collection can be filtered by identifying their consistent patterns and access key IDs
- DevOps CI/CD pipelines that deploy or test applications using SSM may trigger alerts; create exceptions based on known automation roles or specific command patterns
- Security scanning tools that legitimately use SSM for vulnerability assessments should be allowlisted by their known IAM roles or source IPs
- Scheduled maintenance tasks using LOLBins for backup, log rotation, or data synchronization can be excluded by command pattern matching or execution timing

### Response and remediation

- Immediately isolate the affected EC2 instance from the network to prevent further unauthorized command execution or lateral movement
- Review AWS CloudTrail logs to identify the IAM user, role, or access key associated with the suspicious SSM command and revoke or rotate compromised credentials
- Terminate any unauthorized processes identified on the endpoint that match the LOLBin execution patterns detected in the alert
- Conduct a forensic analysis of the affected EC2 instance to identify any persistence mechanisms, backdoors, or data exfiltration indicators
- Implement stricter IAM policies to limit SSM `SendCommand` permissions to only trusted users and roles, following the principle of least privilege
- Enable multi-factor authentication (MFA) for IAM users with SSM execution privileges to reduce the risk of credential compromise
- Review and update VPC security groups and network ACLs to restrict outbound traffic from EC2 instances to only necessary destinations, preventing data exfiltration
- Escalate the incident to the security operations center (SOC) for further investigation and to determine if additional AWS resources or accounts have been compromised
"""
references = [
    "https://www.mitiga.io/blog/abusing-the-amazon-web-services-ssm-agent-as-a-remote-access-trojan",
    "https://www.kali.org/tools/pacu/",
    "https://www.100daysofredteam.com/p/ghost-in-the-cloud-abusing-aws-ssm",
    "https://hackingthe.cloud/aws/post_exploitation/run_shell_commands_on_ec2/",
    "https://gtfobins.github.io/",
]
risk_score = 47
rule_id = "a8b3e2f0-8c7d-11ef-b4c6-f661ea17fbcd"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Domain: Endpoint",
    "OS: Linux",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Tactic: Command and Control",
    "Data Source: AWS",
    "Data Source: Amazon Web Services",
    "Data Source: AWS CloudTrail",
    "Data Source: AWS EC2",
    "Data Source: AWS SSM",
    "Data Source: AWS Systems Manager",
    "Data Source: Elastic Defend",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
FROM logs-aws.cloudtrail*, logs-endpoint.events.process-* METADATA _id, _version, _index
| WHERE
  // CloudTrail SSM SendCommand with AWS-RunShellScript
  (
    data_stream.dataset == "aws.cloudtrail"
    AND event.action == "SendCommand"
    AND aws.cloudtrail.request_parameters LIKE "*documentName=AWS-RunShellScript*"
  )
  // Linux endpoint process events, prefiltered to SSM shell runner OR LOLBins/GTFOBins
  OR
  (
    data_stream.dataset == "endpoint.events.process"
    AND host.os.type == "linux"
    AND (
      // SSM shell (_script.sh) runner
      process.command_line LIKE "%/document/orchestration/%/awsrunShellScript/%/_script.sh"
      // LOLBins / GTFOBins
      OR process.name IN (
        "base64",
        "curl",
        "wget",
        "openssl",
        "nc", "ncat", "netcat",
        "socat",
        "python", "python3",
        "perl",
        "php",
        "ruby",
        "ssh",
        "scp",
        "sftp",
        "rsync"
      )
    )
  )

// Endpoint leg: extract SSM command ID from parent command line
| DISSECT process.parent.command_line
    "%{}/document/orchestration/%{Esql.process_parent_command_line_ssm_command_id}/%{}"

// CloudTrail leg: extract SSM command ID from response_elements
| DISSECT aws.cloudtrail.response_elements
    "%{}commandId=%{Esql.aws_cloudtrail_response_elements_ssm_command_id},%{}"

// Coalesce SSM command ID from both data sources
| EVAL Esql.aws_ssm_command_id = COALESCE(
    Esql.aws_cloudtrail_response_elements_ssm_command_id,
    Esql.process_parent_command_line_ssm_command_id
)
| WHERE Esql.aws_ssm_command_id IS NOT NULL

// Role flags
| EVAL Esql.is_cloud_event    = data_stream.dataset == "aws.cloudtrail"
| EVAL Esql.is_endpoint_event = data_stream.dataset == "endpoint.events.process"

// Identify the SSM shell processes (the _script.sh runners)
| EVAL Esql.is_ssm_shell_process =
    Esql.is_endpoint_event
    AND process.command_line LIKE "%/document/orchestration/%/awsrunShellScript/%/_script.sh"

// LOLBins / GTFOBins on Linux
| EVAL Esql.is_lolbin_process =
    Esql.is_endpoint_event AND NOT Esql.is_ssm_shell_process

// Aggregate per SSM command ID
| STATS
    // Core correlation counts & timing
    Esql.aws_cloudtrail_event_count                 = SUM(CASE(Esql.is_cloud_event, 1, 0)),
    Esql.endpoint_events_process_lolbin_count       = SUM(CASE(Esql.is_lolbin_process, 1, 0)),
    Esql.endpoint_events_process_ssm_shell_count    = SUM(CASE(Esql.is_ssm_shell_process, 1, 0)),
    Esql.aws_cloudtrail_first_event_ts              = MIN(CASE(Esql.is_cloud_event, @timestamp, null)),
    Esql.endpoint_events_process_first_lolbin_ts    = MIN(CASE(Esql.is_lolbin_process, @timestamp, null)),

    // AWS / CloudTrail identity & request context
    Esql_priv.aws_cloudtrail_user_identity_arn_values          =
      VALUES(CASE(Esql.is_cloud_event, aws.cloudtrail.user_identity.arn, null)),
    Esql_priv.aws_cloudtrail_user_identity_access_key_id_values =
      VALUES(CASE(Esql.is_cloud_event, aws.cloudtrail.user_identity.access_key_id, null)),
    Esql_priv.user_name_values                                 =
      VALUES(CASE(Esql.is_cloud_event, user.name, null)),

    // AWS environment / request metadata
    Esql.cloud_region_values     = VALUES(CASE(Esql.is_cloud_event, cloud.region, null)),
    Esql.source_ip_values        = VALUES(CASE(Esql.is_cloud_event, source.ip, null)),
    Esql.user_agent_original_values =
      VALUES(CASE(Esql.is_cloud_event, user_agent.original, null)),

    // Endpoint host & user context
    Esql.host_name_values        = VALUES(CASE(Esql.is_endpoint_event, host.name, null)),
    Esql_priv.endpoint_user_name_values =
      VALUES(CASE(Esql.is_endpoint_event, user.name, null)),

    // SSM shell processes on endpoint
    Esql.process_command_line_ssm_shell_values =
      VALUES(CASE(Esql.is_ssm_shell_process, process.command_line, null)),
    Esql.process_pid_ssm_shell_values =
      VALUES(CASE(Esql.is_ssm_shell_process, process.pid, null)),

    // LOLBin processes on endpoint
    Esql.process_name_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.name, null)),
    Esql.process_executable_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.executable, null)),
    Esql.process_command_line_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.command_line, null)),
    Esql.process_pid_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.pid, null)),
    Esql.process_parent_command_line_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.parent.command_line, null)),

    Esql.data_stream_namespace_values = VALUES(data_stream.namespace)
  BY Esql.aws_ssm_command_id

// Detection condition: SSM SendCommand + AWS-RunShellScript + LOLBin on endpoint
| WHERE Esql.aws_cloudtrail_event_count > 0
  AND Esql.endpoint_events_process_lolbin_count > 0
  AND DATE_DIFF(
        "minutes",
        Esql.endpoint_events_process_first_lolbin_ts,
        Esql.aws_cloudtrail_first_event_ts
      ) <= 5
| SORT Esql.aws_cloudtrail_first_event_ts ASC
| KEEP Esql.*, Esql_priv.*
'''


[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"

[[rule.threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"

[[rule.threat.technique]]
id = "T1651"
name = "Cloud Administration Command"
reference = "https://attack.mitre.org/techniques/T1651/"

[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1105"
name = "Ingress Tool Transfer"
reference = "https://attack.mitre.org/techniques/T1105/"

[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"

Stages and Predicates

Stage 1: from

FROM logs-aws.cloudtrail*, logs-endpoint.events.process-* METADATA _id, _version, _index

Stage 2: where

| WHERE
  (
    data_stream.dataset == "aws.cloudtrail"
    AND event.action == "SendCommand"
    AND aws.cloudtrail.request_parameters LIKE "*documentName=AWS-RunShellScript*"
  )
  OR
  (
    data_stream.dataset == "endpoint.events.process"
    AND host.os.type == "linux"
    AND (
      process.command_line LIKE "%/document/orchestration/%/awsrunShellScript/%/_script.sh"
      OR process.name IN (
        "base64",
        "curl",
        "wget",
        "openssl",
        "nc", "ncat", "netcat",
        "socat",
        "python", "python3",
        "perl",
        "php",
        "ruby",
        "ssh",
        "scp",
        "sftp",
        "rsync"
      )
    )
  )

Stage 3: dissect

| DISSECT process.parent.command_line
    "%{}/document/orchestration/%{Esql.process_parent_command_line_ssm_command_id}/%{}"

Stage 4: dissect

| DISSECT aws.cloudtrail.response_elements
    "%{}commandId=%{Esql.aws_cloudtrail_response_elements_ssm_command_id},%{}"

Stage 5: eval

| EVAL Esql.aws_ssm_command_id = COALESCE(
    Esql.aws_cloudtrail_response_elements_ssm_command_id,
    Esql.process_parent_command_line_ssm_command_id
)

Stage 6: where

| WHERE Esql.aws_ssm_command_id IS NOT NULL

Stage 7: eval

| EVAL Esql.is_cloud_event    = data_stream.dataset == "aws.cloudtrail"

Stage 8: eval

| EVAL Esql.is_endpoint_event = data_stream.dataset == "endpoint.events.process"

Stage 9: eval

| EVAL Esql.is_ssm_shell_process =
    Esql.is_endpoint_event
    AND process.command_line LIKE "%/document/orchestration/%/awsrunShellScript/%/_script.sh"

Stage 10: eval

| EVAL Esql.is_lolbin_process =
    Esql.is_endpoint_event AND NOT Esql.is_ssm_shell_process

Stage 11: stats

| STATS
    Esql.aws_cloudtrail_event_count                 = SUM(CASE(Esql.is_cloud_event, 1, 0)),
    Esql.endpoint_events_process_lolbin_count       = SUM(CASE(Esql.is_lolbin_process, 1, 0)),
    Esql.endpoint_events_process_ssm_shell_count    = SUM(CASE(Esql.is_ssm_shell_process, 1, 0)),
    Esql.aws_cloudtrail_first_event_ts              = MIN(CASE(Esql.is_cloud_event, @timestamp, null)),
    Esql.endpoint_events_process_first_lolbin_ts    = MIN(CASE(Esql.is_lolbin_process, @timestamp, null)),
    Esql_priv.aws_cloudtrail_user_identity_arn_values          =
      VALUES(CASE(Esql.is_cloud_event, aws.cloudtrail.user_identity.arn, null)),
    Esql_priv.aws_cloudtrail_user_identity_access_key_id_values =
      VALUES(CASE(Esql.is_cloud_event, aws.cloudtrail.user_identity.access_key_id, null)),
    Esql_priv.user_name_values                                 =
      VALUES(CASE(Esql.is_cloud_event, user.name, null)),
    Esql.cloud_region_values     = VALUES(CASE(Esql.is_cloud_event, cloud.region, null)),
    Esql.source_ip_values        = VALUES(CASE(Esql.is_cloud_event, source.ip, null)),
    Esql.user_agent_original_values =
      VALUES(CASE(Esql.is_cloud_event, user_agent.original, null)),
    Esql.host_name_values        = VALUES(CASE(Esql.is_endpoint_event, host.name, null)),
    Esql_priv.endpoint_user_name_values =
      VALUES(CASE(Esql.is_endpoint_event, user.name, null)),
    Esql.process_command_line_ssm_shell_values =
      VALUES(CASE(Esql.is_ssm_shell_process, process.command_line, null)),
    Esql.process_pid_ssm_shell_values =
      VALUES(CASE(Esql.is_ssm_shell_process, process.pid, null)),
    Esql.process_name_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.name, null)),
    Esql.process_executable_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.executable, null)),
    Esql.process_command_line_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.command_line, null)),
    Esql.process_pid_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.pid, null)),
    Esql.process_parent_command_line_lolbin_values =
      VALUES(CASE(Esql.is_lolbin_process, process.parent.command_line, null)),
    Esql.data_stream_namespace_values = VALUES(data_stream.namespace)
  BY Esql.aws_ssm_command_id

Stage 12: where

| WHERE Esql.aws_cloudtrail_event_count > 0
  AND Esql.endpoint_events_process_lolbin_count > 0
  AND DATE_DIFF(
        "minutes",
        Esql.endpoint_events_process_first_lolbin_ts,
        Esql.aws_cloudtrail_first_event_ts
      ) <= 5

Stage 13: sort

| SORT Esql.aws_cloudtrail_first_event_ts ASC

Stage 14: keep

| KEEP Esql.*, Esql_priv.*

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Esql.aws_cloudtrail_event_countgt
  • 0
field:"Esql.aws_cloudtrail_event_count" kind:gt value:"0"
Esql.aws_ssm_command_idis_not_null
  • (no value, null check)
field:"Esql.aws_ssm_command_id" kind:is_not_null
Esql.endpoint_events_process_lolbin_countgt
  • 0
field:"Esql.endpoint_events_process_lolbin_count" kind:gt value:"0"
aws.cloudtrail.request_parameterswildcard
  • *documentName=AWS-RunShellScript*
field:"aws::requestParameters" kind:wildcard value:"*documentName=AWS-RunShellScript*"
data_stream.dataseteq
  • aws.cloudtrail corpus 40 (elastic 40)
  • endpoint.events.process
field:"data_stream.dataset" kind:eq
event.actioneq
  • SendCommand
field:"EventType" kind:eq value:"SendCommand"
process.command_linewildcard
  • %/document/orchestration/%/awsrunShellScript/%/_script.sh
field:"CommandLine" kind:wildcard value:"%/document/orchestration/%/awsrunShellScript/%/_script.sh"
process.namein
  • base64 corpus 20 (elastic 20)
  • curl corpus 82 (elastic 82)
  • nc corpus 19 (elastic 19)
  • ncat corpus 21 (elastic 21)
  • netcat corpus 19 (elastic 19)
  • openssl corpus 8 (elastic 8)
  • perl corpus 4 (elastic 4)
  • php corpus 2 (elastic 2)
  • python corpus 5 (elastic 5)
  • python3 corpus 3 (elastic 3)
  • rsync corpus 8 (elastic 8)
  • ruby corpus 4 (elastic 4)
  • scp corpus 6 (elastic 6)
  • sftp corpus 4 (elastic 4)
  • socat corpus 12 (elastic 12)
  • ssh corpus 8 (elastic 8)
  • wget corpus 41 (elastic 41)
field:"process_basename" kind:in

Output Fields

These fields are emitted when the rule matches.

FieldSource
Esql.*KEEP Esql.*
Esql_priv.*KEEP Esql_priv.*

AWS EKS Access Entry Granted Cluster Admin Policy

#
Status
production
Severity
high
Time window
6m
Author
Elastic
Source
github.com/elastic/detection-rules

Detects when the AmazonEKSClusterAdminPolicy or AmazonEKSAdminPolicy is associated with a principal via the EKS Access Entries API. This grants full cluster-admin equivalent access to the specified IAM user or role. Unlike the legacy aws-auth ConfigMap which is only visible in Kubernetes audit logs, Access Entries modifications appear in CloudTrail, providing an additional detection surface. Attackers who have obtained IAM permissions to manage EKS access entries can use this API to backdoor cluster access for persistence, mapping attacker-controlled IAM identities to cluster-admin privileges without modifying any Kubernetes resources.

Known False Positives

  • Platform or security teams may legitimately associate these policies during cluster onboarding, break-glass admin setup, or controlled RBAC migrations from aws-auth. Validate the caller, change ticket, and target IAM principal.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2026/05/06"
integration = ["aws"]
maturity = "production"
updated_date = "2026/05/06"

[rule]
author = ["Elastic"]
description = """
Detects when the AmazonEKSClusterAdminPolicy or AmazonEKSAdminPolicy is associated with a principal via the EKS
Access Entries API. This grants full cluster-admin equivalent access to the specified IAM user or role. Unlike the
legacy aws-auth ConfigMap which is only visible in Kubernetes audit logs, Access Entries modifications appear in
CloudTrail, providing an additional detection surface. Attackers who have obtained IAM permissions to manage EKS
access entries can use this API to backdoor cluster access for persistence, mapping attacker-controlled IAM
identities to cluster-admin privileges without modifying any Kubernetes resources.
"""
false_positives = [
    """
    Platform or security teams may legitimately associate these policies during cluster onboarding, break-glass admin
    setup, or controlled RBAC migrations from aws-auth. Validate the caller, change ticket, and target IAM principal.
    """,
]
from = "now-6m"
index = ["filebeat-*", "logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS EKS Access Entry Granted Cluster Admin Policy"
note = """## Triage and analysis

### Investigating AWS EKS Access Entry Granted Cluster Admin Policy

Successful AssociateAccessPolicy with AmazonEKSClusterAdminPolicy or AmazonEKSAdminPolicy binds highly privileged
Kubernetes access to an IAM principal. Review who invoked the API (user.name, aws.cloudtrail.user_identity fields),
source.ip, user_agent.original, cloud.account.id, and cloud.region.

### Possible investigation steps

- Parse aws.cloudtrail.request_parameters and response elements for cluster name, access entry ARN, and policy ARN.
- Confirm whether the IAM principal receiving the policy is expected to have cluster-admin-class access.
- Correlate with other EKS API calls (CreateAccessEntry, UpdateAccessEntry) and with Kubernetes audit activity from
  newly authorized principals.
- Compare against change records for migrations from aws-auth or new administrator onboarding.

### Response and remediation

- If unauthorized, disassociate the policy or remove the access entry per AWS guidance; audit who can call eks:*
  APIs in IAM.
- Rotate credentials for any suspected compromised IAM principal; review organizational SCPs and cluster auth mode.

### Additional information

- [Amazon EKS access entries](https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html)
- [AssociateAccessPolicy](https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateAccessPolicy.html)
"""
references = [
    "https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html",
    "https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateAccessPolicy.html",
]
risk_score = 73
rule_id = "9550ec87-e73c-4baa-ad44-e448a33fbc3d"
severity = "high"
tags = [
    "Domain: Cloud",
    "Domain: Kubernetes",
    "Data Source: AWS",
    "Data Source: Amazon Web Services",
    "Data Source: AWS CloudTrail",
    "Use Case: Threat Detection",
    "Tactic: Privilege Escalation",
    "Tactic: Persistence",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
data_stream.dataset:"aws.cloudtrail" and
event.provider:"eks.amazonaws.com" and
event.action:"AssociateAccessPolicy" and
event.outcome:"success" and
aws.cloudtrail.request_parameters:(*AmazonEKSClusterAdminPolicy* or *AmazonEKSAdminPolicy*)
'''

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user_agent.original",
    "source.ip",
    "aws.cloudtrail.user_identity.arn",
    "aws.cloudtrail.user_identity.type",
    "event.action",
    "event.outcome",
    "cloud.account.id",
    "cloud.region",
    "aws.cloudtrail.request_parameters",
    "aws.cloudtrail.response_elements",
]

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.006"
name = "Additional Container Cluster Roles"
reference = "https://attack.mitre.org/techniques/T1098/006/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.006"
name = "Additional Container Cluster Roles"
reference = "https://attack.mitre.org/techniques/T1098/006/"

[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"

Stages and Predicates

Stage 1: query

data_stream.dataset:"aws.cloudtrail" and
event.provider:"eks.amazonaws.com" and
event.action:"AssociateAccessPolicy" and
event.outcome:"success" and
aws.cloudtrail.request_parameters:(*AmazonEKSClusterAdminPolicy* or *AmazonEKSAdminPolicy*)

Indicators

These rows show field, operator, and value matches.

AWS S3 Rapid Bucket Posture API Calls from a Single Principal

#
Status
production
Severity
low
Time window
6m
Group by
Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn, source.ip
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies when the same AWS principal, from the same source IP, successfully invokes read-only S3 control-plane APIs that reveal bucket posture across many buckets in a short period. This pattern can indicate automated reconnaissance or security scanning, similar to CSPM tools and post-compromise enumeration. The rule excludes AWS service principals, requires programmatic-style sessions (not Management Console credentials), and requires populated resource and identity fields so nulls do not skew cardinality.

Known False Positives

  • Legitimate security scanners, CSPM products, compliance jobs, and inventory automation may call the same read-only bucket APIs across many buckets quickly. Verify the principal ARN, source IP, user agent, and schedule against known approved tooling before treating the activity as malicious.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2026/04/02"
integration = ["aws"]
maturity = "production"
min_stack_comments = "Changing min stack to 9.3.0, the latest minimum supported version for 9.X releases."
min_stack_version = "9.3.0"
updated_date = "2026/07/20"

[rule]
author = ["Elastic"]
description = """
Identifies when the same AWS principal, from the same source IP, successfully invokes read-only S3 control-plane APIs
that reveal bucket posture across many buckets in a short period. This pattern can indicate automated reconnaissance or
security scanning, similar to CSPM tools and post-compromise enumeration. The rule excludes AWS service principals,
requires programmatic-style sessions (not Management Console credentials), and requires populated resource and identity
fields so nulls do not skew cardinality.
"""
false_positives = [
    """
    Legitimate security scanners, CSPM products, compliance jobs, and inventory automation may call the same read-only
    bucket APIs across many buckets quickly. Verify the principal ARN, source IP, user agent, and schedule against known
    approved tooling before treating the activity as malicious.
    """,
]
from = "now-6m"
language = "esql"
license = "Elastic License v2"
name = "AWS S3 Rapid Bucket Posture API Calls from a Single Principal"
note = """## Triage and analysis

### Investigating AWS S3 Rapid Bucket Posture API Calls from a Single Principal

This rule detects when the same AWS principal (`aws.cloudtrail.user_identity.arn`), from the same `source.ip`, successfully invokes read-only S3 control-plane APIs that reveal bucket posture across more than 15 distinct `aws.cloudtrail.resources.arn` values within a 10-second window.

Security scanners, compliance tools, and post-compromise reconnaissance often walk many buckets quickly to map public access, policies, and versioning. Bursts of distinct buckets in seconds are less typical of one-off console administration or single-bucket troubleshooting. This could be indicative of reconnaissance as seen by threat actors like Team PCP. 

### Possible investigation steps

**Identify the actor and session context**
- **Actor ARN (`aws.cloudtrail.user_identity.arn`)**: Determine which IAM user, role, or federated principal performed the reads. Confirm whether this identity is approved for broad S3 read or security auditing. Unusual types or unfamiliar roles may warrant deeper review.
- **Access key (`Esql.aws_cloudtrail_user_identity_access_key_id_values`)**: Identify which access key or temporary credential was used. Correlate with IAM last-used metadata for the key or role session.

**Characterize the bucket sweep**
- **Distinct bucket count (`Esql.aws_cloudtrail_resources_arn_count_distinct`)**: Compare to normal baselines for this identity; values at or just above the threshold may still warrant review for new automation.
- **Bucket ARNs (`Esql.aws_cloudtrail_resources_arn_values`)**: Identify which buckets were touched. Prioritize buckets that store logs, backups, credentials, or regulated data. Search the same time range for write or policy-change APIs (`PutBucket*`, `DeleteBucket*`) on the same buckets.

**Analyze source and client**
- **Source IP (`Esql.source_ip_values`)**: Map to corporate egress, a known runner or bastion, an EC2 instance, or an unfamiliar ASN. Compare with VPC Flow Logs or proxy logs when available.
- **User agent (`Esql.user_agent_original_values`, `Esql.user_agent_name_values`)**: Identify the AWS CLI, Boto3, a specific scanner, or custom scripts. Unusual or minimal user agents may align with tooling and require investigation.

**Correlate in time**
- Query CloudTrail for the same `aws.cloudtrail.user_identity.arn` and `source.ip` within approximately ±30 minutes for follow-on patterns: `ListBuckets`, `GetObject`, `PutBucketPolicy`, `AssumeRole`, or IAM changes.
- Check for overlapping alerts related to credential access, unusual geolocation, or new external bucket policy grants.

### False positive analysis

Legitimate causes can include:
- **Security and compliance scanners** (for example CSPM or assessment tools) using API credentials with `s3:Get*` permissions across many buckets.
- **Inventory or backup catalog tools** that enumerate bucket metadata for reporting.
- **CI/CD or infrastructure-as-code validation** jobs that verify bucket settings across environments.

Validate whether the principal is a documented service account, the IP belongs to known infrastructure, and the timing matches scheduled jobs. If behavior is expected, consider raising the distinct-bucket threshold, adding `user_agent` filters, or documenting exception identities.

### Response and remediation

**Contain**
- If activity is unexpected, rotate or disable keys for the affected identity, revoke active role sessions where possible, and restrict the source IP at the network layer if it is not authorized.

**Investigate**
- Export CloudTrail for the window around `Esql.time_window_date_trunc` and review all S3 and IAM events for the same actor.
- Review IAM policies attached to the principal for excessive `s3:Get*` or `s3:List*` scope.

**Harden**
- Enforce least privilege on S3 read APIs; use permission boundaries or service control policies where appropriate.
- Ensure sensitive buckets are not unnecessarily reachable from the observed network context.
- Document approved scanning accounts and tune the rule to reduce noise from those identities.

### Additional information

- [AWS Security Incident Response Guide](https://docs.aws.amazon.com/whitepapers/latest/aws-security-incident-response-guide/aws-security-incident-response-guide.pdf)
- [AWS Incident Response Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/)
- [AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework)

"""
references = [
    "https://kudelskisecurity.com/research/investigating-two-variants-of-the-trivy-supply-chain-compromise",
]
risk_score = 21
rule_id = "a7577205-88a1-4a08-85d4-7b72a9a2e969"
severity = "low"
tags = [
    "Domain: Cloud",
    "Data Source: AWS",
    "Data Source: Amazon Web Services",
    "Data Source: AWS S3",
    "Data Source: AWS CloudTrail",
    "Use Case: Threat Detection",
    "Tactic: Discovery",
    "Tactic: Collection",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-aws.cloudtrail-* metadata _id, _version, _index
| eval Esql.time_window_date_trunc = date_trunc(10 seconds, @timestamp)

| where
    data_stream.dataset == "aws.cloudtrail"
    and event.provider == "s3.amazonaws.com"
    and event.outcome == "success"
    and event.action in (
      "GetBucketAcl",
      "GetBucketPublicAccessBlock",
      "GetBucketPolicy",
      "GetBucketPolicyStatus",
      "GetBucketVersioning"
    )
    and aws.cloudtrail.user_identity.type != "AWSService"
    and source.ip IS NOT NULL
    and aws.cloudtrail.resources.arn IS NOT NULL
    and aws.cloudtrail.user_identity.arn IS NOT NULL
    and aws.cloudtrail.session_credential_from_console IS NULL

| keep
    @timestamp,
    Esql.time_window_date_trunc,
    event.action,
    aws.cloudtrail.user_identity.arn,
    aws.cloudtrail.user_identity.type,
    aws.cloudtrail.user_identity.access_key_id,
    source.ip,
    aws.cloudtrail.resources.arn,
    cloud.account.id,
    cloud.region,
    user_agent.original,
    source.as.organization.name,
    data_stream.namespace

| stats
    Esql.aws_cloudtrail_resources_arn_count_distinct = count_distinct(aws.cloudtrail.resources.arn),
    Esql.aws_cloudtrail_resources_arn_values = VALUES(aws.cloudtrail.resources.arn),
    Esql.event_action_values = VALUES(event.action),
    Esql.timestamp_values = VALUES(@timestamp),
    Esql.aws_cloudtrail_user_identity_type_values = VALUES(aws.cloudtrail.user_identity.type),
    Esql.aws_cloudtrail_user_identity_access_key_id_values = VALUES(aws.cloudtrail.user_identity.access_key_id),
    Esql.cloud_account_id_values = VALUES(cloud.account.id),
    Esql.cloud_region_values = VALUES(cloud.region),
    Esql.user_agent_original_values = VALUES(user_agent.original),
    Esql.source_as_organization_name_values = VALUES(source.as.organization.name),
    Esql.data_stream_namespace_values = VALUES(data_stream.namespace)
  by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn, source.ip

| where Esql.aws_cloudtrail_resources_arn_count_distinct > 15

| keep
    aws.cloudtrail.user_identity.arn,
    source.ip,
    Esql.time_window_date_trunc,
    Esql.aws_cloudtrail_resources_arn_count_distinct,
    Esql.aws_cloudtrail_resources_arn_values,
    Esql.event_action_values,
    Esql.timestamp_values,
    Esql.aws_cloudtrail_user_identity_type_values,
    Esql.aws_cloudtrail_user_identity_access_key_id_values,
    Esql.cloud_account_id_values,
    Esql.cloud_region_values,
    Esql.user_agent_original_values,
    Esql.source_as_organization_name_values,
    Esql.data_stream_namespace_values
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1526"
name = "Cloud Service Discovery"
reference = "https://attack.mitre.org/techniques/T1526/"

[[rule.threat.technique]]
id = "T1580"
name = "Cloud Infrastructure Discovery"
reference = "https://attack.mitre.org/techniques/T1580/"

[[rule.threat.technique]]
id = "T1619"
name = "Cloud Storage Object Discovery"
reference = "https://attack.mitre.org/techniques/T1619/"


[rule.threat.tactic]
id = "TA0007"
name = "Discovery"
reference = "https://attack.mitre.org/tactics/TA0007/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1530"
name = "Data from Cloud Storage"
reference = "https://attack.mitre.org/techniques/T1530/"


[rule.threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"

[rule.investigation_fields]
field_names = [
    "Esql.aws_cloudtrail_resources_arn_count_distinct",
    "Esql.time_window_date_trunc",
    "aws.cloudtrail.user_identity.arn",
    "source.ip",
    "Esql.aws_cloudtrail_resources_arn_values",
    "Esql.event_action_values",
    "Esql.timestamp_values",
    "Esql.aws_cloudtrail_user_identity_type_values",
    "Esql.aws_cloudtrail_user_identity_access_key_id_values",
    "Esql.cloud_account_id_values",
    "Esql.cloud_region_values",
    "Esql.user_agent_original_values",
    "Esql.source_as_organization_name_values",
    "Esql.data_stream_namespace_values",
]

Stages and Predicates

Stage 1: from

from logs-aws.cloudtrail-* metadata _id, _version, _index

Stage 2: eval

| eval Esql.time_window_date_trunc = date_trunc(10 seconds, @timestamp)

Stage 3: where

| where
    data_stream.dataset == "aws.cloudtrail"
    and event.provider == "s3.amazonaws.com"
    and event.outcome == "success"
    and event.action in (
      "GetBucketAcl",
      "GetBucketPublicAccessBlock",
      "GetBucketPolicy",
      "GetBucketPolicyStatus",
      "GetBucketVersioning"
    )
    and aws.cloudtrail.user_identity.type != "AWSService"
    and source.ip IS NOT NULL
    and aws.cloudtrail.resources.arn IS NOT NULL
    and aws.cloudtrail.user_identity.arn IS NOT NULL
    and aws.cloudtrail.session_credential_from_console IS NULL

Stage 4: keep

| keep
    @timestamp,
    Esql.time_window_date_trunc,
    event.action,
    aws.cloudtrail.user_identity.arn,
    aws.cloudtrail.user_identity.type,
    aws.cloudtrail.user_identity.access_key_id,
    source.ip,
    aws.cloudtrail.resources.arn,
    cloud.account.id,
    cloud.region,
    user_agent.original,
    source.as.organization.name,
    data_stream.namespace

Stage 5: stats

| stats
    Esql.aws_cloudtrail_resources_arn_count_distinct = count_distinct(aws.cloudtrail.resources.arn),
    Esql.aws_cloudtrail_resources_arn_values = VALUES(aws.cloudtrail.resources.arn),
    Esql.event_action_values = VALUES(event.action),
    Esql.timestamp_values = VALUES(@timestamp),
    Esql.aws_cloudtrail_user_identity_type_values = VALUES(aws.cloudtrail.user_identity.type),
    Esql.aws_cloudtrail_user_identity_access_key_id_values = VALUES(aws.cloudtrail.user_identity.access_key_id),
    Esql.cloud_account_id_values = VALUES(cloud.account.id),
    Esql.cloud_region_values = VALUES(cloud.region),
    Esql.user_agent_original_values = VALUES(user_agent.original),
    Esql.source_as_organization_name_values = VALUES(source.as.organization.name),
    Esql.data_stream_namespace_values = VALUES(data_stream.namespace)
  by Esql.time_window_date_trunc, aws.cloudtrail.user_identity.arn, source.ip

Stage 6: where

| where Esql.aws_cloudtrail_resources_arn_count_distinct > 15

Stage 7: keep

| keep
    aws.cloudtrail.user_identity.arn,
    source.ip,
    Esql.time_window_date_trunc,
    Esql.aws_cloudtrail_resources_arn_count_distinct,
    Esql.aws_cloudtrail_resources_arn_values,
    Esql.event_action_values,
    Esql.timestamp_values,
    Esql.aws_cloudtrail_user_identity_type_values,
    Esql.aws_cloudtrail_user_identity_access_key_id_values,
    Esql.cloud_account_id_values,
    Esql.cloud_region_values,
    Esql.user_agent_original_values,
    Esql.source_as_organization_name_values,
    Esql.data_stream_namespace_values

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
aws.cloudtrail.user_identity.arnKEEP aws.cloudtrail.user_identity.arn
source.ipKEEP source.ip
Esql.time_window_date_truncKEEP Esql.time_window_date_trunc
Esql.aws_cloudtrail_resources_arn_count_distinctKEEP Esql.aws_cloudtrail_resources_arn_count_distinct
Esql.aws_cloudtrail_resources_arn_valuesKEEP Esql.aws_cloudtrail_resources_arn_values
Esql.event_action_valuesKEEP Esql.event_action_values
Esql.timestamp_valuesKEEP Esql.timestamp_values
Esql.aws_cloudtrail_user_identity_type_valuesKEEP Esql.aws_cloudtrail_user_identity_type_values
Esql.aws_cloudtrail_user_identity_access_key_id_valuesKEEP Esql.aws_cloudtrail_user_identity_access_key_id_values
Esql.cloud_account_id_valuesKEEP Esql.cloud_account_id_values
Esql.cloud_region_valuesKEEP Esql.cloud_region_values
Esql.user_agent_original_valuesKEEP Esql.user_agent_original_values
Esql.source_as_organization_name_valuesKEEP Esql.source_as_organization_name_values
Esql.data_stream_namespace_valuesKEEP Esql.data_stream_namespace_values

Azure Diagnostic Settings Deleted

#
Status
production
Severity
medium
Time window
9m
Group by
azure.resource.group
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies the deletion of diagnostic settings in Azure, which send platform logs and metrics to different destinations. An adversary may delete diagnostic settings in an attempt to evade defenses.

Known False Positives

  • Deletion of diagnostic settings may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Diagnostic settings deletion from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2020/08/17"
integration = ["azure"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Identifies the deletion of diagnostic settings in Azure, which send platform logs and metrics to different destinations.
An adversary may delete diagnostic settings in an attempt to evade defenses.
"""
false_positives = [
    """
    Deletion of diagnostic settings may be done by a system or network administrator. Verify whether the username,
    hostname, and/or resource name should be making changes in your environment. Diagnostic settings deletion from
    unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted
    from the rule.
    """,
]
from = "now-9m"
index = ["logs-azure.activitylogs-*", "filebeat-*"]
language = "kuery"
license = "Elastic License v2"
name = "Azure Diagnostic Settings Deleted"
note = """## Triage and analysis

### Investigating Azure Diagnostic Settings Deleted

Azure Diagnostic Settings are crucial for monitoring and logging platform activities, sending data to various destinations for analysis. Adversaries may delete these settings to hinder detection and analysis of their activities, effectively evading defenses. The detection rule identifies such deletions by monitoring specific Azure activity logs for successful deletion operations, flagging potential defense evasion attempts.

### Possible investigation steps

- Identify the user or service principal responsible for the deletion by examining the associated user identity or service principal ID in the activity logs.
- If this is a service principal, determine which application is associated with it and examine credential use with authentication sources to identify potential compromise.
- Examine the resource group and subscription context to understand the scope of the deletion and whether it affects critical resources.
- Check the timestamp of the deletion event to determine when the diagnostic settings were removed and correlate this with other security events or alerts around the same time.
- Investigate the affected resources by identifying which diagnostic settings were deleted and assess the potential impact on monitoring and logging capabilities.
- Review any recent changes or activities performed by the identified user or service principal to determine if there are other suspicious actions that might indicate malicious intent.
- Assess the current security posture by ensuring that diagnostic settings are reconfigured and that logging and monitoring are restored to maintain visibility into platform activities.

### False positive analysis

- Examine the service principal or user account involved in the deletion to determine if it is part of an automated process or legitimate administrative activity.
- Automated scripts or tools used for managing Azure resources might delete diagnostic settings as part of their operation. Review and whitelist these scripts if they are verified as non-threatening.
- Changes in organizational policy or compliance requirements could lead to legitimate deletions. Confirm with relevant teams if such policy changes are in effect.
- Test environments often undergo frequent configuration changes, including the deletion of diagnostic settings. Consider excluding these environments from the rule or adjusting the rule to account for their unique behavior.
- Ensure that any third-party integrations or services with access to Azure resources are reviewed, as they might inadvertently delete diagnostic settings during their operations.

### Response and remediation

- Immediately isolate affected Azure resources to prevent further unauthorized changes or deletions. This may involve temporarily restricting access to the affected subscriptions or resource groups.
- Review the Azure activity logs to identify the source of the deletion request, including the user account, service principal and IP address involved. This will help determine if the action was authorized or malicious.
- Recreate the deleted diagnostic settings as soon as possible to restore logging and monitoring capabilities. Ensure that logs are being sent to secure and appropriate destinations.
- Conduct a thorough investigation of the user account or service principal involved in the deletion. If the account is compromised, reset credentials, and review permissions to ensure they are appropriate and follow the principle of least privilege.
- Escalate the incident to the security operations team for further analysis and to determine if additional resources or expertise are needed to address the threat.
- Implement additional monitoring and alerting for similar deletion activities to ensure rapid detection and response to future attempts.
- Review and update access controls and policies related to diagnostic settings to prevent unauthorized deletions, ensuring that only trusted and necessary personnel have the ability to modify these settings.
"""
references = [
    "https://docs.microsoft.com/en-us/azure/azure-monitor/platform/diagnostic-settings",
    "https://www.microsoft.com/en-us/security/blog/2025/10/20/inside-the-attack-chain-threat-activity-targeting-azure-blob-storage/",
]
risk_score = 47
rule_id = "5370d4cd-2bb3-4d71-abf5-1e1d0ff5a2de"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Data Source: Azure",
    "Data Source: Azure Activity Logs",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"

query = '''
data_stream.dataset:azure.activitylogs
    and azure.activitylogs.operation_name:"MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE"
    and event.outcome:(Success or success)
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"
[[rule.threat.technique.subtechnique]]
id = "T1562.001"
name = "Disable or Modify Tools"
reference = "https://attack.mitre.org/techniques/T1562/001/"

[[rule.threat.technique.subtechnique]]
id = "T1562.008"
name = "Disable or Modify Cloud Logs"
reference = "https://attack.mitre.org/techniques/T1562/008/"



[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "event.action",
    "source.ip",
    "azure.activitylogs.identity.authorization.evidence.principal_type",
    "azure.activitylogs.identity.authorization.evidence.role_assignment_scope",
    "azure.activitylogs.properties.entity",
    "azure.activitylogs.identity.claims.appid",
    "azure.resource.name",
    "azure.resource.provider",
]

[rule.new_terms]
field = "new_terms_fields"
value = ["azure.resource.group"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"


Stages and Predicates

Stage 1: new_terms

data_stream.dataset:azure.activitylogs
    and azure.activitylogs.operation_name:"MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE"
    and event.outcome:(Success or success)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
azure.activitylogs.operation_nameeq
  • MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE
field:"azure.activitylogs.operation_name" kind:eq value:"MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE"
data_stream.dataseteq
  • azure.activitylogs corpus 38 (elastic 38)
field:"data_stream.dataset" kind:eq value:"azure.activitylogs"
event.outcomein
  • Success corpus 306 (elastic 306)
  • success corpus 306 (elastic 306)
field:"event.outcome" kind:in

Deprecated TLS Version or Weak Cipher Negotiated Externally

#
Status
production
Severity
medium
Time window
9m
Group by
destination.ip, source.ip, tls.version
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies successful outbound TLS sessions that negotiate deprecated protocol versions (SSLv3, TLS 1.0, or TLS 1.1) or weak cipher suites such as RC4, 3DES, NULL, EXPORT, or anonymous Diffie-Hellman. Adversaries-in-the-middle and legacy malware often force these negotiations to decrypt or intercept traffic. Modern clients and services should negotiate TLS 1.2 or 1.3 with strong ciphers on internet-bound connections.

Known False Positives

  • Legacy internal applications, industrial control systems, or embedded devices may still require deprecated TLS versions or weak ciphers. Exclude known legacy destination IPs or subnets after validation.

MITRE ATT&CK Coverage

TacticTechniques
Credential Access
Command & Control

Rule Body

[metadata]
creation_date = "2026/06/25"
integration = ["network_traffic"]
maturity = "production"
updated_date = "2026/06/25"

[rule]
author = ["Elastic"]
description = """
Identifies successful outbound TLS sessions that negotiate deprecated protocol versions (SSLv3, TLS 1.0, or TLS 1.1) or
weak cipher suites such as RC4, 3DES, NULL, EXPORT, or anonymous Diffie-Hellman. Adversaries-in-the-middle and legacy
malware often force these negotiations to decrypt or intercept traffic. Modern clients and services should negotiate TLS
1.2 or 1.3 with strong ciphers on internet-bound connections.
"""
false_positives = [
    """
    Legacy internal applications, industrial control systems, or embedded devices may still require deprecated TLS
    versions or weak ciphers. Exclude known legacy destination IPs or subnets after validation.
    """,
]
from = "now-9m"
index = ["logs-network_traffic.tls-*"]
language = "kuery"
license = "Elastic License v2"
name = "Deprecated TLS Version or Weak Cipher Negotiated Externally"
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Deprecated TLS Version or Weak Cipher Negotiated Externally

TLS downgrade and weak-cipher negotiation expose sessions to interception or decryption. This rule flags completed
outbound TLS handshakes from internal hosts to external destinations that negotiated SSLv3, TLS 1.0, TLS 1.1, or a
cipher suite containing RC4, 3DES, NULL, EXPORT, or anonymous key exchange material.

### Possible investigation steps

- Review `source.ip`, `destination.ip`, `destination.port`, `tls.version`, `tls.version_protocol`, and `tls.cipher`.
- Determine whether the destination is a known legacy partner, vendor appliance, or unmanaged IoT device.
- Check for concurrent alerts on the source host (credential access, C2, or proxy manipulation).
- Compare against baseline: does this destination normally negotiate modern TLS from other clients?

### False positive analysis

- Exclude validated legacy B2B endpoints, mainframe gateways, or SCADA systems that cannot be upgraded immediately.
- Some older mobile or embedded clients may still offer weak ciphers even when connecting to modern services; confirm
  whether the server accepted the weak option (this rule requires `tls.established:true`).

### Response and remediation

- Block or proxy traffic to the destination if downgrade appears attacker-driven.
- Patch or replace the client or server that accepted deprecated TLS.
- Enable TLS 1.2+ minimums on egress proxies and inspect for MITM appliances forcing weak negotiation.
"""
references = [
    "https://attack.mitre.org/techniques/T1557/",
    "https://www.elastic.co/docs/reference/integrations/network_traffic",
    "https://www.elastic.co/docs/reference/ecs/ecs-tls",
    "https://www.rfc-editor.org/rfc/rfc9325.html",
]
risk_score = 47
rule_id = "d994a184-ab93-4cff-8fb6-31a4b4dd18b1"
setup = """## Setup

This rule requires TLS metadata from the Elastic network_traffic integration (`network_traffic.tls` data stream) that
populates ECS `tls.version`, `tls.version_protocol`, `tls.cipher`, and `tls.established` fields.
"""
severity = "medium"
tags = [
    "Domain: Network",
    "Use Case: Network Security Monitoring",
    "Use Case: Threat Detection",
    "Data Source: Network Traffic",
    "Tactic: Credential Access",
    "Tactic: Command and Control",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"

query = '''
data_stream.dataset:network_traffic.tls
  and network.protocol: tls
  and network.transport: tcp
  and tls.established: true
  and source.ip:(10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)
  and not destination.ip:(
    10.0.0.0/8 or
    100.64.0.0/10 or
    127.0.0.0/8 or
    169.254.0.0/16 or
    172.16.0.0/12 or
    192.0.0.0/24 or
    192.0.0.0/29 or
    192.0.0.10/32 or
    192.0.0.170/32 or
    192.0.0.171/32 or
    192.0.0.8/32 or
    192.0.0.9/32 or
    192.0.2.0/24 or
    192.168.0.0/16 or
    192.175.48.0/24 or
    192.31.196.0/24 or
    192.52.193.0/24 or
    192.88.99.0/24 or
    198.18.0.0/15 or
    198.51.100.0/24 or
    203.0.113.0/24 or
    224.0.0.0/4 or
    240.0.0.0/4 or
    "::1" or
    "FE80::/10" or
    "FF00::/8"
  )
  and (
    tls.version:(1.0 or 1.1) or
    (tls.version_protocol:ssl and tls.version:3.0) or
    (
      not tls.version:1.3 and (
        tls.cipher:(
          *RC4* or
          *3DES* or
          *NULL* or
          *EXPORT* or
          *_anon_* or
          *ADH* or
          *AECDH*
        )
      )
    )
  )
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1557"
name = "Adversary-in-the-Middle"
reference = "https://attack.mitre.org/techniques/T1557/"


[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1573"
name = "Encrypted Channel"
reference = "https://attack.mitre.org/techniques/T1573/"


[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"

[rule.new_terms]
field = "new_terms_fields"
value = ["source.ip", "destination.ip", "tls.version"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"


Stages and Predicates

Stage 1: new_terms

data_stream.dataset:network_traffic.tls
  and network.protocol: tls
  and network.transport: tcp
  and tls.established: true
  and source.ip:(10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)
  and not destination.ip:(
    10.0.0.0/8 or
    100.64.0.0/10 or
    127.0.0.0/8 or
    169.254.0.0/16 or
    172.16.0.0/12 or
    192.0.0.0/24 or
    192.0.0.0/29 or
    192.0.0.10/32 or
    192.0.0.170/32 or
    192.0.0.171/32 or
    192.0.0.8/32 or
    192.0.0.9/32 or
    192.0.2.0/24 or
    192.168.0.0/16 or
    192.175.48.0/24 or
    192.31.196.0/24 or
    192.52.193.0/24 or
    192.88.99.0/24 or
    198.18.0.0/15 or
    198.51.100.0/24 or
    203.0.113.0/24 or
    224.0.0.0/4 or
    240.0.0.0/4 or
    "::1" or
    "FE80::/10" or
    "FF00::/8"
  )
  and (
    tls.version:(1.0 or 1.1) or
    (tls.version_protocol:ssl and tls.version:3.0) or
    (
      not tls.version:1.3 and (
        tls.cipher:(
          *RC4* or
          *3DES* or
          *NULL* or
          *EXPORT* or
          *_anon_* or
          *ADH* or
          *AECDH*
        )
      )
    )
  )

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
destination.ipin10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.0.0/29, 192.0.0.10/32, 192.0.0.170/32, 192.0.0.171/32, 192.0.0.8/32, 192.0.0.9/32, 192.0.2.0/24, 192.168.0.0/16, 192.175.48.0/24, 192.31.196.0/24, 192.52.193.0/24, 192.88.99.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4, ::1, FE80::/10, FF00::/8excludes:destination.ip

Dylib Injection via Process Environment Variables

#
Status
production
Severity
high
Time window
15s
Sequence by
process.entity_id
Author
Elastic
Source
github.com/elastic/detection-rules

Detects the use of process environment variables (DYLD_INSERT_LIBRARIES or LD_PRELOAD) to inject a shared library into a binary at or prior to execution. A threat actor may use this technique to load a malicious shared library for persistence, privilege escalation, and defense evasion. This activity is uncommon and typically indicates malicious behavior.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2026/01/30"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/03/24"

[rule]
author = ["Elastic"]
description = """
Detects the use of process environment variables (DYLD_INSERT_LIBRARIES or LD_PRELOAD) to inject a shared 
library into a binary at or prior to execution. A threat actor may use this technique to load a malicious 
shared library for persistence, privilege escalation, and defense evasion. This activity is uncommon and 
typically indicates malicious behavior.
"""
from = "now-9m"
index = ["logs-endpoint.events.process-*", "logs-endpoint.events.library-*"]
language = "eql"
license = "Elastic License v2"
name = "Dylib Injection via Process Environment Variables"
references = [
    "https://wojciechregula.blog/post/learn-xpc-exploitation-part-3-code-injections/",
    "https://attack.mitre.org/techniques/T1574/006/"
]
risk_score = 73
rule_id = "fb8790fc-d485-45e2-8d6e-2fb813f4af95"
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: macOS",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Tactic: Persistence",
    "Data Source: Elastic Defend",
    "Resources: Investigation Guide"
]
type = "eql"
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Dylib Injection via Process Environment Variables

Dynamic library injection using DYLD_INSERT_LIBRARIES or LD_PRELOAD environment variables is a powerful technique that allows code to be loaded into a process's address space at runtime. While this capability exists for legitimate debugging and development purposes, threat actors abuse it to hook application functionality, steal credentials, intercept keystrokes, or execute malicious code within trusted processes. This detection rule identifies processes started with these injection environment variables set to non-empty values.

### Possible investigation steps

- Review the process.env_vars field to identify the specific dylib being injected via DYLD_INSERT_LIBRARIES or LD_PRELOAD and determine its file path.
- Locate the injected dylib file on the file system using the path from the environment variable and calculate its hash for threat intelligence lookups.
- Analyze the process.executable and process.name fields to identify the target application being hijacked and assess whether dylib injection makes sense for its normal operation.
- Examine the process.parent.executable and process.command_line to understand how the process with injection was launched and trace back to the initial execution vector.
- Review the code signature of the injected dylib using codesign or similar tools to determine if it is signed, and by whom.
- Check for file creation events to determine when the malicious dylib was placed on the system and how it was delivered.
- Correlate with other security events on the same host to identify if the injection is part of a larger attack chain, such as credential theft or keylogging.

### False positive analysis

- Xcode and iOS Simulator use DYLD_INSERT_LIBRARIES for debugging and testing purposes during application development. These paths are already excluded in the query.
- Security research and reverse engineering tools may use library injection for analysis. Verify with security teams if such activities are expected.
- Some legitimate applications use library injection for specific functionality. Document these applications and create targeted exceptions after verification.
- Homebrew and development environments may occasionally use these environment variables. Confirm with development teams before creating exclusions.

### Response and remediation

- Immediately terminate the process using malicious dylib injection to stop any ongoing malicious activity such as credential theft or keylogging.
- Quarantine the injected dylib file for forensic analysis and malware reverse engineering.
- Remove the malicious dylib from the system and ensure it cannot be reloaded through persistence mechanisms.
- Investigate how the dylib was placed on the system and remediate the initial access or delivery mechanism.
- Review System Integrity Protection (SIP) status on the affected system, as SIP should normally prevent DYLD injection into protected system processes.
- Scan the system for additional indicators of compromise, persistence mechanisms, or lateral movement.
- Reset any credentials that may have been exposed through the injection, particularly if the target application handles sensitive authentication data.
- Escalate to the incident response team for comprehensive analysis if the injection indicates active compromise.
"""
query = '''
sequence by process.entity_id with maxspan=15s
  [process where host.os.type == "macos" and event.type == "start" and event.action == "exec" and
    process.env_vars like ("DYLD_INSERT_LIBRARIES=?*", "LD_PRELOAD=?*") and
    not process.env_vars like ("DYLD_INSERT_LIBRARIES=", "LD_PRELOAD=", "LD_PRELOAD=<null>") and
    not process.executable like ("/Users/*/Library/Developer/Xcode/*", "/Users/*/Library/Developer/CoreSimulator/*") and
    not process.parent.executable like ("/usr/bin/xcrun", "/Applications/Xcode*.app/*", "/Library/Developer/*")]
  [library where host.os.type == "macos" and event.action == "load" and
    not dll.name like ("*.aot", "*.so") and
    not dll.code_signature.trusted == true and
    not dll.path like ("/System/*", "/usr/lib/*", "/opt/homebrew/*", "/private/var/folders/*",
                       "/Library/Apple/*", "/Library/Developer/*",
                       "/Users/*/Library/Developer/Xcode/*", "/Users/*/Library/Developer/CoreSimulator/*")]
'''

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"

[[rule.threat.technique.subtechnique]]
id = "T1574.006"
name = "Dynamic Linker Hijacking"
reference = "https://attack.mitre.org/techniques/T1574/006/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"

[[rule.threat.technique.subtechnique]]
id = "T1574.006"
name = "Dynamic Linker Hijacking"
reference = "https://attack.mitre.org/techniques/T1574/006/"

[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"

[[rule.threat.technique.subtechnique]]
id = "T1574.006"
name = "Dynamic Linker Hijacking"
reference = "https://attack.mitre.org/techniques/T1574/006/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

Stages and Predicates

Ordered sequence: each step below must occur in order within 15s, correlated by process.entity_id.

Stage 1: process

[process where host.os.type == "macos" and event.type == "start" and event.action == "exec" and
    process.env_vars like ("DYLD_INSERT_LIBRARIES=?*", "LD_PRELOAD=?*") and
    not process.env_vars like ("DYLD_INSERT_LIBRARIES=", "LD_PRELOAD=", "LD_PRELOAD=<null>") and
    not process.executable like ("/Users/*/Library/Developer/Xcode/*", "/Users/*/Library/Developer/CoreSimulator/*") and
    not process.parent.executable like ("/usr/bin/xcrun", "/Applications/Xcode*.app/*", "/Library/Developer/*")]

Stage 2: library

[library where host.os.type == "macos" and event.action == "load" and
    not dll.name like ("*.aot", "*.so") and
    not dll.code_signature.trusted == true and
    not dll.path like ("/System/*", "/usr/lib/*", "/opt/homebrew/*", "/private/var/folders/*",
                       "/Library/Apple/*", "/Library/Developer/*",
                       "/Users/*/Library/Developer/Xcode/*", "/Users/*/Library/Developer/CoreSimulator/*")]

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec corpus 547 (elastic 547)
  • load corpus 23 (elastic 23)
field:"EventType" kind:eq
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.env_varswildcard
  • DYLD_INSERT_LIBRARIES=?*
  • LD_PRELOAD=?*
field:"process.env_vars" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.env_varseqDYLD_INSERT_LIBRARIES=, LD_PRELOAD=, LD_PRELOAD=<null>excludes:process.env_vars field:"process.env_vars" value:"DYLD_INSERT_LIBRARIES=" field:"process.env_vars" value:"LD_PRELOAD=" field:"process.env_vars" value:"LD_PRELOAD=<null>"
process.executablewildcard/Users/*/Library/Developer/Xcode/*, /Users/*/Library/Developer/CoreSimulator/*excludes:process.executable field:"process.executable" value:"/Users/*/Library/Developer/Xcode/*" field:"process.executable" value:"/Users/*/Library/Developer/CoreSimulator/*"
process.parent.executablewildcard/usr/bin/xcrun, /Applications/Xcode*.app/*, /Library/Developer/*excludes:process.parent.executable field:"process.parent.executable" value:"/usr/bin/xcrun" field:"process.parent.executable" value:"/Applications/Xcode*.app/*" field:"process.parent.executable" value:"/Library/Developer/*"
dll.code_signature.trustedeqtrueexcludes:dll.code_signature.trusted field:"dll.code_signature.trusted" value:"true"
dll.nameends_with.aot, .soexcludes:dll.name field:"dll.name" value:".aot" field:"dll.name" value:".so"
dll.pathwildcard/System/*, /usr/lib/*, /opt/homebrew/*, /private/var/folders/*, /Library/Apple/*, /Library/Developer/*, /Users/*/Library/Developer/Xcode/*, /Users/*/Library/Developer/CoreSimulator/*excludes:dll.path

Execution of Memory File Descriptor via Suspicious Process

#
Source
github.com/elastic/protections-artifacts

This rule detects when a process executes a file descriptor in the proc (temporary) file system. This activity indicates an active attempt to execute a fileless payload and should be considered highly abnormal or suspicious. This activity can occur when the memfd syscall is utilized to create a memory resident file, like a payload, and then uses it to execute a process via a command and control channel.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
This rule detects when a process executes a file descriptor in the proc (temporary) file system. This activity indicates
an active attempt to execute a fileless payload and should be considered highly abnormal or suspicious. This activity
can occur when the memfd syscall is utilized to create a memory resident file, like a payload, and then uses it to
execute a process via a command and control channel.
"""
id = "dccab9ab-1b40-4d52-85ed-cb41310b0160"
license = "Elastic License v2"
name = "Execution of Memory File Descriptor via Suspicious Process"
os_list = ["linux"]
reference = ["https://man7.org/linux/man-pages/man2/memfd_create.2.html"]
version = "1.0.10"

query = '''
process where event.type == "start" and event.action == "exec" and (
  process.executable regex """/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}""" or
  (
    process.args regex """/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}""" and
    process.executable like (
      "memfd:*", "?memfd:*", "/tmp/*", "/var/tmp/*", "/dev/shm/*", "./*", "/run/user/*", "/var/run/user/*",
      "/boot/*", "/sys/*", "/lost+found/*", "/proc/*", "/var/mail/*", "/root/*"
    )
  )
) and
not (
  process.parent.executable like (
    "/home/*/*steam*", "/usr/bin/podman", "./usr/bin/podman", "/dev/.buildkit_qemu_emulator",
    "/opt/omni/bin/drim/linux-amd64/coolie", "/usr/lib/systemd/systemd", "/usr/libexec/nordlayer/nordlayer-setcap",
    "/usr/bin/nordlayer", "/home/*/playground/general/edgeless/tools/contrast", "/bin/nvidia-cdi-hook",
    "/usr/bin/nvidia-ctk", "/sbin/apk", "/tmp/newroot/usr/bin/podman", "/usr/libexec/nordlayer/nordlayer-resolvconf",
    "/usr/sbin/docker-runc", "/usr/bin/runc", "/opt/teleport/system/bin/teleport", "/usr/local/bin/teleport",
    "/opt/sophos-spl/plugins/runtimedetections/bin/runtimedetections*", "/opt/fireeye/bin/rte-sensor", "/usr/local/sbin/thor-cloud-*",
    "/tmp/newroot/run/media/mm1/RIG_Drive_2/SteamLibrary/steamapps/common/SteamLinuxRuntime_4/pressure-vessel/bin/pressure-vessel-wrap",
    "/tmp/newroot/bin/sh", "/opt/sophos-spl/base/bin/launcher", "/usr/bin/containerd-shim-runc-v2", "/opt/sophos-spl/base/bin/sophos_watchdog.*"
  ) or
  process.executable like (
    "./home/*/.local/share/claude/versions/*", "/tmp/newroot/usr/bin/ls", "/tmp/newroot/var/lib/docker/rootfs/overlayfs/*/usr/bin/chown",
    "/tmp/newroot/*"
  ) or
  process.command_line like (
    "runc init", "/usr/local/bin/runc init", "*/home/*/.claude/shell-snapshots/snapshot*",
    "/proc/self/fd/? -config /etc/nordlayer/config.hcl", "storage-untar / /proc/self/fd/*",
    "/proc/self/exe init"
  ) or
  process.parent.args == "/usr/local/bin/teleport" or
  process.parent.command_line like (
    "/opt/teleport/system/bin/teleport exec", "/opt/teleport/default/versions/*/bin/teleport exec"
  ) or
  (
    process.parent.command_line == "/usr/local/bin/teleport exec" and
    process.command_line == "/memfd:teleport-sessionhelper checkhomedir"
  ) or
  (
    process.command_line like "/usr/lib/podman/netavark --config /run/containers/networks --rootless=false --aardvark-binary=/usr/lib/podman/aardvark-dns *" and
    process.args == "/usr/lib/podman/netavark"
  ) or
  (
    process.args == "lxc-attach" and
    process.args == "-n"
  ) or
  (
    process.args == "bwrap" and
    process.args == "--new-session" and
    process.args == "--die-with-parent"
  ) or
  (
    process.parent.executable in ("/bin/php", "/usr/bin/php") and
    process.args == "datadog-ipc-helper"
  ) or
  process.args like ("/usr/lib/systemd/systemd-executor", "/nix/store/*/lib/systemd/systemd-executor") or
  (
    process.executable like (
      "/tmp/newroot/proc/self/exe", "/tmp/newroot/home/*/.local/share/containers/storage/overlay/*/merged/proc/self/exe",
      "./usr/bin/podman"
    ) and
    process.args == "storage-untar"
  ) or
  (
    process.parent.executable == "/usr/libexec/docker/docker-runc-current" and
    process.command_line == "/proc/self/exe init"
  ) or
  (
    process.parent.executable == "/opt/sentinelone/bin/addon-host" and
    process.args like "/opt/sentinelone/addons/executables/SentinelAppVulnerability/*"
  ) or
  (
    process.executable == "memfd:spawn_worker_trampoline" and
    process.parent.executable == "/usr/local/bin/php"
  ) or
  (
    process.executable like "/tmp/agy-nsjail-exe-*" and
    process.parent.executable like "/home/*/resources/app/extensions/antigravity/bin/language_server_linux_x64"
  ) or
  (
    process.working_directory like "/var/lib/docker/overlay2/*/merged" and
    process.command_line == "/proc/self/exe init"
  ) or
  (
    process.executable == "memfd:spawn_worker_trampoline" and
    process.args == "datadog-ipc-helper"
  ) or
  (
    process.parent.executable == "/usr/bin/docker-runc" and
    process.command_line == "docker-runc init"
  ) or
  process.parent.executable like "*/.codex/tmp/arg0/*/codex-linux-sandbox"
)
'''

min_endpoint_version = "9.1.4"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0

[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1106"
name = "Native API"
reference = "https://attack.mitre.org/techniques/T1106/"


[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1055"
name = "Process Injection"
reference = "https://attack.mitre.org/techniques/T1055/"
[[threat.technique.subtechnique]]
id = "T1055.009"
name = "Proc Memory"
reference = "https://attack.mitre.org/techniques/T1055/009/"


[[threat.technique]]
id = "T1620"
name = "Reflective Code Loading"
reference = "https://attack.mitre.org/techniques/T1620/"


[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[internal]
min_endpoint_version = "9.1.4"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action == "exec" and (
  process.executable regex """/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}""" or
  (
    process.args regex """/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}""" and
    process.executable like (
      "memfd:*", "?memfd:*", "/tmp/*", "/var/tmp/*", "/dev/shm/*", "./*", "/run/user/*", "/var/run/user/*",
      "/boot/*", "/sys/*", "/lost+found/*", "/proc/*", "/var/mail/*", "/root/*"
    )
  )
) and
not (
  process.parent.executable like (
    "/home/*/*steam*", "/usr/bin/podman", "./usr/bin/podman", "/dev/.buildkit_qemu_emulator",
    "/opt/omni/bin/drim/linux-amd64/coolie", "/usr/lib/systemd/systemd", "/usr/libexec/nordlayer/nordlayer-setcap",
    "/usr/bin/nordlayer", "/home/*/playground/general/edgeless/tools/contrast", "/bin/nvidia-cdi-hook",
    "/usr/bin/nvidia-ctk", "/sbin/apk", "/tmp/newroot/usr/bin/podman", "/usr/libexec/nordlayer/nordlayer-resolvconf",
    "/usr/sbin/docker-runc", "/usr/bin/runc", "/opt/teleport/system/bin/teleport", "/usr/local/bin/teleport",
    "/opt/sophos-spl/plugins/runtimedetections/bin/runtimedetections*", "/opt/fireeye/bin/rte-sensor", "/usr/local/sbin/thor-cloud-*",
    "/tmp/newroot/run/media/mm1/RIG_Drive_2/SteamLibrary/steamapps/common/SteamLinuxRuntime_4/pressure-vessel/bin/pressure-vessel-wrap",
    "/tmp/newroot/bin/sh", "/opt/sophos-spl/base/bin/launcher", "/usr/bin/containerd-shim-runc-v2", "/opt/sophos-spl/base/bin/sophos_watchdog.*"
  ) or
  process.executable like (
    "./home/*/.local/share/claude/versions/*", "/tmp/newroot/usr/bin/ls", "/tmp/newroot/var/lib/docker/rootfs/overlayfs/*/usr/bin/chown",
    "/tmp/newroot/*"
  ) or
  process.command_line like (
    "runc init", "/usr/local/bin/runc init", "*/home/*/.claude/shell-snapshots/snapshot*",
    "/proc/self/fd/? -config /etc/nordlayer/config.hcl", "storage-untar / /proc/self/fd/*",
    "/proc/self/exe init"
  ) or
  process.parent.args == "/usr/local/bin/teleport" or
  process.parent.command_line like (
    "/opt/teleport/system/bin/teleport exec", "/opt/teleport/default/versions/*/bin/teleport exec"
  ) or
  (
    process.parent.command_line == "/usr/local/bin/teleport exec" and
    process.command_line == "/memfd:teleport-sessionhelper checkhomedir"
  ) or
  (
    process.command_line like "/usr/lib/podman/netavark --config /run/containers/networks --rootless=false --aardvark-binary=/usr/lib/podman/aardvark-dns *" and
    process.args == "/usr/lib/podman/netavark"
  ) or
  (
    process.args == "lxc-attach" and
    process.args == "-n"
  ) or
  (
    process.args == "bwrap" and
    process.args == "--new-session" and
    process.args == "--die-with-parent"
  ) or
  (
    process.parent.executable in ("/bin/php", "/usr/bin/php") and
    process.args == "datadog-ipc-helper"
  ) or
  process.args like ("/usr/lib/systemd/systemd-executor", "/nix/store/*/lib/systemd/systemd-executor") or
  (
    process.executable like (
      "/tmp/newroot/proc/self/exe", "/tmp/newroot/home/*/.local/share/containers/storage/overlay/*/merged/proc/self/exe",
      "./usr/bin/podman"
    ) and
    process.args == "storage-untar"
  ) or
  (
    process.parent.executable == "/usr/libexec/docker/docker-runc-current" and
    process.command_line == "/proc/self/exe init"
  ) or
  (
    process.parent.executable == "/opt/sentinelone/bin/addon-host" and
    process.args like "/opt/sentinelone/addons/executables/SentinelAppVulnerability/*"
  ) or
  (
    process.executable == "memfd:spawn_worker_trampoline" and
    process.parent.executable == "/usr/local/bin/php"
  ) or
  (
    process.executable like "/tmp/agy-nsjail-exe-*" and
    process.parent.executable like "/home/*/resources/app/extensions/antigravity/bin/language_server_linux_x64"
  ) or
  (
    process.working_directory like "/var/lib/docker/overlay2/*/merged" and
    process.command_line == "/proc/self/exe init"
  ) or
  (
    process.executable == "memfd:spawn_worker_trampoline" and
    process.args == "datadog-ipc-helper"
  ) or
  (
    process.parent.executable == "/usr/bin/docker-runc" and
    process.command_line == "docker-runc init"
  ) or
  process.parent.executable like "*/.codex/tmp/arg0/*/codex-linux-sandbox"
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec
field:"EventType" kind:eq value:"exec"
event.typeeq
  • start
field:"event.type" kind:eq value:"start"
process.argsregex_match
  • /proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}
field:"process.args" kind:regex_match value:"/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}"
process.executableregex_match
  • /proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}
field:"Image" kind:regex_match value:"/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}"
process.executablewildcard
  • ./*
  • /boot/*
  • /dev/shm/*
  • /lost+found/*
  • /proc/*
  • /root/*
  • /run/user/*
  • /sys/*
  • /tmp/*
  • /var/mail/*
  • /var/run/user/*
  • /var/tmp/*
  • ?memfd:*
  • memfd:*
field:"Image" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argseq--die-with-parentexcludes:process.args field:"process.args" value:"--die-with-parent"
process.argseq--new-sessionexcludes:process.args field:"process.args" value:"--new-session"
process.argseqbwrapexcludes:process.args field:"process.args" value:"bwrap"
process.argseq-nexcludes:process.args field:"process.args" value:"-n"
process.argseqlxc-attachexcludes:process.args field:"process.args" value:"lxc-attach"
process.argseq/usr/lib/podman/netavarkexcludes:process.args field:"process.args" value:"/usr/lib/podman/netavark"
process.command_linestarts_with/usr/lib/podman/netavark --config /run/containers/networks --rootless=false --aardvark-binary=/usr/lib/podman/aardvark-dns excludes:process.command_line field:"process.command_line" value:"/usr/lib/podman/netavark --config /run/containers/networks --rootless=false --aardvark-binary=/usr/lib/podman/aardvark-dns "
process.argseqdatadog-ipc-helperexcludes:process.args field:"process.args" value:"datadog-ipc-helper"
process.executableeqmemfd:spawn_worker_trampolineexcludes:process.executable field:"process.executable" value:"memfd:spawn_worker_trampoline"
process.parent.executablein/bin/php, /usr/bin/phpexcludes:process.parent.executable field:"process.parent.executable" value:"/bin/php" field:"process.parent.executable" value:"/usr/bin/php"
process.argseqstorage-untarexcludes:process.args field:"process.args" value:"storage-untar"
process.executablewildcard/tmp/newroot/proc/self/exe, /tmp/newroot/home/*/.local/share/containers/storage/overlay/*/merged/proc/self/exe, ./usr/bin/podmanexcludes:process.executable field:"process.executable" value:"/tmp/newroot/proc/self/exe" field:"process.executable" value:"/tmp/newroot/home/*/.local/share/containers/storage/overlay/*/merged/proc/self/exe" field:"process.executable" value:"./usr/bin/podman"
process.argsstarts_with/opt/sentinelone/addons/executables/SentinelAppVulnerability/excludes:process.args field:"process.args" value:"/opt/sentinelone/addons/executables/SentinelAppVulnerability/"
process.parent.executableeq/opt/sentinelone/bin/addon-hostexcludes:process.parent.executable field:"process.parent.executable" value:"/opt/sentinelone/bin/addon-host"
process.command_lineeq/memfd:teleport-sessionhelper checkhomedirexcludes:process.command_line field:"process.command_line" value:"/memfd:teleport-sessionhelper checkhomedir"
process.parent.command_lineeq/usr/local/bin/teleport execexcludes:process.parent.command_line field:"process.parent.command_line" value:"/usr/local/bin/teleport exec"
process.command_lineeq/proc/self/exe initexcludes:process.command_line field:"process.command_line" value:"/proc/self/exe init"
process.parent.executableeq/usr/libexec/docker/docker-runc-currentexcludes:process.parent.executable field:"process.parent.executable" value:"/usr/libexec/docker/docker-runc-current"
process.working_directorywildcard/var/lib/docker/overlay2/*/mergedexcludes:process.working_directory field:"process.working_directory" value:"/var/lib/docker/overlay2/*/merged"
process.command_lineeqdocker-runc initexcludes:process.command_line field:"process.command_line" value:"docker-runc init"
process.parent.executableeq/usr/bin/docker-runcexcludes:process.parent.executable field:"process.parent.executable" value:"/usr/bin/docker-runc"
process.parent.executableeq/usr/local/bin/phpexcludes:process.parent.executable field:"process.parent.executable" value:"/usr/local/bin/php"
process.executablestarts_with/tmp/agy-nsjail-exe-excludes:process.executable field:"process.executable" value:"/tmp/agy-nsjail-exe-"
process.parent.executablewildcard/home/*/resources/app/extensions/antigravity/bin/language_server_linux_x64excludes:process.parent.executable field:"process.parent.executable" value:"/home/*/resources/app/extensions/antigravity/bin/language_server_linux_x64"
process.argswildcard/usr/lib/systemd/systemd-executor, /nix/store/*/lib/systemd/systemd-executorexcludes:process.args field:"process.args" value:"/usr/lib/systemd/systemd-executor" field:"process.args" value:"/nix/store/*/lib/systemd/systemd-executor"
process.command_linewildcardrunc init, /usr/local/bin/runc init, */home/*/.claude/shell-snapshots/snapshot*, /proc/self/fd/? -config /etc/nordlayer/config.hcl, storage-untar / /proc/self/fd/*, /proc/self/exe initexcludes:process.command_line
process.executablewildcard./home/*/.local/share/claude/versions/*, /tmp/newroot/usr/bin/ls, /tmp/newroot/var/lib/docker/rootfs/overlayfs/*/usr/bin/chown, /tmp/newroot/*excludes:process.executable
process.parent.argseq/usr/local/bin/teleportexcludes:process.parent.args field:"process.parent.args" value:"/usr/local/bin/teleport"
process.parent.command_linewildcard/opt/teleport/system/bin/teleport exec, /opt/teleport/default/versions/*/bin/teleport execexcludes:process.parent.command_line field:"process.parent.command_line" value:"/opt/teleport/system/bin/teleport exec" field:"process.parent.command_line" value:"/opt/teleport/default/versions/*/bin/teleport exec"
process.parent.executablewildcard*/.codex/tmp/arg0/*/codex-linux-sandboxexcludes:process.parent.executable field:"process.parent.executable" value:"*/.codex/tmp/arg0/*/codex-linux-sandbox"
process.parent.executablewildcard/home/*/*steam*, /usr/bin/podman, ./usr/bin/podman, /dev/.buildkit_qemu_emulator, /opt/omni/bin/drim/linux-amd64/coolie, /usr/lib/systemd/systemd, /usr/libexec/nordlayer/nordlayer-setcap, /usr/bin/nordlayer, /home/*/playground/general/edgeless/tools/contrast, /bin/nvidia-cdi-hook, /usr/bin/nvidia-ctk, /sbin/apk, /tmp/newroot/usr/bin/podman, /usr/libexec/nordlayer/nordlayer-resolvconf, /usr/sbin/docker-runc, /usr/bin/runc, /opt/teleport/system/bin/teleport, /usr/local/bin/teleport, /opt/sophos-spl/plugins/runtimedetections/bin/runtimedetections*, /opt/fireeye/bin/rte-sensor, /usr/local/sbin/thor-cloud-*, /tmp/newroot/run/media/mm1/RIG_Drive_2/SteamLibrary/steamapps/common/SteamLinuxRuntime_4/pressure-vessel/bin/pressure-vessel-wrap, /tmp/newroot/bin/sh, /opt/sophos-spl/base/bin/launcher, /usr/bin/containerd-shim-runc-v2, /opt/sophos-spl/base/bin/sophos_watchdog.*excludes:process.parent.executable

GCP IAM Service Account Impersonation Role Granted

#
Status
production
Severity
medium
Time window
9m
Group by
user.id
Author
Elastic, Aryu Zaw
Source
github.com/elastic/detection-rules

Identifies when a service account impersonation role is granted on a Google Cloud Platform (GCP) service account via a SetIamPolicy operation. Roles such as "roles/iam.serviceAccountTokenCreator", "roles/iam.serviceAccountUser", and "roles/iam.serviceAccountOpenIdTokenCreator" allow a principal to mint access or identity tokens for the target service account, or to act as it when deploying resources. Adversaries who have obtained sufficient privileges may grant themselves or an attacker-controlled principal one of these roles to impersonate a higher-privileged service account, escalating privileges and establishing durable, key-less persistence that survives credential rotation. This is a New Terms rule that alerts when the granting principal has not been observed performing this action in the last weeks.

Known False Positives

  • Infrastructure-as-code tooling (e.g. Terraform), CI/CD pipelines, and platform automation routinely grant serviceAccountUser or serviceAccountTokenCreator when wiring up workloads, deployments, or impersonation chains. Identify the expected automation principals and target service accounts and add exceptions for them.
  • Administrators may grant impersonation roles when onboarding new applications or delegating access. Verify that the grant aligns with a known change and that both the granting principal and the added member are expected.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2026/05/30"
integration = ["gcp"]
maturity = "production"
updated_date = "2026/05/30"

[rule]
author = ["Elastic", "Aryu Zaw"]
description = """
Identifies when a service account impersonation role is granted on a Google Cloud Platform (GCP) service account via a
SetIamPolicy operation. Roles such as "roles/iam.serviceAccountTokenCreator", "roles/iam.serviceAccountUser", and
"roles/iam.serviceAccountOpenIdTokenCreator" allow a principal to mint access or identity tokens for the target service
account, or to act as it when deploying resources. Adversaries who have obtained sufficient privileges may grant
themselves or an attacker-controlled principal one of these roles to impersonate a higher-privileged service account,
escalating privileges and establishing durable, key-less persistence that survives credential rotation. This is a New
Terms rule that alerts when the granting principal has not been observed performing this action in the last weeks.
"""
false_positives = [
    """
    Infrastructure-as-code tooling (e.g. Terraform), CI/CD pipelines, and platform automation routinely grant
    serviceAccountUser or serviceAccountTokenCreator when wiring up workloads, deployments, or impersonation chains.
    Identify the expected automation principals and target service accounts and add exceptions for them.
    """,
    """
    Administrators may grant impersonation roles when onboarding new applications or delegating access. Verify that the
    grant aligns with a known change and that both the granting principal and the added member are expected.
    """,
]
from = "now-9m"
index = ["logs-gcp.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "GCP IAM Service Account Impersonation Role Granted"
note = """## Triage and analysis

### Investigating GCP IAM Service Account Impersonation Role Granted

Granting an impersonation role on a service account lets the bound member obtain that service account's credentials
without creating a long-lived key. `roles/iam.serviceAccountTokenCreator` and `roles/iam.serviceAccountOpenIdTokenCreator`
allow minting OAuth2 access tokens and OpenID Connect identity tokens, while `roles/iam.serviceAccountUser` allows the
member to attach (actAs) the service account to new resources. Adversaries abuse these grants to pivot to a
higher-privileged identity, escalate privileges, and persist in a way that is unaffected by key rotation or password
resets.

### Possible investigation steps

- Identify the granting principal via `user.email` and `user.id` and confirm whether that identity is expected to modify
IAM policy on service accounts.
- Review the target service account in `gcp.audit.resource_name` and determine the permissions it holds. Impersonating a
service account with broad project or organization roles represents a significant escalation.
- Inspect the granted binding in `gcp.audit.request` / `gcp.audit.response` to identify the member that was added
(`user:`, `serviceAccount:`, `group:`, or an external domain). External or newly created members are higher risk.
- Examine `gcp.audit.request_metadata.caller_ip` and `gcp.audit.request_metadata.caller_supplied_user_agent` to assess
whether the change originated from an expected location or tool.
- Correlate with recent activity by the granting principal, such as service account key creation, custom role creation,
or `GenerateAccessToken` / `GenerateIdToken` calls that use the newly granted impersonation rights.

### False positive analysis

- Terraform, Deployment Manager, and CI/CD service accounts commonly grant serviceAccountUser and
serviceAccountTokenCreator as part of normal provisioning. Baseline these principals and exclude them with exceptions.
- One-time grants during application onboarding or delegation may be legitimate. Validate against change management
before escalating.

### Response and remediation

- If the grant is unauthorized, remove the impersonation binding from the service account's IAM policy.
- Revoke any access or identity tokens issued for the impacted service account and review its recent activity for abuse.
- Investigate the granting principal for compromise, rotate its credentials if necessary, and review what other IAM
changes it has made.
- Restrict who can set IAM policy on service accounts and require justification or approval for impersonation grants."""
references = [
    "https://securitylabs.datadoghq.com/cloud-security-atlas/attacks/backdooring-service-account/",
    "https://stratus-red-team.cloud/attack-techniques/GCP/gcp.persistence.backdoor-service-account-policy/",
    "https://cloud.google.com/iam/docs/service-account-impersonation",
    "https://cloud.google.com/iam/docs/audit-logging/examples-service-accounts",
]
risk_score = 47
rule_id = "197d2757-eea1-46f9-9ebd-84646d2b45fa"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Data Source: GCP",
    "Data Source: GCP Audit Logs",
    "Data Source: Google Cloud Platform",
    "Use Case: Identity and Access Audit",
    "Use Case: Threat Detection",
    "Tactic: Persistence",
    "Tactic: Privilege Escalation",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"

query = '''
data_stream.dataset: "gcp.audit"
  and event.action: google.iam.admin.v*.SetIAMPolicy
  and event.outcome: "success"
  and gcp.audit.service_data.policy_delta.binding_deltas:{
    action: "ADD" and
    role: (
      "roles/iam.serviceAccountTokenCreator" or
      "roles/iam.serviceAccountUser" or
      "roles/iam.serviceAccountOpenIdTokenCreator"
    )
  }
'''


[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.003"
name = "Additional Cloud Roles"
reference = "https://attack.mitre.org/techniques/T1098/003/"

[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.003"
name = "Additional Cloud Roles"
reference = "https://attack.mitre.org/techniques/T1098/003/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

[rule.new_terms]
field = "new_terms_fields"
value = ["user.id"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-10d"

Stages and Predicates

Stage 1: new_terms

data_stream.dataset: "gcp.audit"
  and event.action: google.iam.admin.v*.SetIAMPolicy
  and event.outcome: "success"
  and gcp.audit.service_data.policy_delta.binding_deltas:{
    action: "ADD" and
    role: (
      "roles/iam.serviceAccountTokenCreator" or
      "roles/iam.serviceAccountUser" or
      "roles/iam.serviceAccountOpenIdTokenCreator"
    )
  }

Indicators

These rows show field, operator, and value matches.

GKE CoreDNS or Kube-DNS Configuration Modified

#
Status
production
Severity
high
Time window
6m
Author
Elastic
Source
github.com/elastic/detection-rules

Detects modifications to the CoreDNS or kube-dns ConfigMap in the kube-system namespace on GKE. These ConfigMaps control cluster DNS resolution for all pods. An attacker who modifies the CoreDNS Corefile can redirect internal service DNS names to attacker-controlled IP addresses, enabling man-in-the-middle attacks against the Kubernetes API server, database services, and other internal endpoints. Pods that resolve service names via cluster DNS will transparently connect to the attacker instead of the legitimate service, allowing interception of service account tokens, database credentials, and API traffic. DNS poisoning at the cluster level is particularly dangerous because it affects every pod in every namespace simultaneously and does not require any modification to the victim workloads. CoreDNS configuration changes are rare in normal operations and any unexpected modification should be investigated immediately.

Known False Positives

  • Cluster administrators may legitimately update CoreDNS configuration for forwarding, stub domains, or cluster DNS troubleshooting. Baseline approved operators and automation identities; tune exclusions for known change pipelines.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2026/07/06"
integration = ["gcp"]
maturity = "production"
updated_date = "2026/07/06"

[rule]
author = ["Elastic"]
description = """
Detects modifications to the CoreDNS or kube-dns ConfigMap in the kube-system namespace on GKE. These ConfigMaps control
cluster DNS resolution for all pods. An attacker who modifies the CoreDNS Corefile can redirect internal service DNS
names to attacker-controlled IP addresses, enabling man-in-the-middle attacks against the Kubernetes API server,
database services, and other internal endpoints. Pods that resolve service names via cluster DNS will transparently
connect to the attacker instead of the legitimate service, allowing interception of service account tokens, database
credentials, and API traffic. DNS poisoning at the cluster level is particularly dangerous because it affects every pod
in every namespace simultaneously and does not require any modification to the victim workloads. CoreDNS configuration
changes are rare in normal operations and any unexpected modification should be investigated immediately.
"""
false_positives = [
    """
    Cluster administrators may legitimately update CoreDNS configuration for forwarding, stub domains, or cluster DNS
    troubleshooting. Baseline approved operators and automation identities; tune exclusions for known change pipelines.
    """,
]
from = "now-6m"
index = ["logs-gcp.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "GKE CoreDNS or Kube-DNS Configuration Modified"
note = """## Triage and analysis

### Investigating GKE CoreDNS or Kube-DNS Configuration Modified

Identify who performed the change (user.email, groups), from where (source.ip), and which ConfigMap was modified.
If request/response capture is available, review the changed Corefile content for upstream redirection, wildcard
rewrites, or unexpected forward/proxy targets.

### Possible investigation steps

- Confirm the actor is authorized to modify kube-system DNS configuration and whether the change aligns with a change window.
- Review the ConfigMap diff for added rewrite rules, hosts entries, or forwarding to external or unexpected internal IPs.
- Correlate with follow-on suspicious activity such as secret reads, token minting, or RBAC modifications.
- Check for cluster-wide symptoms: service connection failures, TLS errors, or sudden endpoint changes across namespaces.

### Response and remediation

- Revert the ConfigMap to a known-good version and restart DNS pods if required by your deployment.
- Restrict RBAC permissions that allow update/patch/delete on kube-system DNS ConfigMaps and investigate the source identity.

## Setup

The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule."""
references = [
    "https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/",
    "https://coredns.io/plugins/rewrite/",
]
risk_score = 73
rule_id = "80528e81-949f-4d38-b0c7-aef4b160212e"
severity = "high"
tags = [
    "Domain: Cloud",
    "Domain: Kubernetes",
    "Data Source: GCP",
    "Data Source: Google Cloud Platform",
    "Use Case: Threat Detection",
    "Tactic: Impact",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset:gcp.audit and service.name:"k8s.io" and event.outcome:success and
event.action:("io.k8s.core.v1.configmaps.update" or "io.k8s.core.v1.configmaps.patch" or "io.k8s.core.v1.configmaps.delete") and
orchestrator.resource.name:("coredns" or "kube-dns" or "coredns-custom") and orchestrator.namespace:"kube-system" and
gcp.audit.labels.authorization.k8s.io/decision:"allow" and
not user.email:(
  "system:serviceaccount:kube-system:coredns" or
  "system:serviceaccount:kube-system:kube-dns" or
  system\:node* or system\:serviceaccount\:kube-system*
)
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1565"
name = "Data Manipulation"
reference = "https://attack.mitre.org/techniques/T1565/"
[[rule.threat.technique.subtechnique]]
id = "T1565.001"
name = "Stored Data Manipulation"
reference = "https://attack.mitre.org/techniques/T1565/001/"



[rule.threat.tactic]
id = "TA0040"
name = "Impact"
reference = "https://attack.mitre.org/tactics/TA0040/"

Stages and Predicates

Stage 1: query

data_stream.dataset:gcp.audit and service.name:"k8s.io" and event.outcome:success and
event.action:("io.k8s.core.v1.configmaps.update" or "io.k8s.core.v1.configmaps.patch" or "io.k8s.core.v1.configmaps.delete") and
orchestrator.resource.name:("coredns" or "kube-dns" or "coredns-custom") and orchestrator.namespace:"kube-system" and
gcp.audit.labels.authorization.k8s.io/decision:"allow" and
not user.email:(
  "system:serviceaccount:kube-system:coredns" or
  "system:serviceaccount:kube-system:kube-dns" or
  system\:node* or system\:serviceaccount\:kube-system*
)

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
user.emaileqsystem:serviceaccount:kube-system:corednsexcludes:user.email field:"user.email" value:"system:serviceaccount:kube-system:coredns"
user.emaileqsystem:serviceaccount:kube-system:kube-dnsexcludes:user.email field:"user.email" value:"system:serviceaccount:kube-system:kube-dns"
user.emailstarts_withsystem:nodeexcludes:user.email field:"user.email" value:"system:node"
user.emailstarts_withsystem:serviceaccount:kube-systemexcludes:user.email field:"user.email" value:"system:serviceaccount:kube-system"

Kirbi File Creation

#
Status
production
Severity
high
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies the creation of .kirbi files, a suspicious Kerberos ticket artifact often produced by ticket export or dumping tools such as Rubeus or Mimikatz. This can indicate preparation for Kerberos ticket theft or later abuse, including Pass-The-Ticket (PTT), and should be validated with writer process and follow-on activity.

MITRE ATT&CK Coverage

Telemetry Coverage

ProviderRecord / event type
SysmonEvent ID 11: FileCreate

Rule Body

[metadata]
creation_date = "2023/08/23"
integration = ["endpoint", "windows", "sentinel_one_cloud_funnel", "m365_defender", "crowdstrike"]
maturity = "production"
updated_date = "2026/04/24"

[rule]
author = ["Elastic"]
description = """
Identifies the creation of .kirbi files, a suspicious Kerberos ticket artifact often produced by ticket export or
dumping tools such as Rubeus or Mimikatz. This can indicate preparation for Kerberos ticket theft or later abuse,
including Pass-The-Ticket (PTT), and should be validated with writer process and follow-on activity.
"""
from = "now-9m"
index = [
    "logs-endpoint.events.file-*",
    "logs-windows.sysmon_operational-*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-m365_defender.event-*",
    "winlogbeat-*",
    "endgame-*",
    "logs-crowdstrike.fdr*",
]
language = "eql"
license = "Elastic License v2"
name = "Kirbi File Creation"
references = [
    "https://attack.mitre.org/techniques/T1558/",
]
risk_score = 73
rule_id = "b8f8da2d-a9dc-48c0-90e4-955c0aa1259a"
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Data Source: SentinelOne",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Elastic Endgame",
    "Data Source: Crowdstrike",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
file where host.os.type == "windows" and event.type == "creation" and file.extension : "kirbi"
'''

note = """## Triage and analysis

### Investigating Kirbi File Creation
#### Possible investigation steps

- What does the alert-local ticket artifact show?
  - Focus: `file.path`, `file.name`, `file.extension`, `file.size`, and `@timestamp`, plus `host.id` and `user.id` for scope.
  - Implication: escalate when a ".kirbi" file lands in temp, public, user-profile, archive, or tool-staging paths, when `file.name` encodes a user, service, or realm, or when size and naming fit ticket export; lower suspicion only when the artifact path, name, host, and user match one known evidence-collection pattern before any workflow corroboration.

- Which process wrote the ticket file?
  - Focus: writer identity and launch context: `process.executable`, `process.pe.original_file_name`, `process.code_signature.subject_name`, and `process.parent.executable`; use `process.entity_id` only to scope this process instance.
  - Hint: if only `process.pid` is present, recover the writer with `host.id`, `process.pid`, and a tight window around `@timestamp`.
  - Implication: escalate when unsigned, renamed, script- or shell-launched, or user-writable tooling writes the file; lower suspicion only when identity, signer, parent, and path match a recognized testing or IR workflow. Trusted identity alone does not clear ticket export.

- Does the command line or lineage show ticket export or ticket-use intent?
  - Focus: `process.command_line`, `process.parent.command_line`, and surrounding process events for the same `host.id` and `process.entity_id`, or `process.pid` when entity IDs are absent. $investigate_3
  - Implication: escalate when arguments or lineage show dump, export, outfile, archive staging, Mimikatz/Rubeus-style verbs, "ptt", "kerberos::ptt", scripting, or remote-admin chains; lower suspicion only when command line and lineage fit the same confirmed test or troubleshooting workflow.

- Did the same writer stage more tickets or hide them?
  - Focus: file events for `host.id` and `process.entity_id`: `file.path` and `file.name` for additional ".kirbi" writes, renames, archives, or extension changes. $investigate_0
  - Implication: escalate when the writer creates several ticket files, renames them into archives, removes the extension, or stores them beside collection tools; one unchanged ticket in a controlled evidence directory lowers scope but does not close by itself.

- How sensitive is the user and host context?
  - Focus: `host.name`, `user.id`, `user.name`, and `user.domain`.
  - Implication: escalate faster when a domain, service, or privileged identity writes the ticket, or when the same host/user also shows staging or follow-on use; lower severity only when a constrained lab identity and lab host match the telemetry and corroborating case evidence.

- Is there follow-on ticket import, remote access, or lateral movement after export?
  - Why: ".kirbi" creation proves ticket material was written; risk increases sharply if the same host or user tries to use it.
  - Focus: start with direct child process events from the writer process using `host.id` with `process.parent.entity_id`, or `process.parent.pid` when entity IDs are absent. $investigate_4 Expand manually to broader later process activity for the same `host.id` or `user.id` when needed, especially `process.command_line`.
  - Implication: escalate when later commands show "ptt", "kerberos::ptt", "klist", remote execution, archive movement, or access to new systems after export; matching authentication or connection telemetry can corroborate impact, but missing telemetry is unresolved, not benign.

- If local evidence stays suspicious or unresolved, do related alerts broaden the case?
  - Focus: related credential-access, lateral-movement, archive, and suspicious-authentication alerts for `user.id` in the last 48 hours. $investigate_1
  - Hint: use the same alert families for `host.id` when host scope, not user scope, decides containment. $investigate_2
  - Implication: broaden containment when related alerts align with ticket export, dumping, archive staging, remote access, or privilege escalation; keep response local when related alerts are absent or unrelated, but do not use absence alone to close the ".kirbi" alert.

- Based on the evidence gathered, what disposition is supported?
  - Focus: artifact path and naming, writer identity and lineage, command intent, staging, user/host sensitivity, and follow-on activity.
  - Implication: escalate when artifact, writer, command, staging, sensitive-context, or follow-on evidence points to unauthorized ticket export or use; close only when the same evidence categories tightly bind one recognized red-team, IR, or Kerberos-troubleshooting workflow and no contradictory evidence remains; preserve and escalate when evidence is mixed or incomplete.

### False positive analysis

- Red-team, purple-team, IR, and Kerberos troubleshooting workflows can legitimately export tickets, but close only after telemetry binds the exact workflow. Confirm that writer identity, parent context, command line, `user.id`, `host.id`, and output `file.path` all align, and that no ticket-import or remote-access follow-on appears; use case, exercise, or troubleshooting records only as corroboration. Use prior alerts only to validate exception stability after the current evidence aligns; do not close the current alert on recurrence alone. Treat production-domain-controller, admin-workstation, or service-account activity as suspicious unless it is explicitly in scope for the same case or exercise.
- Build exceptions from the minimum confirmed workflow pattern: `process.executable`, `process.pe.original_file_name`, `process.code_signature.subject_name`, `process.parent.executable`, `process.command_line`, `user.id`, `host.id`, and output path pattern. Avoid exceptions on ".kirbi" extension, host, or user alone.

### Response and remediation

- If confirmed benign, reverse temporary containment and document the writer identity, parent context, command line, user, host, and output path that proved the recognized workflow. Create an exception only after the same pattern recurs across prior alerts.
- If suspicious but unconfirmed, preserve the ".kirbi" file path, any archive path, the writing `process.entity_id`, command line, parent chain, user/host context, same-process file events, and follow-on process or authentication evidence before containment. Apply reversible containment first, such as suspending the exporting process or temporarily restricting administrative egress if the host role can tolerate it. Escalate to host isolation or account containment only when follow-on ticket use, privileged-host involvement, or repeated exports show progression.
- If confirmed malicious, preserve the process, file, parent-chain, identity, staging, and follow-on evidence set before containment or cleanup. Then isolate or otherwise contain the affected host when artifact, writer, command, staging, or follow-on evidence establishes unauthorized ticket export or use, weighing critical host role before isolation. Contain impacted accounts or service principals when the user context or follow-on activity shows their tickets may be usable. If direct endpoint response is unavailable, hand off the preserved evidence to the team that can act.
- Record process and file identifiers before deleting ticket files, terminating tools, or removing scripts. Revoke or expire exposed Kerberos sessions for affected identities and force reauthentication where appropriate. If evidence shows privileged-ticket theft or Pass-the-Ticket from administrative systems, reset or rotate affected credentials by privilege tier; reserve KRBTGT rotation for confirmed broader Kerberos compromise under the organization's runbook.
- Eradicate only the dumping tools, scripts, staged ".kirbi" files, archives, and persistence mechanisms found during the investigation, then remediate the initial access or privilege path that allowed ticket export.
- After containment, hunt for the same output paths, writer lineage, ticket-import commands, and staged archives across other systems.
"""

setup = """## Setup

This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

### Additional data sources

This rule also supports the following third-party data sources. For setup instructions, refer to the links below:

- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Event ID 11 - File Create](https://ela.st/sysmon-event-11-setup)
"""

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "host.id",
    "user.id",
    "process.entity_id",
    "process.pid",
    "process.executable",
    "process.command_line",
    "process.pe.original_file_name",
    "process.parent.executable",
    "process.parent.command_line",
    "process.code_signature.subject_name",
    "process.code_signature.trusted",
    "file.path",
    "file.name",
    "file.size",
]

[[transform.investigate]]
label = "File events for the same process"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Alerts associated with the user"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[transform.investigate]]
label = "Alerts associated with the host"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[transform.investigate]]
label = "Process events for the writer process"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ],
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Child process events from the writer process"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ],
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.parent.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1003"
name = "OS Credential Dumping"
reference = "https://attack.mitre.org/techniques/T1003/"

[[rule.threat.technique]]
id = "T1558"
name = "Steal or Forge Kerberos Tickets"
reference = "https://attack.mitre.org/techniques/T1558/"

[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"

Stages and Predicates

Stage 1: file

file where host.os.type == "windows" and event.type == "creation" and file.extension : "kirbi"

Indicators

These rows show field, operator, and value matches.

Microsoft Office Process Setting Persistence via Startup

#
Source
github.com/elastic/protections-artifacts

Identifies files written to or modified in the startup folder by a Microsoft Office process. Adversaries may use this technique to maintain persistence and avoid spawning suspicious child processes.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies files written to or modified in the startup folder by a Microsoft Office process. Adversaries may use this
technique to maintain persistence and avoid spawning suspicious child processes.
"""
id = "2b8ea430-897d-486c-85a8-add9d7072ff3"
license = "Elastic License v2"
name = "Microsoft Office Process Setting Persistence via Startup"
os_list = ["windows"]
version = "1.0.36"

query = '''
file where event.action != "deletion" and
  file.path : ("?:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
               "?:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*") and
  process.name : ("EQNEDT32.EXE", "WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE", "MSPUB.EXE") and
  not file.extension : ("docx", "xls", "doc", "xlsx", "tmp", "xlsm") and file.name : "*.*"
'''

min_endpoint_version = "7.15.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0

[[optional_actions]]
action = "rollback"
field = "process.entity_id"
state = 0

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[[threat.technique.subtechnique]]
id = "T1566.001"
name = "Spearphishing Attachment"
reference = "https://attack.mitre.org/techniques/T1566/001/"



[threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1547"
name = "Boot or Logon Autostart Execution"
reference = "https://attack.mitre.org/techniques/T1547/"
[[threat.technique.subtechnique]]
id = "T1547.001"
name = "Registry Run Keys / Startup Folder"
reference = "https://attack.mitre.org/techniques/T1547/001/"



[threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: file

file where event.action != "deletion" and
  file.path : ("?:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
               "?:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*") and
  process.name : ("EQNEDT32.EXE", "WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE", "MSPUB.EXE") and
  not file.extension : ("docx", "xls", "doc", "xlsx", "tmp", "xlsm") and file.name : "*.*"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actionne
  • deletion corpus 90 (elastic 90)
field:"EventType" kind:ne value:"deletion"
file.namewildcard
  • *.*
field:"file.name" kind:wildcard value:"*.*"
file.pathwildcard
  • ?:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\* corpus 12 (elastic 12)
  • ?:\Users\*\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\* corpus 13 (elastic 13)
field:"TargetFilename" kind:wildcard
process.namewildcard
  • EQNEDT32.EXE corpus 8 (elastic 8)
  • EXCEL.EXE corpus 34 (elastic 34)
  • MSPUB.EXE corpus 15 (elastic 15)
  • POWERPNT.EXE corpus 31 (elastic 31)
  • WINWORD.EXE corpus 35 (elastic 35)
field:"process_basename" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
file.extensioneqdocx, xls, doc, xlsx, tmp, xlsmexcludes:file.extension

Mount Launched Inside a Container

#
Status
production
Severity
medium
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

This rule detects the use of the mount utility from inside a container. The mount command is used to make a device or file system accessible to the system, and then to connect its root directory to a specified mount point on the local file system. When launched inside a privileged container--a container deployed with all the capabilities of the host machine-- an attacker can access sensitive host level files which could be used for further privilege escalation and container escapes to the host machine. Any usage of mount inside a running privileged container should be further investigated.

MITRE ATT&CK Coverage

TacticTechniques
Privilege Escalation

Rule Body

[metadata]
creation_date = "2025/03/12"
integration = ["endpoint"]
maturity = "production"
updated_date = "2025/12/23"

[rule]
author = ["Elastic"]
description = """
This rule detects the use of the mount utility from inside a container. The mount command is used to make a
device or file system accessible to the system, and then to connect its root directory to a specified mount point on the
local file system. When launched inside a privileged container--a container deployed with all the capabilities of the
host machine-- an attacker can access sensitive host level files which could be used for further privilege escalation
and container escapes to the host machine. Any usage of mount inside a running privileged container should be further
investigated.
"""
from = "now-9m"
index = ["logs-endpoint.events.process*"]
language = "eql"
license = "Elastic License v2"
name = "Mount Launched Inside a Container"
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Mount Launched Inside a Container

In containerized environments, the `mount` utility is crucial for attaching file systems to the system's directory tree. When executed within a privileged container, which has extensive host capabilities, it can be exploited by adversaries to access sensitive host files, potentially leading to privilege escalation or container escapes. The detection rule identifies such misuse by monitoring the execution of `mount` in containers, flagging potential security threats for further investigation.

### Possible investigation steps

- Review the alert details to confirm that the process name or arguments include "mount" and that the container's security context is marked as privileged.
- Check the container's deployment configuration to verify if it was intentionally set as privileged and assess whether this level of privilege is necessary for its function.
- Investigate the user or process that initiated the mount command within the container to determine if it aligns with expected behavior or if it indicates potential malicious activity.
- Examine the mounted file systems and directories to identify any sensitive host files that may have been accessed or exposed.
- Review logs and historical data for any previous suspicious activities associated with the same container or user to identify patterns or repeated attempts at privilege escalation.

### False positive analysis

- Routine maintenance tasks within privileged containers may trigger the rule. Exclude known maintenance scripts or processes by adding them to an exception list based on their unique identifiers or command patterns.
- Backup operations that require mounting file systems might be flagged. Identify and exclude these operations by specifying the backup process names or arguments in the rule exceptions.
- Development or testing environments often use privileged containers for convenience. If these environments are known and controlled, consider excluding them by container IDs or labels to reduce noise.
- Automated deployment tools that use mount commands in privileged containers can be mistaken for threats. Review and whitelist these tools by their process names or specific arguments to prevent false alerts.
- Certain monitoring or logging solutions may use mount operations for data collection. Verify these solutions and exclude their processes if they are legitimate and necessary for system operations.

### Response and remediation

- Immediately isolate the affected container to prevent further access to sensitive host files. This can be done by stopping the container or disconnecting it from the network.
- Review and revoke any unnecessary privileges from the container's security context to prevent similar incidents. Ensure that containers run with the least privileges necessary.
- Conduct a thorough analysis of the container's file system and logs to identify any unauthorized access or modifications to host files.
- If unauthorized access is confirmed, perform a comprehensive audit of the host system to check for any signs of compromise or privilege escalation attempts.
- Patch and update the container image and host system to address any vulnerabilities that may have been exploited.
- Implement stricter access controls and monitoring for privileged containers, ensuring that only trusted users and processes can execute sensitive commands like `mount`.
- Escalate the incident to the security operations team for further investigation and to assess the need for additional security measures or incident response actions."""
references = [
    "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation#privileged",
]
risk_score = 47
rule_id = "c73cc6ab-b30e-46bf-b5f2-29d9ab4caf7b"
setup = """## Setup

This rule requires data coming in from Elastic Defend.

### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.

#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).

#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.

For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "medium"
tags = [
    "Domain: Container",
    "OS: Linux",
    "Use Case: Threat Detection",
    "Tactic: Privilege Escalation",
    "Data Source: Elastic Defend",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and
process.entry_leader.entry_meta.type == "container" and process.name == "mount" and not (
  process.parent.command_line like "*grep*" or
  process.parent.executable like (
    "/usr/local/bin/dind", "/run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/*/longhorn-instance-manager",
    "/run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/*/longhorn-manager", "/usr/sbin/update-binfmts",
    "/usr/local/bin/engine-manager", "/usr/bin/timeout", "/opt/gitlab/embedded/bin/ruby", "/usr/local/sbin/longhorn-manager",
    "/longhorn-share-manager", "/usr/lib/systemd/systemd", "/lib/systemd/systemd"
  ) or
  process.parent.args in ("/usr/local/bin/instance-manager", "/usr/local/sbin/nsmounter")
)
'''

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1611"
name = "Escape to Host"
reference = "https://attack.mitre.org/techniques/T1611/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

Stages and Predicates

Stage 1: process

process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and
process.entry_leader.entry_meta.type == "container" and process.name == "mount" and not (
  process.parent.command_line like "*grep*" or
  process.parent.executable like (
    "/usr/local/bin/dind", "/run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/*/longhorn-instance-manager",
    "/run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/*/longhorn-manager", "/usr/sbin/update-binfmts",
    "/usr/local/bin/engine-manager", "/usr/bin/timeout", "/opt/gitlab/embedded/bin/ruby", "/usr/local/sbin/longhorn-manager",
    "/longhorn-share-manager", "/usr/lib/systemd/systemd", "/lib/systemd/systemd"
  ) or
  process.parent.args in ("/usr/local/bin/instance-manager", "/usr/local/sbin/nsmounter")
)

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.parent.argsin/usr/local/bin/instance-manager, /usr/local/sbin/nsmounterexcludes:process.parent.args field:"process.parent.args" value:"/usr/local/bin/instance-manager" field:"process.parent.args" value:"/usr/local/sbin/nsmounter"
process.parent.command_linematchgrepexcludes:process.parent.command_line field:"process.parent.command_line" value:"grep"
process.parent.executablewildcard/usr/local/bin/dind, /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/*/longhorn-instance-manager, /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/*/longhorn-manager, /usr/sbin/update-binfmts, /usr/local/bin/engine-manager, /usr/bin/timeout, /opt/gitlab/embedded/bin/ruby, /usr/local/sbin/longhorn-manager, /longhorn-share-manager, /usr/lib/systemd/systemd, /lib/systemd/systemdexcludes:process.parent.executable

Potential Container Escape via Kernel core_pattern Modification

#
Status
production
Severity
medium
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

The Linux kernel invokes the program named in "/proc/sys/kernel/core_pattern" whenever a process core-dumps. When that value begins with a pipe (|), the kernel runs the handler from the host's initial namespace as root, regardless of where the crashing process lived. Because the core-dump up-call is not namespaced, a process inside a container that can write core_pattern can register an attacker-controlled handler and then deliberately crash a process to have it execute on the host as root, resulting in a full container-to-host escape.

MITRE ATT&CK Coverage

TacticTechniques
Privilege Escalation

Rule Body

[metadata]
creation_date = "2026/07/02"
integration = ["endpoint", "auditd_manager", "crowdstrike", "sentinel_one_cloud_funnel", "cloud_defend"]
maturity = "production"
min_stack_comments = "Defend for Containers integration was re-introduced in 9.3.0"
min_stack_version = "9.3.0"
updated_date = "2026/07/06"

[rule]
author = ["Elastic"]
description = """
The Linux kernel invokes the program named in "/proc/sys/kernel/core_pattern" whenever a process core-dumps. When
that value begins with a pipe (|), the kernel runs the handler from the host's initial namespace as root, regardless
of where the crashing process lived. Because the core-dump up-call is not namespaced, a process inside a container
that can write core_pattern can register an attacker-controlled handler and then deliberately crash a process to have
it execute on the host as root, resulting in a full container-to-host escape.
"""
from = "now-9m"
index = [
    "auditbeat-*",
    "endgame-*",
    "logs-auditd_manager.auditd-*",
    "logs-crowdstrike.fdr*",
    "logs-endpoint.events.process*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-cloud_defend.process*",
]
language = "eql"
license = "Elastic License v2"
name = "Potential Container Escape via Kernel core_pattern Modification"
note = """ ## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Potential Container Escape via Kernel core_pattern Modification

This rule detects attempts on Linux to change the kernel’s core dump handler, a setting that can make the host run a program as root when a process crashes. In a container, an attacker can write a pipe-based core_pattern such as a shell script path, then deliberately crash a process so the host executes the handler outside the container, turning container access into full host compromise.

### Possible investigation steps

- Verify the current and recent value of `kernel.core_pattern` on the affected node, prioritizing pipe-based handlers and whether the referenced program lives in a writable, temporary, container-mounted, or otherwise untrusted path.
- Reconstruct the full ancestry and session context of the modifying process to determine whether it came from a legitimate admin workflow or from a containerized shell, and identify the associated user, container, image, pod, and privilege level.
- Review the container or pod security context for escape-enabling conditions such as privileged mode, shared host namespaces, hostPath mounts to `/proc` or the host filesystem, and elevated capabilities that would have allowed changing a host kernel parameter.
- Hunt for follow-on exploitation by looking for deliberate crashes, core-dump activity, and new root-owned host processes launched shortly after the change, especially executions from `/tmp`, container overlay paths, or bind-mounted locations.
- If the activity is not authorized, collect the referenced handler file and related artifacts, assess the host for persistence or lateral movement, and contain the node and implicated workload before restoring `kernel.core_pattern` to a known-good value.

### False positive analysis

- An administrator or approved automation may temporarily change `kernel.core_pattern` from a host shell or privileged container during crash-dump troubleshooting; verify the initiating user and parent process, look for a corresponding maintenance window or change record, and confirm the setting was restored to an approved value afterward.
- A legitimate test or debugging workflow may use `sysctl`, shell redirection, or file-copy utilities to point `core_pattern` to a known crash handler before generating controlled faults; confirm the activity is tied to an expected container or host session, the handler path is trusted, and no unexpected root-owned host processes were launched after the change.

### Response and remediation

- Isolate the affected host from the network, cordon and drain the Kubernetes node if applicable, and stop or quarantine the implicated container or pod so the attacker cannot trigger additional core dumps or spawn new host processes.
- Preserve the malicious artifacts for incident handling and then remove the attacker-controlled core dump handler, including any scripts or binaries referenced by `/proc/sys/kernel/core_pattern` and copies placed in `/tmp`, `/var/tmp`, container overlay paths, bind mounts, or other writable locations.
- Restore the node to a known-good state by resetting `kernel.core_pattern` to the approved value, removing unauthorized entries from `/etc/sysctl.conf`, `/etc/sysctl.d/`, and startup scripts that would reapply it, and rebuilding the host from a trusted image if host-level execution occurred.
- Hunt for and remove persistence added after the escape attempt, including rogue systemd units, cron jobs, `/etc/rc.local` changes, SSH `authorized_keys`, newly created sudoers entries, and unauthorized privileged DaemonSets or containers on the node.
- Escalate immediately to incident response if the handler executed on the host, if you find root-owned processes launched from a container-writable path such as `/tmp` or an overlay mount, or if the same `core_pattern` change appears on more than one node.
- Rotate any credentials or tokens exposed on the host or mounted into the compromised workload, then harden the environment by blocking privileged pods, removing dangerous capabilities such as `CAP_SYS_ADMIN`, prohibiting writable `hostPath` access to `/proc` or the host filesystem, and enforcing pod security or admission policies to prevent recurrence.
"""
references = [
    "https://www.sysdig.com/blog/runc-container-escape-vulnerabilities",
    "https://github.com/opencontainers/runc/security/advisories/GHSA-cgrx-mc8f-2prm",
    "https://kubehound.io/reference/attacks/CE_UMH_CORE_PATTERN/",
    "https://aquasecurity.github.io/tracee/latest/docs/events/builtin/signatures/core_pattern_modification/"
]
risk_score = 47
rule_id = "4872671a-c8d2-4847-9891-d3ce08b9e4c9"
setup = """## Setup

This rule requires data coming in from Elastic Defend.

### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.

#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
#### The following steps should be executed in order to add the Elastic Defend integration on a Linux system:
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "medium"
tags = [
  "Domain: Endpoint",
  "Domain: Container",
  "Domain: Kubernetes",
  "OS: Linux",
  "Use Case: Threat Detection",
  "Tactic: Privilege Escalation",
  "Data Source: Elastic Defend",
  "Data Source: Elastic Endgame",
  "Data Source: Auditd Manager",
  "Data Source: Crowdstrike",
  "Data Source: SentinelOne",
  "Data Source: Elastic Defend for Containers",
  "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "linux" and event.type == "start" and
event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.args like ("*/proc/sys/kernel/core_pattern*", "*kernel.core_pattern*") and
?process.parent.executable != null and
(
  process.name in ("tee", "cp", "mv", "dd") or
  (
    process.name == "sysctl" and
    process.args like ("*-w*", "*core_pattern*")
  ) or
  (
    process.name in ("bash", "dash", "sh", "zsh", "ksh", "fish", "ash", "mksh", "busybox") and
    process.args == "-c" and process.args like ("*echo *", "*printf *")
  )
) and
not ?process.parent.executable in ("/usr/lib/systemd/systemd", "/usr/bin/kdumpctl", "/usr/sbin/abrtd", "/usr/bin/apport")
'''

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1611"
name = "Escape to Host"
reference = "https://attack.mitre.org/techniques/T1611/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

Stages and Predicates

Stage 1: process

process where host.os.type == "linux" and event.type == "start" and
event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.args like ("*/proc/sys/kernel/core_pattern*", "*kernel.core_pattern*") and
?process.parent.executable != null and
(
  process.name in ("tee", "cp", "mv", "dd") or
  (
    process.name == "sysctl" and
    process.args like ("*-w*", "*core_pattern*")
  ) or
  (
    process.name in ("bash", "dash", "sh", "zsh", "ksh", "fish", "ash", "mksh", "busybox") and
    process.args == "-c" and process.args like ("*echo *", "*printf *")
  )
) and
not ?process.parent.executable in ("/usr/lib/systemd/systemd", "/usr/bin/kdumpctl", "/usr/sbin/abrtd", "/usr/bin/apport")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actionin
  • ProcessRollup2
  • exec
  • exec_event
  • executed
  • process_started
  • start
field:"EventType" kind:in
event.typeeq
  • start
field:"event.type" kind:eq value:"start"
process.argseq
  • -c
field:"process.args" kind:eq value:"-c"
process.argswildcard
  • *-w*
  • */proc/sys/kernel/core_pattern*
  • *core_pattern*
  • *echo *
  • *kernel.core_pattern*
  • *printf *
field:"process.args" kind:wildcard
process.nameeq
  • sysctl
field:"process_basename" kind:eq value:"sysctl"
process.namein
  • ash
  • bash
  • busybox
  • cp
  • dash
  • dd
  • fish
  • ksh
  • mksh
  • mv
  • sh
  • tee
  • zsh
field:"process_basename" kind:in
process.parent.executableis_not_null
  • (no value, null check)
field:"ParentImage" kind:is_not_null

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.parent.executablein/usr/bin/apport, /usr/bin/kdumpctl, /usr/lib/systemd/systemd, /usr/sbin/abrtdexcludes:process.parent.executable

Potential CVE-2025-33053 Exploitation

#
Status
production
Severity
high
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies Internet Explorer Diagnostics launching a helper name from a non-System32 path, which may indicate CVE-2025-33053 exploitation.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2025/06/11"
integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/05/03"

[rule]
author = ["Elastic"]
description = """
Identifies Internet Explorer Diagnostics launching a helper name from a non-System32 path, which may indicate
CVE-2025-33053 exploitation.
"""
from = "now-9m"
index = [
    "logs-endpoint.events.process-*",
    "winlogbeat-*",
    "logs-windows.sysmon_operational-*",
    "endgame-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
]
language = "eql"
license = "Elastic License v2"
name = "Potential CVE-2025-33053 Exploitation"
references = [
     "https://research.checkpoint.com/2025/stealth-falcon-zero-day/", 
     "https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2025-33053",
]
risk_score = 73
rule_id = "5e23495f-09e2-4484-8235-bdb150d698c9"
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Initial Access",
    "Data Source: Elastic Endgame",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Data Source: Microsoft Defender XDR",
    "Data Source: SentinelOne",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.type == "start" and
  process.parent.executable : "C:\\Program Files\\Internet Explorer\\iediagcmd.exe" and
  process.name : ("route.exe", "netsh.exe", "ipconfig.exe", "dxdiag.exe", "conhost.exe", "makecab.exe") and
  process.executable != null and
  not process.executable : ("C:\\Windows\\System32\\route.exe",
                            "C:\\Windows\\System32\\netsh.exe",
                            "C:\\Windows\\System32\\ipconfig.exe",
                            "C:\\Windows\\System32\\dxdiag.exe",
                            "C:\\Windows\\System32\\conhost.exe",
                            "C:\\Windows\\System32\\makecab.exe")
'''

note = """## Triage and analysis

### Investigating Potential CVE-2025-33053 Exploitation

#### Possible investigation steps

- Does the alert show "iediagcmd.exe" launching a non-system helper?
  - Focus: `process.parent.executable`, `process.name`, `process.executable`, and `process.command_line`; check for WebDAV, UNC, temp, downloads, archive-extracted, or user-writable helper paths.
  - Implication: escalate when the helper name matches a diagnostics utility but `process.executable` is outside "C:\\Windows\\System32\\" or points to remote/user-writable content; lower suspicion only when the path is a controlled diagnostic harness bounded to this `host.id` and `user.id`.
- Does child identity fit the claimed system utility?
  - Focus: `process.executable`, `process.pe.original_file_name`, `process.hash.sha256`, `process.code_signature.subject_name`, and `process.code_signature.trusted`.
  - Implication: escalate when the child is unsigned, newly seen, remotely hosted, user-writable, or PE metadata mismatches the helper name; a trusted signer/familiar name confirms identity only, not benign "iediagcmd.exe" use.
- Does parent/session context fit user-triggered execution?
  - Focus: `process.parent.command_line`, `process.Ext.session_info.logon_type`, and `user.id`.
  - Hint: inspect `process.Ext.ancestry` only when direct parent/child context is incomplete.
  - Implication: escalate when the parent command line/ancestry points to a shortcut, archive, browser, mail client, or document-open path in an interactive user session; lower suspicion when parent/session evidence stays inside a controlled diagnostic or authorized test launch path.
- If file telemetry is available, did the lure or child stage follow-on artifacts?
  - Focus: recover file events with `host.id` + `process.entity_id`; if absent, use `host.id` + `process.pid` in the alert window. Review `file.name`, `file.path`, `file.origin_url`, and `file.Ext.windows.zone_identifier` for ".url" lures, archive extraction, decoy PDFs, copied helpers, DLLs, or payloads. $investigate_0
  - Hint: if the child writes a file, check later starts where `process.executable` equals `file.path`.
  - Implication: escalate on internet provenance, WebDAV/UNC lure paths, decoys, copied utilities, DLLs, or written artifacts later executed; missing file telemetry is unresolved, not benign.
- If DNS/connection telemetry is available, did the child contact a remote share or callback?
  - Focus: recover network events with `host.id` + `process.entity_id`; if absent, use `host.id` + `process.pid` in the alert window. Separate DNS `dns.question.name`/`dns.resolved_ip` from connection `destination.ip`/`destination.port`. $investigate_1
  - Hint: map "lookup_result" `dns.question.name` to `dns.resolved_ip`, then compare with `destination.ip` and any remote host from the helper path or lure.
  - Implication: escalate when the child reaches a remote-share host, rare public destination, or later C2-like infrastructure unrelated to diagnostics; missing DNS/connection telemetry is unresolved, not benign.
- Do descendants or siblings show cleanup, decoy opening, or payload execution?
  - Focus: later process starts on the same `host.id`, using direct `process.parent.entity_id` links first; review `process.executable`, `process.command_line`, `process.Ext.created_suspended`, and signer context. $investigate_2
  - Hint: use PID matching only in a tight alert-time window, and inspect `process.Ext.ancestry` only when direct lineage is incomplete.
  - Implication: escalate when the chain launches "taskkill.exe", opens a decoy through "cmd.exe", starts a browser from an abnormal path, creates a suspended process, or runs unsigned follow-on payloads; keep host-local only when no follow-on evidence contradicts a bounded diagnostic or test path.
- If local evidence is suspicious or incomplete, do related alerts show broader delivery or post-exploitation?
  - Focus: review same-`user.id` alerts over 48 hours for the same lure, proxy-execution, payload, or C2 pattern. $investigate_3
  - Hint: if the user scope is sparse or shared, compare same-`host.id` alerts for the same ".url", WebDAV, child hash, or payload pattern. $investigate_4
  - Implication: expand response scope when related alerts show the same lure, remote working directory, payload, or post-exploitation pattern; keep response host-local only when related alerts are absent and local telemetry fully explains one recognized workflow.
- What disposition do helper-path, identity, launch, artifact, network, descendant, and related-alert findings support?
  - Implication: escalate on remote working-directory abuse, lure delivery, payload staging, suspicious destinations, cleanup, or broader compromise; close only when process, artifact, network, descendant, and alert-scope evidence bind one recognized diagnostic or authorized test workflow; preserve and escalate on incomplete or mixed visibility.

### False positive analysis

- Routine diagnostics resolve helpers from "C:\\Windows\\System32\\". Treat helper execution from WebDAV, UNC, temp, downloads, or archive paths as an operational anti-pattern unless telemetry proves a controlled harness or authorized exploit test: child identity (`process.executable`, `process.hash.sha256`, signer, `process.command_line`), parent launch context, `user.id`, `host.id`, and ".url", file-provenance, DNS, or destination evidence stay inside the same bounded workflow; use testing records only to corroborate telemetry.
- Before exceptions, validate the minimum recurring pattern: child path or hash, signer, command line, `process.parent.executable`, `user.id`, `host.id`, and bounded lure or destination pattern. Avoid exceptions on "iediagcmd.exe", `process.name`, helper basename, or `host.id` alone because those fields also match malicious working-directory hijack chains.

### Response and remediation

- If confirmed benign, reverse containment and document the exact child path/hash, command line, parent launch context, `user.id`, `host.id`, and lure or destination evidence proving the diagnostic or testing workflow. Create an exception only for that recurring bounded pattern.
- If suspicious but unconfirmed, preserve a case export of the alert, parent/child process details, suspicious helper binary, ".url" or archive artifacts, file-provenance records, DNS/connection records, and descendant process evidence before containment. Apply reversible containment first: block the confirmed WebDAV or callback destination, remove remote-share access, or raise monitoring on `host.id`; isolate only when artifact, network, or descendant evidence shows active compromise and the host role can tolerate disruption.
- If confirmed malicious, isolate the host or terminate the malicious child and confirmed descendants only after recording process entity IDs, command lines, hashes, lure paths, destination indicators, and related alert identifiers. If endpoint response is unavailable, hand off preserved evidence to contain the endpoint or block remote infrastructure.
- Before deleting artifacts, scope other users and hosts for the same ".url" filename pattern, WebDAV/UNC host, child hash, command line, decoy path, and payload path. Remove only lure files, dropped helpers, DLLs, decoys, archives, and payloads found during the investigation, then restore modified execution paths that supported the hijack chain.
- After containment, apply the June 2025 Windows security updates for CVE-2025-33053 where missing, restrict untrusted Internet Shortcut content and remote-working-directory execution paths, retain process/file/network telemetry, and document variants such as helper names or WebDAV paths for detection engineering review.
"""

setup = """## Setup

This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

### Additional data sources

This rule also supports the following third-party data sources. For setup instructions, refer to the links below:

- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
"""

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "host.id",
    "user.id",
    "process.name",
    "process.pid",
    "process.entity_id",
    "process.executable",
    "process.command_line",
    "process.Ext.session_info.logon_type",
    "process.pe.original_file_name",
    "process.code_signature.subject_name",
    "process.code_signature.trusted",
    "process.parent.executable",
    "process.parent.command_line",
    "process.hash.sha256",
]

[transform]

[[transform.investigate]]
label = "File events for the suspicious child process"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ],
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Network events for the suspicious child process"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ],
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Child process starts from the suspicious child process"
description = ""
providers = [
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "event.type", queryType = "phrase", value = "start", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
  ],
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
    { excluded = false, field = "event.type", queryType = "phrase", value = "start", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.parent.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Alerts associated with the user"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[transform.investigate]]
label = "Alerts associated with the host"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"

[[rule.threat.technique.subtechnique]]
id = "T1566.001"
name = "Spearphishing Attachment"
reference = "https://attack.mitre.org/techniques/T1566/001/"

[[rule.threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"

[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1036"
name = "Masquerading"
reference = "https://attack.mitre.org/techniques/T1036/"

[[rule.threat.technique.subtechnique]]
id = "T1036.005"
name = "Match Legitimate Resource Name or Location"
reference = "https://attack.mitre.org/techniques/T1036/005/"

[[rule.threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1203"
name = "Exploitation for Client Execution"
reference = "https://attack.mitre.org/techniques/T1203/"

[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
  process.parent.executable : "C:\\Program Files\\Internet Explorer\\iediagcmd.exe" and
  process.name : ("route.exe", "netsh.exe", "ipconfig.exe", "dxdiag.exe", "conhost.exe", "makecab.exe") and
  process.executable != null and
  not process.executable : ("C:\\Windows\\System32\\route.exe",
                            "C:\\Windows\\System32\\netsh.exe",
                            "C:\\Windows\\System32\\ipconfig.exe",
                            "C:\\Windows\\System32\\dxdiag.exe",
                            "C:\\Windows\\System32\\conhost.exe",
                            "C:\\Windows\\System32\\makecab.exe")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.executableis_not_null
  • (no value, null check)
field:"Image" kind:is_not_null
process.namewildcard
  • conhost.exe corpus 12 (elastic 11, splunk 1)
  • dxdiag.exe corpus 4 (elastic 3, splunk 1)
  • ipconfig.exe corpus 11 (elastic 10, splunk 1)
  • makecab.exe corpus 4 (elastic 4)
  • netsh.exe corpus 21 (elastic 14, splunk 7)
  • route.exe corpus 4 (elastic 3, splunk 1)
field:"process_basename" kind:wildcard
process.parent.executablewildcard
  • C:\Program Files\Internet Explorer\iediagcmd.exe corpus 3 (elastic 2, sigma 1)
field:"ParentImage" kind:wildcard value:"C:\Program Files\Internet Explorer\iediagcmd.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.executableeqC:\Windows\System32\route.exe, C:\Windows\System32\netsh.exe, C:\Windows\System32\ipconfig.exe, C:\Windows\System32\dxdiag.exe, C:\Windows\System32\conhost.exe, C:\Windows\System32\makecab.exeexcludes:process.executable

Potential DGA Activity

#
Status
production
Severity
low
Author
Elastic
Source
github.com/elastic/detection-rules

A population analysis machine learning job detected potential DGA (domain generation algorithm) activity. Such activity is often used by malware command and control (C2) channels. This machine learning job looks for a source IP address making DNS requests that have an aggregate high probability of being DGA activity.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2023/09/14"
integration = ["dga", "endpoint", "network_traffic"]
maturity = "production"
updated_date = "2026/07/27"
min_stack_version = "9.4.0"
min_stack_comments = "Use EA (Entity Analytics) fields"

[rule]
anomaly_threshold = 70
author = ["Elastic"]
description = """
A population analysis machine learning job detected potential DGA (domain generation algorithm) activity. Such activity
is often used by malware command and control (C2) channels. This machine learning job looks for a source IP address
making DNS requests that have an aggregate high probability of being DGA activity.
"""
from = "now-45m"
interval = "15m"
license = "Elastic License v2"
machine_learning_job_id = "dga_high_sum_probability_ea"
name = "Potential DGA Activity"
references = [
    "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html",
    "https://docs.elastic.co/en/integrations/dga",
    "https://www.elastic.co/security-labs/detect-domain-generation-algorithm-activity-with-new-kibana-integration",
]
risk_score = 21
rule_id = "ff0d807d-869b-4a0d-a493-52bc46d2f1b1"
setup = """## Setup

The rule requires the Domain Generation Algorithm (DGA) Detection integration assets to be installed, as well as DNS events collected by integrations such as Elastic Defend, Network Packet Capture, or Packetbeat.

### DGA Detection Setup
The DGA Detection integration consists of an ML-based framework to detect DGA activity in DNS events.

#### Prerequisite Requirements:
- Fleet is required for DGA Detection.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
- DNS events collected by the [Elastic Defend](https://docs.elastic.co/en/integrations/endpoint), [Network Packet Capture](https://docs.elastic.co/integrations/network_traffic) integration, or [Packetbeat](https://www.elastic.co/guide/en/beats/packetbeat/current/packetbeat-overview.html).
- To install Elastic Defend, refer to the [documentation](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
- To add the Network Packet Capture integration to an Elastic Agent policy, refer to [this](https://www.elastic.co/guide/en/fleet/current/add-integration-to-policy.html) guide.
- To set up and run Packetbeat, follow [this](https://www.elastic.co/guide/en/beats/packetbeat/current/setting-up-and-running.html) guide.

#### The following steps should be executed to install assets associated with the DGA Detection integration:
- Go to the Kibana homepage. Under Management, click Integrations.
- In the query bar, search for Domain Generation Algorithm Detection and select the integration to see more details about it.
- Follow the instructions under the **Installation** section.
- For this rule to work, complete the instructions through **Add preconfigured anomaly detection jobs**.

### Anomaly Detection Setup
Before you can enable this rule, you'll need to enable the corresponding Anomaly Detection job.
- Go to the Kibana homepage. Under Analytics, click Machine Learning.
- Under Anomaly Detection, click Jobs, and then click "Create job". Select the Data View containing your enriched DNS events. For example, this would be `logs-endpoint.events.*` if you used Elastic Defend to collect events, or `logs-network_traffic.*` if you used Network Packet Capture.
- If the selected Data View contains events that match the query in [this](https://github.com/elastic/integrations/blob/main/packages/dga/kibana/ml_module/dga-ml.json) configuration file, you will see a card for DGA under "Use preconfigured jobs".
- Keep the default settings and click "Create jobs" to start the anomaly detection job and datafeed.
"""
severity = "low"
tags = [
    "Data Source: Elastic Defend",
    "Data Source: Network Packet Capture",
    "Use Case: Domain Generation Algorithm Detection",
    "Rule Type: ML",
    "Rule Type: Machine Learning",
    "Tactic: Command and Control",
    "Resources: Investigation Guide",
]
type = "machine_learning"
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Potential DGA Activity
Domain Generation Algorithms (DGAs) are used by malware to dynamically generate domain names for command and control (C2) communication, making it difficult to block malicious domains. Adversaries exploit this by frequently changing domains to evade detection. The 'Potential DGA Activity' detection rule leverages machine learning to analyze DNS requests from source IPs, identifying patterns indicative of DGA usage, thus flagging potential threats for further investigation.

### Possible investigation steps

- Review the source IP address identified in the alert to determine if it belongs to a known or trusted entity within the organization.
- Analyze the DNS request patterns from the source IP to identify any unusual or suspicious domain names that may indicate DGA activity.
- Cross-reference the flagged domains with threat intelligence feeds to check for known malicious domains or patterns associated with DGAs.
- Investigate the network traffic associated with the source IP to identify any additional indicators of compromise or communication with known malicious IPs.
- Check for any recent changes or anomalies in the system or network configurations that could explain the detected activity.
- Assess the risk score and severity in the context of the organization's environment to prioritize the investigation and response efforts.

### False positive analysis

- Legitimate software updates or cloud services may generate high volumes of DNS requests that resemble DGA patterns. Users can create exceptions for known update servers or cloud service domains to reduce false positives.
- Content delivery networks (CDNs) often use dynamically generated subdomains for load balancing and distribution, which can trigger DGA alerts. Identifying and excluding these CDN domains from analysis can help mitigate false positives.
- Large organizations with complex internal networks might have internal applications that generate DNS requests similar to DGA activity. Conducting a thorough review of internal DNS traffic and whitelisting known internal domains can prevent these false positives.
- Some security tools or network appliances may perform DNS lookups as part of their normal operation, which could be misclassified as DGA activity. Identifying these tools and excluding their IP addresses from the analysis can help manage false positives.

### Response and remediation

- Isolate the affected systems: Immediately disconnect any systems identified as making suspicious DNS requests from the network to prevent further communication with potential C2 servers.
- Block identified domains: Use firewall and DNS filtering solutions to block the domains flagged by the detection rule, preventing any further communication attempts.
- Conduct a thorough system scan: Use updated antivirus and anti-malware tools to scan the isolated systems for any signs of infection or malicious software.
- Analyze network traffic: Review network logs to identify any additional suspicious activity or other systems that may be affected, focusing on unusual DNS requests and connections.
- Patch and update systems: Ensure all systems, especially those identified in the alert, are fully patched and updated to mitigate vulnerabilities that could be exploited by malware.
- Restore from backups: If malware is confirmed, restore affected systems from clean backups to ensure no remnants of the infection remain.
- Escalate to incident response team: If the threat is confirmed and widespread, escalate the incident to the organization's incident response team for further investigation and coordinated response efforts."""
[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1071"
name = "Application Layer Protocol"
reference = "https://attack.mitre.org/techniques/T1071/"

[[rule.threat.technique.subtechnique]]
id = "T1071.004"
name = "DNS"
reference = "https://attack.mitre.org/techniques/T1071/004/"

[[rule.threat.technique]]
id = "T1568"
name = "Dynamic Resolution"
reference = "https://attack.mitre.org/techniques/T1568/"

[[rule.threat.technique.subtechnique]]
id = "T1568.002"
name = "Domain Generation Algorithms"
reference = "https://attack.mitre.org/techniques/T1568/002/"

[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"

Potential Nologin SSH Backdoor

#
Source
github.com/elastic/protections-artifacts

This rule identifies instances where the nologin command is executed by the sshd process. This behavior is unusual and may indicate an attempt to manipulate a system user for backdoor access.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
This rule identifies instances where the `nologin` command is executed by the `sshd` process. This behavior is unusual
and may indicate an attempt to manipulate a system user for backdoor access.
"""
id = "3bc8af69-707a-482c-b3c1-06bdb1530b94"
license = "Elastic License v2"
name = "Potential Nologin SSH Backdoor"
os_list = ["linux"]
reference = [
    "https://blog.exatrack.com/Perfctl-using-portainer-and-new-persistences/",
    "https://x.com/RFGroenewoud/status/1875112050218922010",
]
version = "1.0.4"

query = '''
process where event.type == "start" and event.action == "exec" and process.name == "nologin " and
process.parent.name == "sshd"
'''

min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
tree = true

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1564"
name = "Hide Artifacts"
reference = "https://attack.mitre.org/techniques/T1564/"
[[threat.technique.subtechnique]]
id = "T1564.002"
name = "Hidden Users"
reference = "https://attack.mitre.org/techniques/T1564/002/"



[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action == "exec" and process.name == "nologin " and
process.parent.name == "sshd"

Indicators

These rows show field, operator, and value matches.

Startup Persistence by a Suspicious Process

#
Status
production
Severity
medium
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies files written to or modified in the startup folder by commonly abused processes. Adversaries may use this technique to maintain persistence.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2020/11/18"
integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/05/04"

[transform]
[[transform.osquery]]
label = "Osquery - Retrieve DNS Cache"
query = "SELECT * FROM dns_cache"

[[transform.osquery]]
label = "Osquery - Retrieve All Services"
query = "SELECT description, display_name, name, path, pid, service_type, start_type, status, user_account FROM services"

[[transform.osquery]]
label = "Osquery - Retrieve Services Running on User Accounts"
query = """
SELECT description, display_name, name, path, pid, service_type, start_type, status, user_account FROM services WHERE
NOT (user_account LIKE '%LocalSystem' OR user_account LIKE '%LocalService' OR user_account LIKE '%NetworkService' OR
user_account == null)
"""

[[transform.osquery]]
label = "Osquery - Retrieve Service Unsigned Executables with Virustotal Link"
query = """
SELECT concat('https://www.virustotal.com/gui/file/', sha1) AS VtLink, name, description, start_type, status, pid,
services.path FROM services JOIN authenticode ON services.path = authenticode.path OR services.module_path =
authenticode.path JOIN hash ON services.path = hash.path WHERE authenticode.result != 'trusted'
"""


[rule]
author = ["Elastic"]
description = """
Identifies files written to or modified in the startup folder by commonly abused processes. Adversaries may use this
technique to maintain persistence.
"""
from = "now-9m"
index = [
    "winlogbeat-*",
    "logs-endpoint.events.file-*",
    "logs-windows.sysmon_operational-*",
    "endgame-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
]
language = "eql"
license = "Elastic License v2"
name = "Startup Persistence by a Suspicious Process"
note = """## Triage and analysis

### Investigating Startup Persistence by a Suspicious Process

The Windows Startup folder is a special folder in Windows. Programs added to this folder are executed during account logon, without user interaction, providing an excellent way for attackers to maintain persistence.

This rule monitors for commonly abused processes writing to the Startup folder locations.

> **Note**:
> This investigation guide uses the [Osquery Markdown Plugin](https://www.elastic.co/guide/en/security/current/invest-guide-run-osquery.html) introduced in Elastic Stack version 8.5.0. Older Elastic Stack versions will display unrendered Markdown in this guide.

#### Possible investigation steps

- Investigate the process execution chain (parent process tree) for unknown processes. Examine their executable files for prevalence, whether they are located in expected locations, and if they are signed with valid digital signatures.
- Investigate other alerts associated with the user/host during the past 48 hours.
- Validate if the activity is not related to planned patches, updates, network administrator activity, or legitimate software installations.
- Assess whether this behavior is prevalent in the environment by looking for similar occurrences across hosts.
- Examine the host for derived artifacts that indicate suspicious activities:
  - Analyze the file using a private sandboxed analysis system.
  - Observe and collect information about the following activities in both the sandbox and the alert subject host:
    - Attempts to contact external domains and addresses.
      - Use the Elastic Defend network events to determine domains and addresses contacted by the subject process by filtering by the process' `process.entity_id`.
      - Examine the DNS cache for suspicious or anomalous entries.
        - $osquery_0
    - Use the Elastic Defend registry events to examine registry keys accessed, modified, or created by the related processes in the process tree.
    - Examine the host services for suspicious or anomalous entries.
      - $osquery_1
      - $osquery_2
      - $osquery_3
  - Retrieve the files' SHA-256 hash values using the PowerShell `Get-FileHash` cmdlet and search for the existence and reputation of the hashes in resources like VirusTotal, Hybrid-Analysis, CISCO Talos, Any.run, etc.
- Investigate potentially compromised accounts. Analysts can do this by searching for login events (for example, 4624) to the target host after the registry modification.

### False positive analysis

- Administrators may add programs to this mechanism via command-line shells. Before the further investigation, verify that this activity is not benign.

### Related rules

- Suspicious Startup Shell Folder Modification - c8b150f0-0164-475b-a75e-74b47800a9ff
- Persistent Scripts in the Startup Directory - f7c4dc5a-a58d-491d-9f14-9b66507121c0

### Response and remediation

- Initiate the incident response process based on the outcome of the triage.
- Isolate the involved host to prevent further post-compromise behavior.
- If the triage identified malware, search the environment for additional compromised hosts.
  - Implement temporary network rules, procedures, and segmentation to contain the malware.
  - Stop suspicious processes.
  - Immediately block the identified indicators of compromise (IoCs).
  - Inspect the affected systems for additional malware backdoors like reverse shells, reverse proxies, or droppers that attackers could use to reinfect the system.
- Remove and block malicious artifacts identified during triage.
- Investigate credential exposure on systems compromised or used by the attacker to ensure all compromised accounts are identified. Reset passwords for these accounts and other potentially compromised credentials, such as email, business systems, and web services.
- Run a full antimalware scan. This may reveal additional artifacts left in the system, persistence mechanisms, and malware components.
- Determine the initial vector abused by the attacker and take action to prevent reinfection through the same vector.
- Using the incident response data, update logging and audit policies to improve the mean time to detect (MTTD) and the mean time to respond (MTTR).
"""

setup = """## Setup

This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

### Additional data sources

This rule also supports the following third-party data sources. For setup instructions, refer to the links below:

- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Event ID 11 - File Create](https://ela.st/sysmon-event-11-setup)
"""

references = [
    "https://www.elastic.co/security-labs/hunting-for-persistence-using-elastic-security-part-1",
    "https://www.elastic.co/security-labs/elastic-security-uncovers-blister-malware-campaign",
]
risk_score = 47
rule_id = "440e2db4-bc7f-4c96-a068-65b78da59bde"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Persistence",
    "Resources: Investigation Guide",
    "Data Source: Elastic Endgame",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Data Source: Microsoft Defender XDR",
    "Data Source: SentinelOne",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
file where host.os.type == "windows" and event.type != "deletion" and
  user.domain != "NT AUTHORITY" and
  file.path : ("C:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
               "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*") and
  process.name : ("cmd.exe",
                  "powershell.exe",
                  "wmic.exe",
                  "mshta.exe",
                  "pwsh.exe",
                  "cscript.exe",
                  "wscript.exe",
                  "regsvr32.exe",
                  "RegAsm.exe",
                  "rundll32.exe",
                  "EQNEDT32.EXE",
                  "WINWORD.EXE",
                  "EXCEL.EXE",
                  "POWERPNT.EXE",
                  "MSPUB.EXE",
                  "MSACCESS.EXE",
                  "iexplore.exe",
                  "InstallUtil.exe")
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1547"
name = "Boot or Logon Autostart Execution"
reference = "https://attack.mitre.org/techniques/T1547/"
[[rule.threat.technique.subtechnique]]
id = "T1547.001"
name = "Registry Run Keys / Startup Folder"
reference = "https://attack.mitre.org/techniques/T1547/001/"



[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"

Stages and Predicates

Stage 1: file

file where host.os.type == "windows" and event.type != "deletion" and
  user.domain != "NT AUTHORITY" and
  file.path : ("C:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
               "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*") and
  process.name : ("cmd.exe",
                  "powershell.exe",
                  "wmic.exe",
                  "mshta.exe",
                  "pwsh.exe",
                  "cscript.exe",
                  "wscript.exe",
                  "regsvr32.exe",
                  "RegAsm.exe",
                  "rundll32.exe",
                  "EQNEDT32.EXE",
                  "WINWORD.EXE",
                  "EXCEL.EXE",
                  "POWERPNT.EXE",
                  "MSPUB.EXE",
                  "MSACCESS.EXE",
                  "iexplore.exe",
                  "InstallUtil.exe")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typene
  • deletion corpus 33 (elastic 33)
field:"event.type" kind:ne value:"deletion"
file.pathwildcard
  • C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\* corpus 3 (elastic 3)
  • C:\Users\*\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\* corpus 3 (elastic 3)
field:"TargetFilename" kind:wildcard
process.namewildcard
  • EQNEDT32.EXE corpus 8 (elastic 8)
  • EXCEL.EXE corpus 34 (elastic 34)
  • InstallUtil.exe corpus 36 (elastic 32, splunk 4)
  • MSACCESS.EXE corpus 19 (elastic 19)
  • MSPUB.EXE corpus 15 (elastic 15)
  • POWERPNT.EXE corpus 31 (elastic 31)
  • RegAsm.exe corpus 25 (elastic 24, splunk 1)
  • WINWORD.EXE corpus 35 (elastic 35)
  • cmd.exe corpus 122 (elastic 93, splunk 29)
  • cscript.exe corpus 68 (elastic 66, splunk 2)
  • iexplore.exe corpus 4 (elastic 3, splunk 1)
  • mshta.exe corpus 84 (elastic 80, splunk 4)
  • powershell.exe corpus 187 (elastic 140, splunk 44, kusto 3)
  • pwsh.exe corpus 78 (elastic 49, splunk 29)
  • regsvr32.exe corpus 74 (elastic 69, splunk 5)
  • rundll32.exe corpus 123 (elastic 100, splunk 23)
  • wmic.exe corpus 66 (elastic 39, splunk 27)
  • wscript.exe corpus 84 (elastic 82, splunk 1, kusto 1)
field:"process_basename" kind:wildcard
user.domainne
  • NT AUTHORITY corpus 5 (elastic 5)
field:"TargetDomainName" kind:ne value:"NT AUTHORITY"

TCC Bypass via Mounted APFS Snapshot Access

#
Status
production
Severity
high
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies the use of the mount_apfs command to mount the entire file system through Apple File System (APFS) snapshots as read-only and with the noowners flag set. This action enables the adversary to access almost any file in the file system, including all user data and files protected by Apple’s privacy framework (TCC).

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2020/01/04"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/03/24"

[rule]
author = ["Elastic"]
description = """
Identifies the use of the mount_apfs command to mount the entire file system through Apple File System (APFS) snapshots
as read-only and with the noowners flag set. This action enables the adversary to access almost any file in the file
system, including all user data and files protected by Apple’s privacy framework (TCC).
"""
from = "now-9m"
index = ["logs-endpoint.events.*"]
language = "eql"
license = "Elastic License v2"
name = "TCC Bypass via Mounted APFS Snapshot Access"
references = ["https://theevilbit.github.io/posts/cve_2020_9771/"]
risk_score = 73
rule_id = "b00bcd89-000c-4425-b94c-716ef67762f6"
setup = """## Setup

This rule requires data coming in from Elastic Defend.

### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.

#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).

#### The following steps should be executed in order to add the Elastic Defend integration on a macOS System:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, for MacOS it is recommended to select "Traditional Endpoints".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/current/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: macOS",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Use Case: Vulnerability",
    "Data Source: Elastic Defend",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "macos" and event.type in ("start", "process_started") and process.name == "mount_apfs" and
 process.args like~ "/System/Volumes/Data" and process.args like~ "noowners"
'''
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating TCC Bypass via Mounted APFS Snapshot Access

Apple's TCC framework safeguards user data by controlling app access to sensitive files. Adversaries exploit APFS snapshots, mounting them with specific flags to bypass these controls, gaining unauthorized access to protected data. The detection rule identifies this misuse by monitoring the execution of the `mount_apfs` command with parameters indicative of such bypass attempts, flagging potential security breaches.

### Possible investigation steps

- Review the process execution details to confirm the presence of the `mount_apfs` command with the specific arguments `/System/Volumes/Data` and `noowners` to verify the alert's accuracy.
- Investigate the user account associated with the process execution to determine if the activity aligns with expected behavior or if it indicates potential unauthorized access.
- Examine the timeline of events leading up to and following the alert to identify any related suspicious activities or processes that may indicate a broader attack or compromise.
- Check for any recent changes or anomalies in system configurations or user permissions that could have facilitated the bypass attempt.
- Correlate the alert with other security logs or alerts to assess if this is part of a larger pattern of malicious behavior or an isolated incident.

### False positive analysis

- System maintenance tools or backup software may legitimately use the mount_apfs command with the noowners flag for routine operations. Users can create exceptions for these specific tools by identifying their process names or paths and excluding them from the detection rule.
- Developers or IT administrators might use the mount_apfs command during testing or troubleshooting. To prevent these activities from triggering false positives, users can whitelist specific user accounts or IP addresses associated with these roles.
- Automated scripts or scheduled tasks that require access to APFS snapshots for legitimate purposes might trigger the rule. Users should review these scripts and, if deemed safe, add them to an exclusion list based on their unique identifiers or execution context.
- Security software or monitoring tools that perform regular checks on file system integrity might inadvertently match the rule's criteria. Users can mitigate this by identifying these tools and excluding their specific process signatures from the detection parameters.

### Response and remediation

- Immediately isolate the affected macOS system from the network to prevent further unauthorized access or data exfiltration.
- Terminate any suspicious processes related to the `mount_apfs` command to halt ongoing unauthorized access attempts.
- Conduct a thorough review of system logs and user activity to identify any data accessed or exfiltrated during the breach.
- Restore any compromised files from a known good backup to ensure data integrity and security.
- Update macOS and all installed applications to the latest versions to patch any vulnerabilities that may have been exploited.
- Implement stricter access controls and monitoring for APFS snapshot usage to prevent similar bypass attempts in the future.
- Escalate the incident to the security operations center (SOC) or relevant IT security team for further investigation and to assess the need for additional security measures."""


[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1006"
name = "Direct Volume Access"
reference = "https://attack.mitre.org/techniques/T1006/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1005"
name = "Data from Local System"
reference = "https://attack.mitre.org/techniques/T1005/"

[rule.threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"

Stages and Predicates

Stage 1: process

process where host.os.type == "macos" and event.type in ("start", "process_started") and process.name == "mount_apfs" and
 process.args like~ "/System/Volumes/Data" and process.args like~ "noowners"

Indicators

These rows show field, operator, and value matches.

UAC Bypass via WSReset Execution Hijack

#
Time window
1m
Source
github.com/elastic/protections-artifacts

Identifies attempts to bypass User Account Control (UAC) via WSReset execution hijack. Attackers bypass UAC to stealthily execute code with elevated permissions.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies attempts to bypass User Account Control (UAC) via WSReset execution hijack. Attackers bypass UAC to
stealthily execute code with elevated permissions.
"""
id = "11c67af9-9599-4800-9e84-bd38f2a51581"
license = "Elastic License v2"
name = "UAC Bypass via WSReset Execution Hijack"
os_list = ["windows"]
reference = ["https://github.com/hfiref0x/UACME"]
version = "1.0.31"

query = '''
sequence with maxspan=60s
 [registry where
  registry.path :
      ("HKEY_USERS\\S-1-5-21-*Classes\\*\\Shell\\open\\command\\DelegateExecute",
       "HKEY_USERS\\S-1-12-1-*Classes\\*\\Shell\\open\\command\\DelegateExecute",
       "*\\ms-windows-store*")]
 [process where event.action == "start" and process.parent.name : "WSReset.exe" and
  process.Ext.token.integrity_level_name == "high" and
  not process.executable :
           ("?:\\Windows\\System32\\WerFault.exe",
            "?:\\Windows\\SysWOW64\\WerFault.exe",
            "?:\\Windows\\System32\\mmc.exe",
            "?:\\Windows\\SysWOW64\\mmc.exe",
            "?:\\Windows\\system32\\conhost.exe",
            "?:\\Windows\\SysWOW6\\conhost.exe")]
'''

min_endpoint_version = "7.15.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1

[[optional_actions]]
action = "rollback"
field = "process.entity_id"
state = 1

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1548"
name = "Abuse Elevation Control Mechanism"
reference = "https://attack.mitre.org/techniques/T1548/"
[[threat.technique.subtechnique]]
id = "T1548.002"
name = "Bypass User Account Control"
reference = "https://attack.mitre.org/techniques/T1548/002/"



[threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: registry

[registry where
  registry.path :
      ("HKEY_USERS\\S-1-5-21-*Classes\\*\\Shell\\open\\command\\DelegateExecute",
       "HKEY_USERS\\S-1-12-1-*Classes\\*\\Shell\\open\\command\\DelegateExecute",
       "*\\ms-windows-store*")]

Stage 2: process

[process where event.action == "start" and process.parent.name : "WSReset.exe" and
  process.Ext.token.integrity_level_name == "high" and
  not process.executable :
           ("?:\\Windows\\System32\\WerFault.exe",
            "?:\\Windows\\SysWOW64\\WerFault.exe",
            "?:\\Windows\\System32\\mmc.exe",
            "?:\\Windows\\SysWOW64\\mmc.exe",
            "?:\\Windows\\system32\\conhost.exe",
            "?:\\Windows\\SysWOW6\\conhost.exe")]

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • start corpus 388 (elastic 388)
field:"EventType" kind:eq value:"start"
process.Ext.token.integrity_level_nameeq
  • high corpus 19 (elastic 19)
field:"process.Ext.token.integrity_level_name" kind:eq value:"high"
process.parent.namewildcard
  • WSReset.exe corpus 2 (elastic 1, kusto 1)
field:"parent_process_basename" kind:wildcard value:"WSReset.exe"
registry.pathwildcard
  • *\ms-windows-store*
  • HKEY_USERS\S-1-12-1-*Classes\*\Shell\open\command\DelegateExecute
  • HKEY_USERS\S-1-5-21-*Classes\*\Shell\open\command\DelegateExecute
field:"TargetObject" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.executableeq?:\Windows\System32\WerFault.exe, ?:\Windows\SysWOW64\WerFault.exe, ?:\Windows\System32\mmc.exe, ?:\Windows\SysWOW64\mmc.exe, ?:\Windows\system32\conhost.exe, ?:\Windows\SysWOW6\conhost.exeexcludes:process.executable

Untrusted Process Execution with Invalid Plist or Code Signature

#
Source
github.com/elastic/protections-artifacts

Detects when an untrusted process is executed and the code signature status indicates an invalid info.plist file and the code signature team id is empty. This is a unique pattern that has matched on a large number of different malware samples and has not been seen to match on anything other than malicious samples.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Detects when an untrusted process is executed and the code signature status indicates an invalid info.plist file and the
code signature team id is empty. This is a unique pattern that has matched on a large number of different malware
samples and has not been seen to match on anything other than malicious samples.
"""
id = "b7516495-66f9-4cb9-abb9-3cede7a0aed7"
license = "Elastic License v2"
name = "Untrusted Process Execution with Invalid Plist or Code Signature"
os_list = ["macos"]
version = "1.0.12"

query = '''
process where event.type == "start" and process.code_signature.status == "invalid Info.plist (plist or signature have been modified)" and
 process.code_signature.exists == true and 
 length(process.code_signature.team_id) == 0 and 
 not process.executable like ("/opt/homebrew/*", "/usr/local/Cellar/*", "/Applications/AutoFirma.app/Contents/MacOS/AutoFirma") and
 not (process.code_signature.subject_name == "Developer ID Application: salesforce.com (62J96EUJ9N)" and process.code_signature.trusted == true) and
 not (process.parent.code_signature.team_id in ("2ZEFAR8TH3", "922YNK5MTB", "62J96EUJ9N") and
      process.parent.code_signature.trusted == true) and
 not process.parent.executable like ("/Library/Developer/CoreSimulator/*", "/Applications/AutoFirma.app/Contents/MacOS/AutoFirma", "/Applications/PCClient.app/Contents/MacOS/PCClient") and
 not process.Ext.effective_parent.executable in ("/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/XPCServices/SimulatorTrampoline.xpc/Contents/MacOS/SimulatorTrampoline",
                                                 "/Applications/AutoFirma.app/Contents/MacOS/AutoFirma", "/Applications/PCClient.app/Contents/MacOS/PCClient")
'''

min_endpoint_version = "8.11.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0

[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1204"
name = "User Execution"
reference = "https://attack.mitre.org/techniques/T1204/"
[[threat.technique.subtechnique]]
id = "T1204.002"
name = "Malicious File"
reference = "https://attack.mitre.org/techniques/T1204/002/"



[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"

[internal]
min_endpoint_version = "8.11.0"

Stages and Predicates

Stage 1: process

process where event.type == "start" and process.code_signature.status == "invalid Info.plist (plist or signature have been modified)" and
 process.code_signature.exists == true and 
 length(process.code_signature.team_id) == 0 and 
 not process.executable like ("/opt/homebrew/*", "/usr/local/Cellar/*", "/Applications/AutoFirma.app/Contents/MacOS/AutoFirma") and
 not (process.code_signature.subject_name == "Developer ID Application: salesforce.com (62J96EUJ9N)" and process.code_signature.trusted == true) and
 not (process.parent.code_signature.team_id in ("2ZEFAR8TH3", "922YNK5MTB", "62J96EUJ9N") and
      process.parent.code_signature.trusted == true) and
 not process.parent.executable like ("/Library/Developer/CoreSimulator/*", "/Applications/AutoFirma.app/Contents/MacOS/AutoFirma", "/Applications/PCClient.app/Contents/MacOS/PCClient") and
 not process.Ext.effective_parent.executable in ("/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/XPCServices/SimulatorTrampoline.xpc/Contents/MacOS/SimulatorTrampoline",
                                                 "/Applications/AutoFirma.app/Contents/MacOS/AutoFirma", "/Applications/PCClient.app/Contents/MacOS/PCClient")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.code_signature.subject_nameeqDeveloper ID Application: salesforce.com (62J96EUJ9N)excludes:process.code_signature.subject_name field:"process.code_signature.subject_name" value:"Developer ID Application: salesforce.com (62J96EUJ9N)"
process.code_signature.trustedeqtrueexcludes:process.code_signature.trusted field:"process.code_signature.trusted" value:"true"
process.parent.code_signature.team_idin2ZEFAR8TH3, 62J96EUJ9N, 922YNK5MTBexcludes:process.parent.code_signature.team_id field:"process.parent.code_signature.team_id" value:"2ZEFAR8TH3" field:"process.parent.code_signature.team_id" value:"62J96EUJ9N" field:"process.parent.code_signature.team_id" value:"922YNK5MTB"
process.parent.code_signature.trustedeqtrueexcludes:process.parent.code_signature.trusted field:"process.parent.code_signature.trusted" value:"true"
process.Ext.effective_parent.executablein/Applications/AutoFirma.app/Contents/MacOS/AutoFirma, /Applications/PCClient.app/Contents/MacOS/PCClient, /Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/XPCServices/SimulatorTrampoline.xpc/Contents/MacOS/SimulatorTrampolineexcludes:process.Ext.effective_parent.executable field:"process.Ext.effective_parent.executable" value:"/Applications/AutoFirma.app/Contents/MacOS/AutoFirma" field:"process.Ext.effective_parent.executable" value:"/Applications/PCClient.app/Contents/MacOS/PCClient" field:"process.Ext.effective_parent.executable" value:"/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/XPCServices/SimulatorTrampoline.xpc/Contents/MacOS/SimulatorTrampoline"
process.executablewildcard/opt/homebrew/*, /usr/local/Cellar/*, /Applications/AutoFirma.app/Contents/MacOS/AutoFirmaexcludes:process.executable field:"process.executable" value:"/opt/homebrew/*" field:"process.executable" value:"/usr/local/Cellar/*" field:"process.executable" value:"/Applications/AutoFirma.app/Contents/MacOS/AutoFirma"
process.parent.executablewildcard/Library/Developer/CoreSimulator/*, /Applications/AutoFirma.app/Contents/MacOS/AutoFirma, /Applications/PCClient.app/Contents/MacOS/PCClientexcludes:process.parent.executable field:"process.parent.executable" value:"/Library/Developer/CoreSimulator/*" field:"process.parent.executable" value:"/Applications/AutoFirma.app/Contents/MacOS/AutoFirma" field:"process.parent.executable" value:"/Applications/PCClient.app/Contents/MacOS/PCClient"

Unusual Process Execution Path - Alternate Data Stream

#
Status
production
Severity
medium
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies processes running from an Alternate Data Stream. This is uncommon for legitimate processes and sometimes done by adversaries to hide malware.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2020/12/04"
integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike"]
maturity = "production"
updated_date = "2026/05/04"

[rule]
author = ["Elastic"]
description = """
Identifies processes running from an Alternate Data Stream. This is uncommon for legitimate processes and sometimes done
by adversaries to hide malware.
"""
from = "now-9m"
index = [
    "logs-endpoint.events.process-*",
    "winlogbeat-*",
    "logs-windows.sysmon_operational-*",
    "endgame-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-crowdstrike.fdr*",
]
language = "eql"
license = "Elastic License v2"
name = "Unusual Process Execution Path - Alternate Data Stream"
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Unusual Process Execution Path - Alternate Data Stream

Alternate Data Streams (ADS) in Windows allow files to contain multiple data streams, which can be exploited by adversaries to conceal malicious code. This technique is often used for defense evasion, as it hides malware within legitimate files. The detection rule identifies processes initiated from ADS by monitoring specific execution patterns, such as unique argument structures, to flag potential threats.

### Possible investigation steps

- Review the process details, including the process name and path, to determine if it is a known legitimate application or potentially malicious.
- Examine the process arguments, specifically looking for the pattern "?:\\\\*:*", to understand the context of the execution and identify any suspicious or unusual characteristics.
- Check the parent process of the flagged process to assess if it was initiated by a legitimate or expected source.
- Investigate the user account associated with the process execution to determine if the activity aligns with the user's typical behavior or if it appears anomalous.
- Correlate the event with other security logs or alerts from data sources like Sysmon, Microsoft Defender XDR, or Crowdstrike to gather additional context and identify any related suspicious activities.
- Search for any known indicators of compromise (IOCs) related to the process or file path in threat intelligence databases to assess if the activity is associated with known threats.

### False positive analysis

- Legitimate software installations or updates may use alternate data streams to execute processes. Users can create exceptions for known software update paths to prevent unnecessary alerts.
- Some backup or file synchronization tools might utilize alternate data streams for metadata storage. Identify these tools and exclude their execution paths from the detection rule.
- Certain system administration scripts or tools may leverage alternate data streams for legitimate purposes. Review and whitelist these scripts if they are verified as non-threatening.
- Developers might use alternate data streams during software development for testing purposes. Ensure development environments are accounted for in the exception list to avoid false positives.
- Security tools themselves may use alternate data streams for scanning or monitoring activities. Verify and exclude these tools from the detection rule to reduce noise.

### Response and remediation

- Isolate the affected system from the network to prevent further spread of potential malware.
- Terminate any suspicious processes identified as running from an Alternate Data Stream to halt malicious activity.
- Conduct a thorough scan of the affected system using updated antivirus or endpoint detection and response (EDR) tools to identify and remove any hidden malware.
- Examine the file system for any additional Alternate Data Streams and remove or quarantine any suspicious files.
- Restore any affected files or systems from known good backups to ensure system integrity.
- Monitor the network for any unusual outbound traffic from the affected system that may indicate data exfiltration attempts.
- Escalate the incident to the security operations center (SOC) or incident response team for further analysis and to determine if additional systems are compromised."""
risk_score = 47
rule_id = "4bd1c1af-79d4-4d37-9efa-6e0240640242"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Data Source: Elastic Endgame",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Data Source: Microsoft Defender XDR",
    "Data Source: SentinelOne",
    "Data Source: Crowdstrike",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.type == "start" and
  process.args : "?:\\*:*" and
  (
    process.args_count == 1 and

    /* Excludes bug where a missing closing quote sets args_count to 1 despite extra args */
    not process.command_line regex~ """\".*\.exe[^\"].*"""
  )
'''

setup = """## Setup

This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

### Additional data sources

This rule also supports the following third-party data sources. For setup instructions, refer to the links below:

- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
"""


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1564"
name = "Hide Artifacts"
reference = "https://attack.mitre.org/techniques/T1564/"
[[rule.threat.technique.subtechnique]]
id = "T1564.004"
name = "NTFS File Attributes"
reference = "https://attack.mitre.org/techniques/T1564/004/"



[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
  process.args : "?:\\*:*" and
  (
    process.args_count == 1 and
    not process.command_line regex~ """\".*\.exe[^\"].*"""
  )

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.command_lineregex_match\".*.exe[^\"].*excludes:process.command_line

VirtualProtect via Indirect Syscall

#
Source
github.com/elastic/protections-artifacts

Identifies VirtualProtect API calls using indirect syscall. This may be an attempt to conceal the true source of the call.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = """
Identifies VirtualProtect API calls using indirect syscall. This may be an attempt to conceal the true source of the
call.
"""
id = "e7d63d66-2d46-4051-a304-4c34f7bbf11d"
license = "Elastic License v2"
name = "VirtualProtect via Indirect Syscall"
os_list = ["windows"]
version = "1.0.6"

query = '''
api where process.Ext.api.name == "VirtualProtect" and
 process.Ext.api.behaviors == "image_indirect_call" and process.Ext.api.behaviors == "native_api" and
 (
  (process.thread.Ext.call_stack_final_user_module.path like "c:\\windows\\system32\\*.dll" and
   process.thread.Ext.call_stack_final_user_module.protection_provenance != null) or

  (process.thread.Ext.call_stack_summary == "ntdll.dll|Unknown" and process.thread.Ext.call_stack_final_user_module.name == "Unknown")
  ) and
 not process.thread.Ext.call_stack_final_user_module.protection_provenance like ("Kernel*", "ntdll.dll") and
 not process.thread.Ext.call_stack_summary like "ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|ntdll.dll|execmodelclient.dll|*" and
 not _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry, $entry.trusted == true and
                  $entry.subject_name in ("Microsoft Windows Hardware Compatibility Publisher",
                                          "Microsoft Windows Software Compatibility Publisher",
                                          "Sentinel Labs, Inc.",  "ESET, spol. s r.o.", "MUSARUBRA US LLC",
                                          "WIBU-SYSTEMS AG",  "Carbon Black, Inc.", "Adobe Inc.", "Adobe Systems, Incorporated",
                                          "Mozilla Corporation", "Google LLC", "Fasoo Co., Ltd.", "AhnLab, Inc.",
                                          "Data Encryption Systems Ltd", "Aviata, Inc.")) and
 process.thread.Ext.call_stack_final_user_module.hash.sha256 != "ebdf952adb27745e16e033f3364ce090833e6ecdafa450241793b6f290410fe9" and
 not process.thread.Ext.call_stack_final_user_module.path like "c:\\windows\\system32\\tmumh\\*\\tmmon64.dll" and
 not process.thread.Ext.call_stack_final_user_module.protection_provenance_path like
                               ("c:\\program files\\common files\\microsoft shared\\clicktorun\\appvisvsubsystems64.dll",
                                "c:\\program files\\common files\\mcafee\\systemcore\\mfehcthe.dll",
                                "c:\\program files\\windowsapps\\microsoft.net.native.runtime.*\\mrt*_app.dll",
                                "c:\\windows\\winsxs\\amd64_microsoft-windows-servicingstack_*\\turbocontainer.dll",
                                "c:\\windows\\ccm\\localapphandler.dll",
                                "c:\\program files (x86)\\adobe\\acrobat dc\\acrobat\\acrobat.exe",
                                "c:\\program files (x86)\\adobe\\acrobat reader dc\\reader\\acrord32.exe",
                                "c:\\windows\\system32\\sppcext.dll",
                                "c:\\windows\\system32\\geolocation.dll",
                                "c:\\windows\\system32\\msvcr*.dll",
                                "c:\\windows\\system32\\windows.devices.sensors.dll",
                                "c:\\windows\\system32\\tmumh\\*\\tmmon64.dll") and
 not _arraysearch(process.thread.Ext.call_stack, $entry,
                  $entry.symbol_info : ("c:\\windows\\sys?????\\ntdll.dll!LdrLoadDll*",
                                        "c:\\windows\\system32\\mdmregistration.dll!FindDiscoveryService*",
                                        "c:\\windows\\sys?????\\ntdll.dll!LdrGetProcedureAddress*",
                                        "c:\\windows\\sys?????\\ntdll.dll!LdrShutdownProcess*",
                                        "c:\\windows\\sys?????\\apphelp.dll!SE_DllLoaded*",
                                        "c:\\windows\\system32\\msvcr100.dll!tanhf*",
                                        "c:\\windows\\sys?????\\win32u.dll!NtUserCreateWindowEx*")) and
 not _arraysearch(process.thread.Ext.call_stack, $entry,$entry.callsite_trailing_bytes like "488da42428000000c3000000000000000000000000000df0adba0d*") and
 not (process.name:"powershell.exe" and
      process.parent.executable : ("C:\\Windows\\System32\\Empirum\\EmpInventory.exe",
                                   "C:\\Program Files\\ESET\\ESET Security\\ekrn.exe",
                                   "C:\\Program Files\\ESET\\ESET Endpoint Antivirus\\ekrn.exe")) and
 not (process.executable : "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" and
      process.Ext.api.summary like "VirtualProtect( clr.dll, 0x?, * )") and
 not (process.thread.Ext.call_stack_summary == "ntdll.dll|protector64.dll|wsmsvc.dll" and process.thread.Ext.call_stack_final_user_module.path == "c:\\windows\\system32\\wsmsvc.dll")
'''

min_endpoint_version = "8.14.2"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
tree = true

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1055"
name = "Process Injection"
reference = "https://attack.mitre.org/techniques/T1055/"


[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[internal]
min_endpoint_version = "8.14.2"

Stages and Predicates

Stage 1: api

api where process.Ext.api.name == "VirtualProtect" and
 process.Ext.api.behaviors == "image_indirect_call" and process.Ext.api.behaviors == "native_api" and
 (
  (process.thread.Ext.call_stack_final_user_module.path like "c:\\windows\\system32\\*.dll" and
   process.thread.Ext.call_stack_final_user_module.protection_provenance != null) or

  (process.thread.Ext.call_stack_summary == "ntdll.dll|Unknown" and process.thread.Ext.call_stack_final_user_module.name == "Unknown")
  ) and
 not process.thread.Ext.call_stack_final_user_module.protection_provenance like ("Kernel*", "ntdll.dll") and
 not process.thread.Ext.call_stack_summary like "ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|ntdll.dll|execmodelclient.dll|*" and
 not _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry, $entry.trusted == true and
                  $entry.subject_name in ("Microsoft Windows Hardware Compatibility Publisher",
                                          "Microsoft Windows Software Compatibility Publisher",
                                          "Sentinel Labs, Inc.",  "ESET, spol. s r.o.", "MUSARUBRA US LLC",
                                          "WIBU-SYSTEMS AG",  "Carbon Black, Inc.", "Adobe Inc.", "Adobe Systems, Incorporated",
                                          "Mozilla Corporation", "Google LLC", "Fasoo Co., Ltd.", "AhnLab, Inc.",
                                          "Data Encryption Systems Ltd", "Aviata, Inc.")) and
 process.thread.Ext.call_stack_final_user_module.hash.sha256 != "ebdf952adb27745e16e033f3364ce090833e6ecdafa450241793b6f290410fe9" and
 not process.thread.Ext.call_stack_final_user_module.path like "c:\\windows\\system32\\tmumh\\*\\tmmon64.dll" and
 not process.thread.Ext.call_stack_final_user_module.protection_provenance_path like
                               ("c:\\program files\\common files\\microsoft shared\\clicktorun\\appvisvsubsystems64.dll",
                                "c:\\program files\\common files\\mcafee\\systemcore\\mfehcthe.dll",
                                "c:\\program files\\windowsapps\\microsoft.net.native.runtime.*\\mrt*_app.dll",
                                "c:\\windows\\winsxs\\amd64_microsoft-windows-servicingstack_*\\turbocontainer.dll",
                                "c:\\windows\\ccm\\localapphandler.dll",
                                "c:\\program files (x86)\\adobe\\acrobat dc\\acrobat\\acrobat.exe",
                                "c:\\program files (x86)\\adobe\\acrobat reader dc\\reader\\acrord32.exe",
                                "c:\\windows\\system32\\sppcext.dll",
                                "c:\\windows\\system32\\geolocation.dll",
                                "c:\\windows\\system32\\msvcr*.dll",
                                "c:\\windows\\system32\\windows.devices.sensors.dll",
                                "c:\\windows\\system32\\tmumh\\*\\tmmon64.dll") and
 not _arraysearch(process.thread.Ext.call_stack, $entry,
                  $entry.symbol_info : ("c:\\windows\\sys?????\\ntdll.dll!LdrLoadDll*",
                                        "c:\\windows\\system32\\mdmregistration.dll!FindDiscoveryService*",
                                        "c:\\windows\\sys?????\\ntdll.dll!LdrGetProcedureAddress*",
                                        "c:\\windows\\sys?????\\ntdll.dll!LdrShutdownProcess*",
                                        "c:\\windows\\sys?????\\apphelp.dll!SE_DllLoaded*",
                                        "c:\\windows\\system32\\msvcr100.dll!tanhf*",
                                        "c:\\windows\\sys?????\\win32u.dll!NtUserCreateWindowEx*")) and
 not _arraysearch(process.thread.Ext.call_stack, $entry,$entry.callsite_trailing_bytes like "488da42428000000c3000000000000000000000000000df0adba0d*") and
 not (process.name:"powershell.exe" and
      process.parent.executable : ("C:\\Windows\\System32\\Empirum\\EmpInventory.exe",
                                   "C:\\Program Files\\ESET\\ESET Security\\ekrn.exe",
                                   "C:\\Program Files\\ESET\\ESET Endpoint Antivirus\\ekrn.exe")) and
 not (process.executable : "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" and
      process.Ext.api.summary like "VirtualProtect( clr.dll, 0x?, * )") and
 not (process.thread.Ext.call_stack_summary == "ntdll.dll|protector64.dll|wsmsvc.dll" and process.thread.Ext.call_stack_final_user_module.path == "c:\\windows\\system32\\wsmsvc.dll")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.thread.Ext.call_stack_final_user_module.code_signaturearray_any(no value, null check)excludes:process.thread.Ext.call_stack_final_user_module.code_signature
process.Ext.api.summarywildcardVirtualProtect( clr.dll, 0x?, * )excludes:process.Ext.api.summary field:"process.Ext.api.summary" value:"VirtualProtect( clr.dll, 0x?, * )"
process.executableeqC:\Windows\System32\WindowsPowerShell\v1.0\powershell.exeexcludes:process.executable field:"process.executable" value:"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
process.nameeqpowershell.exeexcludes:process.name field:"process.name" value:"powershell.exe"
process.parent.executableeqC:\Windows\System32\Empirum\EmpInventory.exe, C:\Program Files\ESET\ESET Security\ekrn.exe, C:\Program Files\ESET\ESET Endpoint Antivirus\ekrn.exeexcludes:process.parent.executable field:"process.parent.executable" value:"C:\Windows\System32\Empirum\EmpInventory.exe" field:"process.parent.executable" value:"C:\Program Files\ESET\ESET Security\ekrn.exe" field:"process.parent.executable" value:"C:\Program Files\ESET\ESET Endpoint Antivirus\ekrn.exe"
process.thread.Ext.call_stackarray_any(no value, null check)excludes:process.thread.Ext.call_stack
process.thread.Ext.call_stack_final_user_module.patheqc:\windows\system32\wsmsvc.dllexcludes:process.thread.Ext.call_stack_final_user_module.path field:"process.thread.Ext.call_stack_final_user_module.path" value:"c:\windows\system32\wsmsvc.dll"
process.thread.Ext.call_stack_summaryeqntdll.dll|protector64.dll|wsmsvc.dllexcludes:process.thread.Ext.call_stack_summary field:"process.thread.Ext.call_stack_summary" value:"ntdll.dll|protector64.dll|wsmsvc.dll"
process.thread.Ext.call_stack_final_user_module.pathwildcardc:\windows\system32\tmumh\*\tmmon64.dllexcludes:process.thread.Ext.call_stack_final_user_module.path field:"process.thread.Ext.call_stack_final_user_module.path" value:"c:\windows\system32\tmumh\*\tmmon64.dll"
process.thread.Ext.call_stack_final_user_module.protection_provenancewildcardKernel*, ntdll.dllexcludes:process.thread.Ext.call_stack_final_user_module.protection_provenance field:"process.thread.Ext.call_stack_final_user_module.protection_provenance" value:"Kernel*" field:"process.thread.Ext.call_stack_final_user_module.protection_provenance" value:"ntdll.dll"
process.thread.Ext.call_stack_final_user_module.protection_provenance_pathwildcardc:\program files\common files\microsoft shared\clicktorun\appvisvsubsystems64.dll, c:\program files\common files\mcafee\systemcore\mfehcthe.dll, c:\program files\windowsapps\microsoft.net.native.runtime.*\mrt*_app.dll, c:\windows\winsxs\amd64_microsoft-windows-servicingstack_*\turbocontainer.dll, c:\windows\ccm\localapphandler.dll, c:\program files (x86)\adobe\acrobat dc\acrobat\acrobat.exe, c:\program files (x86)\adobe\acrobat reader dc\reader\acrord32.exe, c:\windows\system32\sppcext.dll, c:\windows\system32\geolocation.dll, c:\windows\system32\msvcr*.dll, c:\windows\system32\windows.devices.sensors.dll, c:\windows\system32\tmumh\*\tmmon64.dllexcludes:process.thread.Ext.call_stack_final_user_module.protection_provenance_path
process.thread.Ext.call_stack_summarystarts_withntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|ntdll.dll|execmodelclient.dll|excludes:process.thread.Ext.call_stack_summary field:"process.thread.Ext.call_stack_summary" value:"ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|ntdll.dll|execmodelclient.dll|"

Werfault ReflectDebugger Persistence

#
Status
production
Severity
low
Time window
9m
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies the registration of a Werfault Debugger. Attackers may abuse this mechanism to execute malicious payloads every time the utility is executed with the "-pr" parameter.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2023/08/29"
integration = ["endpoint", "m365_defender", "sentinel_one_cloud_funnel", "windows", "crowdstrike"]
maturity = "production"
updated_date = "2026/05/04"

[rule]
author = ["Elastic"]
description = """
Identifies the registration of a Werfault Debugger. Attackers may abuse this mechanism to execute malicious payloads
every time the utility is executed with the "-pr" parameter.
"""
from = "now-9m"
index = [
    "logs-endpoint.events.registry-*",
    "endgame-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-windows.sysmon_operational-*",
    "logs-crowdstrike.fdr*",
]
language = "eql"
license = "Elastic License v2"
name = "Werfault ReflectDebugger Persistence"
note = """## Triage and analysis

> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

### Investigating Werfault ReflectDebugger Persistence

Werfault, the Windows Error Reporting service, can be manipulated by attackers to maintain persistence. By registering a ReflectDebugger, adversaries can execute malicious code whenever Werfault is triggered with specific parameters. The detection rule monitors registry changes in key paths associated with ReflectDebugger, alerting on unauthorized modifications indicative of potential abuse.

### Possible investigation steps

- Review the registry change event details to identify the specific path modified, focusing on the paths listed in the query: "HKLM\\Software\\Microsoft\\Windows\\Windows Error Reporting\\Hangs\\ReflectDebugger", "\\REGISTRY\\MACHINE\\Software\\Microsoft\\Windows\\Windows Error Reporting\\Hangs\\ReflectDebugger", or "MACHINE\\Software\\Microsoft\\Windows\\Windows Error Reporting\\Hangs\\ReflectDebugger".
- Check the timestamp of the registry change event to determine when the modification occurred and correlate it with other suspicious activities or events on the system around the same time.
- Investigate the user account or process responsible for the registry change to assess whether it is a legitimate action or potentially malicious. Look for unusual or unauthorized accounts making the change.
- Examine the system for any recent executions of Werfault with the "-pr" parameter, as this could indicate attempts to trigger the malicious payload.
- Search for any related alerts or logs from data sources such as Elastic Endgame, Elastic Defend, Microsoft Defender XDR, SentinelOne, or Sysmon that might provide additional context or corroborate the suspicious activity.
- Assess the system for any signs of compromise or persistence mechanisms, such as unexpected startup items, scheduled tasks, or other registry modifications that could indicate a broader attack.

### False positive analysis

- Legitimate software installations or updates may modify the ReflectDebugger registry key as part of their error reporting configuration. Users can create exceptions for known software vendors by verifying the digital signature of the executable associated with the change.
- System administrators may intentionally configure the ReflectDebugger for debugging purposes. Document and whitelist these changes in the security monitoring system to prevent unnecessary alerts.
- Automated system maintenance tools might interact with the ReflectDebugger registry key. Identify and exclude these tools by correlating the registry changes with scheduled maintenance activities.
- Security software or endpoint protection solutions may alter the ReflectDebugger settings as part of their protective measures. Confirm these changes with the security vendor and add them to the exclusion list if deemed safe.

### Response and remediation

- Immediately isolate the affected system from the network to prevent further execution of malicious code via the Werfault ReflectDebugger.
- Terminate any suspicious processes associated with Werfault that are running with the "-pr" parameter to halt potential malicious activity.
- Remove unauthorized entries from the registry path "HKLM\\Software\\Microsoft\\Windows\\Windows Error Reporting\\Hangs\\ReflectDebugger" to eliminate persistence mechanisms.
- Conduct a thorough scan of the affected system using updated antivirus or endpoint detection tools to identify and remove any additional malware or malicious artifacts.
- Review and restore any system or application configurations that may have been altered by the attacker to their original state.
- Escalate the incident to the security operations team for further analysis and to determine if additional systems are affected.
- Implement enhanced monitoring and alerting for registry changes in the specified paths to detect and respond to similar threats in the future."""
references = ["https://cocomelonc.github.io/malware/2022/11/02/malware-pers-18.html"]
risk_score = 21
rule_id = "205b52c4-9c28-4af4-8979-935f3278d61a"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Persistence",
    "Data Source: Elastic Endgame",
    "Data Source: Elastic Defend",
    "Data Source: Microsoft Defender XDR",
    "Data Source: SentinelOne",
    "Data Source: Sysmon",
    "Data Source: Crowdstrike",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
registry where host.os.type == "windows" and event.type == "change" and
  registry.value : "ReflectDebugger"

  /*
    Full registry key path omitted due to data source variations:
    HKLM\\Software\\Microsoft\\Windows\\Windows Error Reporting\\Hangs\\ReflectDebugger
  */
'''

setup = """## Setup

This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

### Additional data sources

This rule also supports the following third-party data sources. For setup instructions, refer to the links below:

- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Registry Events](https://ela.st/sysmon-event-reg-setup)
"""


[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1546"
name = "Event Triggered Execution"
reference = "https://attack.mitre.org/techniques/T1546/"

[[rule.threat.technique.subtechnique]]
id = "T1546.012"
name = "Image File Execution Options Injection"
reference = "https://attack.mitre.org/techniques/T1546/012/"

[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"

[[rule.threat]]
framework = "MITRE ATT&CK"

[[rule.threat.technique]]
id = "T1112"
name = "Modify Registry"
reference = "https://attack.mitre.org/techniques/T1112/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

Stages and Predicates

Stage 1: registry

registry where host.os.type == "windows" and event.type == "change" and
  registry.value : "ReflectDebugger"

  /*
    Full registry key path omitted due to data source variations:
    HKLM\\Software\\Microsoft\\Windows\\Windows Error Reporting\\Hangs\\ReflectDebugger
  */

Indicators

These rows show field, operator, and value matches.

Back to all Elastic rules