Detection rules › Elastic

Elastic rules: 3e

API Call via Jump ROP Gadget

#
Source
github.com/elastic/protections-artifacts

Identifies Windows Native API calls with ROP gadgets and from an unusual Microsoft signed module. This may be the result of a code injection.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = """
Identifies Windows Native API calls with ROP gadgets and from an unusual Microsoft signed module. This may be the result
of a code injection.
"""
id = "d869a5ff-5bda-4417-90c9-c353a949d26e"
license = "Elastic License v2"
name = "API Call via Jump ROP Gadget"
os_list = ["windows"]
version = "1.0.11"

query = '''
api where process.Ext.api.behaviors == "image_rop" and
 process.Ext.api.name in ("VirtualAlloc", "VirtualProtect", "WriteProcessMemory", "SetThreadContext", "SuspendThread", "VirtualProtectEx") and
 not process.thread.Ext.call_stack_final_user_module.name in ("Kernel", "Unbacked") and 
 /* final user module trailing bytes starts with JMP or CALL REG pattern */
 (
  _arraysearch(process.thread.Ext.call_stack, $entry,
               stringcontains~($entry.symbol_info, process.thread.Ext.call_stack_final_user_module.name) and $entry.callsite_trailing_bytes regex """(([23][6e]|[45].|6[4-7]|90|f[023])?ff[12de][3-7]|([23][6e]|4.|6[4-7]|90|f[023])?5[3-7]c3).+""" and not $entry.callsite_trailing_bytes : "ff15*") or

   (process.thread.Ext.call_stack_final_user_module.name == "Undetermined" and
    process.thread.Ext.call_stack_summary in 
             ("ntdll.dll|kernelbase.dll|Unbacked", 
              "ntdll.dll|kernelbase.dll|ntdll.dll",
              "ntdll.dll|kernelbase.dll|ntdll.dll|kernel32.dll|ntdll.dll") and
    _arraysearch(process.thread.Ext.call_stack, $entry,
                $entry.symbol_info : ("*kernelbase.dll*", "*ntdll.dll*") and $entry.callsite_trailing_bytes regex """(([23][6e]|[45].|6[4-7]|90|f[023])?ff([de][3-7]|[12][367]|1424|55)|([23][6e]|4.|6[4-7]|90|f[023])?5[3-7]c3).+""" and not $entry.callsite_trailing_bytes : "ff15*")) or

    (process.Ext.api.behaviors == "proxy_call" and
     process.thread.Ext.call_stack_final_user_module.name == "Undetermined" and
     process.thread.Ext.call_stack_summary like "ntdll.dll|kernelbase.dll|*" and
     _arraysearch(process.thread.Ext.call_stack, $entry, $entry.callsite_trailing_bytes regex """(([23][6e]|[45].|6[4-7]|90|f[023])?ff([de][3-7]|[12][367]|1424|55)|([23][6e]|4.|6[4-7]|90|f[023])?5[3-7]c3).+""" and not $entry.callsite_trailing_bytes : "ff15*"))
  ) and
  not (process.thread.Ext.call_stack_final_user_module.path like
                              ("c:\\program files (x86)\\*",
                               "c:\\windows\\syswow64\\*",
                               "c:\\windows\\system32\\spool\\drivers\\x64\\3\\x2wfuv0u.dll") and
       _arraysearch(process.thread.Ext.call_stack, $entry, $entry.callsite_trailing_bytes : ("??ffd6f*", "ffd6*", "??ff15*", "??ff14*", "55c316*"))) and
  not process.thread.Ext.call_stack_final_user_module.hash.sha256 in
                                  ("5e3758ffbb23dd84717ba3193deea24d47de15de5f65dd7051fcb5ede6938340",
                                   "526104f18200c6cd055886c4d08f02278aa0325abe17b697529e4a67ac7582f8",
                                   "579ab93c5db70cd3b3b3e2372cfcba1d968336e7e88b6ffc9e85160cc7c41d93",
                                   "0d5d73d3bea132f98be91f918d13043791decb419a81d9e755979315a7cf0502",
                                   "55bc12b34f81f43fa99bbe18d4ca1f07ccdde962039c59959d212aa7eac7586d",
                                   "92090a86491251f461e1b8e6e7c6ff9f1ed0aebd63c19381850e219d2dd44708",
                                   "9ace6b6d2093f4812461a4d05c66cf3a4f838b5292deea78c31e7301feeebc82",
                                   "e093097faf851745b434c376dd48139eb0883805f130cb94d8ed5a10317dc745",
                                   "a86749e6e28a8991c0b04fd626f49731e6b1185686e52523ea51a00f10f709d9",
                                   "f7df966bb1aab2a430134148bd5fd9024cc69b0e4f22ee2db00130effc577965") and
  not (process.executable : "C:\\Program Files\\Evolution Services Manager\\FireDaemon.exe" and
       process.thread.Ext.call_stack_final_user_module.path == "c:\\program files\\evolution services manager\\licensing.dll") and 
  not process.thread.Ext.call_stack_summary like ("ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|*", "wow64cpu.dll|wow64.dll|ntdll.dll|kernelbase.dll|webio.dll|*") and
  not _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature,
                   $entry, $entry.subject_name in ("Microsoft Windows Hardware Compatibility Publisher", "Microsoft Windows Software Compatibility Publisher") and $entry.status == "trusted") and
  process.thread.Ext.call_stack_final_user_module.path != "c:\\program files\\microsoft office\\office16\\gkexcel.dll" and
  not _arraysearch(process.thread.Ext.call_stack, $entry,
                   $entry.callsite_trailing_bytes like
                               ("f0ffe*",
                                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
                                "48ff25da280000*", "48ff15339d0000*", "48ff1524a601000f1f4400008bf0*", "ff24bc1894320000ff24bc1894320000ff24*",
                                "48ff1594aa01000f1f4400008bf0488d84249800000048398424900000007459488d8c2490000000e8e2f4ffffeb4a488d8424a00100004883ceff48ffc66639"))
'''

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

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

[[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.10.0"

Stages and Predicates

Stage 1: api

api where process.Ext.api.behaviors == "image_rop" and
 process.Ext.api.name in ("VirtualAlloc", "VirtualProtect", "WriteProcessMemory", "SetThreadContext", "SuspendThread", "VirtualProtectEx") and
 not process.thread.Ext.call_stack_final_user_module.name in ("Kernel", "Unbacked") and
 (
  _arraysearch(process.thread.Ext.call_stack, $entry,
               stringcontains~($entry.symbol_info, process.thread.Ext.call_stack_final_user_module.name) and $entry.callsite_trailing_bytes regex """(([23][6e]|[45].|6[4-7]|90|f[023])?ff[12de][3-7]|([23][6e]|4.|6[4-7]|90|f[023])?5[3-7]c3).+""" and not $entry.callsite_trailing_bytes : "ff15*") or
   (process.thread.Ext.call_stack_final_user_module.name == "Undetermined" and
    process.thread.Ext.call_stack_summary in
             ("ntdll.dll|kernelbase.dll|Unbacked",
              "ntdll.dll|kernelbase.dll|ntdll.dll",
              "ntdll.dll|kernelbase.dll|ntdll.dll|kernel32.dll|ntdll.dll") and
    _arraysearch(process.thread.Ext.call_stack, $entry,
                $entry.symbol_info : ("*kernelbase.dll*", "*ntdll.dll*") and $entry.callsite_trailing_bytes regex """(([23][6e]|[45].|6[4-7]|90|f[023])?ff([de][3-7]|[12][367]|1424|55)|([23][6e]|4.|6[4-7]|90|f[023])?5[3-7]c3).+""" and not $entry.callsite_trailing_bytes : "ff15*")) or
    (process.Ext.api.behaviors == "proxy_call" and
     process.thread.Ext.call_stack_final_user_module.name == "Undetermined" and
     process.thread.Ext.call_stack_summary like "ntdll.dll|kernelbase.dll|*" and
     _arraysearch(process.thread.Ext.call_stack, $entry, $entry.callsite_trailing_bytes regex """(([23][6e]|[45].|6[4-7]|90|f[023])?ff([de][3-7]|[12][367]|1424|55)|([23][6e]|4.|6[4-7]|90|f[023])?5[3-7]c3).+""" and not $entry.callsite_trailing_bytes : "ff15*"))
  ) and
  not (process.thread.Ext.call_stack_final_user_module.path like
                              ("c:\\program files (x86)\\*",
                               "c:\\windows\\syswow64\\*",
                               "c:\\windows\\system32\\spool\\drivers\\x64\\3\\x2wfuv0u.dll") and
       _arraysearch(process.thread.Ext.call_stack, $entry, $entry.callsite_trailing_bytes : ("??ffd6f*", "ffd6*", "??ff15*", "??ff14*", "55c316*"))) and
  not process.thread.Ext.call_stack_final_user_module.hash.sha256 in
                                  ("5e3758ffbb23dd84717ba3193deea24d47de15de5f65dd7051fcb5ede6938340",
                                   "526104f18200c6cd055886c4d08f02278aa0325abe17b697529e4a67ac7582f8",
                                   "579ab93c5db70cd3b3b3e2372cfcba1d968336e7e88b6ffc9e85160cc7c41d93",
                                   "0d5d73d3bea132f98be91f918d13043791decb419a81d9e755979315a7cf0502",
                                   "55bc12b34f81f43fa99bbe18d4ca1f07ccdde962039c59959d212aa7eac7586d",
                                   "92090a86491251f461e1b8e6e7c6ff9f1ed0aebd63c19381850e219d2dd44708",
                                   "9ace6b6d2093f4812461a4d05c66cf3a4f838b5292deea78c31e7301feeebc82",
                                   "e093097faf851745b434c376dd48139eb0883805f130cb94d8ed5a10317dc745",
                                   "a86749e6e28a8991c0b04fd626f49731e6b1185686e52523ea51a00f10f709d9",
                                   "f7df966bb1aab2a430134148bd5fd9024cc69b0e4f22ee2db00130effc577965") and
  not (process.executable : "C:\\Program Files\\Evolution Services Manager\\FireDaemon.exe" and
       process.thread.Ext.call_stack_final_user_module.path == "c:\\program files\\evolution services manager\\licensing.dll") and
  not process.thread.Ext.call_stack_summary like ("ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|*", "wow64cpu.dll|wow64.dll|ntdll.dll|kernelbase.dll|webio.dll|*") and
  not _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature,
                   $entry, $entry.subject_name in ("Microsoft Windows Hardware Compatibility Publisher", "Microsoft Windows Software Compatibility Publisher") and $entry.status == "trusted") and
  process.thread.Ext.call_stack_final_user_module.path != "c:\\program files\\microsoft office\\office16\\gkexcel.dll" and
  not _arraysearch(process.thread.Ext.call_stack, $entry,
                   $entry.callsite_trailing_bytes like
                               ("f0ffe*",
                                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
                                "48ff25da280000*", "48ff15339d0000*", "48ff1524a601000f1f4400008bf0*", "ff24bc1894320000ff24bc1894320000ff24*",
                                "48ff1594aa01000f1f4400008bf0488d84249800000048398424900000007459488d8c2490000000e8e2f4ffffeb4a488d8424a00100004883ceff48ffc66639"))

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
process.Ext.api.behaviorseq
  • image_rop corpus 3 (elastic 3)
  • proxy_call corpus 4 (elastic 4)
field:"process.Ext.api.behaviors" kind:eq
process.Ext.api.namein
  • SetThreadContext corpus 14 (elastic 14)
  • SuspendThread corpus 12 (elastic 12)
  • VirtualAlloc corpus 27 (elastic 27)
  • VirtualProtect corpus 35 (elastic 35)
  • VirtualProtectEx corpus 29 (elastic 29)
  • WriteProcessMemory corpus 23 (elastic 23)
field:"process.Ext.api.name" kind:in
process.thread.Ext.call_stack_final_user_module.nameeq
  • Undetermined corpus 4 (elastic 4)
field:"process.thread.Ext.call_stack_final_user_module.name" kind:eq value:"Undetermined"
process.thread.Ext.call_stack_final_user_module.pathne
  • c:\program files\microsoft office\office16\gkexcel.dll
field:"process.thread.Ext.call_stack_final_user_module.path" kind:ne value:"c:\program files\microsoft office\office16\gkexcel.dll"
process.thread.Ext.call_stack_summaryin
  • ntdll.dll|kernelbase.dll|Unbacked corpus 11 (elastic 11)
  • ntdll.dll|kernelbase.dll|ntdll.dll
  • ntdll.dll|kernelbase.dll|ntdll.dll|kernel32.dll|ntdll.dll corpus 4 (elastic 4)
field:"process.thread.Ext.call_stack_summary" kind:in
process.thread.Ext.call_stack_summarywildcard
  • ntdll.dll|kernelbase.dll|* corpus 4 (elastic 4)
field:"process.thread.Ext.call_stack_summary" kind:wildcard value:"ntdll.dll|kernelbase.dll|*"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.thread.Ext.call_stackarray_any(no value, null check)excludes:process.thread.Ext.call_stack
process.thread.Ext.call_stack_final_user_module.pathwildcardc:\program files (x86)\*, c:\windows\syswow64\*, c:\windows\system32\spool\drivers\x64\3\x2wfuv0u.dllexcludes:process.thread.Ext.call_stack_final_user_module.path field:"process.thread.Ext.call_stack_final_user_module.path" value:"c:\program files (x86)\*" field:"process.thread.Ext.call_stack_final_user_module.path" value:"c:\windows\syswow64\*" field:"process.thread.Ext.call_stack_final_user_module.path" value:"c:\windows\system32\spool\drivers\x64\3\x2wfuv0u.dll"
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.executableeqC:\Program Files\Evolution Services Manager\FireDaemon.exeexcludes:process.executable field:"process.executable" value:"C:\Program Files\Evolution Services Manager\FireDaemon.exe"
process.thread.Ext.call_stack_final_user_module.patheqc:\program files\evolution services manager\licensing.dllexcludes:process.thread.Ext.call_stack_final_user_module.path field:"process.thread.Ext.call_stack_final_user_module.path" value:"c:\program files\evolution services manager\licensing.dll"
process.thread.Ext.call_stack_final_user_module.hash.sha256in0d5d73d3bea132f98be91f918d13043791decb419a81d9e755979315a7cf0502, 526104f18200c6cd055886c4d08f02278aa0325abe17b697529e4a67ac7582f8, 55bc12b34f81f43fa99bbe18d4ca1f07ccdde962039c59959d212aa7eac7586d, 579ab93c5db70cd3b3b3e2372cfcba1d968336e7e88b6ffc9e85160cc7c41d93, 5e3758ffbb23dd84717ba3193deea24d47de15de5f65dd7051fcb5ede6938340, 92090a86491251f461e1b8e6e7c6ff9f1ed0aebd63c19381850e219d2dd44708, 9ace6b6d2093f4812461a4d05c66cf3a4f838b5292deea78c31e7301feeebc82, a86749e6e28a8991c0b04fd626f49731e6b1185686e52523ea51a00f10f709d9, e093097faf851745b434c376dd48139eb0883805f130cb94d8ed5a10317dc745, f7df966bb1aab2a430134148bd5fd9024cc69b0e4f22ee2db00130effc577965excludes:process.thread.Ext.call_stack_final_user_module.hash.sha256
process.thread.Ext.call_stack_final_user_module.nameinKernel, Unbackedexcludes:process.thread.Ext.call_stack_final_user_module.name field:"process.thread.Ext.call_stack_final_user_module.name" value:"Kernel" field:"process.thread.Ext.call_stack_final_user_module.name" value:"Unbacked"
process.thread.Ext.call_stack_summarystarts_withntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|, wow64cpu.dll|wow64.dll|ntdll.dll|kernelbase.dll|webio.dll|excludes:process.thread.Ext.call_stack_summary field:"process.thread.Ext.call_stack_summary" value:"ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|" field:"process.thread.Ext.call_stack_summary" value:"wow64cpu.dll|wow64.dll|ntdll.dll|kernelbase.dll|webio.dll|"

AWS Bedrock Automated Reasoning Safety Policy Tampering

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

Detects deletion or modification of AWS Bedrock Automated Reasoning policies via the DeleteAutomatedReasoningPolicy, UpdateAutomatedReasoningPolicy, or UpdateAutomatedReasoningPolicyAnnotations CloudTrail actions. Automated Reasoning policies are a Bedrock safety and validation control that constrains model outputs against formal rules. An adversary who deletes a policy or alters the policy definition or its annotations weakens an enforced output-validation defense, potentially allowing unsafe or non-compliant model responses to pass unchecked. Benign build, test-workflow, and test-case CRUD operations are intentionally excluded as they have no coherent abuse path.

Known False Positives

  • Policy administrators, ML platform engineers, or infrastructure-as-code pipelines may legitimately update or remove Automated Reasoning policies during model governance changes, policy tuning, or environment teardown. Verify that the user identity, source IP, and user agent correspond to an approved change and that a corresponding change request exists. Known automation roles can be exempted if they generate recurring noise.

MITRE ATT&CK Coverage

TacticTechniques
Defense Impairment

Telemetry Coverage

Rule Body

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

[rule]
author = ["Elastic"]
description = """
Detects deletion or modification of AWS Bedrock Automated Reasoning policies via the DeleteAutomatedReasoningPolicy,
UpdateAutomatedReasoningPolicy, or UpdateAutomatedReasoningPolicyAnnotations CloudTrail actions. Automated Reasoning
policies are a Bedrock safety and validation control that constrains model outputs against formal rules. An adversary
who deletes a policy or alters the policy definition or its annotations weakens an enforced output-validation defense,
potentially allowing unsafe or non-compliant model responses to pass unchecked. Benign build, test-workflow, and
test-case CRUD operations are intentionally excluded as they have no coherent abuse path.
"""
false_positives = [
    """
    Policy administrators, ML platform engineers, or infrastructure-as-code pipelines may legitimately update or remove
    Automated Reasoning policies during model governance changes, policy tuning, or environment teardown. Verify that
    the user identity, source IP, and user agent correspond to an approved change and that a corresponding change
    request exists. Known automation roles can be exempted if they generate recurring noise.
    """,
]
from = "now-6m"
index = ["logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS Bedrock Automated Reasoning Safety Policy Tampering"
note = """## Triage and analysis

### Investigating AWS Bedrock Automated Reasoning Safety Policy Tampering

AWS Bedrock Automated Reasoning policies enforce formal, rule-based validation of model outputs, acting as a
safety control that constrains what a model is permitted to return. Deleting a policy or modifying its
definition or annotations directly weakens this control. Adversaries who have gained access to the Bedrock
control plane may tamper with these policies to evade output-validation defenses, enabling unsafe, manipulated,
or non-compliant model behavior. This detection identifies `DeleteAutomatedReasoningPolicy`,
`UpdateAutomatedReasoningPolicy`, and `UpdateAutomatedReasoningPolicyAnnotations` calls so responders can
confirm whether the change was authorized.

#### Possible investigation steps

- **Identify the actor and context**
  - Review `aws.cloudtrail.user_identity.arn`, `aws.cloudtrail.user_identity.type`,
    `aws.cloudtrail.user_identity.access_key_id`, `source.ip`, and `user_agent.original`.
  - Determine whether the identity normally administers Bedrock safety policies and whether the action aligns
    with an approved change request.
- **Review the specific action**
  - For `DeleteAutomatedReasoningPolicy`, identify the deleted policy in
    `aws.cloudtrail.flattened.request_parameters` and confirm whether a replacement control exists.
  - For `UpdateAutomatedReasoningPolicy` / `UpdateAutomatedReasoningPolicyAnnotations`, inspect
    `aws.cloudtrail.request_parameters` and `aws.cloudtrail.response_elements` to understand what was changed
    and whether the change loosens validation constraints.
- **Correlate surrounding activity**
  - Look for other Defense Evasion or Bedrock control-plane activity from the same identity in the surrounding
    window (model invocation changes, guardrail modifications, logging changes).
  - Check `cloud.account.id` and `cloud.region` to scope blast radius across the environment.

### False positive analysis

- **Planned policy maintenance**: Governance teams may legitimately tune or retire Automated Reasoning
  policies. Validate against change tickets and standard templates.
- **Automation**: IaC or CI/CD pipelines may update policies during deployments. Confirm the actor maps to
  known automation infrastructure.

### Response and remediation

- If the change is unauthorized, restore the prior policy definition or recreate the deleted policy from a
  known-good configuration.
- Revoke or rotate the credentials in `aws.cloudtrail.user_identity.access_key_id` if compromise is suspected.
- Review all Bedrock control-plane activity from the same identity in the preceding window for further
  defense-impairing actions.
- Restrict `bedrock:DeleteAutomatedReasoningPolicy` and `bedrock:UpdateAutomatedReasoningPolicy*` permissions
  to a small set of administrative roles and enforce approval workflows.
"""
references = [
    "https://docs.aws.amazon.com/bedrock/latest/userguide/automated-reasoning.html"
]
risk_score = 47
rule_id = "2d7822a5-418c-4cde-a96e-e337d77b67e7"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Domain: LLM",
    "Data Source: AWS",
    "Data Source: AWS CloudTrail",
    "Data Source: Amazon Web Services",
    "Data Source: Amazon Bedrock",
    "Use Case: Threat Detection",
    "Resources: Investigation Guide",
    "Tactic: Defense Evasion"
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset: "aws.cloudtrail" and
    event.provider: "bedrock.amazonaws.com" and
    event.action: (
        "DeleteAutomatedReasoningPolicy" or
        "UpdateAutomatedReasoningPolicy" or
        "UpdateAutomatedReasoningPolicyAnnotations"
    ) and event.outcome: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.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

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

Stages and Predicates

Stage 1: query

data_stream.dataset: "aws.cloudtrail" and
    event.provider: "bedrock.amazonaws.com" and
    event.action: (
        "DeleteAutomatedReasoningPolicy" or
        "UpdateAutomatedReasoningPolicy" or
        "UpdateAutomatedReasoningPolicyAnnotations"
    ) and event.outcome:success

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
data_stream.dataseteq
  • aws.cloudtrail corpus 143 (elastic 143)
field:"data_stream.dataset" kind:eq value:"aws.cloudtrail"
event.actionin
  • DeleteAutomatedReasoningPolicy
  • UpdateAutomatedReasoningPolicy
  • UpdateAutomatedReasoningPolicyAnnotations
field:"EventType" kind:in
event.outcomeeq
  • success corpus 306 (elastic 306)
field:"event.outcome" kind:eq value:"success"
event.providereq
  • bedrock.amazonaws.com corpus 13 (elastic 13)
field:"Provider_Name" kind:eq value:"bedrock.amazonaws.com"

AWS EC2 EBS Snapshot Access Removed

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

Identifies the removal of access permissions from a shared AWS EC2 EBS snapshot. EBS snapshots are essential for data retention and disaster recovery. Adversaries may revoke or modify snapshot permissions to prevent legitimate users from accessing backups, thereby obstructing recovery efforts after data loss or destructive actions. This tactic can also be used to evade detection or maintain exclusive access to critical backups, ultimately increasing the impact of an attack and complicating incident response.

Known False Positives

  • Access removal may be a part of normal operations and should be verified before taking action.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

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

[rule]
author = ["Elastic"]
description = """
Identifies the removal of access permissions from a shared AWS EC2 EBS snapshot. EBS snapshots are essential for data
retention and disaster recovery. Adversaries may revoke or modify snapshot permissions to prevent legitimate users from
accessing backups, thereby obstructing recovery efforts after data loss or destructive actions. This tactic can also be
used to evade detection or maintain exclusive access to critical backups, ultimately increasing the impact of an attack
and complicating incident response.
"""
event_category_override = "event.type"
false_positives = ["Access removal may be a part of normal operations and should be verified before taking action."]
from = "now-6m"
index = ["filebeat-*", "logs-aws.cloudtrail-*"]
language = "eql"
license = "Elastic License v2"
name = "AWS EC2 EBS Snapshot Access Removed"
note = """## Triage and analysis

### Investigating AWS EC2 EBS Snapshot Access Removed

This rule detects when access is removed for an AWS EC2 EBS snapshot. EBS virtual disks can be copied into snapshots, which can then be used as backups for recovery and data retention efforts. Adversaries may attempt to remove access to snapshots in order to prevent legitimate users or automated processes from accessing or restoring from snapshots following data loss, ransomware, or destructive actions. This can significantly delay or even prevent recovery, increasing the impact of the attack. Restricting snapshot access may help adversaries cover their tracks by making it harder for defenders to analyze or recover deleted or altered data. Attackers may remove permissions for all users except their own compromised account, allowing them to maintain exclusive access to backups for future use or leverage. Understanding the context and legitimacy of such changes is crucial to determine if the action is benign or malicious.

#### Possible investigation steps:

- **Identify who performed the action**: Review `aws.cloudtrail.user_identity.arn` and `aws.cloudtrail.user_identity.access_key_id` to identify who made the change. Evaluate whether the identity is authorized to manage EBS snapshot permissions (check IAM policies for `ec2:ModifySnapshotAttribute`). 

- **Analyze the source of the request**: Examine `source.ip` and `source.geo` fields to determine the geographical origin of the request. An external or unexpected location might indicate compromised credentials or unauthorized access. Review `user_agent.original` to determine if the request came from an expected administrative tool or host.

- **Examine the scope of the change**:
  - Review `aws.cloudtrail.request_parameters` to understand which accounts or entities had access removed.  
    - Look for unusual patterns such as `createVolumePermission={remove=all}` or removal of specific external or organizational accounts.  
  - Cross-check the affected `snapshotId` in the AWS console or via CLI to confirm current sharing status and determine if any copies or dependent volumes exist.  
  - Use AWS Config or AWS CLI (`describe-snapshot-attribute`) to verify whether other snapshots were modified within the same timeframe.

- **Correlate with other activities**:
  - Search CloudTrail for additional activity from the same actor or `source.ip` around the event time.  
    - Pay special attention to subsequent `DeleteSnapshot`, `DeregisterImage`, or `RevokeSnapshotAccess` events, which may signal ongoing destruction.  
    - Check for parallel IAM activity, such as policy changes that grant or revoke permissions.  
  - Correlate with GuardDuty or Security Hub findings related to data exfiltration, destructive actions, or unauthorized configuration changes.  
  - Determine if any high-value or production snapshots were affected, especially those linked to business-critical EBS volumes.

- **Evaluate timing and intent**: Compare `@timestamp` with maintenance windows or known change requests. Actions taken outside approved hours or without associated tickets may indicate compromise or sabotage. If this change coincides with other detections (for example, `EBS encryption disabled` or `root login` events), treat it as part of a coordinated impact campaign.

### False positive analysis:

- **Planned administrative maintenance**: Confirm whether this snapshot modification aligns with backup rotation, retention policy enforcement, or snapshot lifecycle automation.  
- **Automation and tooling**: Infrastructure-as-code pipelines or DevOps scripts may legitimately remove snapshot sharing to enforce compliance. Review tags, user agents, and automation identifiers.  
- **Testing or sandbox accounts**: Some non-production environments may modify snapshot access for isolation. Validate account purpose before escalating.

If the action was expected, document the change approval and reconcile against internal audit or change-control systems.

### Response and remediation:

**Containment and validation**
- Review and, if necessary, restore snapshot permissions using AWS Console or CLI (`modify-snapshot-attribute` with `add` parameters).  
- Confirm that no additional snapshots or AMIs have had access removed.  
- Restrict `ec2:ModifySnapshotAttribute` permissions to only trusted administrative roles.

**Investigate for data destruction or persistence**
- Determine if the same actor also deleted or copied snapshots (`DeleteSnapshot`, `CopySnapshot`).  
- Review subsequent volume creation or image registration events that could indicate snapshot reuse.  
- Identify whether any snapshot was shared to or copied by an external AWS account.

**Strengthen detection and monitoring**
- Enable AWS Config rules and Security Hub controls such as `ebs-snapshot-public-restorable-check`.  
- Establish continuous monitoring for `ModifySnapshotAttribute` and `DeleteSnapshot` operations.  
- Correlate future detections with user identity and source IP context to identify recurring behavior.

**Recovery and hardening**
- Verify that critical snapshots and backups are retained and encrypted.  
- Implement backup immutability with AWS Backup Vault Lock or S3 Object Lock for long-term protection.  
- Apply service control policies (SCPs) to prevent unauthorized modification of snapshot sharing attributes.  
- Conduct a post-incident review to identify the root cause and strengthen least-privilege enforcement for EBS management roles.

### Additional information

- **[AWS Incident Response Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/blob/c151b0dc091755fffd4d662a8f29e2f6794da52c/playbooks/)**: guidance for investigating unauthorized access to modify account settings.  
- **[AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework/)**: Example framework for customers to create, develop, and integrate security playbooks in preparation for potential attack scenarios when using AWS services
- **AWS Documentation**  
  - [EBS Snapshot Permissions](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-modifying-snapshot-permissions.html)  
  - [ModifySnapshotAttribute API Reference](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifySnapshotAttribute.html)
"""
references = [
    "https://docs.aws.amazon.com/ebs/latest/userguide/ebs-modifying-snapshot-permissions.html",
    "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifySnapshotAttribute.html",
]
risk_score = 47
rule_id = "713e0f5f-caf7-4dc2-88a7-3561f61f262a"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Platform: AWS",
    "Data Source: AWS CloudTrail",
    "Service: AWS EC2",
    "Tactic: Impact",
    "Rule Type: Event Correlation (EQL)",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
info where data_stream.dataset == "aws.cloudtrail"  
  and event.action == "ModifySnapshotAttribute"
  and event.outcome == "success"
  and stringContains (aws.cloudtrail.request_parameters, "attributeType=CREATE_VOLUME_PERMISSION")
  and stringContains (aws.cloudtrail.request_parameters, "remove=")
  and not source.address == "backup.amazonaws.com"
  and not user_agent.original like~ ("*Terraform*", "*Pulumi*")
'''

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

[[rule.threat.technique]]
id = "T1485"
name = "Data Destruction"
reference = "https://attack.mitre.org/techniques/T1485/"

[[rule.threat.technique]]
id = "T1490"
name = "Inhibit System Recovery"
reference = "https://attack.mitre.org/techniques/T1490/"

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

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

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

[[rule.threat.technique.subtechnique]]
id = "T1578.005"
name = "Modify Cloud Compute Configurations"
reference = "https://attack.mitre.org/techniques/T1578/005/"

[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[rule.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user_agent.original",
    "source.ip",
    "aws.cloudtrail.user_identity.arn",
    "aws.cloudtrail.user_identity.type",
    "aws.cloudtrail.user_identity.access_key_id",
    "event.action",
    "event.outcome",
    "cloud.account.id",
    "cloud.region",
    "aws.cloudtrail.request_parameters",
    "aws.cloudtrail.response_elements",
]

Stages and Predicates

Stage 1: info

info where data_stream.dataset == "aws.cloudtrail"  
  and event.action == "ModifySnapshotAttribute"
  and event.outcome == "success"
  and stringContains (aws.cloudtrail.request_parameters, "attributeType=CREATE_VOLUME_PERMISSION")
  and stringContains (aws.cloudtrail.request_parameters, "remove=")
  and not source.address == "backup.amazonaws.com"
  and not user_agent.original like~ ("*Terraform*", "*Pulumi*")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
aws.cloudtrail.request_parameterscontains
  • attributeType=CREATE_VOLUME_PERMISSION corpus 2 (elastic 2)
  • remove=
field:"aws::requestParameters" kind:contains
data_stream.dataseteq
  • aws.cloudtrail corpus 40 (elastic 40)
field:"data_stream.dataset" kind:eq value:"aws.cloudtrail"
event.actioneq
  • ModifySnapshotAttribute corpus 2 (elastic 2)
field:"EventType" kind:eq value:"ModifySnapshotAttribute"
event.outcomeeq
  • success corpus 82 (elastic 82)
field:"event.outcome" kind:eq value:"success"

Exclusions

The rule actively suppresses these predicates.

AWS Lambda Function Invoked Cross-Account

#
Status
production
Severity
medium
Time window
61m
Group by
Esql.caller_account, Esql.function_account, aws.cloudtrail.user_identity.arn
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies an AWS Lambda function invoked by a principal whose AWS account differs from the account that owns the function (a cross-account invocation). The caller's account is parsed from the invoking principal's ARN and compared to the function account. Adversaries who have been granted invoke permission on a function from an external account, or who operate from a separate attacker-controlled account, can use cross-account invocation to execute functions or retrieve the data they return. This is the data-plane counterpart to detecting the cross-account grant itself, and relies on AWS Lambda data event logging, which is not enabled by default.

Known False Positives

  • Multi-account architectures and partner integrations legitimately invoke functions across account boundaries. Verify the caller account, the principal in `aws.cloudtrail.user_identity.arn`, and the function against approved cross-account access, and exclude known trusted accounts or identities after validation.

MITRE ATT&CK Coverage

TacticTechniques
Execution

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

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

[rule]
author = ["Elastic"]
description = """
Identifies an AWS Lambda function invoked by a principal whose AWS account differs from the account that owns the
function (a cross-account invocation). The caller's account is parsed from the invoking principal's ARN and compared to
the function account. Adversaries who have been granted invoke permission on a function from an external account, or who
operate from a separate attacker-controlled account, can use cross-account invocation to execute functions or retrieve
the data they return. This is the data-plane counterpart to detecting the cross-account grant itself, and relies on AWS
Lambda data event logging, which is not enabled by default.
"""
false_positives = [
    """
    Multi-account architectures and partner integrations legitimately invoke functions across account boundaries. Verify
    the caller account, the principal in `aws.cloudtrail.user_identity.arn`, and the function against approved
    cross-account access, and exclude known trusted accounts or identities after validation.
    """,
]
from = "now-61m"
interval = "60m"
language = "esql"
license = "Elastic License v2"
name = "AWS Lambda Function Invoked Cross-Account"
note = """## Triage and analysis

### Investigating AWS Lambda Function Invoked Cross-Account

A Lambda function invoked by a principal from a different AWS account indicates cross-account invocation - the data-plane realization of a cross-account resource-policy grant. CloudTrail data events record the invoking principal's ARN (which contains the caller's account) and the function's owning account. When these differ, an external account executed the function. This can be a legitimate multi-account integration or an adversary using granted or attacker-controlled cross-account access.

#### Possible investigation steps

- Review `Esql.caller_account` (the invoking principal's account) versus `Esql.function_account` (the invoked function's owning account) and confirm whether the caller account is a known, trusted account.
- Identify the principal in `aws.cloudtrail.user_identity.arn` and pivot to the raw CloudTrail events (for the same principal/time window) to identify the invoked function(s) in `aws.cloudtrail.request_parameters`.
- Determine whether a corresponding `AddPermission` cross-account grant exists for the function and whether it was expected (correlate with the cross-account resource-policy rule).
- Review `Esql.source_ips` and recent activity from the caller account for other cross-account actions.

### False positive analysis

- Cross-account invocation is common in multi-account architectures and partner integrations. Confirm the caller account is approved and exclude known trusted accounts or identities after validation.

### Response and remediation

- If the cross-account access is unauthorized, remove the function's cross-account resource-policy statement (`RemovePermission`) and review what the function accessed or returned.
- Constrain `lambda:InvokeFunction` grants to approved accounts and review the function's execution-role permissions.

### Additional information

- [Lambda resource-based policies](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)
- [Logging Lambda data events with CloudTrail](https://docs.aws.amazon.com/lambda/latest/dg/logging-using-cloudtrail.html)
"""
references = [
    "https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html",
    "https://docs.aws.amazon.com/lambda/latest/dg/logging-using-cloudtrail.html",
]
risk_score = 47
rule_id = "49002bbe-7aea-4146-91eb-b2b683bf5ed5"
setup = """## Setup

This rule requires AWS Lambda data events to be logged in CloudTrail and ingested via the AWS integration. Lambda
invocation (`Invoke`) is a data-plane event and is NOT logged by default; enable data event logging for Lambda functions
in the trail (optionally scoped to sensitive functions to manage volume).
"""
severity = "medium"
tags = [
    "Domain: Cloud",
    "Data Source: AWS",
    "Data Source: Amazon Web Services",
    "Data Source: AWS Lambda",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-aws.cloudtrail-*

| where
    event.provider == "lambda.amazonaws.com"
    and event.action like "Invoke*"
    and event.outcome == "success"
    and aws.cloudtrail.user_identity.arn IS NOT NULL
    and aws.cloudtrail.user_identity.invoked_by IS NULL
    and aws.cloudtrail.request_parameters IS NOT NULL

| grok aws.cloudtrail.user_identity.arn """:(?<Esql.caller_account>[0-9]{12}):"""
| grok aws.cloudtrail.request_parameters """functionName=arn:aws:lambda:[a-z0-9-]*:(?<Esql.function_account>[0-9]{12}):"""

| where Esql.caller_account IS NOT NULL and Esql.function_account IS NOT NULL and Esql.caller_account != Esql.function_account

| stats
    Esql.invocation_count = count(*),
    Esql.source_ips = values(source.ip),
    Esql.function_arns = values(aws.cloudtrail.resources.arn)
  by
    aws.cloudtrail.user_identity.arn,
    Esql.caller_account,
    Esql.function_account

| keep
    aws.cloudtrail.user_identity.arn,
    Esql.caller_account,
    Esql.function_account,
    Esql.function_arns,
    Esql.invocation_count,
    Esql.source_ips

'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1648"
name = "Serverless Execution"
reference = "https://attack.mitre.org/techniques/T1648/"


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

[rule.investigation_fields]
field_names = [
    "aws.cloudtrail.user_identity.arn",
    "Esql.caller_account",
    "Esql.function_account",
    "Esql.function_arns",
    "Esql.invocation_count",
    "Esql.source_ips",
]

Stages and Predicates

Stage 1: from

from logs-aws.cloudtrail-*

Stage 2: where

| where
    event.provider == "lambda.amazonaws.com"
    and event.action like "Invoke*"
    and event.outcome == "success"
    and aws.cloudtrail.user_identity.arn IS NOT NULL
    and aws.cloudtrail.user_identity.invoked_by IS NULL
    and aws.cloudtrail.request_parameters IS NOT NULL

Stage 3: grok

| grok aws.cloudtrail.user_identity.arn """:(?<Esql.caller_account>[0-9]{12}):"""

Stage 4: grok

| grok aws.cloudtrail.request_parameters """functionName=arn:aws:lambda:[a-z0-9-]*:(?<Esql.function_account>[0-9]{12}):"""

Stage 5: where

| where Esql.caller_account IS NOT NULL and Esql.function_account IS NOT NULL and Esql.caller_account != Esql.function_account

Stage 6: stats

| stats
    Esql.invocation_count = count(*),
    Esql.source_ips = values(source.ip),
    Esql.function_arns = values(aws.cloudtrail.resources.arn)
  by
    aws.cloudtrail.user_identity.arn,
    Esql.caller_account,
    Esql.function_account

Stage 7: keep

| keep
    aws.cloudtrail.user_identity.arn,
    Esql.caller_account,
    Esql.function_account,
    Esql.function_arns,
    Esql.invocation_count,
    Esql.source_ips

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
Esql.caller_accountKEEP Esql.caller_account
Esql.function_accountKEEP Esql.function_account
Esql.function_arnsKEEP Esql.function_arns
Esql.invocation_countKEEP Esql.invocation_count
Esql.source_ipsKEEP Esql.source_ips

AWS RDS Snapshot Export

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

Identifies the export of a DB snapshot or DB cluster data to Amazon S3. Snapshot exports can be used for analytics or migration workflows, but adversaries may abuse them to exfiltrate sensitive data outside of RDS-managed storage. Exporting a snapshot creates a portable copy of the database contents, which, if performed without authorization, can indicate data theft, staging for exfiltration, or operator misconfiguration that exposes regulated information.

Known False Positives

  • Snapshot exports may be performed by administrators, automation pipelines, or data engineering workflows. Confirm whether the export was expected and initiated by an authorized user, role, or automation process. Snapshot exports by unfamiliar principals or from unexpected networks should be investigated. If known behavior causes false positives, it can be exempted from the rule.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2021/06/06"
integration = ["aws"]
maturity = "production"
updated_date = "2026/07/08"

[rule]
author = ["Elastic", "Austin Songer"]
description = """
Identifies the export of a DB snapshot or DB cluster data to Amazon S3. Snapshot exports can be used for analytics or
migration workflows, but adversaries may abuse them to exfiltrate sensitive data outside of RDS-managed storage.
Exporting a snapshot creates a portable copy of the database contents, which, if performed without authorization, can
indicate data theft, staging for exfiltration, or operator misconfiguration that exposes regulated information.
"""
false_positives = [
    """
    Snapshot exports may be performed by administrators, automation pipelines, or data engineering workflows. Confirm
    whether the export was expected and initiated by an authorized user, role, or automation process. Snapshot exports
    by unfamiliar principals or from unexpected networks should be investigated. If known behavior causes false
    positives, it can be exempted from the rule.
    """,
]
from = "now-6m"
index = ["filebeat-*", "logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS RDS Snapshot Export"
note = """## Triage and analysis

### Investigating AWS RDS Snapshot Export

Exporting an RDS snapshot to Amazon S3 allows the full contents of a database to be written outside the managed
RDS service boundary. While legitimate for analytics or migration, this action can also be a mechanism for data
exfiltration. Because snapshot exports produce files that can be downloaded, shared, or accessed by other AWS principals,
unauthorized exports may indicate staging for data theft or attempts to bypass database access controls.

This rule detects successful `StartExportTask` events. Activity of this type should be validated to ensure that only
authorized database, platform engineering, or analytics workflows initiated the export.

#### Possible investigation steps

- **Identify the actor and context**
  - Review `aws.cloudtrail.user_identity.arn` and `aws.cloudtrail.user_identity.access_key_id` to determine which principal initiated the export.
  - Look at `source.ip`, `user.name`, and `user_agent.original` to understand where the export originated (console, CLI, SDK, automation).
  - Check whether the principal has historically performed snapshot exports.

- **Determine what was exported**
  - Examine `aws.cloudtrail.request_parameters`:
    - Snapshot identifier being exported.
    - S3 bucket name and path.
    - KMS key used (or absence of encryption).
  - Map the snapshot and destination bucket to:
    - Application/owner team.
    - Environment (prod/staging/dev).
    - Data classification (PII, PHI, PCI, internal).

- **Reconstruct timing and surrounding context**
  - Use `@timestamp` to correlate the export with:
    - Recent RDS modifications (`ModifyDBInstance`, `ModifyDBCluster`), snapshot deletions, or retention changes.
    - IAM role changes, access key issuance, or privilege escalation attempts.
    - Unusual authentication patterns (e.g., successful logins from new locations, failed console logins).
  - Check whether the export timing aligns with approved deployments or maintenance windows.

- **Correlate with broader CloudTrail activity**
  - Pivot on the same user, role, or access key ID to look for:
    - Prior reconnaissance (e.g., `DescribeDBSnapshots`, `DescribeDBClusters`, `ListBuckets`).
    - Permission changes (`PutRolePolicy`, `AttachUserPolicy`).
    - Public exposure (e.g., S3 bucket ACL changes).
  - Determine whether multiple snapshots were exported around the same time.

- **Validate intent with stakeholders**
  - Confirm with the database owner, analytics team, or platform engineering team whether:
    - The export was planned and authorized.
    - The target S3 bucket is approved for storing database contents.
    - Encryption and access controls meet organizational policy.

### False positive analysis

- **Authorized data analytics or ETL workflows**
  - Many organizations export snapshots for reporting, ML pipelines, or external data processing.
  - Validate that the export aligns with documented ETL or analytics processes.

- **Automated snapshot export tools**
  - Backup pipelines, cost optimization, or data replication systems may export snapshots.
  - Tune the rule by excluding known IAM roles or automation user agents.

- **CloudFormation or IaC triggers**
  - Infrastructure-as-code pipelines may trigger snapshot exports as part of stack updates.
  - Correlate with CloudFormation events to confirm legitimacy.

### Response and remediation

- **Contain potential exfiltration**
  - Review access to the destination S3 bucket and confirm that:
    - Bucket is encrypted with the expected KMS key.
    - Access is restricted to authorized principals.
    - No unusual downloads or cross-account accesses occurred.

- **Investigate scope and impact**
  - Use CloudTrail to enumerate:
    - All export tasks started by the same actor.
    - Other snapshot or data-access API calls in the same time window.
  - Validate whether sensitive or regulated data may have been included.

- **Credential and access remediation**
  - If activity appears unauthorized:
    - Revoke or rotate compromised IAM credentials.
    - Review STS session activity related to the actor.
    - Inspect IAM role policies for privilege escalation.

- **Hardening and preventive controls**
  - Restrict the ability to call `StartExportTask` using:
    - IAM least-privilege policies.
    - Service Control Policies (SCPs) in production accounts.
    - Conditional IAM (e.g., requiring MFA, restricting by VPC endpoint or IP range).
  - Enable guardrails:
    - AWS Config/Security Hub controls for monitoring snapshot policy changes.
    - Alerts for exports to buckets outside approved accounts.

### Additional information

- **[AWS IR Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/blob/c151b0dc091755fffd4d662a8f29e2f6794da52c/playbooks/)** 
- **[AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework/tree/a8c7b313636b406a375952ac00b2d68e89a991f2/docs)** 
- **Security Best Practices:** [AWS Knowledge Center – Security Best Practices](https://aws.amazon.com/premiumsupport/knowledge-center/security-best-practices/).

"""
references = ["https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_StartExportTask.html"]
risk_score = 73
rule_id = "119c8877-8613-416d-a98a-96b6664ee73a"
severity = "high"
tags = [
    "Domain: Cloud",
    "Data Source: AWS",
    "Data Source: Amazon Web Services",
    "Use Case: Asset Visibility",
    "Tactic: Collection",
    "Tactic: Exfiltration",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset: aws.cloudtrail 
    and event.provider: rds.amazonaws.com 
    and event.action: StartExportTask 
    and event.outcome: success
'''


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

[[rule.threat.technique]]
id = "T1567"
name = "Exfiltration Over Web Service"
reference = "https://attack.mitre.org/techniques/T1567/"

[[rule.threat.technique.subtechnique]]
id = "T1567.002"
name = "Exfiltration to Cloud Storage"
reference = "https://attack.mitre.org/techniques/T1567/002/"

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

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

[[rule.threat.technique]]
id = "T1213"
name = "Data from Information Repositories"
reference = "https://attack.mitre.org/techniques/T1213/"

[[rule.threat.technique.subtechnique]]
id = "T1213.006"
name = "Databases"
reference = "https://attack.mitre.org/techniques/T1213/006/"

[rule.threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"
[rule.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user_agent.original",
    "source.ip",
    "aws.cloudtrail.user_identity.arn",
    "aws.cloudtrail.user_identity.type",
    "aws.cloudtrail.user_identity.access_key_id",
    "event.action",
    "event.outcome",
    "cloud.account.id",
    "cloud.region",
    "aws.cloudtrail.request_parameters",
    "aws.cloudtrail.response_elements",
]

Stages and Predicates

Stage 1: query

data_stream.dataset: aws.cloudtrail 
    and event.provider: rds.amazonaws.com 
    and event.action: StartExportTask 
    and event.outcome: success

Indicators

These rows show field, operator, and value matches.

AWS S3 Object Versioning Suspended

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

Identifies when object versioning is suspended for an Amazon S3 bucket. Object versioning allows for multiple versions of an object to exist in the same bucket. This allows for easy recovery of deleted or overwritten objects. When object versioning is suspended for a bucket, it could indicate an adversary's attempt to inhibit system recovery following malicious activity. Additionally, when versioning is suspended, buckets can then be deleted.

Known False Positives

  • Administrators within an AWS Organization structure may legitimately suspend object versioning. Ensure that this behavior is not part of a legitimate operation before taking action.

MITRE ATT&CK Coverage

TacticTechniques
Impact

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2024/07/12"
integration = ["aws"]
maturity = "production"
updated_date = "2026/08/05"

[rule]
author = ["Elastic"]
description = """
Identifies when object versioning is suspended for an Amazon S3 bucket. Object versioning allows for multiple versions of an object to exist in the same bucket. This allows for easy recovery of deleted or overwritten objects. When object versioning is suspended for a bucket, it could indicate an adversary's attempt to inhibit system recovery following malicious activity. Additionally, when versioning is suspended, buckets can then be deleted.
"""
event_category_override = "event.type"
false_positives = [
    """
    Administrators within an AWS Organization structure may legitimately suspend object versioning. Ensure that this behavior is not part of a legitimate operation before taking action.
    """,
]
from = "now-6m"
index = ["filebeat-*", "logs-aws.cloudtrail-*"]
language = "eql"
license = "Elastic License v2"
name = "AWS S3 Object Versioning Suspended"
note = """## Triage and analysis

### Investigating AWS S3 Object Versioning Suspended

This rule detects when object versioning for an S3 bucket is suspended. S3 object versioning protects against data loss by maintaining prior versions of objects, allowing recovery if they are deleted or overwritten.  
Adversaries with access to a misconfigured or compromised S3 bucket may disable versioning to inhibit recovery efforts, conceal data destruction, or prepare for ransomware-like activity.  
This rule uses [EQL](https://www.elastic.co/guide/en/security/current/rules-ui-create.html#create-eql-rule) to detect use of the `PutBucketVersioning` API operation where the request parameters include `Status=Suspended`.

#### Possible investigation steps

- **Identify the Actor**  
  - Review `aws.cloudtrail.user_identity.arn` and `aws.cloudtrail.user_identity.access_key_id` to determine who performed the action.  
  - Verify whether this user or role has a legitimate operational reason to modify bucket versioning and whether such actions are common for this identity.

- **Analyze the Source and Context**  
  - Review `source.ip` and `user_agent.original` to assess the origin of the request.  
  - Check for unusual geographic locations, IP ranges, or clients that do not typically manage storage configurations.  

- **Evaluate the Affected Resource**  
  - Review `aws.cloudtrail.resources.arn` or `aws.cloudtrail.request_parameters` to identify which bucket’s versioning was modified.  
  - Determine whether this bucket contains critical or regulated data (logs, backups, audit evidence, etc.) that would be impacted by versioning suspension.

- **Correlate with Related Activity**  
  - Search for additional CloudTrail events performed by the same actor or IP address within the same timeframe, such as:  
    - `DeleteObject`, `DeleteObjects`, or `PutBucketLifecycle` events (potential data destruction).  
    - `PutBucketPolicy` or `PutBucketAcl` changes (permission manipulation).  
  - Review other detections related to S3 buckets or IAM changes to determine if this event is part of a larger sequence of destructive or unauthorized actions.

- **Validate Intent**  
  - Confirm whether this configuration change aligns with approved maintenance or automation activity (e.g., cost optimization, test environment reset).  
  - If no corresponding change request or justification exists, treat this as a potential defense evasion or impact event.

### False positive analysis

- **Legitimate Administrative Actions**  
  - Administrators or infrastructure automation tools may suspend versioning during migrations or lifecycle testing. Confirm through change management documentation.  
- **Automation and Pipelines**  
  - Verify whether Infrastructure-as-Code tools (e.g., Terraform, CloudFormation) or backup lifecycle scripts routinely modify versioning states.  
  - Exclude predictable automation identities where justified, while ensuring strong audit controls remain in place.

### Response and remediation

**Containment and Validation**  
- Re-enable versioning immediately for the affected bucket using the AWS Console or CLI (`aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Enabled`).  
- Verify the change with `get-bucket-versioning` to confirm the bucket is restored to “Enabled.”  
- Identify IAM users or roles with `s3:PutBucketVersioning` permissions and restrict access to trusted administrators only.  
- Preserve relevant CloudTrail, Config, and CloudWatch logs for the timeframe of the change to ensure integrity of investigation evidence.

**Investigation and Scoping**  
- Search CloudTrail for related actions by the same user or IP, including `DeleteObject`, `PutBucketLifecycle`, or `PutBucketPolicy`, to determine whether versioning suspension preceded object deletion or policy manipulation.  
- Review S3 access logs or Data Events for deleted, overwritten, or newly uploaded files after versioning suspension.  
- Validate if the change corresponds to an authorized change request or approved pipeline deployment.

**Recovery and Hardening**  
- If object loss or overwrites occurred, attempt recovery using cross-region replication, AWS Backup, or previous snapshot copies.  
- Enable S3 Object Lock and MFA Delete on critical buckets to prevent future tampering.  
- Configure the AWS Config rule `s3-bucket-versioning-enabled` to continuously monitor for versioning suspension and trigger automated alerts.  
- Review IAM and service control policies to ensure the principle of least privilege is enforced for all S3 management actions.  
- Document findings and update incident response procedures to include versioning protection as part of ransomware and data destruction prevention strategies.


### Additional information
- AWS Documentation: [Using Versioning in S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html)  
- API Reference: [PutBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html)  
- [AWS IR Playbooks](https://github.com/aws-samples/aws-incident-response-playbooks/blob/c151b0dc091755fffd4d662a8f29e2f6794da52c/playbooks/)
- [AWS Customer Playbook Framework](https://github.com/aws-samples/aws-customer-playbook-framework/tree/a8c7b313636b406a375952ac00b2d68e89a991f2/docs)
"""
references = [
    "https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html/",
    "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html/",
    "https://cloud.hacktricks.xyz/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/",
    "https://www.invictus-ir.com/news/ransomware-in-the-cloud/",
    "https://rhinosecuritylabs.com/aws/s3-ransomware-part-2-prevention-and-defense/",
]
risk_score = 47
rule_id = "30b5bb96-c7db-492c-80e9-1eab00db580b"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Platform: AWS",
    "Data Source: AWS CloudTrail",
    "Service: AWS S3",
    "Tactic: Impact",
    "Rule Type: Event Correlation (EQL)",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
info where data_stream.dataset == "aws.cloudtrail"
   and event.provider == "s3.amazonaws.com"
   and event.action == "PutBucketVersioning"
   and event.outcome == "success"
   and stringContains(aws.cloudtrail.request_parameters, "Status=Suspended")
   and not user_agent.original like~ ("*Terraform*", "*Pulumi*")
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1490"
name = "Inhibit System Recovery"
reference = "https://attack.mitre.org/techniques/T1490/"


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

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

Stages and Predicates

Stage 1: info

info where data_stream.dataset == "aws.cloudtrail"
   and event.provider == "s3.amazonaws.com"
   and event.action == "PutBucketVersioning"
   and event.outcome == "success"
   and stringContains(aws.cloudtrail.request_parameters, "Status=Suspended")
   and not user_agent.original like~ ("*Terraform*", "*Pulumi*")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

Azure Storage Blob Retrieval via AzCopy

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

Identifies successful GetBlob operations on Azure Storage Accounts using AzCopy user agent with SAS token authentication. AzCopy is a command-line utility for copying data to and from Azure Storage. While legitimate for data migration, adversaries may abuse AzCopy with compromised SAS tokens to exfiltrate data from Azure Storage Accounts. This rule detects the first occurrence of GetBlob operations from a specific storage account using this pattern.

Known False Positives

  • Legitimate data migration or backup operations using AzCopy with SAS tokens may trigger this rule.
  • Automated scripts or processes that use AzCopy for routine data transfers from Azure Storage Accounts.
  • DevOps or IT teams performing authorized data transfers or downloads from Azure Storage using AzCopy.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2025/10/02"
integration = ["azure"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Identifies successful GetBlob operations on Azure Storage Accounts using AzCopy user agent with SAS token
authentication. AzCopy is a command-line utility for copying data to and from Azure Storage. While legitimate for data
migration, adversaries may abuse AzCopy with compromised SAS tokens to exfiltrate data from Azure Storage Accounts. This
rule detects the first occurrence of GetBlob operations from a specific storage account using this pattern.
"""
false_positives = [
    "Legitimate data migration or backup operations using AzCopy with SAS tokens may trigger this rule.",
    "Automated scripts or processes that use AzCopy for routine data transfers from Azure Storage Accounts.",
    "DevOps or IT teams performing authorized data transfers or downloads from Azure Storage using AzCopy.",
]
from = "now-9m"
index = ["logs-azure.platformlogs-*"]
language = "kuery"
license = "Elastic License v2"
name = "Azure Storage Blob Retrieval via AzCopy"
note = """## Triage and analysis

### Investigating Azure Storage Blob Retrieval via AzCopy

Azure Storage Accounts provide cloud storage services for blobs, files, queues, and tables. Shared Access Signatures (SAS) tokens provide delegated access to resources in a storage account with specific permissions and time constraints. AzCopy is a Microsoft command-line utility designed for efficient data transfers to and from Azure Storage. While AzCopy is a legitimate tool, adversaries may abuse it with compromised SAS tokens to exfiltrate data from Azure Storage Accounts.

### Possible investigation steps
- Review the `azure.platformlogs.properties.accountName` field to identify which storage account is being accessed and assess the sensitivity of data stored in that account.
- Examine the `azure.platformlogs.properties.objectKey` field to identify the specific blob(s) being retrieved. Determine if the accessed files contain sensitive or confidential data.
- Check the `source.address` field to identify the source IP address of the request. Investigate if this IP is unusual, unexpected, or originates from an unexpected network or geographic location.
- Review the `azure.platformlogs.uri` field to examine the SAS token parameters, including:
  - `se` (expiry time): Check when the SAS token expires
  - `sp` (permissions): Verify what permissions were granted (e.g., "rl" for read and list)
  - `sv` (API version): Note the storage service version being used
- Examine the `azure.platformlogs.identity.tokenHash` field to identify the specific SAS token signature being used. Correlate this with SAS token generation logs to determine when and how the token was created.
- Check the `azure.platformlogs.properties.responseBodySize` field to assess the volume of data being downloaded. Multiple GetBlob operations with large response sizes may indicate bulk data exfiltration.
- Search for related GetBlob operations from the same `source.address` or with the same `azure.platformlogs.identity.tokenHash` to identify patterns of systematic data retrieval.
- Review Azure Activity Logs for recent SAS token generation events or storage account key access operations that may indicate how the adversary obtained the credentials.
- Correlate this activity with ListBlobs or ListContainers operations from the same source, as adversaries often enumerate storage contents before exfiltration.
- Investigate the `azure.resource.group` field to understand which resource group the storage account belongs to and check for any recent security events or configuration changes in that resource group.

### False positive analysis
- Routine data migration or backup operations using AzCopy with SAS tokens are common in enterprise environments. If this is expected behavior for the storage account, consider adding exceptions for specific accounts or IP ranges.
- DevOps pipelines or automated workflows may use AzCopy with SAS tokens for legitimate data transfers. Review the automation configuration and add exceptions if appropriate.
- Third-party services or partners may have authorized access to storage accounts using AzCopy and SAS tokens. Verify these relationships and create exceptions for known authorized sources.

### Response and remediation
- If unauthorized access is confirmed, immediately revoke the compromised SAS token to prevent further data exfiltration.
- Review and rotate any additional SAS tokens that may have been compromised through the same attack vector.
- Assess the scope of data accessed or exfiltrated during the unauthorized GetBlob operations and determine if sensitive data was compromised.
- Implement additional monitoring and alerting for the affected storage account to detect any further suspicious activity.
- Review and strengthen SAS token generation policies, including implementing shorter expiration times and more restrictive permissions.
- Consider implementing Azure Storage firewall rules or private endpoints to restrict access to storage accounts from trusted networks only.
- Investigate how the SAS token was compromised and remediate the initial access vector to prevent future incidents.
- Document the incident and update security procedures to prevent similar compromises in the future.
"""
references = [
    "https://www.microsoft.com/en-us/security/blog/2025/08/27/storm-0501s-evolving-techniques-lead-to-cloud-based-ransomware/",
    "https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-v10",
    "https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview",
]
risk_score = 47
rule_id = "a8b3c4d5-e6f7-8901-a2b3-c4d5e6f78901"
setup = """#### Required Azure Storage Diagnostic Logs

To ensure this rule functions correctly, the following diagnostic logs must be enabled for Azure Storage Accounts:
- StorageRead: This log captures all read operations performed on blobs in the storage account, including GetBlob operations. These logs should be streamed to the Event Hub used for the Azure integration configuration.
"""
severity = "medium"
tags = [
    "Domain: Cloud",
    "Domain: Storage",
    "Data Source: Azure",
    "Data Source: Azure Platform Logs",
    "Data Source: Azure Storage",
    "Use Case: Threat Detection",
    "Tactic: Exfiltration",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"

query = '''
data_stream.dataset: azure.platformlogs and
    event.action: GetBlob and
    azure.platformlogs.identity.type: SAS and
    azure.platformlogs.properties.userAgentHeader: AzCopy* and
    azure.platformlogs.statusCode: 200
'''


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

[[rule.threat.technique]]
id = "T1567"
name = "Exfiltration Over Web Service"
reference = "https://attack.mitre.org/techniques/T1567/"

[[rule.threat.technique.subtechnique]]
id = "T1567.002"
name = "Exfiltration to Cloud Storage"
reference = "https://attack.mitre.org/techniques/T1567/002/"

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

[[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.new_terms]
field = "new_terms_fields"
value = ["azure.platformlogs.properties.accountName"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"


Stages and Predicates

Stage 1: new_terms

data_stream.dataset: azure.platformlogs and
    event.action: GetBlob and
    azure.platformlogs.identity.type: SAS and
    azure.platformlogs.properties.userAgentHeader: AzCopy* and
    azure.platformlogs.statusCode: 200

Indicators

These rows show field, operator, and value matches.

Binary Executed from Shared Memory Directory

#
Source
github.com/elastic/protections-artifacts

Identifies the execution of a binary Linux shared memory directories: (/dev/shm/, /run/shm/). This activity is to be considered highly abnormal and should be investigated. Threat actors have placed executables used for persistence on high-uptime servers in these directories as system backdoors. Binaries executed from these directories are memory resident making them harder to detect and allowing them to remain hidden for long periods of time.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = """
Identifies the execution of a binary Linux shared memory directories: (/dev/shm/, /run/shm/). This activity is to be
considered highly abnormal and should be investigated. Threat actors have placed executables used for persistence on
high-uptime servers in these directories as system backdoors. Binaries executed from these directories are memory
resident making them harder to detect and allowing them to remain hidden for long periods of time.
"""
id = "78ae5dbd-477b-4ce7-a7f7-8c4b5e228df2"
license = "Elastic License v2"
name = "Binary Executed from Shared Memory Directory"
os_list = ["linux"]
reference = ["https://intezer.com/blog/incident-response/orbit-new-undetected-linux-threat/"]
version = "1.0.12"

query = '''
process where event.type == "start" and event.action == "exec" and process.executable like ("/dev/shm/*", "/run/shm/*") and
not (
   (process.executable like "/dev/shm/gitlab/*" and process.pid == 0) or
   (process.executable like "/dev/shm/ansible-tmp*")
 )
'''

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

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

[[threat]]
framework = "MITRE ATT&CK"
[[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 = "8.3.0"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action == "exec" and process.executable like ("/dev/shm/*", "/run/shm/*") and
not (
   (process.executable like "/dev/shm/gitlab/*" and process.pid == 0) or
   (process.executable like "/dev/shm/ansible-tmp*")
 )

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.executablestarts_with/dev/shm/gitlab/excludes:process.executable field:"process.executable" value:"/dev/shm/gitlab/"
process.pideq0excludes:process.pid field:"process.pid" value:"0"
process.executablestarts_with/dev/shm/ansible-tmpexcludes:process.executable field:"process.executable" value:"/dev/shm/ansible-tmp"

BLF File Creation by an Unusual Process

#
Source
github.com/elastic/protections-artifacts

Identifies an unelevated attempt to create a BLF file by an unusual process. This may indicate an attempt to exploit a CLFS vulnerability for privilege escalation.

MITRE ATT&CK Coverage

TacticTechniques
Privilege Escalation

Rule Body

[rule]
description = """
Identifies an unelevated attempt to create a BLF file by an unusual process. This may indicate an attempt to exploit a
CLFS vulnerability for privilege escalation.
"""
id = "734e9e5c-865e-46e0-a4c1-c8fc56910bf2"
license = "Elastic License v2"
name = "BLF File Creation by an Unusual Process"
os_list = ["windows"]
reference = [
    "https://securelist.com/windows-clfs-exploits-ransomware/111560/",
    "https://www.elastic.co/security-labs/itw-windows-lpe-0days-insights-and-detection-strategies",
    "https://ti.qianxin.com/blog/articles/cve-2025-29824-0-day-vulnerability-exploitation-sample-research-en/",
]
version = "1.0.3"

query = '''
file where event.action == "creation" and user.id != "S-1-5-18" and user.id != null and process.pid != 4 and
 file.extension : "blf" and file.Ext.header_bytes == "1500010002000200000000004b824cc6" and file.path : "C:\\*.blf" and
 (process.code_signature.exists == false or process.code_signature.trusted == false) and not process.code_signature.status like "errorCode_endpoint*" and
 not file.path : ("C:\\Windows\\System32\\*.blf",
                  "C:\\Windows\\SysWOW64\\*.blf",
                  "C:\\Windows\\appcompat\\*.blf",
                  "C:\\Windows\\ServiceProfiles\\*.blf",
                  "C:\\Users\\*\\AppData\\Local\\Temp\\*\\UsrClass.dat*.blf",
                  "C:\\Users\\*\\NTUSER.DAT{*}.TM.blf",
                  "C:\\System Volume Information\\*.blf",
                  "C:\\$WINDOWS.~BT\\NewOS\\Windows\\*.blf",
                  "C:\\Users\\*\\AppData\\Local\\Temp\\Ruf*.tmp\\SYSTEM{*}.TM.blf",
                  "C:\\Users\\*\\SetupRST_RecoveryImage\\Windows\\System32\\config\\*.TM.blf") and
 not process.executable : ("C:\\Windows\\System32\\SystemSettingsAdminFlows.exe",
                           "C:\\Windows\\explorer.exe",
                           "C:\\Program Files\\*.exe",
                           "C:\\Program Files (x86)\\*.exe",
                           "C:\\Windows\\System32\\pnputil.exe",
                           "C:\\$WINDOWS.~BT\\*.exe")
'''

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

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1068"
name = "Exploitation for Privilege Escalation"
reference = "https://attack.mitre.org/techniques/T1068/"


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

[internal]
min_endpoint_version = "8.7.0"

Stages and Predicates

Stage 1: file

file where event.action == "creation" and user.id != "S-1-5-18" and user.id != null and process.pid != 4 and
 file.extension : "blf" and file.Ext.header_bytes == "1500010002000200000000004b824cc6" and file.path : "C:\\*.blf" and
 (process.code_signature.exists == false or process.code_signature.trusted == false) and not process.code_signature.status like "errorCode_endpoint*" and
 not file.path : ("C:\\Windows\\System32\\*.blf",
                  "C:\\Windows\\SysWOW64\\*.blf",
                  "C:\\Windows\\appcompat\\*.blf",
                  "C:\\Windows\\ServiceProfiles\\*.blf",
                  "C:\\Users\\*\\AppData\\Local\\Temp\\*\\UsrClass.dat*.blf",
                  "C:\\Users\\*\\NTUSER.DAT{*}.TM.blf",
                  "C:\\System Volume Information\\*.blf",
                  "C:\\$WINDOWS.~BT\\NewOS\\Windows\\*.blf",
                  "C:\\Users\\*\\AppData\\Local\\Temp\\Ruf*.tmp\\SYSTEM{*}.TM.blf",
                  "C:\\Users\\*\\SetupRST_RecoveryImage\\Windows\\System32\\config\\*.TM.blf") and
 not process.executable : ("C:\\Windows\\System32\\SystemSettingsAdminFlows.exe",
                           "C:\\Windows\\explorer.exe",
                           "C:\\Program Files\\*.exe",
                           "C:\\Program Files (x86)\\*.exe",
                           "C:\\Windows\\System32\\pnputil.exe",
                           "C:\\$WINDOWS.~BT\\*.exe")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
file.pathwildcardC:\Windows\System32\*.blf, C:\Windows\SysWOW64\*.blf, C:\Windows\appcompat\*.blf, C:\Windows\ServiceProfiles\*.blf, C:\Users\*\AppData\Local\Temp\*\UsrClass.dat*.blf, C:\Users\*\NTUSER.DAT{*}.TM.blf, C:\System Volume Information\*.blf, C:\$WINDOWS.~BT\NewOS\Windows\*.blf, C:\Users\*\AppData\Local\Temp\Ruf*.tmp\SYSTEM{*}.TM.blf, C:\Users\*\SetupRST_RecoveryImage\Windows\System32\config\*.TM.blfexcludes:file.path
process.code_signature.statusstarts_witherrorCode_endpointexcludes:process.code_signature.status field:"process.code_signature.status" value:"errorCode_endpoint"
process.executablewildcardC:\Windows\System32\SystemSettingsAdminFlows.exe, C:\Windows\explorer.exe, C:\Program Files\*.exe, C:\Program Files (x86)\*.exe, C:\Windows\System32\pnputil.exe, C:\$WINDOWS.~BT\*.exeexcludes:process.executable

Curl or Wget Execution from Container Context

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

Detects execution of curl or wget from processes whose title aligns with runc init, a common fingerprint for workloads running inside OCI/runc-backed containers on Linux hosts instrumented with Auditd Manager. After breaking out of an application container or abusing a privileged workload, attackers often pull ingress tooling (stagers, scripts, implants) or stage exfiltration with minimal HTTP clients. Those utilities are also used benignly in images, so context matters; the runc init anchor narrows the signal to the container runtime boundary where unexpected download clients are more worthy of review than the same binaries on a bare-metal admin shell.

Known False Positives

  • Base images, entrypoints, or init wrappers may legitimately invoke curl or wget during container startup (package installs, health checks); baseline trusted images and exclude stable image digests or namespaces when noisy.
  • Developer-oriented containers and CI build pods can run curl/wget from PID 1 descendants under runc; correlate with build pipelines and approved registries.

MITRE ATT&CK Coverage

TacticTechniques
Command & Control

Rule Body

[metadata]
creation_date = "2026/04/22"
integration = ["auditd_manager"]
maturity = "production"
updated_date = "2026/05/11"

[rule]
author = ["Elastic"]
description = """
Detects execution of curl or wget from processes whose title aligns with **`runc init`**, a common fingerprint 
for workloads running inside **OCI/runc-backed containers** on Linux hosts instrumented with Auditd Manager. 
After breaking out of an application container or abusing a privileged workload, attackers often pull ingress tooling
(stagers, scripts, implants) or stage exfiltration with minimal HTTP clients. Those utilities are also used
benignly in images, so context matters; the `runc init` anchor narrows the signal to the container runtime boundary
where unexpected download clients are more worthy of review than the same binaries on a bare-metal admin shell.
"""
false_positives = [
    """
    Base images, entrypoints, or init wrappers may legitimately invoke curl or wget during container startup (package
    installs, health checks); baseline trusted images and exclude stable image digests or namespaces when noisy.
    """,
    """
    Developer-oriented containers and CI build pods can run curl/wget from PID 1 descendants under runc; correlate with
    build pipelines and approved registries.
    """,
]
from = "now-9m"
index = ["auditbeat-*", "logs-auditd_manager.auditd-*"]
language = "kuery"
license = "Elastic License v2"
name = "Curl or Wget Execution from Container Context"
note = """## Triage and analysis

### Investigating Curl or Wget Execution from Container Context

The rule matches Auditd-backed process events where `process.title` is `runc init` and the executed program is
curl/wget (by `process.name`) or the argument vector suggests curl or wget paths. Use it to spot ingress tool 
transfer or scripted downloads from inside a container as seen at the host audit layer.

### Possible investigation steps

- Reconstruct the full command line from `process.args` / `process.command_line` and identify URLs, output paths, and
  flags such as `-O`, `--post-file`, or TLS bypass (`-k`).
- Map the event to the container: cgroup, `container.id`, `kubernetes.pod.*`, or runtime metadata if present on the
  document; identify the image, namespace, and workload owner.
- Review egress from the host or pod network policy logs for destinations contacted shortly after the execution.
- Compare against recent image or manifest changes for the workload to rule out intentional startup scripts.

### False positive analysis

- Package managers and bootstrap scripts in official images may run curl/wget once at start; document and exclude when
  verified.
- Security scanners or health checks running in sidecars could match; validate agent type and schedule.

### Response and remediation

- If unauthorized, isolate the node or workload, revoke credentials available to the container, inspect for dropped
  binaries or cron/systemd additions, and rotate any secrets the container could reach.
"""
references = [
    "https://attack.mitre.org/techniques/T1105/",
    "https://gtfobins.github.io/gtfobins/curl/",
    "https://gtfobins.github.io/gtfobins/wget/",
]
risk_score = 47
rule_id = "e7b2c3d4-5a6b-4e8f-9c0d-1a2b3e4f5a6b"
setup = """## Setup

This rule requires data from **Auditd Manager** (or legacy Auditbeat shipping comparable ECS fields).

### Auditd Manager Integration Setup
The Auditd Manager integration receives audit events from the Linux Audit Framework. With `auditd_manager`,
administrators can define audit rules, track system events, and generate reports.

#### Steps to deploy Auditd Manager
- In Kibana, open **Add integrations**, search for **Auditd Manager**, and add it to an agent policy deployed on Linux
  hosts that should emit syscall audit data.
- For integration details, see the [Auditd Manager documentation](https://docs.elastic.co/integrations/auditd_manager).

#### Rule-specific notes
- Ensure syscall coverage includes **execve** (or equivalent) for processes inside containers so `curl`, `wget`, and
  argument lists are captured on the host.
- Confirm that **`process.title`** (or the mapped proctitle field) reflects **`runc init`** for your runtime; other
  runtimes may use different titles—tune the predicate if you standardize on `crun`, `containerd-shim`, etc.
"""
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Linux",
    "Use Case: Threat Detection",
    "Tactic: Command and Control",
    "Tactic: Execution",
    "Domain: Containers",
    "Data Source: Auditd Manager",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
host.os.type:linux and 
data_stream.dataset:"auditd_manager.auditd" and
event.action:("executed" or "exec") and
process.title:"runc init" and
(
  process.name:(curl or wget) or
  process.args:(* curl* or */bin/curl* or *wget*)
) and 
not process.args :(*127.0.0.1* or *localhost* or "wget --no-verbose --tries=1 --spider --no-check-certificate http://${WEB_HOST}:${WEB_PORT}/api/ping || exit 1")
'''

[[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: query

host.os.type:linux and 
data_stream.dataset:"auditd_manager.auditd" and
event.action:("executed" or "exec") and
process.title:"runc init" and
(
  process.name:(curl or wget) or
  process.args:(* curl* or */bin/curl* or *wget*)
) and 
not process.args :(*127.0.0.1* or *localhost* or "wget --no-verbose --tries=1 --spider --no-check-certificate http://${WEB_HOST}:${WEB_PORT}/api/ping || exit 1")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argseqwget --no-verbose --tries=1 --spider --no-check-certificate http://${WEB_HOST}:${WEB_PORT}/api/ping || exit 1excludes:process.args field:"process.args" value:"wget --no-verbose --tries=1 --spider --no-check-certificate http://${WEB_HOST}:${WEB_PORT}/api/ping || exit 1"
process.argsmatch127.0.0.1excludes:process.args field:"process.args" value:"127.0.0.1"
process.argsmatchlocalhostexcludes:process.args field:"process.args" value:"localhost"

Environment Variable Secret Collection

#
Source
github.com/elastic/protections-artifacts

Identifies the execution of the env or printenv commands followed by a grep command to collect environment variable secrets. This is a common technique used by attackers to collect sensitive information from the environment.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[rule]
description = """
Identifies the execution of the env or printenv commands followed by a grep command to collect environment variable
secrets. This is a common technique used by attackers to collect sensitive information from the environment.
"""
id = "4fab1a5b-18c4-4f7b-91dd-7ac8a08e5762"
license = "Elastic License v2"
name = "Environment Variable Secret Collection"
os_list = ["linux", "macos"]
reference = [
    "https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack/",
    "https://www.virustotal.com/gui/file/71e35aef03099cd1f2d6446734273025a163597de93912df321ef118bf135238",
]
version = "1.0.4"

query = '''
process where event.type == "start" and event.action == "exec" and process.name in ("env", "printenv") and
process.parent.command_line like ("* env*|*grep*", "* printenv*|*grep*") and
process.parent.command_line like~ (
  "*azure*", "*kube*", "*k8s", "*aws*", "*database*", "*db_*", "*mysql*", "*postgres*", "*mongo*", "*redis*",
  "*vault*", "*password*", "*passwd*", "*pwd*", "*secret*", "*token*", "*apikey*", "*api.key*", "*access_key*",
  "*private_key*", "*client_secret*", "*credential*", "*auth*", "*gcp*", "*google*", "*kubernetes*", "*service_account*"
) and
not (
  /* Exclude unrelated Gen-AI command lines */
  length(process.parent.command_line) >= 100 or
  process.parent.args in ("env|grep -i \"^shell=\"", "env | grep ^PATH=", "env|grep -i '^shell='") or
  process.args == "/usr/local/bin/pm2"
)
'''

min_endpoint_version = "7.15.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 = "T1074"
name = "Data Staged"
reference = "https://attack.mitre.org/techniques/T1074/"
[[threat.technique.subtechnique]]
id = "T1074.001"
name = "Local Data Staging"
reference = "https://attack.mitre.org/techniques/T1074/001/"


[[threat.technique]]
id = "T1119"
name = "Automated Collection"
reference = "https://attack.mitre.org/techniques/T1119/"


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

[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 in ("env", "printenv") and
process.parent.command_line like ("* env*|*grep*", "* printenv*|*grep*") and
process.parent.command_line like~ (
  "*azure*", "*kube*", "*k8s", "*aws*", "*database*", "*db_*", "*mysql*", "*postgres*", "*mongo*", "*redis*",
  "*vault*", "*password*", "*passwd*", "*pwd*", "*secret*", "*token*", "*apikey*", "*api.key*", "*access_key*",
  "*private_key*", "*client_secret*", "*credential*", "*auth*", "*gcp*", "*google*", "*kubernetes*", "*service_account*"
) and
not (
  length(process.parent.command_line) >= 100 or
  process.parent.args in ("env|grep -i \"^shell=\"", "env | grep ^PATH=", "env|grep -i '^shell='") or
  process.args == "/usr/local/bin/pm2"
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec corpus 547 (elastic 547)
field:"EventType" kind:eq value:"exec"
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.namein
  • env corpus 16 (elastic 16)
  • printenv corpus 4 (elastic 4)
field:"process_basename" kind:in
process.parent.command_linewildcard
  • * env*|*grep*
  • * printenv*|*grep*
  • *access_key*
  • *api.key*
  • *apikey*
  • *auth*
  • *aws*
  • *azure*
  • *client_secret*
  • *credential*
  • *database*
  • *db_*
  • *gcp*
  • *google*
  • *k8s
  • *kube*
  • *kubernetes*
  • *mongo*
  • *mysql*
  • *passwd*
  • *password*
  • *postgres*
  • *private_key*
  • *pwd*
  • *redis*
  • *secret*
  • *service_account*
  • *token*
  • *vault*
field:"ParentCommandLine" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argseq/usr/local/bin/pm2excludes:process.args field:"process.args" value:"/usr/local/bin/pm2"
process.parent.argsinenv | grep ^PATH=, env|grep -i "^shell=", env|grep -i '^shell='excludes:process.parent.args
process.parent.command_linelength_compare>=, 100excludes:process.parent.command_line field:"process.parent.command_line" value:">=" field:"process.parent.command_line" value:"100"

M365 SharePoint Site Sharing Policy Weakened

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

Identifies when a SharePoint or OneDrive site sharing policy is changed to weaken security controls. The SharingPolicyChanged event fires for many routine policy modifications, but this rule targets specific high-risk transitions where sharing restrictions are relaxed. This includes enabling guest sharing, enabling anonymous link sharing, making a site public, or enabling guest user access. Adversaries who compromise administrative accounts may weaken sharing policies to exfiltrate data to external accounts or create persistent external access paths.

Known False Positives

  • Administrators legitimately enabling external sharing for a new collaboration site or project.
  • Organizational policy changes that intentionally broaden sharing capabilities across sites.
  • Migration or onboarding projects that temporarily require external sharing to be enabled.

MITRE ATT&CK Coverage

Telemetry Coverage

PlatformRecord / event type
Microsoft 365SharingPolicyChanged

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2026/02/27"
integration = ["o365"]
maturity = "production"
updated_date = "2026/05/15"

[rule]
author = ["Elastic", "Austin Songer"]
description = """
Identifies when a SharePoint or OneDrive site sharing policy is changed to weaken security controls. The
SharingPolicyChanged event fires for many routine policy modifications, but this rule targets specific high-risk
transitions where sharing restrictions are relaxed. This includes enabling guest sharing, enabling anonymous link
sharing, making a site public, or enabling guest user access. Adversaries who compromise administrative accounts may
weaken sharing policies to exfiltrate data to external accounts or create persistent external access paths.
"""
false_positives = [
    "Administrators legitimately enabling external sharing for a new collaboration site or project.",
    "Organizational policy changes that intentionally broaden sharing capabilities across sites.",
    "Migration or onboarding projects that temporarily require external sharing to be enabled.",
]
from = "now-9m"
index = ["filebeat-*", "logs-o365.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "M365 SharePoint Site Sharing Policy Weakened"
note = """## Triage and Analysis

### Investigating M365 SharePoint Site Sharing Policy Weakened

This rule detects when SharePoint or OneDrive sharing policies are modified to weaken security controls. The `SharingPolicyChanged` event captures modifications to site-level sharing settings stored in `ModifiedProperties`, where the setting name is a dynamic field key and `OldValue`/`NewValue` track the transition. This rule targets specific transitions that represent a security posture degradation. Note that Microsoft uses inconsistent keyword value formats across settings, some use `True`/`False` while others use `Enabled`/`Disabled`.

#### Possible Investigation Steps

- Identify the user who performed the change via `user.id` and determine if they have a legitimate administrative role.
- Check if the acting user is a service principal (e.g., `ServiceOperator`, `app@sharepoint`) or a human account. Service principal changes may indicate automated processes or compromised application credentials.
- Review which specific setting was changed by examining the `o365.audit.ModifiedProperties.*` fields:
    - ShareWithGuests: Guest/external sharing was enabled on the site. External users can now be invited to access content.
    - ShareUsingAnonymousLinks: Anonymous "Anyone" link sharing was enabled. Content can now be shared via unauthenticated links.
    - IsPublic: The site or group was changed from private to public visibility.
    - AllowGuestUser: Guest user access was enabled for the site.
    - AllowFederatedUsers: Federated (external organization) user access was enabled.
    - AllowTeamsConsumer: Teams personal account (consumer) user access was enabled.
- Identify the affected site via `o365.audit.ObjectId` (the site URL) and assess the sensitivity of its content.
- Review Azure AD / Entra ID sign-in logs for the acting account to check for authentication anomalies (unusual location, device code flow, new device).
- Look for subsequent sharing activity on the same site — `SharingSet`, `AnonymousLinkCreated`, `SharingInvitationCreated`, or file download events shortly after the policy change.
- Determine if the change was part of a planned change request or occurred outside of normal change windows.

### False Positive Analysis

- IT administrators enabling external sharing for legitimate collaboration needs. Correlate with change management tickets or Slack/Teams messages.
- Automated provisioning scripts that configure sharing settings during site creation. These typically use service principal accounts with predictable patterns.
- Microsoft service operations (`ServiceOperator`) may modify settings as part of tenant-level policy propagation.

### Response and Remediation

- If the change is unauthorized, immediately revert the sharing policy to its previous restrictive state.
- Revoke sessions and reset credentials for the compromised account.
- Review what content was accessed or shared after the policy change using `FileAccessed`, `FileDownloaded`, and sharing audit events.
- Audit all sites for similar unauthorized sharing policy changes.
- Implement Conditional Access policies to restrict administrative actions to trusted networks and compliant devices.
- Enable Privileged Identity Management (PIM) for SharePoint administrator roles to enforce just-in-time access.
"""
references = [
    "https://learn.microsoft.com/en-us/purview/audit-log-activities#site-administration-activities",
    "https://learn.microsoft.com/en-us/purview/audit-log-sharing",
    "https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off",
]
risk_score = 47
rule_id = "632906c6-ba8f-44c0-8386-ec0bbc8518bf"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Domain: SaaS",
    "Data Source: Microsoft 365",
    "Data Source: Microsoft 365 Audit Logs",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset: "o365.audit" and event.provider: ("SharePoint" or "OneDrive") and
    event.action: "SharingPolicyChanged" and event.outcome: "success" and
    (
        (o365.audit.ModifiedProperties.ShareWithGuests.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.ShareWithGuests.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.IsPublic.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.IsPublic.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.AllowGuestUser.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.AllowGuestUser.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.AllowFederatedUsers.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.AllowFederatedUsers.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.AllowTeamsConsumer.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.AllowTeamsConsumer.OldValue: (false or "Disabled"))
    )
'''


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

[[rule.threat.technique]]
id = "T1484"
name = "Domain or Tenant Policy Modification"
reference = "https://attack.mitre.org/techniques/T1484/"

[[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.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "host.id",
    "host.name",
    "user.id",
    "user.name",
    "user.domain",
    "source.ip",
    "source.as.number",
    "o365.audit.AppAccessContext.AADSessionId",
    "o365.audit.AppAccessContext.ClientAppName",
    "o365.audit.AppAccessContext.UniqueTokenId",
    "o365.audit.EventSource",
    "user_agent.original",
    "o365.audit.Site",
    "o365.audit.ObjectId"
]

Stages and Predicates

Stage 1: query

data_stream.dataset: "o365.audit" and event.provider: ("SharePoint" or "OneDrive") and
    event.action: "SharingPolicyChanged" and event.outcome: "success" and
    (
        (o365.audit.ModifiedProperties.ShareWithGuests.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.ShareWithGuests.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.IsPublic.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.IsPublic.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.AllowGuestUser.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.AllowGuestUser.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.AllowFederatedUsers.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.AllowFederatedUsers.OldValue: (false or "Disabled"))
        or
        (o365.audit.ModifiedProperties.AllowTeamsConsumer.NewValue: (true or "Enabled") and
            o365.audit.ModifiedProperties.AllowTeamsConsumer.OldValue: (false or "Disabled"))
    )

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
data_stream.dataseteq
  • o365.audit corpus 38 (elastic 38)
field:"data_stream.dataset" kind:eq value:"o365.audit"
event.actioneq
  • SharingPolicyChanged
field:"EventType" kind:eq value:"SharingPolicyChanged"
event.outcomeeq
  • success corpus 306 (elastic 306)
field:"event.outcome" kind:eq value:"success"
event.providerin
  • OneDrive corpus 3 (elastic 3)
  • SharePoint corpus 3 (elastic 3)
field:"Provider_Name" kind:in
o365.audit.ModifiedProperties.AllowFederatedUsers.NewValuein
  • Enabled
  • true
field:"o365.audit.ModifiedProperties.AllowFederatedUsers.NewValue" kind:in
o365.audit.ModifiedProperties.AllowFederatedUsers.OldValuein
  • Disabled
  • false
field:"o365.audit.ModifiedProperties.AllowFederatedUsers.OldValue" kind:in
o365.audit.ModifiedProperties.AllowGuestUser.NewValuein
  • Enabled
  • true
field:"o365.audit.ModifiedProperties.AllowGuestUser.NewValue" kind:in
o365.audit.ModifiedProperties.AllowGuestUser.OldValuein
  • Disabled
  • false
field:"o365.audit.ModifiedProperties.AllowGuestUser.OldValue" kind:in
o365.audit.ModifiedProperties.AllowTeamsConsumer.NewValuein
  • Enabled
  • true
field:"o365.audit.ModifiedProperties.AllowTeamsConsumer.NewValue" kind:in
o365.audit.ModifiedProperties.AllowTeamsConsumer.OldValuein
  • Disabled
  • false
field:"o365.audit.ModifiedProperties.AllowTeamsConsumer.OldValue" kind:in
o365.audit.ModifiedProperties.IsPublic.NewValuein
  • Enabled
  • true
field:"o365.audit.ModifiedProperties.IsPublic.NewValue" kind:in
o365.audit.ModifiedProperties.IsPublic.OldValuein
  • Disabled
  • false
field:"o365.audit.ModifiedProperties.IsPublic.OldValue" kind:in
o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.NewValuein
  • Enabled
  • true
field:"o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.NewValue" kind:in
o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.OldValuein
  • Disabled
  • false
field:"o365.audit.ModifiedProperties.ShareUsingAnonymousLinks.OldValue" kind:in
o365.audit.ModifiedProperties.ShareWithGuests.NewValuein
  • Enabled
  • true
field:"o365.audit.ModifiedProperties.ShareWithGuests.NewValue" kind:in
o365.audit.ModifiedProperties.ShareWithGuests.OldValuein
  • Disabled
  • false
field:"o365.audit.ModifiedProperties.ShareWithGuests.OldValue" kind:in

Multiple Remote Management Tool Vendors on Same Host

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

Identifies a Windows host where two or more distinct remote monitoring and management (RMM) or remote-access tool vendors are observed starting processes within the same eight-minute window. Legitimate MSP environments may run multiple tools, but this pattern can also indicate compromise, shadow IT, or attacker staging of redundant access. Processes are mapped to a single vendor label so multiple binaries from the same vendor do not inflate the count.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2026/03/23"
integration = ["endpoint", "windows", "sentinel_one_cloud_funnel", "m365_defender", "system", "crowdstrike"]
maturity = "production"
updated_date = "2026/06/24"

[rule]
author = ["Elastic"]
description = """
Identifies a Windows host where two or more distinct remote monitoring and management (RMM) or remote-access tool
vendors are observed starting processes within the same eight-minute window. Legitimate MSP environments may run
multiple tools, but this pattern can also indicate compromise, shadow IT, or attacker staging of redundant access.
Processes are mapped to a single vendor label so multiple binaries from the same vendor do not inflate the count.
"""
from = "now-9m"
interval = "8m"
language = "esql"
license = "Elastic License v2"
name = "Multiple Remote Management Tool Vendors on Same Host"
note = """## Triage and analysis

### Investigating Multiple Remote Management Tool Vendors on Same Host

This rule aggregates process start events by `host.id` and host name within the rule's nine-minute lookback window. Data can come from Elastic Defend, Sysmon, Winlogbeat, Windows Security / forwarded events, Microsoft Defender XDR, SentinelOne, or CrowdStrike FDR—where ECS process fields are populated. Each known RMM-related process name maps to one **vendor** label (e.g. TeamViewer, AnyDesk, ScreenConnect). If **two or more different vendor labels** appear within the same lookback window, the rule signals.

### Possible investigation steps

- Open **Esql.vendors_seen** and **Esql.processes_executable_values** on the alert to see which tools fired in the window.
- Confirm whether the host is an MSP-managed jump box, helpdesk workstation, or lab where multiple RMM stacks are expected.
- For servers or standard user endpoints, treat as higher risk: review install source, code signatures, and recent logons.
- Correlate with other alerts (ingress tool transfer, suspicious scripting, new persistence) on the same `host.id`.
- Check asset inventory and change tickets for approved RMM software.

### False positive analysis

- **MSP / IT tooling**: A technician machine with two approved agents (e.g. RMM + remote support) may match. Tune with host or organizational unit exceptions, or raise the vendor threshold if your environment standardizes on a known pair.
- **Vendor rebrands or bundles**: Rare overlaps during migrations can briefly show two vendors; validate timeline and packages.

### Response and remediation

- If unauthorized or unexplained: isolate the host, inventory installed remote-access software, remove unapproved tools, and reset credentials that may have been exposed. Enforce a single approved RMM stack per asset class where possible.
"""

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)
- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
"""

references = [
    "https://attack.mitre.org/techniques/T1219/",
    "https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-025a",
    "https://lolrmm.io/",
]
risk_score = 47
rule_id = "c3f8a1d2-4b5e-4c6f-9a8b-1e2d3f4a5b6c"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Command and Control",
    "Resources: Investigation Guide",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Data Source: SentinelOne",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Crowdstrike",
    "Data Source: Windows Security Event Logs",
    "Data Source: Winlogbeat",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-endpoint.events.process-*, logs-crowdstrike.fdr*, logs-m365_defender.event-*, logs-sentinel_one_cloud_funnel.*, logs-system.security*, logs-windows.sysmon_operational-*, logs-windows.forwarded*, winlogbeat-* metadata _id, _version, _index
| where (host.os.type == "windows" or host.os.family == "windows")
    and event.category == "process"
    and event.type == "start"
    and process.name is not null
| eval Esql.rmm_vendor = case(
    process.name.caseless like "aa_v*.exe", "AnyAssist",
    process.name.caseless == "acroniscyberprotectconnectagent.exe", "Acronis",
    process.name.caseless == "aeroadmin.exe", "AeroAdmin",
    process.name.caseless == "agentmon.exe", "ConnectWiseAutomate",
    process.name.caseless == "anydesk.exe", "AnyDesk",
    process.name.caseless == "apc_admin.exe", "APC",
    process.name.caseless == "apc_host.exe", "APC",
    process.name.caseless == "ateraagent.exe", "Atera",
    process.name.caseless like "aweray_remote*.exe", "AweSun",
    process.name.caseless == "awesun.exe", "AweSun",
    process.name.caseless == "b4-service.exe", "BeyondTrust",
    process.name.caseless == "basupsrvc.exe", "BeyondTrust",
    process.name.caseless == "bomgar-scc.exe", "BeyondTrust",
    process.name.caseless == "remote support.exe", "BeyondTrust",
    process.name.caseless == "cagservice.exe", "BarracudaRMM",
    process.name.caseless == "cloudracmd.exe", "CloudRadial",
    process.name.caseless == "cloudrasd.exe", "CloudRadial",
    process.name.caseless == "cloudraservice.exe", "CloudRadial",
    process.name.caseless like "connectwisecontrol*.exe", "ScreenConnect",
    process.name.caseless == "domotzagent.exe", "Domotz",
    process.name.caseless == "domotz-windows-x64-10.exe", "Domotz",
    process.name.caseless == "dwagsvc.exe", "DWService",
    process.name.caseless == "dwrcc.exe", "DWService",
    process.name.caseless == "dwrcs.exe", "DWService",
    process.name.caseless == "dwrcst.exe", "DWService",
    process.name.caseless like "fleetdeck_commander*.exe", "FleetDeck",
    process.name.caseless == "g2aservice.exe", "GoTo",
    process.name.caseless == "getscreen.exe", "GetScreen",
    process.name.caseless == "gotoassistservice.exe", "GoTo",
    process.name.caseless == "gotohttp.exe", "GoTo",
    process.name.caseless == "gotoresolveprocesschecker.exe", "GoTo",
    process.name.caseless == "gotoresolveremotecontrol.exe", "GoTo",
    process.name.caseless == "gotoresolveservice.exe", "GoTo",
    process.name.caseless == "gotoresolveterminal.exe", "GoTo",
    process.name.caseless == "gotoresolveunattended.exe", "GoTo",
    process.name.caseless == "helpwire.exe", "HelpWire",
    process.name.caseless == "immyagent.exe", "ImmyBot",
    process.name.caseless == "immybot.agent.ephemeral.exe", "ImmyBot",
    process.name.caseless == "immyupdater.exe", "ImmyBot",
    process.name.caseless == "imperoclientsvc.exe", "Impero",
    process.name.caseless == "imperoserversvc.exe", "Impero",
    process.name.caseless == "isllight.exe", "ISLOnline",
    process.name.caseless == "isllightclient.exe", "ISLOnline",
    process.name.caseless == "jumpcloud-agent.exe", "JumpCloud",
    process.name.caseless == "komari.exe", "Komari",
    process.name.caseless == "komari-agent.exe", "Komari",
    process.name.caseless == "level.exe", "Level",
    process.name.caseless == "lmi_rescue.exe", "LogMeIn",
    process.name.caseless == "lmi_rescue_srv.exe", "LogMeIn",
    process.name.caseless == "lmiignition.exe", "LogMeIn",
    process.name.caseless == "logmein.exe", "LogMeIn",
    process.name.caseless == "ltsvc.exe", "ConnectWiseAutomate",
    process.name.caseless == "ltsvcmon.exe", "ConnectWiseAutomate",
    process.name.caseless == "lttray.exe", "ConnectWiseAutomate",
    process.name.caseless == "lunixar.exe", "Lunixar",
    process.name.caseless == "lunixarremote.exe", "Lunixar",
    process.name.caseless == "lunixarupdater.exe", "Lunixar",
    process.name.caseless == "lvagent.exe", "Level",
    process.name.caseless == "manageengine_remote_access_plus.exe", "ManageEngine",
    process.name.caseless == "meshagent.exe", "MeshCentral",
    process.name.caseless == "mikogo-service.exe", "Mikogo",
    process.name.caseless == "nezha-agent.exe", "Nezha",
    process.name.caseless == "ninjarmmagent.exe", "NinjaOne",
    process.name.caseless == "ninjarmmagentpatcher.exe", "NinjaOne",
    process.name.caseless == "ninjarmm-cli.exe", "NinjaOne",
    process.name.caseless == "parsec.exe", "Parsec",
    process.name.caseless == "pservice.exe", "Pulseway",
    process.name.caseless == "quickassist.exe", "QuickAssist",
    process.name.caseless == "r_server.exe", "Radmin",
    process.name.caseless == "radmin.exe", "Radmin",
    process.name.caseless == "radmin3.exe", "Radmin",
    process.name.caseless == "rcengmgru.exe", "Rsupport",
    process.name.caseless == "rcclient.exe", "RPCSuite",
    process.name.caseless == "rcmgrsvc.exe", "Rsupport",
    process.name.caseless == "rcservice.exe", "RPCSuite",
    process.name.caseless == "remotedesktopmanager.exe", "Devolutions",
    process.name.caseless == "remotely_agent.exe", "Remotely",
    process.name.caseless == "remotely_desktop.exe", "Remotely",
    process.name.caseless == "remotepc.exe", "RemotePC",
    process.name.caseless == "remotepcdesktop.exe", "RemotePC",
    process.name.caseless == "remotepcservice.exe", "RemotePC",
    process.name.caseless == "remoteview.exe", "Rsupport",
    process.name.caseless == "rfusclient.exe", "RemoteUtilities",
    process.name.caseless == "rmm.agent.exe", "SuperOps",
    process.name.caseless == "romserver.exe", "RealVNC",
    process.name.caseless == "romviewer.exe", "RealVNC",
    process.name.caseless == "rpcsuite.exe", "RPCSuite",
    process.name.caseless == "rserver3.exe", "Radmin",
    process.name.caseless == "rustdesk.exe", "RustDesk",
    process.name.caseless == "rutserv.exe", "RemoteUtilities",
    process.name.caseless == "rutview.exe", "RemoteUtilities",
    process.name.caseless == "rvagent.exe", "Rsupport",
    process.name.caseless == "rvagtray.exe", "Rsupport",
    process.name.caseless == "saazapsc.exe", "Kaseya",
    process.name.caseless like "screenconnect*.exe", "ScreenConnect",
    process.name.caseless == "session_win.exe", "ZohoAssist",
    process.name.caseless == "simplegatewayservice.exe", "SimpleHelp",
    process.name.caseless == "simplehelpcustomer.exe", "SimpleHelp",
    process.name.caseless == "smpcview.exe", "Splashtop",
    process.name.caseless == "spclink.exe", "Splashtop",
    process.name.caseless == "splashtop-streamer.exe", "Splashtop",
    process.name.caseless == "splashtopsos.exe", "Splashtop",
    process.name.caseless == "spsrv.exe", "Splashtop",
    process.name.caseless == "sragent.exe", "Splashtop",
    process.name.caseless == "srservice.exe", "Splashtop",
    process.name.caseless == "srmanager.exe", "Splashtop",
    process.name.caseless == "srserver.exe", "Splashtop",
    process.name.caseless == "strwinclt.exe", "Splashtop",
    process.name.caseless == "supremo.exe", "Supremo",
    process.name.caseless == "supremoservice.exe", "Supremo",
    process.name.caseless == "syncro.app.runner.exe", "Splashtop",
    process.name.caseless == "syncro.installer.exe", "Splashtop",
    process.name.caseless == "syncro.overmind.service.exe", "Splashtop",
    process.name.caseless == "syncro.service.exe", "Splashtop",
    process.name.caseless == "syncrolive.agent.exe", "Splashtop",
    process.name.caseless == "syncrolive.agent.runner.exe", "Splashtop",
    process.name.caseless == "syncrolive.service.exe", "Splashtop",
    process.name.caseless == "tacticalrmm.exe", "TacticalRMM",
    process.name.caseless == "tailscale.exe", "Tailscale",
    process.name.caseless == "tailscaled.exe", "Tailscale",
    process.name.caseless == "teamviewer.exe", "TeamViewer",
    process.name.caseless == "teamviewer_desktop.exe", "TeamViewer",
    process.name.caseless == "teamviewer_service.exe", "TeamViewer",
    process.name.caseless == "tiagent.exe", "Tiflux",
    process.name.caseless == "ticlientcore.exe", "Tiflux",
    process.name.caseless == "todesk_service.exe", "ToDesk",
    process.name.caseless == "toolsiq.exe", "ToolsIQ",
    process.name.caseless == "tsclient.exe", "Techinline",
    process.name.caseless == "tvn.exe", "TightVNC",
    process.name.caseless == "tvnserver.exe", "TightVNC",
    process.name.caseless == "tvnviewer.exe", "TightVNC",
    process.name.caseless == "twingate.exe", "Twingate",
    process.name.caseless like "ultravnc*.exe", "UltraVNC",
    process.name.caseless like "ultraviewer*.exe", "UltraViewer",
    process.name.caseless == "velociraptor.exe", "Velociraptor",
    process.name.caseless == "vncserver.exe", "RealVNC",
    process.name.caseless == "vncviewer.exe", "RealVNC",
    process.name.caseless == "winvnc.exe", "RealVNC",
    process.name.caseless == "winwvc.exe", "TightVNC",
    process.name.caseless == "za_access.exe", "ZohoAssist",
    process.name.caseless == "za_connect.exe", "ZohoAssist",
    process.name.caseless == "zaservice.exe", "ZohoAssist",
    process.name.caseless == "zmagent.exe", "ZohoAssist",
    process.name.caseless == "zohomeeting.exe", "ZohoAssist",
    process.name.caseless == "zohotray.exe", "ZohoAssist",
    process.name.caseless == "zohours.exe", "ZohoAssist",
    process.name.caseless == "zohoursservice.exe", "ZohoAssist",
    ""
  )
| where Esql.rmm_vendor != "" and Esql.rmm_vendor is not NULL
| stats Esql.vendor_count = count_distinct(Esql.rmm_vendor),
        Esql.vendors_seen = values(Esql.rmm_vendor),
        Esql.processes_executable_values = values(process.executable),
        Esql.first_seen = min(@timestamp),
        Esql.last_seen = max(@timestamp)
  by host.name, host.id
| where Esql.vendor_count >= 2
| sort Esql.vendor_count desc
| keep host.id, host.name, Esql.*
'''

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

[[rule.threat.technique]]
id = "T1219"
name = "Remote Access Tools"
reference = "https://attack.mitre.org/techniques/T1219/"

[[rule.threat.technique.subtechnique]]
id = "T1219.002"
name = "Remote Desktop Software"
reference = "https://attack.mitre.org/techniques/T1219/002/"

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

Stages and Predicates

Stage 1: from

from logs-endpoint.events.process-*, logs-crowdstrike.fdr*, logs-m365_defender.event-*, logs-sentinel_one_cloud_funnel.*, logs-system.security*, logs-windows.sysmon_operational-*, logs-windows.forwarded*, winlogbeat-* metadata _id, _version, _index

Stage 2: where

| where (host.os.type == "windows" or host.os.family == "windows")
    and event.category == "process"
    and event.type == "start"
    and process.name is not null

Stage 3: eval

| eval Esql.rmm_vendor = case(
    process.name.caseless like "aa_v*.exe", "AnyAssist",
    process.name.caseless == "acroniscyberprotectconnectagent.exe", "Acronis",
    process.name.caseless == "aeroadmin.exe", "AeroAdmin",
    process.name.caseless == "agentmon.exe", "ConnectWiseAutomate",
    process.name.caseless == "anydesk.exe", "AnyDesk",
    process.name.caseless == "apc_admin.exe", "APC",
    process.name.caseless == "apc_host.exe", "APC",
    process.name.caseless == "ateraagent.exe", "Atera",
    process.name.caseless like "aweray_remote*.exe", "AweSun",
    process.name.caseless == "awesun.exe", "AweSun",
    process.name.caseless == "b4-service.exe", "BeyondTrust",
    process.name.caseless == "basupsrvc.exe", "BeyondTrust",
    process.name.caseless == "bomgar-scc.exe", "BeyondTrust",
    process.name.caseless == "remote support.exe", "BeyondTrust",
    process.name.caseless == "cagservice.exe", "BarracudaRMM",
    process.name.caseless == "cloudracmd.exe", "CloudRadial",
    process.name.caseless == "cloudrasd.exe", "CloudRadial",
    process.name.caseless == "cloudraservice.exe", "CloudRadial",
    process.name.caseless like "connectwisecontrol*.exe", "ScreenConnect",
    process.name.caseless == "domotzagent.exe", "Domotz",
    process.name.caseless == "domotz-windows-x64-10.exe", "Domotz",
    process.name.caseless == "dwagsvc.exe", "DWService",
    process.name.caseless == "dwrcc.exe", "DWService",
    process.name.caseless == "dwrcs.exe", "DWService",
    process.name.caseless == "dwrcst.exe", "DWService",
    process.name.caseless like "fleetdeck_commander*.exe", "FleetDeck",
    process.name.caseless == "g2aservice.exe", "GoTo",
    process.name.caseless == "getscreen.exe", "GetScreen",
    process.name.caseless == "gotoassistservice.exe", "GoTo",
    process.name.caseless == "gotohttp.exe", "GoTo",
    process.name.caseless == "gotoresolveprocesschecker.exe", "GoTo",
    process.name.caseless == "gotoresolveremotecontrol.exe", "GoTo",
    process.name.caseless == "gotoresolveservice.exe", "GoTo",
    process.name.caseless == "gotoresolveterminal.exe", "GoTo",
    process.name.caseless == "gotoresolveunattended.exe", "GoTo",
    process.name.caseless == "helpwire.exe", "HelpWire",
    process.name.caseless == "immyagent.exe", "ImmyBot",
    process.name.caseless == "immybot.agent.ephemeral.exe", "ImmyBot",
    process.name.caseless == "immyupdater.exe", "ImmyBot",
    process.name.caseless == "imperoclientsvc.exe", "Impero",
    process.name.caseless == "imperoserversvc.exe", "Impero",
    process.name.caseless == "isllight.exe", "ISLOnline",
    process.name.caseless == "isllightclient.exe", "ISLOnline",
    process.name.caseless == "jumpcloud-agent.exe", "JumpCloud",
    process.name.caseless == "komari.exe", "Komari",
    process.name.caseless == "komari-agent.exe", "Komari",
    process.name.caseless == "level.exe", "Level",
    process.name.caseless == "lmi_rescue.exe", "LogMeIn",
    process.name.caseless == "lmi_rescue_srv.exe", "LogMeIn",
    process.name.caseless == "lmiignition.exe", "LogMeIn",
    process.name.caseless == "logmein.exe", "LogMeIn",
    process.name.caseless == "ltsvc.exe", "ConnectWiseAutomate",
    process.name.caseless == "ltsvcmon.exe", "ConnectWiseAutomate",
    process.name.caseless == "lttray.exe", "ConnectWiseAutomate",
    process.name.caseless == "lunixar.exe", "Lunixar",
    process.name.caseless == "lunixarremote.exe", "Lunixar",
    process.name.caseless == "lunixarupdater.exe", "Lunixar",
    process.name.caseless == "lvagent.exe", "Level",
    process.name.caseless == "manageengine_remote_access_plus.exe", "ManageEngine",
    process.name.caseless == "meshagent.exe", "MeshCentral",
    process.name.caseless == "mikogo-service.exe", "Mikogo",
    process.name.caseless == "nezha-agent.exe", "Nezha",
    process.name.caseless == "ninjarmmagent.exe", "NinjaOne",
    process.name.caseless == "ninjarmmagentpatcher.exe", "NinjaOne",
    process.name.caseless == "ninjarmm-cli.exe", "NinjaOne",
    process.name.caseless == "parsec.exe", "Parsec",
    process.name.caseless == "pservice.exe", "Pulseway",
    process.name.caseless == "quickassist.exe", "QuickAssist",
    process.name.caseless == "r_server.exe", "Radmin",
    process.name.caseless == "radmin.exe", "Radmin",
    process.name.caseless == "radmin3.exe", "Radmin",
    process.name.caseless == "rcengmgru.exe", "Rsupport",
    process.name.caseless == "rcclient.exe", "RPCSuite",
    process.name.caseless == "rcmgrsvc.exe", "Rsupport",
    process.name.caseless == "rcservice.exe", "RPCSuite",
    process.name.caseless == "remotedesktopmanager.exe", "Devolutions",
    process.name.caseless == "remotely_agent.exe", "Remotely",
    process.name.caseless == "remotely_desktop.exe", "Remotely",
    process.name.caseless == "remotepc.exe", "RemotePC",
    process.name.caseless == "remotepcdesktop.exe", "RemotePC",
    process.name.caseless == "remotepcservice.exe", "RemotePC",
    process.name.caseless == "remoteview.exe", "Rsupport",
    process.name.caseless == "rfusclient.exe", "RemoteUtilities",
    process.name.caseless == "rmm.agent.exe", "SuperOps",
    process.name.caseless == "romserver.exe", "RealVNC",
    process.name.caseless == "romviewer.exe", "RealVNC",
    process.name.caseless == "rpcsuite.exe", "RPCSuite",
    process.name.caseless == "rserver3.exe", "Radmin",
    process.name.caseless == "rustdesk.exe", "RustDesk",
    process.name.caseless == "rutserv.exe", "RemoteUtilities",
    process.name.caseless == "rutview.exe", "RemoteUtilities",
    process.name.caseless == "rvagent.exe", "Rsupport",
    process.name.caseless == "rvagtray.exe", "Rsupport",
    process.name.caseless == "saazapsc.exe", "Kaseya",
    process.name.caseless like "screenconnect*.exe", "ScreenConnect",
    process.name.caseless == "session_win.exe", "ZohoAssist",
    process.name.caseless == "simplegatewayservice.exe", "SimpleHelp",
    process.name.caseless == "simplehelpcustomer.exe", "SimpleHelp",
    process.name.caseless == "smpcview.exe", "Splashtop",
    process.name.caseless == "spclink.exe", "Splashtop",
    process.name.caseless == "splashtop-streamer.exe", "Splashtop",
    process.name.caseless == "splashtopsos.exe", "Splashtop",
    process.name.caseless == "spsrv.exe", "Splashtop",
    process.name.caseless == "sragent.exe", "Splashtop",
    process.name.caseless == "srservice.exe", "Splashtop",
    process.name.caseless == "srmanager.exe", "Splashtop",
    process.name.caseless == "srserver.exe", "Splashtop",
    process.name.caseless == "strwinclt.exe", "Splashtop",
    process.name.caseless == "supremo.exe", "Supremo",
    process.name.caseless == "supremoservice.exe", "Supremo",
    process.name.caseless == "syncro.app.runner.exe", "Splashtop",
    process.name.caseless == "syncro.installer.exe", "Splashtop",
    process.name.caseless == "syncro.overmind.service.exe", "Splashtop",
    process.name.caseless == "syncro.service.exe", "Splashtop",
    process.name.caseless == "syncrolive.agent.exe", "Splashtop",
    process.name.caseless == "syncrolive.agent.runner.exe", "Splashtop",
    process.name.caseless == "syncrolive.service.exe", "Splashtop",
    process.name.caseless == "tacticalrmm.exe", "TacticalRMM",
    process.name.caseless == "tailscale.exe", "Tailscale",
    process.name.caseless == "tailscaled.exe", "Tailscale",
    process.name.caseless == "teamviewer.exe", "TeamViewer",
    process.name.caseless == "teamviewer_desktop.exe", "TeamViewer",
    process.name.caseless == "teamviewer_service.exe", "TeamViewer",
    process.name.caseless == "tiagent.exe", "Tiflux",
    process.name.caseless == "ticlientcore.exe", "Tiflux",
    process.name.caseless == "todesk_service.exe", "ToDesk",
    process.name.caseless == "toolsiq.exe", "ToolsIQ",
    process.name.caseless == "tsclient.exe", "Techinline",
    process.name.caseless == "tvn.exe", "TightVNC",
    process.name.caseless == "tvnserver.exe", "TightVNC",
    process.name.caseless == "tvnviewer.exe", "TightVNC",
    process.name.caseless == "twingate.exe", "Twingate",
    process.name.caseless like "ultravnc*.exe", "UltraVNC",
    process.name.caseless like "ultraviewer*.exe", "UltraViewer",
    process.name.caseless == "velociraptor.exe", "Velociraptor",
    process.name.caseless == "vncserver.exe", "RealVNC",
    process.name.caseless == "vncviewer.exe", "RealVNC",
    process.name.caseless == "winvnc.exe", "RealVNC",
    process.name.caseless == "winwvc.exe", "TightVNC",
    process.name.caseless == "za_access.exe", "ZohoAssist",
    process.name.caseless == "za_connect.exe", "ZohoAssist",
    process.name.caseless == "zaservice.exe", "ZohoAssist",
    process.name.caseless == "zmagent.exe", "ZohoAssist",
    process.name.caseless == "zohomeeting.exe", "ZohoAssist",
    process.name.caseless == "zohotray.exe", "ZohoAssist",
    process.name.caseless == "zohours.exe", "ZohoAssist",
    process.name.caseless == "zohoursservice.exe", "ZohoAssist",
    ""
  )
Esql.rmm_vendor =
ifprocess.name.caseless like "aa_v*.exe""AnyAssist"
elifprocess.name.caseless == "acroniscyberprotectconnectagent.exe""Acronis"
elifprocess.name.caseless == "aeroadmin.exe""AeroAdmin"
elifprocess.name.caseless == "agentmon.exe""ConnectWiseAutomate"
elifprocess.name.caseless == "anydesk.exe""AnyDesk"
elifprocess.name.caseless == "apc_admin.exe""APC"
elifprocess.name.caseless == "apc_host.exe""APC"
elifprocess.name.caseless == "ateraagent.exe""Atera"
elifprocess.name.caseless like "aweray_remote*.exe""AweSun"
elifprocess.name.caseless == "awesun.exe""AweSun"
elifprocess.name.caseless == "b4-service.exe""BeyondTrust"
elifprocess.name.caseless == "basupsrvc.exe""BeyondTrust"
elifprocess.name.caseless == "bomgar-scc.exe""BeyondTrust"
elifprocess.name.caseless == "remote support.exe""BeyondTrust"
elifprocess.name.caseless == "cagservice.exe""BarracudaRMM"
elifprocess.name.caseless == "cloudracmd.exe""CloudRadial"
elifprocess.name.caseless == "cloudrasd.exe""CloudRadial"
elifprocess.name.caseless == "cloudraservice.exe""CloudRadial"
elifprocess.name.caseless like "connectwisecontrol*.exe""ScreenConnect"
elifprocess.name.caseless == "domotzagent.exe""Domotz"
elifprocess.name.caseless == "domotz-windows-x64-10.exe""Domotz"
elifprocess.name.caseless == "dwagsvc.exe""DWService"
elifprocess.name.caseless == "dwrcc.exe""DWService"
elifprocess.name.caseless == "dwrcs.exe""DWService"
elifprocess.name.caseless == "dwrcst.exe""DWService"
elifprocess.name.caseless like "fleetdeck_commander*.exe""FleetDeck"
elifprocess.name.caseless == "g2aservice.exe""GoTo"
elifprocess.name.caseless == "getscreen.exe""GetScreen"
elifprocess.name.caseless == "gotoassistservice.exe""GoTo"
elifprocess.name.caseless == "gotohttp.exe""GoTo"
elifprocess.name.caseless == "gotoresolveprocesschecker.exe""GoTo"
elifprocess.name.caseless == "gotoresolveremotecontrol.exe""GoTo"
elifprocess.name.caseless == "gotoresolveservice.exe""GoTo"
elifprocess.name.caseless == "gotoresolveterminal.exe""GoTo"
elifprocess.name.caseless == "gotoresolveunattended.exe""GoTo"
elifprocess.name.caseless == "helpwire.exe""HelpWire"
elifprocess.name.caseless == "immyagent.exe""ImmyBot"
elifprocess.name.caseless == "immybot.agent.ephemeral.exe""ImmyBot"
elifprocess.name.caseless == "immyupdater.exe""ImmyBot"
elifprocess.name.caseless == "imperoclientsvc.exe""Impero"
elifprocess.name.caseless == "imperoserversvc.exe""Impero"
elifprocess.name.caseless == "isllight.exe""ISLOnline"
elifprocess.name.caseless == "isllightclient.exe""ISLOnline"
elifprocess.name.caseless == "jumpcloud-agent.exe""JumpCloud"
elifprocess.name.caseless == "komari.exe""Komari"
elifprocess.name.caseless == "komari-agent.exe""Komari"
elifprocess.name.caseless == "level.exe""Level"
elifprocess.name.caseless == "lmi_rescue.exe""LogMeIn"
elifprocess.name.caseless == "lmi_rescue_srv.exe""LogMeIn"
elifprocess.name.caseless == "lmiignition.exe""LogMeIn"
elifprocess.name.caseless == "logmein.exe""LogMeIn"
elifprocess.name.caseless == "ltsvc.exe""ConnectWiseAutomate"
elifprocess.name.caseless == "ltsvcmon.exe""ConnectWiseAutomate"
elifprocess.name.caseless == "lttray.exe""ConnectWiseAutomate"
elifprocess.name.caseless == "lunixar.exe""Lunixar"
elifprocess.name.caseless == "lunixarremote.exe""Lunixar"
elifprocess.name.caseless == "lunixarupdater.exe""Lunixar"
elifprocess.name.caseless == "lvagent.exe""Level"
elifprocess.name.caseless == "manageengine_remote_access_plus.exe""ManageEngine"
elifprocess.name.caseless == "meshagent.exe""MeshCentral"
elifprocess.name.caseless == "mikogo-service.exe""Mikogo"
elifprocess.name.caseless == "nezha-agent.exe""Nezha"
elifprocess.name.caseless == "ninjarmmagent.exe""NinjaOne"
elifprocess.name.caseless == "ninjarmmagentpatcher.exe""NinjaOne"
elifprocess.name.caseless == "ninjarmm-cli.exe""NinjaOne"
elifprocess.name.caseless == "parsec.exe""Parsec"
elifprocess.name.caseless == "pservice.exe""Pulseway"
elifprocess.name.caseless == "quickassist.exe""QuickAssist"
elifprocess.name.caseless == "r_server.exe""Radmin"
elifprocess.name.caseless == "radmin.exe""Radmin"
elifprocess.name.caseless == "radmin3.exe""Radmin"
elifprocess.name.caseless == "rcengmgru.exe""Rsupport"
elifprocess.name.caseless == "rcclient.exe""RPCSuite"
elifprocess.name.caseless == "rcmgrsvc.exe""Rsupport"
elifprocess.name.caseless == "rcservice.exe""RPCSuite"
elifprocess.name.caseless == "remotedesktopmanager.exe""Devolutions"
elifprocess.name.caseless == "remotely_agent.exe""Remotely"
elifprocess.name.caseless == "remotely_desktop.exe""Remotely"
elifprocess.name.caseless == "remotepc.exe""RemotePC"
elifprocess.name.caseless == "remotepcdesktop.exe""RemotePC"
elifprocess.name.caseless == "remotepcservice.exe""RemotePC"
elifprocess.name.caseless == "remoteview.exe""Rsupport"
elifprocess.name.caseless == "rfusclient.exe""RemoteUtilities"
elifprocess.name.caseless == "rmm.agent.exe""SuperOps"
elifprocess.name.caseless == "romserver.exe""RealVNC"
elifprocess.name.caseless == "romviewer.exe""RealVNC"
elifprocess.name.caseless == "rpcsuite.exe""RPCSuite"
elifprocess.name.caseless == "rserver3.exe""Radmin"
elifprocess.name.caseless == "rustdesk.exe""RustDesk"
elifprocess.name.caseless == "rutserv.exe""RemoteUtilities"
elifprocess.name.caseless == "rutview.exe""RemoteUtilities"
elifprocess.name.caseless == "rvagent.exe""Rsupport"
elifprocess.name.caseless == "rvagtray.exe""Rsupport"
elifprocess.name.caseless == "saazapsc.exe""Kaseya"
elifprocess.name.caseless like "screenconnect*.exe""ScreenConnect"
elifprocess.name.caseless == "session_win.exe""ZohoAssist"
elifprocess.name.caseless == "simplegatewayservice.exe""SimpleHelp"
elifprocess.name.caseless == "simplehelpcustomer.exe""SimpleHelp"
elifprocess.name.caseless == "smpcview.exe""Splashtop"
elifprocess.name.caseless == "spclink.exe""Splashtop"
elifprocess.name.caseless == "splashtop-streamer.exe""Splashtop"
elifprocess.name.caseless == "splashtopsos.exe""Splashtop"
elifprocess.name.caseless == "spsrv.exe""Splashtop"
elifprocess.name.caseless == "sragent.exe""Splashtop"
elifprocess.name.caseless == "srservice.exe""Splashtop"
elifprocess.name.caseless == "srmanager.exe""Splashtop"
elifprocess.name.caseless == "srserver.exe""Splashtop"
elifprocess.name.caseless == "strwinclt.exe""Splashtop"
elifprocess.name.caseless == "supremo.exe""Supremo"
elifprocess.name.caseless == "supremoservice.exe""Supremo"
elifprocess.name.caseless == "syncro.app.runner.exe""Splashtop"
elifprocess.name.caseless == "syncro.installer.exe""Splashtop"
elifprocess.name.caseless == "syncro.overmind.service.exe""Splashtop"
elifprocess.name.caseless == "syncro.service.exe""Splashtop"
elifprocess.name.caseless == "syncrolive.agent.exe""Splashtop"
elifprocess.name.caseless == "syncrolive.agent.runner.exe""Splashtop"
elifprocess.name.caseless == "syncrolive.service.exe""Splashtop"
elifprocess.name.caseless == "tacticalrmm.exe""TacticalRMM"
elifprocess.name.caseless == "tailscale.exe""Tailscale"
elifprocess.name.caseless == "tailscaled.exe""Tailscale"
elifprocess.name.caseless == "teamviewer.exe""TeamViewer"
elifprocess.name.caseless == "teamviewer_desktop.exe""TeamViewer"
elifprocess.name.caseless == "teamviewer_service.exe""TeamViewer"
elifprocess.name.caseless == "tiagent.exe""Tiflux"
elifprocess.name.caseless == "ticlientcore.exe""Tiflux"
elifprocess.name.caseless == "todesk_service.exe""ToDesk"
elifprocess.name.caseless == "toolsiq.exe""ToolsIQ"
elifprocess.name.caseless == "tsclient.exe""Techinline"
elifprocess.name.caseless == "tvn.exe""TightVNC"
elifprocess.name.caseless == "tvnserver.exe""TightVNC"
elifprocess.name.caseless == "tvnviewer.exe""TightVNC"
elifprocess.name.caseless == "twingate.exe""Twingate"
elifprocess.name.caseless like "ultravnc*.exe""UltraVNC"
elifprocess.name.caseless like "ultraviewer*.exe""UltraViewer"
elifprocess.name.caseless == "velociraptor.exe""Velociraptor"
elifprocess.name.caseless == "vncserver.exe""RealVNC"
elifprocess.name.caseless == "vncviewer.exe""RealVNC"
elifprocess.name.caseless == "winvnc.exe""RealVNC"
elifprocess.name.caseless == "winwvc.exe""TightVNC"
elifprocess.name.caseless == "za_access.exe""ZohoAssist"
elifprocess.name.caseless == "za_connect.exe""ZohoAssist"
elifprocess.name.caseless == "zaservice.exe""ZohoAssist"
elifprocess.name.caseless == "zmagent.exe""ZohoAssist"
elifprocess.name.caseless == "zohomeeting.exe""ZohoAssist"
elifprocess.name.caseless == "zohotray.exe""ZohoAssist"
elifprocess.name.caseless == "zohours.exe""ZohoAssist"
elifprocess.name.caseless == "zohoursservice.exe""ZohoAssist"
else""

Stage 4: where

| where Esql.rmm_vendor != "" and Esql.rmm_vendor is not NULL

Stage 5: stats

| stats Esql.vendor_count = count_distinct(Esql.rmm_vendor),
        Esql.vendors_seen = values(Esql.rmm_vendor),
        Esql.processes_executable_values = values(process.executable),
        Esql.first_seen = min(@timestamp),
        Esql.last_seen = max(@timestamp)
  by host.name, host.id

Stage 6: where

| where Esql.vendor_count >= 2

Stage 7: sort

| sort Esql.vendor_count desc

Stage 8: keep

| keep host.id, host.name, Esql.*

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
host.idKEEP host.id
host.nameKEEP host.name
Esql.*KEEP Esql.*

Parent Process PID Spoofing

#
Status
production
Severity
high
Time window
3m
Sequence by
host.id, process.parent.Ext.real.pid, process.pid, user.id
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies parent process spoofing used to thwart detection. Adversaries may spoof the parent process identifier (PPID) of a new process to evade process-monitoring defenses or to elevate privileges.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2021/07/14"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/04/30"

[rule]
author = ["Elastic"]
description = """
Identifies parent process spoofing used to thwart detection. Adversaries may spoof the parent process identifier (PPID)
of a new process to evade process-monitoring defenses or to elevate privileges.
"""
from = "now-9m"
index = ["logs-endpoint.events.process-*"]
language = "eql"
license = "Elastic License v2"
name = "Parent Process PID Spoofing"
references = [
    "https://blog.didierstevens.com/2017/03/20/that-is-not-my-child-process/",
    "https://www.elastic.co/security-labs/elastic-security-labs-steps-through-the-r77-rootkit",
]
risk_score = 73
rule_id = "c88d4bd0-5649-4c52-87ea-9be59dbfbcf2"
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Data Source: Elastic Defend",
    "Resources: Investigation Guide",
]
type = "eql"

query = '''
/* This rule is compatible with Elastic Endpoint only */

sequence by host.id, user.id with maxspan=3m

 [process where host.os.type == "windows" and event.type == "start" and
  process.Ext.token.integrity_level_name != "system" and
  (
    process.pe.original_file_name : ("winword.exe", "excel.exe", "outlook.exe", "powerpnt.exe", "eqnedt32.exe",
                                     "fltldr.exe", "mspub.exe", "msaccess.exe", "powershell.exe", "pwsh.exe",
                                     "cscript.exe", "wscript.exe", "rundll32.exe", "regsvr32.exe", "msbuild.exe",
                                     "mshta.exe", "wmic.exe", "cmstp.exe", "msxsl.exe") or

    (process.executable : ("?:\\Users\\*.exe",
                           "?:\\ProgramData\\*.exe",
                           "?:\\Windows\\Temp\\*.exe",
                           "?:\\Windows\\Tasks\\*") and
      (process.code_signature.exists == false or process.code_signature.status : "errorBadDigest")) or

    process.executable : "?:\\Windows\\Microsoft.NET\\*.exe"
  ) and

  not process.executable :
             ("?:\\Windows\\System32\\WerFaultSecure.exe",
              "?:\\WINDOWS\\SysWOW64\\WerFaultSecure.exe",
              "?:\\Windows\\System32\\WerFault.exe",
              "?:\\Windows\\SysWOW64\\WerFault.exe")
  ] by process.pid
 [process where host.os.type == "windows" and event.type == "start" and
  process.parent.Ext.real.pid > 0 and

  /* process.parent.Ext.real.pid is only populated if the parent process pid doesn't match */
  not (process.name : "msedge.exe" and process.parent.name : "sihost.exe") and

   not process.executable :
             ("?:\\Windows\\System32\\WerFaultSecure.exe",
              "?:\\WINDOWS\\SysWOW64\\WerFaultSecure.exe",
              "?:\\Windows\\System32\\WerFault.exe",
              "?:\\Windows\\SysWOW64\\WerFault.exe")
 ] by process.parent.Ext.real.pid
'''

note = """## Triage and analysis

### Investigating Parent Process PID Spoofing

#### Possible investigation steps

- Which source events prove the real creator, spoofed child, and visible-parent mismatch?
  - Focus: Timeline source events for shared `host.id` and `user.id`; record creator and child `process.entity_id`, `process.pid`, `process.executable`, and child `process.parent.pid` versus `process.parent.Ext.real.pid`.
  - Hint: the sequence alert may not expose `process.parent.Ext.real.pid`; use the recovered child event. If absent, empty, or mapped to multiple creator candidates, treat recovery as unresolved, not benign.
  - Implication: escalate when `process.parent.Ext.real.pid` maps to the recovered creator while the child reports a different visible parent with no brokered-launch explanation; lower suspicion when both events resolve to one recognized broker, installer, support, or sensor-corrected path for the same product/user.
- Does the recovered creator look like a plausible spoofing initiator?
  - Focus: creator `process.pe.original_file_name`, `process.executable`, `process.command_line`, `process.code_signature.exists`, and `process.code_signature.status`.
  - Implication: higher concern when the creator is an Office process, script host, LOLBin, user-writable or .NET executable, or unsigned/bad-signature binary whose command line does not fit software deployment; lower suspicion when creator identity and command line fit the recognized updater, installer, EDR, or support component from step 1.
- Is the spoofed child a credible target for cover or a likely payload?
  - Focus: child `process.executable`, `process.pe.original_file_name`, `process.code_signature.subject_name`, `process.code_signature.trusted`, `process.Ext.relative_file_creation_time`, and file events for the child path. $investigate_0
  - Implication: escalate when the child is newly created, unsigned or untrusted, renamed, or launched from user-writable, temp, task, or unusual .NET paths; lower suspicion when path, signer, original file name, and file age match the same recognized product layout. Identity alone does not clear lineage manipulation.
- Is the visible parent credible for this child?
  - Focus: child `process.parent.name`, `process.parent.executable`, `process.parent.command_line`, and `process.parent.pid`, compared with recovered creator `process.entity_id`.
  - Implication: stronger evidence of deliberate cover when the visible parent is a trusted system, shell, productivity, or management process with no command context or product relationship to the child; lower suspicion when a recognized service, compatibility layer, or broker mediates that exact child on this host.
- Does user, session, or token context raise severity?
  - Focus: `user.id`, `user.domain`, child `process.Ext.session_info.logon_type`, and `process.Ext.token.integrity_level_name`.
  - Implication: escalate faster when the chain runs under an unexpected account, remote or network session, service context, or higher integrity than the creator-child role explains; lower suspicion when user, session, integrity, and host pairing fit the recovered support or management workflow.
- Did the spoofed child immediately continue execution in a way that matches payload launch or hollowing?
  - Focus: recovered child `process.entity_id` and descendants where `process.parent.entity_id` matches it, checking `process.Ext.created_suspended`, `process.command_line`, and descendant `process.executable`. $investigate_1
  - Implication: escalate when the child is created suspended, spawns shells, script hosts, credential tools, unusual binaries, or synthetic process-id/GUID-like command-line values; lower suspicion when descendants stay inside the recovered product workflow.
- If local lineage remains suspicious or unresolved, do related alerts change scope?
  - Focus: related alerts for the same `user.id`: PPID spoofing, unusual parent-child, injection, suspicious launcher, or payload execution. $investigate_2
  - Hint: if user scope is sparse or ambiguous, check the same `host.id`. $investigate_3
  - Implication: broaden scope when the same user or host shows related process manipulation or payload activity; keep local when related alerts are quiet and source-event evidence resolves to one recognized workflow.

- Escalate when source recovery, creator role, visible-parent mismatch, child identity, session/token context, or follow-on behavior indicates deliberate lineage manipulation or payload launch; close only when all recovered process evidence binds to one exact recognized brokered-launch workflow with no contradiction; preserve source events and escalate when evidence is mixed or incomplete.

### False positive analysis

- Treat installers, updaters, application brokers, remote-support tools, and endpoint-security components as candidate explanations, not benign categories. Close only when one recovered creator-child-visible-parent tuple is internally consistent across creator and child `process.executable`, visible parent `process.parent.executable`, signer `process.code_signature.subject_name`, command intent `process.command_line`, session type `process.Ext.session_info.logon_type`, and the same `user.id` plus `host.id`. If telemetry cannot prove legitimacy, require outside confirmation for that exact activity before closing.
- Before creating an exception, validate recurrence of the same recovered creator-child-visible-parent pattern for the same host or user cohort across prior alerts from this rule. Anchor on stable creator, child, and visible-parent executables, `process.code_signature.subject_name`, session/integrity context, and relevant `host.id` or `user.id`; avoid exceptions on `process.name`, process IDs, or real-parent PID values alone.

### Response and remediation

- Before containment reversal, isolation, process termination, or cleanup, preserve Timeline source events, recovered creator and child `process.entity_id` values, the real-vs-visible parent PID mapping, command lines, signer/hash context, session/token context, and descendant process events.
- If confirmed benign after preservation, reverse temporary containment and document the exact creator-child-visible-parent workflow, including stable creator and child identity, visible parent identity, signer, command context, session type, and `host.id` or `user.id` scope. Create an exception only after recurrence or outside confirmation proves the same workflow.
- Apply reversible containment first: heightened monitoring, temporary user-session containment, or policy controls on affected `host.id` and `user.id`; use host isolation only when recovered lineage, abnormal token/session context, created-suspended evidence, or suspicious descendants indicate likely payload execution or spread.
- If confirmed malicious after preservation, isolate the endpoint or affected account scope according to evidence; take credential action only when session or token evidence indicates account misuse. Terminate the malicious process tree only after recording creator and child entity IDs, command lines, visible parent, and descendant process evidence.
- Remove the malicious launcher, spoofed child binary, and any payload artifacts identified during investigation; restore only confirmed configuration changes tied to the launch path, and remediate the entry vector. Delay destructive cleanup until scoping has captured the same creator, child, signer, or parent-selection pattern across related host and user alerts.
- Post-incident hardening: restrict only the confirmed parent-selection path and retain endpoint process telemetry needed to compare the recovered real creator with the visible parent in future repeat alerts."""

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
"""

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "host.id",
    "host.name",
    "user.id",
    "user.name",
    "process.entity_id",
    "process.pid",
    "process.executable",
    "process.command_line",
    "process.Ext.token.integrity_level_name",
    "process.parent.pid",
    "process.parent.name",
    "process.parent.executable",
    "process.code_signature.subject_name",
    "process.code_signature.trusted",
]

[transform]

[[transform.investigate]]
label = "File events for the spoofed child path"
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 = "file.path", queryType = "phrase", value = "{{process.executable}}", valueType = "string" }
  ]
]
relativeFrom = "now-24h"
relativeTo = "now"

[[transform.investigate]]
label = "Descendant process events for the spoofed child"
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" }
  ]
]
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 = "T1134"
name = "Access Token Manipulation"
reference = "https://attack.mitre.org/techniques/T1134/"
[[rule.threat.technique.subtechnique]]
id = "T1134.004"
name = "Parent PID Spoofing"
reference = "https://attack.mitre.org/techniques/T1134/004/"

[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 = "T1134"
name = "Access Token Manipulation"
reference = "https://attack.mitre.org/techniques/T1134/"
[[rule.threat.technique.subtechnique]]
id = "T1134.004"
name = "Parent PID Spoofing"
reference = "https://attack.mitre.org/techniques/T1134/004/"

[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 3m, correlated by host.id, process.parent.Ext.real.pid, process.pid, user.id.

Stage 1: process

[process where host.os.type == "windows" and event.type == "start" and
  process.Ext.token.integrity_level_name != "system" and
  (
    process.pe.original_file_name : ("winword.exe", "excel.exe", "outlook.exe", "powerpnt.exe", "eqnedt32.exe",
                                     "fltldr.exe", "mspub.exe", "msaccess.exe", "powershell.exe", "pwsh.exe",
                                     "cscript.exe", "wscript.exe", "rundll32.exe", "regsvr32.exe", "msbuild.exe",
                                     "mshta.exe", "wmic.exe", "cmstp.exe", "msxsl.exe") or

    (process.executable : ("?:\\Users\\*.exe",
                           "?:\\ProgramData\\*.exe",
                           "?:\\Windows\\Temp\\*.exe",
                           "?:\\Windows\\Tasks\\*") and
      (process.code_signature.exists == false or process.code_signature.status : "errorBadDigest")) or

    process.executable : "?:\\Windows\\Microsoft.NET\\*.exe"
  ) and

  not process.executable :
             ("?:\\Windows\\System32\\WerFaultSecure.exe",
              "?:\\WINDOWS\\SysWOW64\\WerFaultSecure.exe",
              "?:\\Windows\\System32\\WerFault.exe",
              "?:\\Windows\\SysWOW64\\WerFault.exe")
  ] by process.pid

Stage 2: process

[process where host.os.type == "windows" and event.type == "start" and
  process.parent.Ext.real.pid > 0 and
  not (process.name : "msedge.exe" and process.parent.name : "sihost.exe") and
   not process.executable :
             ("?:\\Windows\\System32\\WerFaultSecure.exe",
              "?:\\WINDOWS\\SysWOW64\\WerFaultSecure.exe",
              "?:\\Windows\\System32\\WerFault.exe",
              "?:\\Windows\\SysWOW64\\WerFault.exe")
 ] by process.parent.Ext.real.pid

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.Ext.token.integrity_level_namene
  • system corpus 2 (elastic 2)
field:"process.Ext.token.integrity_level_name" kind:ne value:"system"
process.code_signature.existseq
  • false transforms: boolean corpus 118 (elastic 118)
field:"process.code_signature.exists" kind:eq value:"false"
process.code_signature.statuswildcard
  • errorBadDigest
field:"SignatureStatus" kind:wildcard value:"errorBadDigest"
process.executablewildcard
  • ?:\ProgramData\*.exe corpus 9 (elastic 9)
  • ?:\Users\*.exe corpus 6 (elastic 6)
  • ?:\Windows\Microsoft.NET\*.exe corpus 8 (elastic 8)
  • ?:\Windows\Tasks\* corpus 7 (elastic 7)
  • ?:\Windows\Temp\*.exe
field:"Image" kind:wildcard
process.parent.Ext.real.pidgt
  • 0 transforms: number corpus 11 (elastic 11)
field:"process.parent.Ext.real.pid" kind:gt value:"0"
process.pe.original_file_namewildcard
  • cmstp.exe corpus 9 (sigma 5, elastic 4)
  • cscript.exe corpus 32 (sigma 17, elastic 15)
  • eqnedt32.exe
  • excel.exe corpus 4 (sigma 3, elastic 1)
  • fltldr.exe
  • msaccess.exe corpus 2 (sigma 1, elastic 1)
  • msbuild.exe corpus 16 (elastic 11, splunk 4, sigma 1)
  • mshta.exe corpus 40 (elastic 21, sigma 13, splunk 6)
  • mspub.exe corpus 3 (sigma 2, elastic 1)
  • msxsl.exe corpus 9 (elastic 6, sigma 3)
  • outlook.exe corpus 2 (sigma 1, elastic 1)
  • powerpnt.exe corpus 4 (sigma 3, elastic 1)
  • powershell.exe corpus 134 (sigma 86, splunk 30, elastic 18)
  • pwsh.exe corpus 7 (elastic 7)
  • regsvr32.exe corpus 37 (sigma 17, elastic 15, splunk 5)
  • rundll32.exe corpus 72 (sigma 35, splunk 21, elastic 16)
  • winword.exe corpus 6 (sigma 4, elastic 2)
  • wmic.exe corpus 74 (sigma 38, elastic 18, splunk 18)
  • wscript.exe corpus 37 (elastic 20, sigma 17)
field:"OriginalFileName" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.executableeq?:\Windows\System32\WerFaultSecure.exe, ?:\WINDOWS\SysWOW64\WerFaultSecure.exe, ?:\Windows\System32\WerFault.exe, ?:\Windows\SysWOW64\WerFault.exeexcludes:process.executable
process.nameeqmsedge.exeexcludes:process.name field:"process.name" value:"msedge.exe"
process.parent.nameeqsihost.exeexcludes:process.parent.name field:"process.parent.name" value:"sihost.exe"

Potential ADIDNS Poisoning via Wildcard Record Creation

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

Active Directory Integrated DNS (ADIDNS) is one of the core components of AD DS, leveraging AD's access control and replication to maintain domain consistency. It stores DNS zones as AD objects, a feature that, while robust, introduces some security issues, such as wildcard records, mainly because of the default permission (Any authenticated users) to create DNS-named records. Attackers can create wildcard records to redirect traffic for names that do not explicitly match records in the zone, positioning themselves as an adversary-in-the-middle and enabling credential interception or relay through ADIDNS manipulation similar in outcome to LLMNR/NBNS spoofing.

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2024/03/26"
integration = ["system", "windows"]
maturity = "production"
updated_date = "2026/04/22"

[rule]
author = ["Elastic"]
description = """
Active Directory Integrated DNS (ADIDNS) is one of the core components of AD DS, leveraging AD's access control and
replication to maintain domain consistency. It stores DNS zones as AD objects, a feature that, while robust, introduces
some security issues, such as wildcard records, mainly because of the default permission (Any authenticated users) to
create DNS-named records. Attackers can create wildcard records to redirect traffic for names that do not explicitly
match records in the zone, positioning themselves as an adversary-in-the-middle and enabling credential interception or
relay through ADIDNS manipulation similar in outcome to LLMNR/NBNS spoofing.
"""
from = "now-9m"
index = ["logs-system.security*", "logs-windows.forwarded*", "winlogbeat-*"]
language = "eql"
license = "Elastic License v2"
name = "Potential ADIDNS Poisoning via Wildcard Record Creation"
references = [
    "https://www.netspi.com/blog/technical/network-penetration-testing/exploiting-adidns/",
    "https://www.thehacker.recipes/a-d/movement/mitm-and-coerced-authentications/adidns-spoofing",
]
risk_score = 73
rule_id = "8f242ffb-b191-4803-90ec-0f19942e17fd"
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Data Source: Active Directory",
    "Use Case: Active Directory Monitoring",
    "Data Source: Windows Security Event Logs",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
any where host.os.type == "windows" and event.code == "5137" and
    startsWith(winlog.event_data.ObjectDN, "DC=*,")
'''

note = """## Triage and analysis

### Investigating Potential ADIDNS Poisoning via Wildcard Record Creation

#### Possible investigation steps

- What wildcard object did the alert create, and which ADIDNS scope can it affect?
  - Why: a leading `DC=*` object can answer otherwise unresolved names across that ADIDNS zone, so the zone and partition define the first impact boundary.
  - Focus: `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, and `winlog.computer_name`.
  - Hint: parse `winlog.event_data.ObjectDN` from left to right. In `DC=*,DC=example.com,CN=MicrosoftDNS,DC=DomainDnsZones,DC=example,DC=com`, `DC=*` is the wildcard node, `DC=example.com` is the DNS zone, and `DC=DomainDnsZones,...` identifies the AD DNS partition.
  - Implication: escalate faster when the object is a wildcard dnsNode in a production domain or forest DNS partition; lower concern only when the same object, zone, and domain controller align with a defensive sinkhole or contained test candidate, then continue to session and change evidence before closure.

- Which account created the wildcard?
  - Focus: `user.name`, `user.id`, and `winlog.event_data.SubjectLogonId`.
  - Implication: escalate when the creator is not a recognized zone-management, defensive sinkhole, or test identity for this object and zone; keep investigating when the account fits a known role because identity alone does not clear wildcard creation.

- Where did the creating session originate?
  - Focus: 4624 events on the same `host.id` where `winlog.event_data.TargetLogonId` matches `winlog.event_data.SubjectLogonId`; review `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`.
    - $investigate_2
  - Implication: escalate when the source, logon type, or authentication method is unexpected for DC-side ADIDNS changes; missing 4624 origin data is unresolved, not benign.

- What DNS attributes or neighboring objects changed in the same operation?
  - Focus: same-session 5136/5137 records keyed by `winlog.event_data.OpCorrelationID` or `winlog.event_data.SubjectLogonId`, then grouped by `winlog.event_data.ObjectGUID`; inspect `winlog.event_data.AttributeLDAPDisplayName` and `winlog.event_data.AttributeValue`.
  - Hint: query the same domain controller and alert window for matching directory-service changes. Treat `winlog.event_data.AttributeValue` for `dnsRecord` as a lead because Security logs may encode or truncate record data. If the target is unclear, retrieve the current ADIDNS object or DNS record and compare it to `ObjectDN`, `ObjectGUID`, and the event timeline because current state may differ from event-time state. Missing DNS record data is unresolved, not benign. Windows Security alone does not prove tool identity or client redirection.
    - $investigate_3
  - Implication: escalate when 5136 data shows a dnsRecord target or adjacent ADIDNS changes not tied to the same verified sinkhole or test object; if `winlog.event_data.AttributeValue` is opaque or absent, the target remains unresolved.

- Did clients use the wildcard or authenticate to the recovered target?
  - Focus: DNS/client telemetry for names in the affected zone and downstream network or authentication events to the recovered target; compare `dns.question.name`, `dns.resolved_ip`, `source.ip`, and `destination.ip`.
  - Implication: escalate impact when clients query unresolved names that resolve to the wildcard target, then connect or authenticate to that target; missing DNS, network, or authentication telemetry is unresolved, not benign.

- If object, session, or change-set evidence stays suspicious, do related alerts suggest broader AD abuse?
  - Focus: related alerts for `user.id` and `host.id` involving repeated directory-service changes, ADIDNS abuse, or credential access.
    - $investigate_0
    - $investigate_1
  - Implication: broaden scope when the same actor or domain controller shows related AD, relay, or credential-access activity; keep scope local only when related alerts are absent and object, session, and change-set evidence fit a recognized sinkhole or test.

- Escalate when production wildcard scope, unrecognized creator/session, suspicious dnsRecord target, client-impact evidence, adjacent ADIDNS changes, or related AD-abuse alerts point to unrecognized wildcard creation; close only when all evidence fits the exact defensive sinkhole or contained test object; if mixed or incomplete, preserve and escalate.

### False positive analysis

- Wildcard records in AD-integrated DNS zones are an anti-pattern because they can replace NXDOMAIN behavior and redirect unresolved names. The plausible benign paths are narrow: an administrator-controlled defensive sinkhole or a contained red-team or penetration test. Confirm by verifying that `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, `user.id`, `winlog.event_data.SubjectLogonId`, and recovered 5136 attribute evidence all align with that exact object and scope.
- If independent confirmation of the sinkhole or test is unavailable, do not close as benign even when the Windows Security evidence is internally consistent.
- Before creating an exception, require the same wildcard object, authorized zone, creator identity, and defensive or test window to recur as one stable workflow. Avoid exceptions on `user.name`, `user.id`, or the domain partition alone because those would suppress lookalike wildcard creation.

### Response and remediation

- If confirmed as an authorized defensive sinkhole or test, reverse any temporary containment, verify the wildcard is removed or retained according to that scope, and document `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, creating `user.id`, `winlog.event_data.SubjectLogonId`, `winlog.computer_name`, and the confirming scope.
- If suspicious but unconfirmed, export the AD object state, replication context, and related 5136/5137 Windows Security events before modifying the record or account. Then apply reversible containment tied to the evidence, such as restricting the creating account's ADIDNS write path or temporarily limiting that account while scope is clarified.
- If confirmed malicious, preserve the exported AD object, 5136 attribute evidence, session-origin evidence, and related alerts before deletion. Remove the wildcard and any unauthorized ADIDNS objects from the same session, then verify removal replicated to all domain controllers.
- Disable or restrict the creating account after evidence preservation to prevent re-poisoning. Use `winlog.event_data.SubjectLogonId` and recovered `source.ip` to hand off the source system for endpoint investigation of ADIDNS tooling, credential capture, or follow-on authentication.
- If separate response evidence proves client redirection through the wildcard, treat credentials active on affected systems as exposed. Reset those accounts, prioritizing privileged and service accounts, and investigate for relayed authentication or follow-on access.
- Review ADIDNS permissions for the affected zone; reduce wildcard-creation opportunities, especially broadly delegated or authenticated-user create-child rights. Search all AD-integrated zones for additional wildcard or suspicious ADIDNS objects and document the final evidence set for future narrow exceptions.
"""

setup = """## Setup

Audit Directory Service Changes must be enabled to generate the events used by this rule.
Setup instructions: https://ela.st/audit-directory-service-changes
"""

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user.id",
    "winlog.event_data.SubjectLogonId",
    "winlog.event_data.OpCorrelationID",
    "winlog.event_data.ObjectDN",
    "winlog.event_data.ObjectGUID",
    "winlog.event_data.DSName",
    "winlog.computer_name",
    "host.id"
]

[[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 domain controller"
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 = "Session origin (4624) for the wildcard-creating logon"
description = ""
providers = [
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "winlog.event_data.TargetLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" },
    { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[transform.investigate]]
label = "Directory service changes from the wildcard-creating session"
description = ""
providers = [
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "winlog.event_data.OpCorrelationID", queryType = "phrase", value = "{{winlog.event_data.OpCorrelationID}}", valueType = "string" },
    { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }
  ],
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" },
    { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }
  ],
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" },
    { excluded = false, field = "event.code", queryType = "phrase", value = "5137", valueType = "string" }
  ]
]
relativeFrom = "now-1h/h"
relativeTo = "now"

[[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/"

Stages and Predicates

Stage 1: any

any where host.os.type == "windows" and event.code == "5137" and
    startsWith(winlog.event_data.ObjectDN, "DC=*,")

Indicators

These rows show field, operator, and value matches.

Potential Binary Masquerading via Invalid Code Signature

#
Source
github.com/elastic/protections-artifacts

Identifies binaries that have been identically named to Apple or popular third-party programs and have invalid or untrusted code signatures. Adversaries may attempt to manipulate the name of a process to make it appear legitimate or benign.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[rule]
description = """
Identifies binaries that have been identically named to Apple or popular third-party programs and have invalid or
untrusted code signatures. Adversaries may attempt to manipulate the name of a process to make it appear legitimate or
benign.
"""
id = "4154c8ce-c718-4641-80db-a6a52276f1a4"
license = "Elastic License v2"
name = "Potential Binary Masquerading via Invalid Code Signature"
os_list = ["macos"]
version = "1.0.40"

query = '''
process where event.action == "exec" and
 (
   process.name like ("com.apple.*", "com.jamf.*", "jamf*", "zoom.us") or 
   process.executable like "/Users/*/Library/com.apple.*"
  ) and
 (process.code_signature.trusted == false or process.code_signature.exists == false) and
 not (process.code_signature.subject_name in ("Software Signing", "com.apple.WebKit.Networking", "com.apple.WebKit.WebContent") and
      process.name in
           ("com.apple.WebKit.WebContent.Development",
            "com.apple.WebKit.GPU.Development",
            "com.apple.WebKit.Networking.Development",
            "com.apple.WebKit.Storage.Development")) and
 not process.executable like~ ("/usr/local/jamf/bin/jamf", "com.apple.WebKit.Networking.Development", "/Library/Application Support/JAMF/Remote Assist/jamfRemoteAssistLauncher",
                           "/Library/Application Support/JAMF/Remote Assist/jamfRemoteAssistConnectorUI.app/Contents/MacOS/jamfRemoteAssistConnectorUI",
                           "/Users/*/Library/Caches/ms-playwright/*") and
 not process.parent.executable in ("/sbin/launchd", "/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon") and
 not process.Ext.effective_parent.executable in ("/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon",
                                                "/System/Library/PrivateFrameworks/CoreSpeech.framework/corespeechd") and
 not (process.Ext.effective_parent.executable == "/Applications/Visual Studio Code.app/Contents/MacOS/Electron" and process.name == "com.apple.WebKit.WebContent.Development") and
 not (process.code_signature.signing_id in ("com.apple.WebKit.WebContent", "us.zoom.xos") and process.code_signature.trusted == true) and
 not (process.name == "zoom.us" and process.code_signature.subject_name == "Developer ID Application: Zoom Video Communications, Inc. (BJ4HAAB9B3)" and process.code_signature.team_id == "BJ4HAAB9B3") and
 not process.hash.sha256 in ("7519ac10c724566b7a57607cc2fc88a876bdd91a585e690c2480093b582c73e6", "930b075c52f829efcd431cee324403e1e8b03bf2039b1343aae31570034d30e2")
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1036"
name = "Masquerading"
reference = "https://attack.mitre.org/techniques/T1036/"
[[threat.technique.subtechnique]]
id = "T1036.001"
name = "Invalid Code Signature"
reference = "https://attack.mitre.org/techniques/T1036/001/"



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

[internal]
min_endpoint_version = "8.7.0"

Stages and Predicates

Stage 1: process

process where event.action == "exec" and
 (
   process.name like ("com.apple.*", "com.jamf.*", "jamf*", "zoom.us") or 
   process.executable like "/Users/*/Library/com.apple.*"
  ) and
 (process.code_signature.trusted == false or process.code_signature.exists == false) and
 not (process.code_signature.subject_name in ("Software Signing", "com.apple.WebKit.Networking", "com.apple.WebKit.WebContent") and
      process.name in
           ("com.apple.WebKit.WebContent.Development",
            "com.apple.WebKit.GPU.Development",
            "com.apple.WebKit.Networking.Development",
            "com.apple.WebKit.Storage.Development")) and
 not process.executable like~ ("/usr/local/jamf/bin/jamf", "com.apple.WebKit.Networking.Development", "/Library/Application Support/JAMF/Remote Assist/jamfRemoteAssistLauncher",
                           "/Library/Application Support/JAMF/Remote Assist/jamfRemoteAssistConnectorUI.app/Contents/MacOS/jamfRemoteAssistConnectorUI",
                           "/Users/*/Library/Caches/ms-playwright/*") and
 not process.parent.executable in ("/sbin/launchd", "/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon") and
 not process.Ext.effective_parent.executable in ("/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon",
                                                "/System/Library/PrivateFrameworks/CoreSpeech.framework/corespeechd") and
 not (process.Ext.effective_parent.executable == "/Applications/Visual Studio Code.app/Contents/MacOS/Electron" and process.name == "com.apple.WebKit.WebContent.Development") and
 not (process.code_signature.signing_id in ("com.apple.WebKit.WebContent", "us.zoom.xos") and process.code_signature.trusted == true) and
 not (process.name == "zoom.us" and process.code_signature.subject_name == "Developer ID Application: Zoom Video Communications, Inc. (BJ4HAAB9B3)" and process.code_signature.team_id == "BJ4HAAB9B3") and
 not process.hash.sha256 in ("7519ac10c724566b7a57607cc2fc88a876bdd91a585e690c2480093b582c73e6", "930b075c52f829efcd431cee324403e1e8b03bf2039b1343aae31570034d30e2")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.Ext.effective_parent.executableeq/Applications/Visual Studio Code.app/Contents/MacOS/Electronexcludes:process.Ext.effective_parent.executable field:"process.Ext.effective_parent.executable" value:"/Applications/Visual Studio Code.app/Contents/MacOS/Electron"
process.nameeqcom.apple.WebKit.WebContent.Developmentexcludes:process.name field:"process.name" value:"com.apple.WebKit.WebContent.Development"
process.code_signature.signing_idincom.apple.WebKit.WebContent, us.zoom.xosexcludes:process.code_signature.signing_id field:"process.code_signature.signing_id" value:"com.apple.WebKit.WebContent" field:"process.code_signature.signing_id" value:"us.zoom.xos"
process.code_signature.trustedeqtrueexcludes:process.code_signature.trusted field:"process.code_signature.trusted" value:"true"
process.code_signature.subject_nameeqDeveloper ID Application: Zoom Video Communications, Inc. (BJ4HAAB9B3)excludes:process.code_signature.subject_name field:"process.code_signature.subject_name" value:"Developer ID Application: Zoom Video Communications, Inc. (BJ4HAAB9B3)"
process.code_signature.team_ideqBJ4HAAB9B3excludes:process.code_signature.team_id field:"process.code_signature.team_id" value:"BJ4HAAB9B3"
process.nameeqzoom.usexcludes:process.name field:"process.name" value:"zoom.us"
process.code_signature.subject_nameinSoftware Signing, com.apple.WebKit.Networking, com.apple.WebKit.WebContentexcludes:process.code_signature.subject_name field:"process.code_signature.subject_name" value:"Software Signing" field:"process.code_signature.subject_name" value:"com.apple.WebKit.Networking" field:"process.code_signature.subject_name" value:"com.apple.WebKit.WebContent"
process.nameincom.apple.WebKit.GPU.Development, com.apple.WebKit.Networking.Development, com.apple.WebKit.Storage.Development, com.apple.WebKit.WebContent.Developmentexcludes:process.name
process.Ext.effective_parent.executablein/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon, /System/Library/PrivateFrameworks/CoreSpeech.framework/corespeechdexcludes:process.Ext.effective_parent.executable field:"process.Ext.effective_parent.executable" value:"/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon" field:"process.Ext.effective_parent.executable" value:"/System/Library/PrivateFrameworks/CoreSpeech.framework/corespeechd"
process.executablewildcard/usr/local/jamf/bin/jamf, com.apple.WebKit.Networking.Development, /Library/Application Support/JAMF/Remote Assist/jamfRemoteAssistLauncher, /Library/Application Support/JAMF/Remote Assist/jamfRemoteAssistConnectorUI.app/Contents/MacOS/jamfRemoteAssistConnectorUI, /Users/*/Library/Caches/ms-playwright/*excludes:process.executable
process.hash.sha256in7519ac10c724566b7a57607cc2fc88a876bdd91a585e690c2480093b582c73e6, 930b075c52f829efcd431cee324403e1e8b03bf2039b1343aae31570034d30e2excludes:process.hash.sha256 field:"process.hash.sha256" value:"7519ac10c724566b7a57607cc2fc88a876bdd91a585e690c2480093b582c73e6" field:"process.hash.sha256" value:"930b075c52f829efcd431cee324403e1e8b03bf2039b1343aae31570034d30e2"
process.parent.executablein/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon, /sbin/launchdexcludes:process.parent.executable field:"process.parent.executable" value:"/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon" field:"process.parent.executable" value:"/sbin/launchd"

Potential Cluster Enumeration via jq Detected via Defend for Containers

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

This rule detects the enumeration of the cluster by the "jq" command inside a container. The "jq" command is used to parse JSON data, and may be used by an adversary to gain information about the cluster and the services running inside it. This behavior is uncommon within a container, and is commonly leveraged by attackers to help parse cluster information in a more readable format, or set the output as environment variables.

Known False Positives

  • There is a potential for false positives if the "jq" command is used for legitimate purposes, such as debugging or troubleshooting. It is important to investigate any alerts generated by this rule to determine if they are indicative of malicious activity or part of legitimate container activity.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2026/02/02"
integration = ["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/29"

[rule]
author = ["Elastic"]
description = """
This rule detects the enumeration of the cluster by the "jq" command inside a container. The "jq" command is used to
parse JSON data, and may be used by an adversary to gain information about the cluster and the services running inside it.
This behavior is uncommon within a container, and is commonly leveraged by attackers to help parse
cluster information in a more readable format, or set the output as environment variables.
"""
false_positives = [
    """
    There is a potential for false positives if the "jq" command is used for legitimate purposes,
    such as debugging or troubleshooting. It is important to investigate any alerts generated by this rule to determine
    if they are indicative of malicious activity or part of legitimate container activity.
    """,
]
from = "now-6m"
index = ["logs-cloud_defend.process*"]
interval = "5m"
language = "eql"
license = "Elastic License v2"
name = "Potential Cluster Enumeration via jq Detected via Defend for Containers"
risk_score = 21
rule_id = "33ff31e9-3872-4944-8394-81dae76c12d9"
severity = "low"
tags = [
    "Data Source: Elastic Defend for Containers",
    "Domain: Container",
    "OS: Linux",
    "Use Case: Threat Detection",
    "Tactic: Discovery",
    "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.name == "jq" and
container.id like "?*" 
'''

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

[[rule.threat.technique]]
id = "T1613"
name = "Container and Resource Discovery"
reference = "https://attack.mitre.org/techniques/T1613/"

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

Stages and Predicates

Stage 1: process

process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.name == "jq" and
container.id like "?*"

Indicators

These rows show field, operator, and value matches.

Potential Initial Access via Rogue RDP Server

#
Time window
5m
Sequence by
process.entity_id
Source
github.com/elastic/protections-artifacts

Identifies attempts to drop an executable file via a malicious RDP connection file. This may indicate an attempt to get initial access by connecting to an adversary controlled malicious RDP server.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

[rule]
description = """
Identifies attempts to drop an executable file via a malicious RDP connection file. This may indicate an attempt to get
initial access by connecting to an adversary controlled malicious RDP server.
"""
id = "4c6cea1d-7c50-4d83-861b-3fee8c079d97"
license = "Elastic License v2"
name = "Potential Initial Access via Rogue RDP Server"
os_list = ["windows"]
reference = [
    "https://www.blackhillsinfosec.com/rogue-rdp-revisiting-initial-access-methods/",
    "https://shorsec.io/blog/malrdp-implementing-rouge-rdp-manually/",
]
version = "1.0.8"

query = '''
sequence by process.entity_id with maxspan=5m
 [process where event.action == "start" and process.name : "mstsc.exe" and process.args_count >= 2 and
  not (process.args : "-Embedding" and process.parent.name : "svchost.exe") and
  not process.parent.executable :
             ("?:\\Program Files\\Thycotic Software Ltd\\Secret Server Protocol Handler\\RDPWin.exe",
              "?:\\Program Files (x86)\\Thycotic Software Ltd\\Secret Server Protocol Handler\\RDPWin.exe")]
 [network where event.action == "connection_attempted" and process.name : "mstsc.exe"]
 [file where event.action != "deletion" and process.name : "mstsc.exe" and 
  (
   (file.extension : ("dll", "exe", "cpl", "pif", "com", "js", "vbs", "wsh", "vbe", "jse", "bat", "cmd") or
    file.Ext.header_bytes : "4d5a*" or file.name : "*.exe.config") or

   file.path : ("?:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
               "?:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*",
               "?:\\Users\\*\\Desktop\\*.lnk")
   ) and
   not file.path : ("?:\\*\\AppData\\Local\\Temp\\*", "?:\\Program Files*") and
   not (file.path : "?:\\ProgramData\\*" and not file.path : "?:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*")]
'''

min_endpoint_version = "7.16.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/"

[internal]
min_endpoint_version = "7.16.0"

Stages and Predicates

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

Stage 1: process

[process where event.action == "start" and process.name : "mstsc.exe" and process.args_count >= 2 and
  not (process.args : "-Embedding" and process.parent.name : "svchost.exe") and
  not process.parent.executable :
             ("?:\\Program Files\\Thycotic Software Ltd\\Secret Server Protocol Handler\\RDPWin.exe",
              "?:\\Program Files (x86)\\Thycotic Software Ltd\\Secret Server Protocol Handler\\RDPWin.exe")]

Stage 2: network

[network where event.action == "connection_attempted" and process.name : "mstsc.exe"]

Stage 3: file

[file where event.action != "deletion" and process.name : "mstsc.exe" and 
  (
   (file.extension : ("dll", "exe", "cpl", "pif", "com", "js", "vbs", "wsh", "vbe", "jse", "bat", "cmd") or
    file.Ext.header_bytes : "4d5a*" or file.name : "*.exe.config") or

   file.path : ("?:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
               "?:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*",
               "?:\\Users\\*\\Desktop\\*.lnk")
   ) and
   not file.path : ("?:\\*\\AppData\\Local\\Temp\\*", "?:\\Program Files*") and
   not (file.path : "?:\\ProgramData\\*" and not file.path : "?:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*")]

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • connection_attempted corpus 72 (elastic 72)
  • start corpus 388 (elastic 388)
field:"EventType" kind:eq
event.actionne
  • deletion corpus 90 (elastic 90)
field:"EventType" kind:ne value:"deletion"
file.Ext.header_byteswildcard
  • 4d5a* corpus 45 (elastic 45)
field:"file.Ext.header_bytes" kind:wildcard value:"4d5a*"
file.extensionwildcard
  • bat corpus 13 (elastic 13)
  • cmd corpus 15 (elastic 15)
  • com corpus 16 (elastic 16)
  • cpl corpus 19 (elastic 19)
  • dll corpus 32 (elastic 32)
  • exe corpus 32 (elastic 32)
  • js corpus 22 (elastic 22)
  • jse corpus 18 (elastic 18)
  • pif corpus 18 (elastic 18)
  • vbe corpus 18 (elastic 18)
  • vbs corpus 19 (elastic 19)
  • wsh corpus 16 (elastic 16)
field:"file.extension" kind:wildcard
file.namewildcard
  • *.exe.config corpus 2 (elastic 2)
field:"file.name" kind:wildcard value:"*.exe.config"
file.pathwildcard
  • ?:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\* corpus 12 (elastic 12)
  • ?:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\*
  • ?:\Users\*\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\* corpus 13 (elastic 13)
  • ?:\Users\*\Desktop\*.lnk corpus 3 (elastic 3)
field:"TargetFilename" kind:wildcard
process.args_countge
  • 2 transforms: number corpus 18 (elastic 18)
field:"process.args_count" kind:ge value:"2"
process.namewildcard
  • mstsc.exe corpus 8 (elastic 5, splunk 2, kusto 1)
field:"process_basename" kind:wildcard value:"mstsc.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argseq-Embeddingexcludes:process.args field:"process.args" value:"-Embedding"
process.parent.nameeqsvchost.exeexcludes:process.parent.name field:"process.parent.name" value:"svchost.exe"
process.parent.executableeq?:\Program Files\Thycotic Software Ltd\Secret Server Protocol Handler\RDPWin.exe, ?:\Program Files (x86)\Thycotic Software Ltd\Secret Server Protocol Handler\RDPWin.exeexcludes:process.parent.executable field:"process.parent.executable" value:"?:\Program Files\Thycotic Software Ltd\Secret Server Protocol Handler\RDPWin.exe" field:"process.parent.executable" value:"?:\Program Files (x86)\Thycotic Software Ltd\Secret Server Protocol Handler\RDPWin.exe"
file.pathstarts_with?:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\excludes:file.path field:"file.path" value:"?:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\"
file.pathstarts_with?:\ProgramData\excludes:file.path field:"file.path" value:"?:\ProgramData\"
file.pathwildcard?:\*\AppData\Local\Temp\*, ?:\Program Files*excludes:file.path field:"file.path" value:"?:\*\AppData\Local\Temp\*" field:"file.path" value:"?:\Program Files*"

Potential Linux Tunneling via Cloudflared

#
Source
github.com/elastic/protections-artifacts

Identifies the use of Cloudflare Tunnel (cloudflared) to expose a local service or create an outbound tunnel. Adversaries may abuse quick tunnels or named tunnels to proxy C2 traffic or exfiltrate data through Cloudflare's edge while evading direct connection blocking.

MITRE ATT&CK Coverage

TacticTechniques
Command & Control

Rule Body

[rule]
description = """
Identifies the use of Cloudflare Tunnel (cloudflared) to expose a local service or create an outbound tunnel.
Adversaries may abuse quick tunnels or named tunnels to proxy C2 traffic or exfiltrate data through Cloudflare's edge
while evading direct connection blocking.
"""
id = "9e8589a6-96fe-450b-b33a-a8be509dbf35"
license = "Elastic License v2"
name = "Potential Linux Tunneling via Cloudflared"
os_list = ["linux"]
reference = [
    "https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-commands/",
    "https://attack.mitre.org/techniques/T1572/",
    "https://www.trendmicro.com/tr_tr/research/26/c/dissecting-a-warlock-attack.html",
]
version = "1.0.5"

query = '''
process where event.type == "start" and event.action == "exec" and
(
  (
    process.name == "cloudflared" or
    process.args in ("--url", "-url", "--token", "-token")
  ) and
  process.args == "tunnel" 
) and not (
  process.args in ("info", "delete") or
  process.parent.executable in ("/usr/lib/systemd/systemd", "/lib/systemd/systemd", "./runc", "/usr/bin/runc") or
  process.parent.executable like ("/var/lib/rancher/*/bin/runc", "/home/*/.nvm/versions/node/*/bin/node") or
  process.parent.command_line == "runc init" or
  process.parent.args in ("/etc/init.d/cloudflared", "/usr/bin/crun") or
  process.executable in ("/usr/bin/podman", "/usr/bin/docker") or
  (process.parent.executable == "/bin/busybox" and process.parent.args like "/home/*/tunnel-exit-node.sh") or
  (process.name == "echo" and process.parent.name == "xargs" and process.parent.command_line == "xargs --null") or
  process.working_directory like "/home/*/Desktop/*" or
  (
    process.executable == "/builds/qa/ai-test-runner/helpers/modules/cloudflared-linux-amd64" and
    process.working_directory == "/builds/qa/ai-test-runner"
  ) or
  (
    process.executable == "/app/ai-test-generation/helpers/modules/cloudflared-linux-amd64" and
    process.working_directory == "/app/ai-test-generation"
  ) or
  process.parent.executable like "*/node_modules/opencode-ai/bin/opencode*"
)
'''

min_endpoint_version = "7.15.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 = "T1572"
name = "Protocol Tunneling"
reference = "https://attack.mitre.org/techniques/T1572/"


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

[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 == "cloudflared" or
    process.args in ("--url", "-url", "--token", "-token")
  ) and
  process.args == "tunnel" 
) and not (
  process.args in ("info", "delete") or
  process.parent.executable in ("/usr/lib/systemd/systemd", "/lib/systemd/systemd", "./runc", "/usr/bin/runc") or
  process.parent.executable like ("/var/lib/rancher/*/bin/runc", "/home/*/.nvm/versions/node/*/bin/node") or
  process.parent.command_line == "runc init" or
  process.parent.args in ("/etc/init.d/cloudflared", "/usr/bin/crun") or
  process.executable in ("/usr/bin/podman", "/usr/bin/docker") or
  (process.parent.executable == "/bin/busybox" and process.parent.args like "/home/*/tunnel-exit-node.sh") or
  (process.name == "echo" and process.parent.name == "xargs" and process.parent.command_line == "xargs --null") or
  process.working_directory like "/home/*/Desktop/*" or
  (
    process.executable == "/builds/qa/ai-test-runner/helpers/modules/cloudflared-linux-amd64" and
    process.working_directory == "/builds/qa/ai-test-runner"
  ) or
  (
    process.executable == "/app/ai-test-generation/helpers/modules/cloudflared-linux-amd64" and
    process.working_directory == "/app/ai-test-generation"
  ) or
  process.parent.executable like "*/node_modules/opencode-ai/bin/opencode*"
)

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.executableeq/app/ai-test-generation/helpers/modules/cloudflared-linux-amd64excludes:process.executable field:"process.executable" value:"/app/ai-test-generation/helpers/modules/cloudflared-linux-amd64"
process.working_directoryeq/app/ai-test-generationexcludes:process.working_directory field:"process.working_directory" value:"/app/ai-test-generation"
process.executableeq/builds/qa/ai-test-runner/helpers/modules/cloudflared-linux-amd64excludes:process.executable field:"process.executable" value:"/builds/qa/ai-test-runner/helpers/modules/cloudflared-linux-amd64"
process.working_directoryeq/builds/qa/ai-test-runnerexcludes:process.working_directory field:"process.working_directory" value:"/builds/qa/ai-test-runner"
process.nameeqechoexcludes:process.name field:"process.name" value:"echo"
process.parent.command_lineeqxargs --nullexcludes:process.parent.command_line field:"process.parent.command_line" value:"xargs --null"
process.parent.nameeqxargsexcludes:process.parent.name field:"process.parent.name" value:"xargs"
process.parent.argswildcard/home/*/tunnel-exit-node.shexcludes:process.parent.args field:"process.parent.args" value:"/home/*/tunnel-exit-node.sh"
process.parent.executableeq/bin/busyboxexcludes:process.parent.executable field:"process.parent.executable" value:"/bin/busybox"
process.argsindelete, infoexcludes:process.args field:"process.args" value:"delete" field:"process.args" value:"info"
process.executablein/usr/bin/docker, /usr/bin/podmanexcludes:process.executable field:"process.executable" value:"/usr/bin/docker" field:"process.executable" value:"/usr/bin/podman"
process.parent.argsin/etc/init.d/cloudflared, /usr/bin/crunexcludes:process.parent.args field:"process.parent.args" value:"/etc/init.d/cloudflared" field:"process.parent.args" value:"/usr/bin/crun"
process.parent.command_lineeqrunc initexcludes:process.parent.command_line field:"process.parent.command_line" value:"runc init"
process.parent.executablein./runc, /lib/systemd/systemd, /usr/bin/runc, /usr/lib/systemd/systemdexcludes:process.parent.executable
process.parent.executablematch/node_modules/opencode-ai/bin/opencodeexcludes:process.parent.executable field:"process.parent.executable" value:"/node_modules/opencode-ai/bin/opencode"
process.parent.executablewildcard/var/lib/rancher/*/bin/runc, /home/*/.nvm/versions/node/*/bin/nodeexcludes:process.parent.executable field:"process.parent.executable" value:"/var/lib/rancher/*/bin/runc" field:"process.parent.executable" value:"/home/*/.nvm/versions/node/*/bin/node"
process.working_directorywildcard/home/*/Desktop/*excludes:process.working_directory field:"process.working_directory" value:"/home/*/Desktop/*"

Potential Privilege Escalation via SetWindowsHook DLL Injection

#
Source
github.com/elastic/protections-artifacts

Identifies a potentially untrusted DLL loaded by a privileged account from a suspicious location where the call stack indicates a user-mode callback path consistent with SetWindowsHookEx-style window hook execution. Adversaries can abuse window hooks to force a privileged process to load attacker-controlled DLLs and elevate privileges.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies a potentially untrusted DLL loaded by a privileged account from a suspicious location where the call stack
indicates a user-mode callback path consistent with SetWindowsHookEx-style window hook execution. Adversaries can abuse
window hooks to force a privileged process to load attacker-controlled DLLs and elevate privileges.
"""
id = "6eec7771-953c-46a0-9765-93000de1c237"
license = "Elastic License v2"
name = "Potential Privilege Escalation via SetWindowsHook DLL Injection"
os_list = ["windows"]
reference = [
    "https://attack.mitre.org/techniques/T1055/001/",
    "https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa",
]
version = "1.0.1"

query = '''
library where
  user.id in ("S-1-5-18", "S-1-5-19", "S-1-5-20") and
  not dll.code_signature.status like ("trusted", "errorCode_endpoint*") and
  process.thread.Ext.call_stack_summary == "ntdll.dll|kernelbase.dll|user32.dll|ntdll.dll" and
  (dll.Ext.relative_file_creation_time <= 900 or dll.Ext.relative_file_name_modify_time <= 900) and
  _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info like "?:\\Windows\\System32\\ntdll.dll!KiUserCallbackDispatcher*") and
  not dll.path : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*", "?:\\Windows\\System32\\*")
'''

min_endpoint_version = "8.12.0"
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.technique.subtechnique]]
id = "T1055.001"
name = "Dynamic-link Library Injection"
reference = "https://attack.mitre.org/techniques/T1055/001/"



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

[internal]
min_endpoint_version = "8.12.0"

Stages and Predicates

Stage 1: library

library where
  user.id in ("S-1-5-18", "S-1-5-19", "S-1-5-20") and
  not dll.code_signature.status like ("trusted", "errorCode_endpoint*") and
  process.thread.Ext.call_stack_summary == "ntdll.dll|kernelbase.dll|user32.dll|ntdll.dll" and
  (dll.Ext.relative_file_creation_time <= 900 or dll.Ext.relative_file_name_modify_time <= 900) and
  _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info like "?:\\Windows\\System32\\ntdll.dll!KiUserCallbackDispatcher*") and
  not dll.path : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*", "?:\\Windows\\System32\\*")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

Potential Process Injection via PowerShell

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

Detects PowerShell scripts that combine Win32 APIs for allocation, protection, process access, or dynamic resolution with injection or execution APIs. Attackers use these API chains for potential process injection or in-memory payload execution.

Known False Positives

  • Controlled red-team, malware-analysis, detection-validation, or harness activity where script content, target process set, origin, user/host scope, and recovered launcher align.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2021/10/14"
integration = ["windows"]
maturity = "production"
updated_date = "2026/04/30"

[rule]
author = ["Elastic"]
description = """
Detects PowerShell scripts that combine Win32 APIs for allocation, protection, process access, or dynamic resolution with
injection or execution APIs. Attackers use these API chains for potential process injection or in-memory payload execution.
"""
false_positives = ["Controlled red-team, malware-analysis, detection-validation, or harness activity where script content, target process set, origin, user/host scope, and recovered launcher align."]
from = "now-9m"
index = ["logs-windows.powershell*", "winlogbeat-*"]
language = "kuery"
license = "Elastic License v2"
name = "Potential Process Injection via PowerShell"
references = [
    "https://github.com/EmpireProject/Empire/blob/master/data/module_source/management/Invoke-PSInject.ps1",
    "https://github.com/EmpireProject/Empire/blob/master/data/module_source/management/Invoke-ReflectivePEInjection.ps1",
    "https://github.com/BC-SECURITY/Empire/blob/master/empire/server/data/module_source/credentials/Invoke-Mimikatz.ps1",
    "https://www.elastic.co/security-labs/detect-credential-access",
]
risk_score = 73
rule_id = "2e29e96a-b67c-455a-afe4-de6183431d0d"
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Tactic: Execution",
    "Resources: Investigation Guide",
    "Data Source: PowerShell Logs",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
event.category:process and host.os.type:windows and
  powershell.file.script_block_text : (
   (VirtualAlloc or VirtualAllocEx or VirtualProtect or LdrLoadDll or LoadLibrary or LoadLibraryA or
      LoadLibraryEx or GetProcAddress or OpenProcess or OpenProcessToken or AdjustTokenPrivileges) and
   (WriteProcessMemory or CreateRemoteThread or NtCreateThreadEx or CreateThread or QueueUserAPC or
      SuspendThread or ResumeThread or GetDelegateForFunctionPointer)
  ) and not 
  file.directory: (
    "C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\SenseCM" or
    "C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads"
  )
'''

note = """## Triage and analysis

### Investigating Potential Process Injection via PowerShell

#### Possible investigation steps

- Does the reconstructed script show an executable injection path or only isolated helper code?
  - Focus: reconstruct with `powershell.file.script_block_id`, `powershell.sequence`, and `powershell.total`, then review `powershell.file.script_block_text` and `powershell.file.script_block_length`. $investigate_2
  - Implication: escalate when the ordered script combines target access, memory allocation/protection, remote write, and thread/APC execution; lower concern when reconstruction proves only comments, imports, or unused helper functions in a bounded test script.

- If endpoint process telemetry is available for this host, can you recover how PowerShell was launched?
  - Focus: same-host process starts for the PowerShell instance: `process.command_line`, `process.parent.executable`, `process.parent.command_line`, and `process.entity_id`. $investigate_3
  - Hint: recover the matching process via `host.id + process.pid` before interpreting `process.*` or `process.parent.*`; if absent, expand the same-host window. Missing endpoint process telemetry is unresolved, not benign.
  - Implication: escalate when the launcher is a document, browser, remote-management tool, scheduled task, encoded command, or user-writable path that does not fit the user; lower concern when launch chain and script origin match the same recognized lab or validation workflow.

- What payload style does the reconstructed script stage?
  - Why: Empire-style loaders commonly patch or reflectively load PE bytes before injection, so payload form changes what to preserve and how urgently to respond.
  - Focus: `powershell.file.script_block_text` for byte arrays, Base64 PE blobs, reflective loader names, Mimikatz or credential-dumping commands, and PE/DLL paths or URLs. If endpoint telemetry is available, recover same-PID file and network/DNS events surrounding `@timestamp` to validate writes, staging, or retrieval. Missing file or network/DNS telemetry is unresolved, not benign. $investigate_4 $investigate_5
  - Implication: escalate when the script embeds or fetches shellcode/PE content, calls reflective loading, or references credential dumping; lower concern only when payload handling is absent and the code remains a controlled harness with no execution path.

- Which target and access path does the script choose?
  - Focus: `powershell.file.script_block_text` for process-name or PID selectors, credential-rich or security-sensitive targets, token changes, broad access masks, and thread/APC primitives.
  - Implication: escalate when the script targets credential-rich, security-sensitive, user-facing, or many candidate processes and requests broad rights or debug privilege; lower concern when the target is one controlled lab process and the access path matches the recognized exercise.

- Does the user, host, and script origin fit one controlled workflow?
  - Focus: `user.id`, `user.domain`, `host.id`, `host.name`, and `file.path` when present, interpreted with the reconstructed script and recovered launch chain.
  - Implication: escalate when the script is fileless or sourced from temp, profile, share, or staging paths under an unexpected account or host; lower concern only when user, host cohort, source path or fileless launcher pattern, target process, and payload choice all align with one controlled test or diagnostic workflow.

- If local evidence remains suspicious or unresolved, does the same injection pattern appear elsewhere?
  - Focus: smallest stable suspicious pattern from `powershell.file.script_block_text`, such as loader function, target process, Mimikatz command, or distinctive payload string, plus `user.id` for actor scope. $investigate_0
  - Hint: run the `host.id` asset-scope check only after script logic, target/access path, and launch context remain suspicious or incomplete. $investigate_1
  - Implication: broaden when the same injection pattern or target selection appears on unrelated hosts or users; keep scope local when it stays confined to one recognized testing cohort or one unresolved host.

- What disposition is supported?
  - Escalate on script logic plus payload, sensitive target, broad access, suspicious launcher, or spread; close only when telemetry proves one controlled workflow with no contradictory payload or target abuse; preserve artifacts and escalate when evidence is mixed or endpoint process recovery is unavailable.

### False positive analysis

- Authorized red-team, malware-analysis, or detection-validation exercises can trigger this rule when the reconstructed script injects only into controlled targets on lab or canary hosts. Require `powershell.file.script_block_text`, target process names, `file.path` when present, `user.id`, and `host.id` to align with the exercise. If endpoint process telemetry is available, recover via `host.id + process.pid` and require `process.command_line` plus `process.parent.executable` to align. Use calendars or change records only to document telemetry-aligned activity; do not close when script, target, or launcher evidence conflicts.
- Security-product validation or compatibility harnesses are rare; do not close unless the script stays limited to the product's expected target set and lacks embedded payloads, Mimikatz commands, privilege escalation, or broad target loops. If endpoint process telemetry is available, recover via `host.id + process.pid` and require `process.parent.executable` plus `process.command_line` to match the same controlled path or harness. Build exceptions only from the minimum confirmed pattern: stable script origin or distinctive harness substring, bounded target set, `host.id` or `user.id`, and recovered launcher when available; never exempt generic API names alone.

### Response and remediation

- If confirmed benign:
  - Document the reconstructed script, target process set, script origin, `user.id`, `host.id`, and the exercise or harness evidence that established the workflow before reversing temporary containment. If endpoint process telemetry was available and recovered via `host.id + process.pid`, include the recovered `process.command_line` and `process.parent.executable`. Build exceptions only from the minimum confirmed workflow pattern, not from generic API names.
- If suspicious but unconfirmed:
  - Preserve the reconstructed `powershell.file.script_block_text`, every fragment tied to `powershell.file.script_block_id`, target process names or PIDs, payload strings, `file.path` when present, alert `process.pid`, `user.id`, and `host.id` before cleanup. If endpoint process telemetry was available and recovered via `host.id + process.pid`, also preserve `process.entity_id`, `process.command_line`, and `process.parent.command_line`.
  - Apply reversible containment such as temporary network restrictions, heightened monitoring, or access limits on the affected `host.id` and `user.id`; escalate to host isolation only when host criticality permits or payload execution, sensitive target selection, or spread evidence raises confidence.
- If confirmed malicious:
  - Record the preserved evidence set and recovered process identifiers first when endpoint process telemetry was available. Then isolate the host when script logic, target selection, payload style, recovered launcher, or related-alert scope confirms malicious injection; if direct endpoint response is unavailable, hand off that evidence set to the team that can contain the host.
  - Block confirmed malicious payload file paths and infrastructure indicators found during investigation, then review related hosts and users for the same loader, payload, target process, or recovered launcher pattern before eradication. Do not block on generic API names.
  - Remove the malicious script, payload files, scheduled tasks, startup paths, or delivery artifacts identified during the investigation. Reset or investigate affected accounts when the payload, target process, or Mimikatz command indicates credential access, then remediate the path that launched PowerShell.
- Post-incident hardening:
  - Keep Script Block logging and the endpoint process telemetry needed for `host.id + process.pid` recovery enabled on the affected host class.
  - Restrict PowerShell execution, Constrained Language Mode, or code-signing policy where appropriate for the host role, and record any telemetry gaps that limited reconstruction or process recovery.
"""

setup = """## Setup

PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104).
Setup instructions: https://ela.st/powershell-logging-setup
"""

[[rule.filters]]

[rule.filters.meta]
negate = true
[rule.filters.query.wildcard."file.path"]
case_insensitive = true
value = "?:\\\\ProgramData\\\\Microsoft\\\\Windows Defender Advanced Threat Protection\\\\DataCollection\\\\*"

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user.id",
    "user.domain",
    "powershell.file.script_block_text",
    "powershell.file.script_block_id",
    "powershell.sequence",
    "powershell.total",
    "file.path",
    "file.directory",
    "file.name",
    "process.pid",
    "host.name",
    "host.id",
    "powershell.file.script_block_length"
]

[transform]

[[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 = "Script block fragments for the same script"
description = ""
providers = [
  [
    { excluded = false, field = "powershell.file.script_block_id", queryType = "phrase", value = "{{powershell.file.script_block_id}}", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

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

[[transform.investigate]]
label = "File events for the PowerShell PID"
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.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Network and DNS events for the PowerShell PID"
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.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
  ],
  [
    { excluded = false, field = "event.category", queryType = "phrase", value = "dns", 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"

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

[[rule.threat.technique]]
id = "T1055"
name = "Process Injection"
reference = "https://attack.mitre.org/techniques/T1055/"

[[rule.threat.technique.subtechnique]]
id = "T1055.001"
name = "Dynamic-link Library Injection"
reference = "https://attack.mitre.org/techniques/T1055/001/"

[[rule.threat.technique.subtechnique]]
id = "T1055.002"
name = "Portable Executable Injection"
reference = "https://attack.mitre.org/techniques/T1055/002/"

[[rule.threat.technique.subtechnique]]
id = "T1055.003"
name = "Thread Execution Hijacking"
reference = "https://attack.mitre.org/techniques/T1055/003/"

[[rule.threat.technique.subtechnique]]
id = "T1055.004"
name = "Asynchronous Procedure Call"
reference = "https://attack.mitre.org/techniques/T1055/004/"

[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 = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"

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

[[rule.threat.technique]]
id = "T1106"
name = "Native API"
reference = "https://attack.mitre.org/techniques/T1106/"

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

Stages and Predicates

Stage 1: query

event.category:process and host.os.type:windows and
  powershell.file.script_block_text : (
   (VirtualAlloc or VirtualAllocEx or VirtualProtect or LdrLoadDll or LoadLibrary or LoadLibraryA or
      LoadLibraryEx or GetProcAddress or OpenProcess or OpenProcessToken or AdjustTokenPrivileges) and
   (WriteProcessMemory or CreateRemoteThread or NtCreateThreadEx or CreateThread or QueueUserAPC or
      SuspendThread or ResumeThread or GetDelegateForFunctionPointer)
  ) and not 
  file.directory: (
    "C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\SenseCM" or
    "C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads"
  )

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.categoryeq
  • process corpus 105 (elastic 105)
field:"event.category" kind:eq value:"process"
powershell.file.script_block_textin
  • AdjustTokenPrivileges
  • CreateRemoteThread
  • CreateThread
  • GetDelegateForFunctionPointer corpus 2 (elastic 2)
  • GetProcAddress corpus 2 (elastic 2)
  • LdrLoadDll
  • LoadLibrary
  • LoadLibraryA
  • LoadLibraryEx
  • NtCreateThreadEx
  • OpenProcess
  • OpenProcessToken
  • QueueUserAPC
  • ResumeThread
  • SuspendThread
  • VirtualAlloc
  • VirtualAllocEx
  • VirtualProtect corpus 2 (elastic 2)
  • WriteProcessMemory
field:"ScriptBlockText" kind:in

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
file.directoryinC:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads, C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\SenseCMexcludes:file.directory field:"file.directory" value:"C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads" field:"file.directory" value:"C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\SenseCM"

Python Path Configuration File (.pth) with Import Preface

#
Source
github.com/elastic/protections-artifacts

Detects creation or change of a Python path configuration file (.pth). These files are processed by the interpreter site machinery and normally list directories or comments. This rule matches .pth files whose leading bytes correspond to UTF-8 text beginning with an import-style preface (for example, the string starting with "import os, subpr" as used before subprocess or similar calls). That pattern is atypical and may indicate code execution via the .pth mechanism.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Detects creation or change of a Python path configuration file (.pth). These files are processed by the interpreter site
machinery and normally list directories or comments. This rule matches .pth files whose leading bytes correspond to
UTF-8 text beginning with an import-style preface (for example, the string starting with "import os, subpr" as used
before subprocess or similar calls). That pattern is atypical and may indicate code execution via the .pth mechanism.
"""
id = "e7b2c4a1-5f0d-4e8c-9a3b-1d6f8e0c2a4b"
license = "Elastic License v2"
name = "Python Path Configuration File (.pth) with Import Preface"
os_list = ["macos", "windows"]
reference = ["https://docs.python.org/3/library/site.html", "https://attack.mitre.org/techniques/T1546/"]
version = "1.0.1"

query = '''
file where event.type in ("creation", "change") and 
 file.extension : "pth" and 
 (
  file.Ext.header_bytes : "696d706f7274206f732c207375627072" or
  (file.path : "*site-packages*" and file.size >= 30000 and file.Ext.header_bytes : "696d706f7274*")
  )
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.006"
name = "Python"
reference = "https://attack.mitre.org/techniques/T1059/006/"



[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1546"
name = "Event Triggered Execution"
reference = "https://attack.mitre.org/techniques/T1546/"


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

[internal]
min_endpoint_version = "8.10.0"

Stages and Predicates

Stage 1: file

file where event.type in ("creation", "change") and 
 file.extension : "pth" and 
 (
  file.Ext.header_bytes : "696d706f7274206f732c207375627072" or
  (file.path : "*site-packages*" and file.size >= 30000 and file.Ext.header_bytes : "696d706f7274*")
  )

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typein
  • change corpus 18 (elastic 18)
  • creation corpus 17 (elastic 17)
field:"event.type" kind:in
file.Ext.header_byteswildcard
  • 696d706f7274*
  • 696d706f7274206f732c207375627072
field:"file.Ext.header_bytes" kind:wildcard
file.extensionwildcard
  • pth
field:"file.extension" kind:wildcard value:"pth"
file.pathwildcard
  • *site-packages*
field:"TargetFilename" kind:wildcard value:"*site-packages*"
file.sizege
  • 30000 transforms: number corpus 5 (elastic 5)
field:"file.size" kind:ge value:"30000"

Registry Modification via WMI StdRegProv

#
Source
github.com/elastic/protections-artifacts

Identifies registry modification using the Windows Management Instrumentation SrdRegProv provider. Adversaries may leverage WMI to modify system configuration via registry changes.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies registry modification using the Windows Management Instrumentation SrdRegProv provider. Adversaries may
leverage WMI to modify system configuration via registry changes.
"""
id = "325933f6-e0b9-4cd2-bc4f-a91d78f97f1d"
license = "Elastic License v2"
name = "Registry Modification via WMI StdRegProv"
os_list = ["windows"]
version = "1.0.8"

query = '''
api where
  process.Ext.api.name == "IWbemServices::ExecMethod" and user.id != "S-1-5-18" and
   process.Ext.api.parameters.operation : "*StdRegProv::SetStringValue*" and

   process.executable != "C:\\Program Files (x86)\\GreenwayTR\\GMTGC.exe" and

   not (process.code_signature.trusted == true and
        process.code_signature.subject_name in ("Reason Cybersecurity Inc.", "Micro-Star International CO., LTD.", "Lansweeper NV", "LANSWEEPER NV", "YANDEX LLC", "Beijing Sogou Technology Development Co., Ltd.", "HP Inc.", "95895A1E-217A-4242-9200-7E698391758E", "Omnissa, LLC", "Beijing Kingsoft Security software Co.,Ltd")) and
       
   not (process.executable == "C:\\Windows\\SysWOW64\\wscript.exe" and process.parent.executable == "C:\\Windows\\SysWOW64\\cmd.exe" and
        process.command_line in ("WSCRIPT /B parseXML.vbs base_agentdata.xml agentdata.xml", "WSCRIPT /B ae_scan.vbs agentdata")) and

  not (process.name : ("wscript.exe", "cscript.exe") and process.command_line : ("*\\\\*\\netlogon\\*", "\"C:\\Windows\\system32\\wscript.exe\" \"C:\\Program Files (x86)\\RoomSeeker\\DBChange.vbs\"")) and 

   not (process.executable == "C:\\Windows\\System32\\wscript.exe" and process.parent.executable == "C:\\Windows\\System32\\gpscript.exe") and

   not (process.executable : "C:\\Windows\\System32\\svchost.exe" and process.parent.executable : "C:\\Windows\\System32\\services.exe") and

   not process.executable : ("C:\\Windows\\System32\\cscript.exe",
                             "C:\\Windows\\SysWOW64\\cscript.exe",
                             "C:\\Windows\\System32\\msiexec.exe",
                             "C:\\Windows\\SysWOW64\\msiexec.exe",
                             "C:\\Program Files (x86)\\Sage\\*.exe") and
   not process.parent.executable : ("C:\\Program Files (x86)\\PCMatic\\PCPitstopScheduleService.exe",
                                    "C:\\Program Files (x86)\\Sage\\Sage 100\\9.0\\Shared\\OLStart.exe",
                                    "E:\\BELOFF_2O2O.O3L\\wpi\\WPI.exe")
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1047"
name = "Windows Management Instrumentation"
reference = "https://attack.mitre.org/techniques/T1047/"


[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1112"
name = "Modify Registry"
reference = "https://attack.mitre.org/techniques/T1112/"


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

[internal]
min_endpoint_version = "8.15.0"

Stages and Predicates

Stage 1: api

api where
  process.Ext.api.name == "IWbemServices::ExecMethod" and user.id != "S-1-5-18" and
   process.Ext.api.parameters.operation : "*StdRegProv::SetStringValue*" and

   process.executable != "C:\\Program Files (x86)\\GreenwayTR\\GMTGC.exe" and

   not (process.code_signature.trusted == true and
        process.code_signature.subject_name in ("Reason Cybersecurity Inc.", "Micro-Star International CO., LTD.", "Lansweeper NV", "LANSWEEPER NV", "YANDEX LLC", "Beijing Sogou Technology Development Co., Ltd.", "HP Inc.", "95895A1E-217A-4242-9200-7E698391758E", "Omnissa, LLC", "Beijing Kingsoft Security software Co.,Ltd")) and
       
   not (process.executable == "C:\\Windows\\SysWOW64\\wscript.exe" and process.parent.executable == "C:\\Windows\\SysWOW64\\cmd.exe" and
        process.command_line in ("WSCRIPT /B parseXML.vbs base_agentdata.xml agentdata.xml", "WSCRIPT /B ae_scan.vbs agentdata")) and

  not (process.name : ("wscript.exe", "cscript.exe") and process.command_line : ("*\\\\*\\netlogon\\*", "\"C:\\Windows\\system32\\wscript.exe\" \"C:\\Program Files (x86)\\RoomSeeker\\DBChange.vbs\"")) and 

   not (process.executable == "C:\\Windows\\System32\\wscript.exe" and process.parent.executable == "C:\\Windows\\System32\\gpscript.exe") and

   not (process.executable : "C:\\Windows\\System32\\svchost.exe" and process.parent.executable : "C:\\Windows\\System32\\services.exe") and

   not process.executable : ("C:\\Windows\\System32\\cscript.exe",
                             "C:\\Windows\\SysWOW64\\cscript.exe",
                             "C:\\Windows\\System32\\msiexec.exe",
                             "C:\\Windows\\SysWOW64\\msiexec.exe",
                             "C:\\Program Files (x86)\\Sage\\*.exe") and
   not process.parent.executable : ("C:\\Program Files (x86)\\PCMatic\\PCPitstopScheduleService.exe",
                                    "C:\\Program Files (x86)\\Sage\\Sage 100\\9.0\\Shared\\OLStart.exe",
                                    "E:\\BELOFF_2O2O.O3L\\wpi\\WPI.exe")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.code_signature.subject_namein95895A1E-217A-4242-9200-7E698391758E, Beijing Kingsoft Security software Co.,Ltd, Beijing Sogou Technology Development Co., Ltd., HP Inc., LANSWEEPER NV, Lansweeper NV, Micro-Star International CO., LTD., Omnissa, LLC, Reason Cybersecurity Inc., YANDEX LLCexcludes:process.code_signature.subject_name
process.code_signature.trustedeqtrueexcludes:process.code_signature.trusted field:"process.code_signature.trusted" value:"true"
process.command_lineinWSCRIPT /B ae_scan.vbs agentdata, WSCRIPT /B parseXML.vbs base_agentdata.xml agentdata.xmlexcludes:process.command_line field:"process.command_line" value:"WSCRIPT /B ae_scan.vbs agentdata" field:"process.command_line" value:"WSCRIPT /B parseXML.vbs base_agentdata.xml agentdata.xml"
process.executableeqC:\Windows\SysWOW64\wscript.exeexcludes:process.executable field:"process.executable" value:"C:\Windows\SysWOW64\wscript.exe"
process.parent.executableeqC:\Windows\SysWOW64\cmd.exeexcludes:process.parent.executable field:"process.parent.executable" value:"C:\Windows\SysWOW64\cmd.exe"
process.command_linewildcard*\\*\netlogon\*, "C:\Windows\system32\wscript.exe" "C:\Program Files (x86)\RoomSeeker\DBChange.vbs"excludes:process.command_line
process.nameeqwscript.exe, cscript.exeexcludes:process.name field:"process.name" value:"wscript.exe" field:"process.name" value:"cscript.exe"
process.executableeqC:\Windows\System32\wscript.exeexcludes:process.executable field:"process.executable" value:"C:\Windows\System32\wscript.exe"
process.parent.executableeqC:\Windows\System32\gpscript.exeexcludes:process.parent.executable field:"process.parent.executable" value:"C:\Windows\System32\gpscript.exe"
process.executableeqC:\Windows\System32\svchost.exeexcludes:process.executable field:"process.executable" value:"C:\Windows\System32\svchost.exe"
process.parent.executableeqC:\Windows\System32\services.exeexcludes:process.parent.executable field:"process.parent.executable" value:"C:\Windows\System32\services.exe"
process.executablewildcardC:\Windows\System32\cscript.exe, C:\Windows\SysWOW64\cscript.exe, C:\Windows\System32\msiexec.exe, C:\Windows\SysWOW64\msiexec.exe, C:\Program Files (x86)\Sage\*.exeexcludes:process.executable
process.parent.executableeqC:\Program Files (x86)\PCMatic\PCPitstopScheduleService.exe, C:\Program Files (x86)\Sage\Sage 100\9.0\Shared\OLStart.exe, E:\BELOFF_2O2O.O3L\wpi\WPI.exeexcludes:process.parent.executable field:"process.parent.executable" value:"C:\Program Files (x86)\PCMatic\PCPitstopScheduleService.exe" field:"process.parent.executable" value:"C:\Program Files (x86)\Sage\Sage 100\9.0\Shared\OLStart.exe" field:"process.parent.executable" value:"E:\BELOFF_2O2O.O3L\wpi\WPI.exe"

Renice or Ulimit Execution from Unusual Parent

#
Source
github.com/elastic/protections-artifacts

This rule detects the execution of the renice or ulimit commands from an unusual parent, which are used to change the priority of processes or set resource limits for processes. Threat actors may abuse these commands to change the priority of malicious processes. This is commonly used by miner malware to increase the priority of mining processes to maximize the mining performance.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
This rule detects the execution of the renice or ulimit commands from an unusual parent, which are used to change the
priority of processes or set resource limits for processes. Threat actors may abuse these commands to change the
priority of malicious processes. This is commonly used by miner malware to increase the priority of mining processes to
maximize the mining performance.
"""
id = "57ed0e43-643a-47f3-936e-138dc6f480da"
license = "Elastic License v2"
name = "Renice or Ulimit Execution from Unusual Parent"
os_list = ["linux"]
version = "1.0.8"

query = '''
process where event.type == "start" and event.action == "exec" and (
  process.name in ("ulimit", "renice") or (
    process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.args == "-c" and
    process.command_line like ("*ulimit*", "*renice*")
  )
) and process.parent.executable != null and
(process.parent.executable like ("/tmp/*", "/var/tmp/*", "/dev/shm/*") or process.parent.name like ".*") and
not (
  process.parent.command_line in ("/bin/sh /usr/bin/byobu-status tmux_right", "runc init") or
  process.parent.executable like (
    "/tmp/newroot/*", "/tmp/vmis.*/vmware-installer/vmis-launcher", "/tmp/baum/easybuild/*", "/tmp/wbrashear/easybuild/*",
    "/tmp/par-*/temp-*/nbsu"
  ) or
  process.parent.name in ("java", "make", "python3.10.real")
)
'''

min_endpoint_version = "7.15.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 = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"



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

[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 in ("ulimit", "renice") or (
    process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.args == "-c" and
    process.command_line like ("*ulimit*", "*renice*")
  )
) and process.parent.executable != null and
(process.parent.executable like ("/tmp/*", "/var/tmp/*", "/dev/shm/*") or process.parent.name like ".*") and
not (
  process.parent.command_line in ("/bin/sh /usr/bin/byobu-status tmux_right", "runc init") or
  process.parent.executable like (
    "/tmp/newroot/*", "/tmp/vmis.*/vmware-installer/vmis-launcher", "/tmp/baum/easybuild/*", "/tmp/wbrashear/easybuild/*",
    "/tmp/par-*/temp-*/nbsu"
  ) or
  process.parent.name in ("java", "make", "python3.10.real")
)

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.parent.command_linein/bin/sh /usr/bin/byobu-status tmux_right, runc initexcludes:process.parent.command_line field:"process.parent.command_line" value:"/bin/sh /usr/bin/byobu-status tmux_right" field:"process.parent.command_line" value:"runc init"
process.parent.executablewildcard/tmp/newroot/*, /tmp/vmis.*/vmware-installer/vmis-launcher, /tmp/baum/easybuild/*, /tmp/wbrashear/easybuild/*, /tmp/par-*/temp-*/nbsuexcludes:process.parent.executable
process.parent.nameinjava, make, python3.10.realexcludes:process.parent.name field:"process.parent.name" value:"java" field:"process.parent.name" value:"make" field:"process.parent.name" value:"python3.10.real"

Suspicious Child Process of Expect

#
Source
github.com/elastic/protections-artifacts

Detects when commonly abused tools on macOS are executed via the Expect binary. The Expect binary on macOS (by default and other Unix-like systems) is a powerful scripting tool designed to automate interactive applications. It utilizes the TCL (Tool Command Language) for its syntax. An Expect script can be created using the .exp file extension. It can then be executed as either a normal binary or via the Expect binary itself. Expect is ripe for abuse by threat actors that can use it to avoid security controls and traditional defense detections.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[rule]
description = """
Detects when commonly abused tools on macOS are executed via the Expect binary. The Expect binary on macOS (by default
and other Unix-like systems) is a powerful scripting tool designed to automate interactive applications. It utilizes the
TCL (Tool Command Language) for its syntax. An Expect script can be created using the .exp file extension. It can then
be executed as either a normal binary or via the Expect binary itself. Expect is ripe for abuse by threat actors that
can use it to avoid security controls and traditional defense detections.
"""
id = "e1b837f1-625b-4494-a489-20356b6dedc0"
license = "Elastic License v2"
name = "Suspicious Child Process of Expect"
os_list = ["macos"]
version = "1.0.6"

query = '''
process where event.type == "start" and event.action == "exec" and process.parent.name == "expect" and 
 ((process.name in ("curl", "nscurl", "osascript", "security", "node", "ruby")) or 
  (process.code_signature.trusted == false or process.code_signature.exists == false)) and
 process.Ext.effective_parent.executable != "/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon"
'''

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 = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"



[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 event.action == "exec" and process.parent.name == "expect" and 
 ((process.name in ("curl", "nscurl", "osascript", "security", "node", "ruby")) or 
  (process.code_signature.trusted == false or process.code_signature.exists == false)) and
 process.Ext.effective_parent.executable != "/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec corpus 547 (elastic 547)
field:"EventType" kind:eq value:"exec"
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.Ext.effective_parent.executablene
  • /Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon
field:"process.Ext.effective_parent.executable" kind:ne value:"/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon"
process.code_signature.existseq
  • false transforms: boolean corpus 118 (elastic 118)
field:"process.code_signature.exists" kind:eq value:"false"
process.code_signature.trustedeq
  • false transforms: boolean corpus 114 (elastic 114)
field:"process.code_signature.trusted" kind:eq value:"false"
process.namein
  • curl corpus 82 (elastic 82)
  • node corpus 25 (elastic 25)
  • nscurl corpus 41 (elastic 41)
  • osascript corpus 12 (elastic 12)
  • ruby corpus 4 (elastic 4)
  • security
field:"process_basename" kind:in
process.parent.nameeq
  • expect
field:"parent_process_basename" kind:eq value:"expect"

Suspicious Execution from a PDF Documents

#
Source
github.com/elastic/protections-artifacts

Identifies a suspicious execution from a PDF document with embedded objects. This behavior is consistent with the successful exploitation using spearphishing attachment.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

[rule]
description = """
Identifies a suspicious execution from a PDF document with embedded objects. This behavior is consistent with the
successful exploitation using spearphishing attachment.
"""
id = "4994b3af-632c-41b8-9bff-d96488b1af52"
license = "Elastic License v2"
name = "Suspicious Execution from a PDF Documents"
os_list = ["windows"]
version = "1.0.8"

query = '''
process where event.action == "start" and
 (
  (process.parent.name : "AcroRd*.exe" and
   process.name : ("chrome.exe", "firefox.exe", "msedge.exe", "cscript.exe", "wscript.exe",
                   "mshta.exe", "powershell.exe", "hh.exe", "cmd.exe") and
   process.args : "?:\\Users\\*\\AppData\\Local\\Temp\\acrord*_sbx\\*") or

  (process.parent.name : ("chrome.exe", "firefox.exe", "msedge.exe") and process.parent.args : "?:\\Users\\*\\AppData\\Local\\Temp\\acrord*_sbx\\*" and
   not process.name : ("chrome.exe", "firefox.exe", "msedge.exe")) or

  (process.executable : "?:\\Users\\*\\AppData\\Local\\Temp\\acrord*_sbx\\*" and
   not process.code_signature.status : ("trusted", "errorExpired", "errorCode_endpoint*"))
 )
'''

min_endpoint_version = "7.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
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/"

[internal]
min_endpoint_version = "7.16.0"

Stages and Predicates

Stage 1: process

process where event.action == "start" and
 (
  (process.parent.name : "AcroRd*.exe" and
   process.name : ("chrome.exe", "firefox.exe", "msedge.exe", "cscript.exe", "wscript.exe",
                   "mshta.exe", "powershell.exe", "hh.exe", "cmd.exe") and
   process.args : "?:\\Users\\*\\AppData\\Local\\Temp\\acrord*_sbx\\*") or

  (process.parent.name : ("chrome.exe", "firefox.exe", "msedge.exe") and process.parent.args : "?:\\Users\\*\\AppData\\Local\\Temp\\acrord*_sbx\\*" and
   not process.name : ("chrome.exe", "firefox.exe", "msedge.exe")) or

  (process.executable : "?:\\Users\\*\\AppData\\Local\\Temp\\acrord*_sbx\\*" and
   not process.code_signature.status : ("trusted", "errorExpired", "errorCode_endpoint*"))
 )

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • start corpus 388 (elastic 388)
field:"EventType" kind:eq value:"start"
process.argswildcard
  • ?:\Users\*\AppData\Local\Temp\acrord*_sbx\*
field:"process.args" kind:wildcard value:"?:\Users\*\AppData\Local\Temp\acrord*_sbx\*"
process.executablewildcard
  • ?:\Users\*\AppData\Local\Temp\acrord*_sbx\*
field:"Image" kind:wildcard value:"?:\Users\*\AppData\Local\Temp\acrord*_sbx\*"
process.namewildcard
  • chrome.exe corpus 16 (elastic 14, splunk 2)
  • cmd.exe corpus 122 (elastic 93, splunk 29)
  • cscript.exe corpus 68 (elastic 66, splunk 2)
  • firefox.exe corpus 5 (elastic 5)
  • hh.exe corpus 8 (elastic 5, splunk 3)
  • msedge.exe corpus 12 (elastic 12)
  • mshta.exe corpus 84 (elastic 80, splunk 4)
  • powershell.exe corpus 187 (elastic 140, splunk 44, kusto 3)
  • wscript.exe corpus 84 (elastic 82, splunk 1, kusto 1)
field:"process_basename" kind:wildcard
process.parent.argswildcard
  • ?:\Users\*\AppData\Local\Temp\acrord*_sbx\*
field:"process.parent.args" kind:wildcard value:"?:\Users\*\AppData\Local\Temp\acrord*_sbx\*"
process.parent.namewildcard
  • AcroRd*.exe
  • chrome.exe corpus 9 (elastic 9)
  • firefox.exe corpus 9 (elastic 9)
  • msedge.exe corpus 7 (elastic 7)
field:"parent_process_basename" kind:wildcard

Suspicious JetBrains TeamCity Child Process

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

Identifies suspicious processes being spawned by the JetBrain TeamCity process. This activity could be related to JetBrains remote code execution vulnerabilities.

Known False Positives

  • Powershell and Windows Command Shell are often observed as legit child processes of the Jetbrains TeamCity service and may require further tuning.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2024/03/24"
integration = ["endpoint", "windows", "system", "m365_defender", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/05/04"

[rule]
author = ["Elastic"]
description = """
Identifies suspicious processes being spawned by the JetBrain TeamCity process. This activity could be related to
JetBrains remote code execution vulnerabilities.
"""
false_positives = [
    """
    Powershell and Windows Command Shell are often observed as legit child processes of the Jetbrains TeamCity service
    and may require further tuning.
    """,
]
from = "now-9m"
index = [
    "endgame-*",
    "logs-endpoint.events.process-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-system.security*",
    "logs-windows.forwarded*",
    "logs-windows.sysmon_operational-*",
    "winlogbeat-*",
]
language = "eql"
license = "Elastic License v2"
name = "Suspicious JetBrains TeamCity Child Process"
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 Suspicious JetBrains TeamCity Child Process

JetBrains TeamCity is a continuous integration and deployment server used to automate software development processes. Adversaries may exploit vulnerabilities in TeamCity to execute unauthorized code, potentially spawning malicious child processes. The detection rule identifies unusual child processes initiated by TeamCity's Java executable, flagging potential exploitation attempts by monitoring for known suspicious executables, while excluding legitimate operations.

### Possible investigation steps

- Review the process tree to identify the parent and child processes associated with the suspicious activity, focusing on the parent executable paths like "?:\\TeamCity\\jre\\bin\\java.exe".
- Examine the command-line arguments of the suspicious child processes, especially those involving "cmd.exe" or "powershell.exe", to understand the actions being executed.
- Check for any recent vulnerabilities or patches related to JetBrains TeamCity that might explain the suspicious behavior.
- Investigate the user account under which the suspicious processes were executed to determine if it aligns with expected usage patterns or if it indicates potential compromise.
- Correlate the alert with other security events or logs from data sources like Sysmon or Microsoft Defender XDR to identify any related malicious activity or indicators of compromise.
- Assess network activity from the host to detect any unusual outbound connections that might suggest data exfiltration or communication with a command and control server.

### False positive analysis

- Legitimate build scripts may invoke command-line utilities like cmd.exe or powershell.exe. To handle these, create exceptions for specific scripts by matching known safe arguments or paths.
- Automated tasks or maintenance scripts might use network utilities such as ping.exe or netstat.exe. Exclude these by identifying and allowing specific scheduled tasks or maintenance windows.
- System monitoring tools could trigger processes like tasklist.exe or systeminfo.exe. Whitelist these tools by verifying their source and ensuring they are part of authorized monitoring solutions.
- Development or testing environments may frequently use utilities like explorer.exe or control.exe. Establish exceptions for these environments by defining specific hostnames or IP ranges where such activity is expected.
- Custom scripts or applications might use msiexec.exe for legitimate software installations. Allow these by confirming the source and purpose of the installations, and excluding them based on known safe paths or signatures.

### Response and remediation

- Immediately isolate the affected TeamCity server from the network to prevent further unauthorized access or lateral movement.
- Terminate any suspicious child processes identified by the detection rule, such as cmd.exe or powershell.exe, to halt potential malicious activities.
- Conduct a thorough review of recent changes and deployments in TeamCity to identify any unauthorized modifications or suspicious activities.
- Apply the latest security patches and updates to TeamCity and its underlying Java runtime environment to mitigate known vulnerabilities.
- Restore the affected system from a clean backup taken before the suspicious activity was detected, ensuring no remnants of the exploit remain.
- Monitor network traffic and system logs for any signs of continued or related suspicious activity, focusing on the indicators identified in the detection rule.
- 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."""
references = [
    "https://www.trendmicro.com/en_us/research/24/c/teamcity-vulnerability-exploits-lead-to-jasmin-ransomware.html",
]
risk_score = 47
rule_id = "730ed57d-ae0f-444f-af50-78708b57edd5"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Initial Access",
    "Data Source: Elastic Endgame",
    "Use Case: Vulnerability",
    "Data Source: Elastic Defend",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Windows Security Event Logs",
    "Data Source: Sysmon",
    "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 :
                 ("?:\\TeamCity\\jre\\bin\\java.exe",
                  "?:\\Program Files\\TeamCity\\jre\\bin\\java.exe",
                  "?:\\Program Files (x86)\\TeamCity\\jre\\bin\\java.exe",
                  "?:\\TeamCity\\BuildAgent\\jre\\bin\\java.exe") and
  process.name : ("cmd.exe", "powershell.exe", "msiexec.exe", "certutil.exe", "bitsadmin.exe", "wmic.exe", "curl.exe", "ssh.exe",
                   "rundll32.exe", "regsvr32.exe", "mshta.exe", "certreq.exe", "net.exe", "nltest.exe", "whoami.exe", "hostname.exe",
                   "tasklist.exe", "arp.exe", "nbtstat.exe", "netstat.exe", "reg.exe", "tasklist.exe", "Microsoft.Workflow.Compiler.exe",
                   "arp.exe", "atbroker.exe", "bginfo.exe", "bitsadmin.exe", "cdb.exe", "cmstp.exe", "control.exe", "cscript.exe", "csi.exe",
                   "dnx.exe", "dsget.exe", "dsquery.exe", "forfiles.exe", "fsi.exe", "ftp.exe", "gpresult.exe", "ieexec.exe", "iexpress.exe",
                   "installutil.exe", "ipconfig.exe","msxsl.exe", "netsh.exe", "odbcconf.exe", "ping.exe", "pwsh.exe", "qprocess.exe",
                   "quser.exe", "qwinsta.exe", "rcsi.exe", "regasm.exe", "regsvcs.exe", "regsvr32.exe", "sc.exe", "schtasks.exe",
                   "systeminfo.exe", "tracert.exe", "wmic.exe", "wscript.exe","xwizard.exe", "explorer.exe", "msdt.exe") and
 not (process.name : "powershell.exe" and process.args : "-ExecutionPolicy" and process.args : "?:\\TeamCity\\buildAgent\\work\\*.ps1") and
 not (process.name : "cmd.exe" and process.args : "dir" and process.args : "/-c")
'''

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)
- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
"""


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

[[rule.threat.technique]]
id = "T1190"
name = "Exploit Public-Facing Application"
reference = "https://attack.mitre.org/techniques/T1190/"

[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 = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"

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

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

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

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

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

[[rule.threat.technique.subtechnique]]
id = "T1218.003"
name = "CMSTP"
reference = "https://attack.mitre.org/techniques/T1218/003/"

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

[[rule.threat.technique.subtechnique]]
id = "T1218.005"
name = "Mshta"
reference = "https://attack.mitre.org/techniques/T1218/005/"

[[rule.threat.technique.subtechnique]]
id = "T1218.007"
name = "Msiexec"
reference = "https://attack.mitre.org/techniques/T1218/007/"

[[rule.threat.technique.subtechnique]]
id = "T1218.008"
name = "Odbcconf"
reference = "https://attack.mitre.org/techniques/T1218/008/"

[[rule.threat.technique.subtechnique]]
id = "T1218.010"
name = "Regsvr32"
reference = "https://attack.mitre.org/techniques/T1218/010/"

[[rule.threat.technique.subtechnique]]
id = "T1218.011"
name = "Rundll32"
reference = "https://attack.mitre.org/techniques/T1218/011/"

[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 = "T1016"
name = "System Network Configuration Discovery"
reference = "https://attack.mitre.org/techniques/T1016/"

[[rule.threat.technique]]
id = "T1033"
name = "System Owner/User Discovery"
reference = "https://attack.mitre.org/techniques/T1033/"

[[rule.threat.technique]]
id = "T1049"
name = "System Network Connections Discovery"
reference = "https://attack.mitre.org/techniques/T1049/"

[[rule.threat.technique]]
id = "T1057"
name = "Process Discovery"
reference = "https://attack.mitre.org/techniques/T1057/"

[[rule.threat.technique]]
id = "T1082"
name = "System Information Discovery"
reference = "https://attack.mitre.org/techniques/T1082/"

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

[[rule.threat.technique]]
id = "T1482"
name = "Domain Trust Discovery"
reference = "https://attack.mitre.org/techniques/T1482/"

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

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
  process.parent.executable :
                 ("?:\\TeamCity\\jre\\bin\\java.exe",
                  "?:\\Program Files\\TeamCity\\jre\\bin\\java.exe",
                  "?:\\Program Files (x86)\\TeamCity\\jre\\bin\\java.exe",
                  "?:\\TeamCity\\BuildAgent\\jre\\bin\\java.exe") and
  process.name : ("cmd.exe", "powershell.exe", "msiexec.exe", "certutil.exe", "bitsadmin.exe", "wmic.exe", "curl.exe", "ssh.exe",
                   "rundll32.exe", "regsvr32.exe", "mshta.exe", "certreq.exe", "net.exe", "nltest.exe", "whoami.exe", "hostname.exe",
                   "tasklist.exe", "arp.exe", "nbtstat.exe", "netstat.exe", "reg.exe", "tasklist.exe", "Microsoft.Workflow.Compiler.exe",
                   "arp.exe", "atbroker.exe", "bginfo.exe", "bitsadmin.exe", "cdb.exe", "cmstp.exe", "control.exe", "cscript.exe", "csi.exe",
                   "dnx.exe", "dsget.exe", "dsquery.exe", "forfiles.exe", "fsi.exe", "ftp.exe", "gpresult.exe", "ieexec.exe", "iexpress.exe",
                   "installutil.exe", "ipconfig.exe","msxsl.exe", "netsh.exe", "odbcconf.exe", "ping.exe", "pwsh.exe", "qprocess.exe",
                   "quser.exe", "qwinsta.exe", "rcsi.exe", "regasm.exe", "regsvcs.exe", "regsvr32.exe", "sc.exe", "schtasks.exe",
                   "systeminfo.exe", "tracert.exe", "wmic.exe", "wscript.exe","xwizard.exe", "explorer.exe", "msdt.exe") and
 not (process.name : "powershell.exe" and process.args : "-ExecutionPolicy" and process.args : "?:\\TeamCity\\buildAgent\\work\\*.ps1") and
 not (process.name : "cmd.exe" and process.args : "dir" and process.args : "/-c")

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.namewildcard
  • Microsoft.Workflow.Compiler.exe corpus 12 (elastic 11, splunk 1)
  • arp.exe corpus 10 (elastic 8, splunk 1, kusto 1)
  • atbroker.exe corpus 6 (elastic 6)
  • bginfo.exe corpus 6 (elastic 6)
  • bitsadmin.exe corpus 25 (elastic 22, splunk 2, kusto 1)
  • cdb.exe corpus 8 (elastic 8)
  • certreq.exe corpus 20 (elastic 20)
  • certutil.exe corpus 45 (elastic 39, splunk 6)
  • cmd.exe corpus 122 (elastic 93, splunk 29)
  • cmstp.exe corpus 25 (elastic 25)
  • control.exe corpus 10 (elastic 8, splunk 2)
  • cscript.exe corpus 68 (elastic 66, splunk 2)
  • csi.exe corpus 6 (elastic 6)
  • curl.exe corpus 34 (elastic 32, splunk 2)
  • dnx.exe corpus 6 (elastic 6)
  • dsget.exe corpus 8 (elastic 8)
  • dsquery.exe corpus 12 (elastic 8, splunk 4)
  • explorer.exe corpus 21 (elastic 19, splunk 2)
  • forfiles.exe corpus 7 (elastic 6, splunk 1)
  • fsi.exe corpus 6 (elastic 6)
  • ftp.exe corpus 5 (elastic 5)
  • gpresult.exe corpus 7 (elastic 7)
  • hostname.exe corpus 7 (elastic 7)
  • ieexec.exe corpus 10 (elastic 10)
  • iexpress.exe corpus 9 (elastic 9)
  • installutil.exe corpus 36 (elastic 32, splunk 4)
  • ipconfig.exe corpus 11 (elastic 10, splunk 1)
  • msdt.exe corpus 9 (elastic 7, splunk 2)
  • mshta.exe corpus 84 (elastic 80, splunk 4)
  • msiexec.exe corpus 45 (elastic 40, splunk 5)
  • msxsl.exe corpus 22 (elastic 22)
  • nbtstat.exe corpus 9 (elastic 9)
  • net.exe corpus 30 (elastic 27, splunk 2, kusto 1)
  • netsh.exe corpus 21 (elastic 14, splunk 7)
  • netstat.exe corpus 10 (elastic 8, splunk 1, kusto 1)
  • nltest.exe corpus 12 (elastic 10, splunk 2)
  • odbcconf.exe corpus 14 (elastic 11, splunk 3)
  • ping.exe corpus 12 (elastic 8, splunk 2, kusto 2)
  • powershell.exe corpus 187 (elastic 140, splunk 44, kusto 3)
  • pwsh.exe corpus 78 (elastic 49, splunk 29)
  • qprocess.exe corpus 8 (elastic 8)
  • quser.exe corpus 10 (elastic 9, splunk 1)
  • qwinsta.exe corpus 9 (elastic 8, splunk 1)
  • rcsi.exe corpus 6 (elastic 6)
  • reg.exe corpus 28 (elastic 18, splunk 9, kusto 1)
  • regasm.exe corpus 25 (elastic 24, splunk 1)
  • regsvcs.exe corpus 22 (elastic 21, splunk 1)
  • regsvr32.exe corpus 74 (elastic 69, splunk 5)
  • rundll32.exe corpus 123 (elastic 100, splunk 23)
  • sc.exe corpus 32 (elastic 17, splunk 15)
  • schtasks.exe corpus 30 (elastic 19, splunk 11)
  • ssh.exe corpus 8 (elastic 8)
  • systeminfo.exe corpus 10 (elastic 10)
  • tasklist.exe corpus 11 (elastic 11)
  • tracert.exe corpus 6 (elastic 6)
  • whoami.exe corpus 14 (elastic 11, splunk 2, kusto 1)
  • wmic.exe corpus 66 (elastic 39, splunk 27)
  • wscript.exe corpus 84 (elastic 82, splunk 1, kusto 1)
  • xwizard.exe corpus 16 (elastic 16)
field:"process_basename" kind:wildcard
process.parent.executablewildcard
  • ?:\Program Files (x86)\TeamCity\jre\bin\java.exe
  • ?:\Program Files\TeamCity\jre\bin\java.exe
  • ?:\TeamCity\BuildAgent\jre\bin\java.exe
  • ?:\TeamCity\jre\bin\java.exe
field:"ParentImage" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

Suspicious Memory Mapping from a Windows Installer

#
Source
github.com/elastic/protections-artifacts

Identifies suspicious API calls from a Windows Installer module. This behavior is consistent with code injection attacks.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies suspicious API calls from a Windows Installer module. This behavior is consistent with code injection
attacks.
"""
id = "1604d90a-3fa2-494e-987b-f5196186c4b0"
license = "Elastic License v2"
name = "Suspicious Memory Mapping from a Windows Installer"
os_list = ["windows"]
version = "1.0.3"

query = '''
api where
   process.parent.executable : "C:\\Windows\\Sys?????\\msiexec.exe" and
   process.Ext.api.name in ("MapViewOfFile", "MapViewOfFile2") and
   process.Ext.api.parameters.size >= 100000 and process.Ext.api.parameters.protection in ("RWX", "R-X") and
   _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry, $entry.trusted == false or $entry.exists == false) and
   _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info : "C:\\Windows\\Sys?????\\ntdll.dll!NtMapViewOfSection*")
'''

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

[[actions]]
action = "kill_process"
field = "process.parent.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.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[[threat.technique.subtechnique]]
id = "T1218.007"
name = "Msiexec"
reference = "https://attack.mitre.org/techniques/T1218/007/"



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

[internal]
min_endpoint_version = "8.10.0"

Stages and Predicates

Stage 1: api

api where
   process.parent.executable : "C:\\Windows\\Sys?????\\msiexec.exe" and
   process.Ext.api.name in ("MapViewOfFile", "MapViewOfFile2") and
   process.Ext.api.parameters.size >= 100000 and process.Ext.api.parameters.protection in ("RWX", "R-X") and
   _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry, $entry.trusted == false or $entry.exists == false) and
   _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info : "C:\\Windows\\Sys?????\\ntdll.dll!NtMapViewOfSection*")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
process.Ext.api.namein
  • MapViewOfFile corpus 24 (elastic 24)
  • MapViewOfFile2 corpus 24 (elastic 24)
field:"process.Ext.api.name" kind:in
process.Ext.api.parameters.protectionin
  • R-X corpus 2 (elastic 2)
  • RWX corpus 2 (elastic 2)
field:"process.Ext.api.parameters.protection" kind:in
process.Ext.api.parameters.sizege
  • 100000 transforms: number corpus 6 (elastic 6)
field:"process.Ext.api.parameters.size" kind:ge value:"100000"
process.parent.executablewildcard
  • C:\Windows\Sys?????\msiexec.exe
field:"ParentImage" kind:wildcard value:"C:\Windows\Sys?????\msiexec.exe"

Transacted File Activity via an Unsigned DLL

#
Time window
1m
Sequence by
process.entity_id
Source
github.com/elastic/protections-artifacts

Identifies the creation of a transacted file by an unsigned DLL. This may indicate an attempt to use Transactional NTFS to execute arbitrary code in the address space of a running process, without committing the code to disk.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = """
Identifies the creation of a transacted file by an unsigned DLL. This may indicate an attempt to use Transactional NTFS
to execute arbitrary code in the address space of a running process, without committing the code to disk.
"""
id = "e80eb716-d5b0-4e85-b778-b9a4f3d6e303"
license = "Elastic License v2"
name = "Transacted File Activity via an Unsigned DLL"
os_list = ["windows"]
version = "1.0.2"

query = '''
sequence by process.entity_id with maxspan=1m
[library where event.action == "load" and process.pid != 4 and not dll.code_signature.status : "trusted" and
  (dll.Ext.relative_file_creation_time < 500 or
   dll.Ext.relative_file_name_modify_time < 500 or
   (dll.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk","USB *") and not dll.path : "C:\\*")
   )] as event0
[file where event.action == "overwrite" and
 _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info: "*\\kernel32.dll!CreateFileTransacted*") and
 stringcontains~(process.thread.Ext.call_stack_summary, concat("kernel32.dll|", event0.dll.name))]
'''

min_endpoint_version = "8.7.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 = "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.7.0"

Stages and Predicates

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

Stage 1: library

[library where event.action == "load" and process.pid != 4 and not dll.code_signature.status : "trusted" and
  (dll.Ext.relative_file_creation_time < 500 or
   dll.Ext.relative_file_name_modify_time < 500 or
   (dll.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk","USB *") and not dll.path : "C:\\*")
   )] as event0

Stage 2: file

[file where event.action == "overwrite" and
 _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info: "*\\kernel32.dll!CreateFileTransacted*") and
 stringcontains~(process.thread.Ext.call_stack_summary, concat("kernel32.dll|", event0.dll.name))]

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
dll.Ext.device.product_idwildcard
  • USB * corpus 3 (elastic 3)
  • Virtual DVD-ROM corpus 3 (elastic 3)
  • Virtual Disk corpus 3 (elastic 3)
field:"dll.Ext.device.product_id" kind:wildcard
dll.Ext.relative_file_creation_timelt
  • 500 transforms: number
field:"dll.Ext.relative_file_creation_time" kind:lt value:"500"
dll.Ext.relative_file_name_modify_timelt
  • 500 transforms: number
field:"dll.Ext.relative_file_name_modify_time" kind:lt value:"500"
event.actioneq
  • load corpus 23 (elastic 23)
  • overwrite corpus 8 (elastic 8)
field:"EventType" kind:eq
process.pidne
  • 4 transforms: number corpus 44 (elastic 44)
field:"process_id" kind:ne value:"4"
process.thread.Ext.call_stack_summarycontains
  • concat("kernel32.dll|", event0.dll.name) (expression)
field:"process.thread.Ext.call_stack_summary" kind:contains

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
dll.code_signature.statuseqtrustedexcludes:dll.code_signature.status field:"dll.code_signature.status" value:"trusted"

Back to all Elastic rules