Detection rules › Elastic
Elastic rules: 3e
API Call via Jump ROP Gadget
#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
| Tactic | Techniques |
|---|---|
| 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.
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.thread.Ext.call_stack | array_any | excludes:process.thread.Ext.call_stack | |
process.thread.Ext.call_stack_final_user_module.path | wildcard | c:\program files (x86)\*, c:\windows\syswow64\*, c:\windows\system32\spool\drivers\x64\3\x2wfuv0u.dll | excludes: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_signature | array_any | excludes:process.thread.Ext.call_stack_final_user_module.code_signature | |
process.executable | eq | C:\Program Files\Evolution Services Manager\FireDaemon.exe | excludes:process.executable field:"process.executable" value:"C:\Program Files\Evolution Services Manager\FireDaemon.exe" |
process.thread.Ext.call_stack_final_user_module.path | eq | c:\program files\evolution services manager\licensing.dll | excludes: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.sha256 | in | 0d5d73d3bea132f98be91f918d13043791decb419a81d9e755979315a7cf0502, 526104f18200c6cd055886c4d08f02278aa0325abe17b697529e4a67ac7582f8, 55bc12b34f81f43fa99bbe18d4ca1f07ccdde962039c59959d212aa7eac7586d, 579ab93c5db70cd3b3b3e2372cfcba1d968336e7e88b6ffc9e85160cc7c41d93, 5e3758ffbb23dd84717ba3193deea24d47de15de5f65dd7051fcb5ede6938340, 92090a86491251f461e1b8e6e7c6ff9f1ed0aebd63c19381850e219d2dd44708, 9ace6b6d2093f4812461a4d05c66cf3a4f838b5292deea78c31e7301feeebc82, a86749e6e28a8991c0b04fd626f49731e6b1185686e52523ea51a00f10f709d9, e093097faf851745b434c376dd48139eb0883805f130cb94d8ed5a10317dc745, f7df966bb1aab2a430134148bd5fd9024cc69b0e4f22ee2db00130effc577965 | excludes:process.thread.Ext.call_stack_final_user_module.hash.sha256 |
process.thread.Ext.call_stack_final_user_module.name | in | Kernel, Unbacked | excludes: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_summary | starts_with | ntdll.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
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"aws.cloudtrail" |
event.action | in |
| field:"EventType" kind:in |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
event.provider | eq |
| field:"Provider_Name" kind:eq value:"bedrock.amazonaws.com" |
AWS EC2 EBS Snapshot Access Removed
#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
| Tactic | Techniques |
|---|---|
| Defense Impairment | |
| Impact |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- ASL AWS EC2 Snapshot Shared Externally (Splunk)
- AWS EC2 EBS Snapshot Shared or Made Public (Elastic)
- AWS EC2 Snapshot Shared Externally (Splunk)
- AWS Exfiltration via EC2 Snapshot (Splunk)
- AWS Snapshot Made Public (Panther)
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.
| Field | Kind | Values | Search |
|---|---|---|---|
aws.cloudtrail.request_parameters | contains |
| field:"aws::requestParameters" kind:contains |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"aws.cloudtrail" |
event.action | eq |
| field:"EventType" kind:eq value:"ModifySnapshotAttribute" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
source.address | eq | backup.amazonaws.com | excludes:source.address field:"source.address" value:"backup.amazonaws.com" |
user_agent.original | match | Terraform, Pulumi | excludes:user_agent.original field:"user_agent.original" value:"Terraform" field:"user_agent.original" value:"Pulumi" |
AWS Lambda Function Invoked Cross-Account
#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
| Tactic | Techniques |
|---|---|
| Execution |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- AWS Discovery API Calls via CLI from a Single Resource (Elastic)
- AWS Lambda Event Source Mapping Creation (Elastic)
- AWS Lambda Function Created or Updated (Elastic)
- AWS Lambda Function High-Frequency Invocation by a Single Principal (Elastic)
- AWS Lambda Function Invoked by an Unusual Principal (Elastic)
- AWS Lambda Function Invoked from an Unusual Source ASN (Elastic)
- AWS Lambda Function Policy Updated to Allow Cross-Account Invocation (Elastic)
- AWS Lambda Function Policy Updated to Allow Public Invocation (Elastic)
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.
| Field | Source |
|---|---|
aws.cloudtrail.user_identity.arn | KEEP aws.cloudtrail.user_identity.arn |
Esql.caller_account | KEEP Esql.caller_account |
Esql.function_account | KEEP Esql.function_account |
Esql.function_arns | KEEP Esql.function_arns |
Esql.invocation_count | KEEP Esql.invocation_count |
Esql.source_ips | KEEP Esql.source_ips |
AWS RDS Snapshot Export
#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
| Tactic | Techniques |
|---|---|
| Collection | |
| Exfiltration |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- AWS RDS Snapshot Exported to S3 (Panther)
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.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"aws.cloudtrail" |
event.action | eq |
| field:"EventType" kind:eq value:"StartExportTask" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
event.provider | eq |
| field:"Provider_Name" kind:eq value:"rds.amazonaws.com" |
AWS S3 Object Versioning Suspended
#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
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| AWS | CloudTrail event PutBucketVersioning: Sets the versioning state for a specified S3 bucket. |
Rules Detecting the Same Action
These rules filter on the same operation.
- AWS S3 Bucket MFA Delete Disabled (Elastic)
- AWS S3 Bucket Versioning Disable (Sigma)
- AWS S3 Security Control Disabling (Panther)
- S3 Bucket Versioning Suspended (Panther)
- S3 MFA Delete Disabled (Panther)
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.
| Field | Kind | Values | Search |
|---|---|---|---|
aws.cloudtrail.request_parameters | contains |
| field:"aws::requestParameters" kind:contains value:"Status=Suspended" |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"aws.cloudtrail" |
event.action | eq |
| field:"EventType" kind:eq value:"PutBucketVersioning" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
event.provider | eq |
| field:"Provider_Name" kind:eq value:"s3.amazonaws.com" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
user_agent.original | match | Terraform, Pulumi | excludes:user_agent.original field:"user_agent.original" value:"Terraform" field:"user_agent.original" value:"Pulumi" |
Azure Storage Blob Retrieval via AzCopy
#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
| Tactic | Techniques |
|---|---|
| Collection | |
| Exfiltration |
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.
BLF File Creation by an Unusual Process
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
file.path | wildcard | 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 | excludes:file.path |
process.code_signature.status | starts_with | errorCode_endpoint | excludes:process.code_signature.status field:"process.code_signature.status" value:"errorCode_endpoint" |
process.executable | wildcard | 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 | excludes:process.executable |
Curl or Wget Execution from Container Context
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"auditd_manager.auditd" |
event.action | in |
| field:"EventType" kind:in |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | in |
| field:"process_basename" kind:in |
process.title | eq |
| field:"HostName" kind:eq value:"runc init" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | eq | wget --no-verbose --tries=1 --spider --no-check-certificate http://${WEB_HOST}:${WEB_PORT}/api/ping || exit 1 | excludes: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.args | match | 127.0.0.1 | excludes:process.args field:"process.args" value:"127.0.0.1" |
process.args | match | localhost | excludes:process.args field:"process.args" value:"localhost" |
Environment Variable Secret Collection
#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
| Tactic | Techniques |
|---|---|
| Collection |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.name | in |
| field:"process_basename" kind:in |
process.parent.command_line | wildcard |
| field:"ParentCommandLine" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | eq | /usr/local/bin/pm2 | excludes:process.args field:"process.args" value:"/usr/local/bin/pm2" |
process.parent.args | in | env | grep ^PATH=, env|grep -i "^shell=", env|grep -i '^shell=' | excludes:process.parent.args |
process.parent.command_line | length_compare | >=, 100 | excludes:process.parent.command_line field:"process.parent.command_line" value:">=" field:"process.parent.command_line" value:"100" |
Multiple Remote Management Tool Vendors on Same Host
#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
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
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 =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"""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.
| Field | Source |
|---|---|
host.id | KEEP host.id |
host.name | KEEP host.name |
Esql.* | KEEP Esql.* |
Parent Process PID Spoofing
#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
| Tactic | Techniques |
|---|---|
| Privilege Escalation | |
| Stealth |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.Ext.token.integrity_level_name | ne |
| field:"process.Ext.token.integrity_level_name" kind:ne value:"system" |
process.code_signature.exists | eq |
| field:"process.code_signature.exists" kind:eq value:"false" |
process.code_signature.status | wildcard |
| field:"SignatureStatus" kind:wildcard value:"errorBadDigest" |
process.executable | wildcard |
| field:"Image" kind:wildcard |
process.parent.Ext.real.pid | gt |
| field:"process.parent.Ext.real.pid" kind:gt value:"0" |
process.pe.original_file_name | wildcard |
| field:"OriginalFileName" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.executable | eq | ?:\Windows\System32\WerFaultSecure.exe, ?:\WINDOWS\SysWOW64\WerFaultSecure.exe, ?:\Windows\System32\WerFault.exe, ?:\Windows\SysWOW64\WerFault.exe | excludes:process.executable |
process.name | eq | msedge.exe | excludes:process.name field:"process.name" value:"msedge.exe" |
process.parent.name | eq | sihost.exe | excludes:process.parent.name field:"process.parent.name" value:"sihost.exe" |
Potential ADIDNS Poisoning via Wildcard Record Creation
#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
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Security-Auditing | Event ID 5137: A directory service object was created. |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.code | eq |
| field:"EventID" kind:eq value:"5137" |
winlog.event_data.ObjectDN | starts_with |
| field:"ObjectDN" kind:starts_with value:"DC=*," |
Potential Binary Masquerading via Invalid Code Signature
#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
| Tactic | Techniques |
|---|---|
| Stealth |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
process.code_signature.exists | eq |
| field:"process.code_signature.exists" kind:eq value:"false" |
process.code_signature.trusted | eq |
| field:"process.code_signature.trusted" kind:eq value:"false" |
process.executable | wildcard |
| field:"Image" kind:wildcard value:"/Users/*/Library/com.apple.*" |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
Potential Cluster Enumeration via jq Detected via Defend for Containers
#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
| Tactic | Techniques |
|---|---|
| Discovery |
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
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq |
event.action | ne |
| field:"EventType" kind:ne value:"deletion" |
file.Ext.header_bytes | wildcard |
| field:"file.Ext.header_bytes" kind:wildcard value:"4d5a*" |
file.extension | wildcard |
| field:"file.extension" kind:wildcard |
file.name | wildcard |
| field:"file.name" kind:wildcard value:"*.exe.config" |
file.path | wildcard |
| field:"TargetFilename" kind:wildcard |
process.args_count | ge |
| field:"process.args_count" kind:ge value:"2" |
process.name | wildcard |
| field:"process_basename" kind:wildcard value:"mstsc.exe" |
Exclusions
The rule actively suppresses these predicates.
Potential Linux Tunneling via Cloudflared
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq value:"tunnel" |
process.args | in |
| field:"process.args" kind:in |
process.name | eq |
| field:"process_basename" kind:eq value:"cloudflared" |
Exclusions
The rule actively suppresses these predicates.
Potential Privilege Escalation via SetWindowsHook DLL Injection
#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
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
dll.Ext.relative_file_creation_time | le |
| field:"dll.Ext.relative_file_creation_time" kind:le value:"900" |
dll.Ext.relative_file_name_modify_time | le |
| field:"dll.Ext.relative_file_name_modify_time" kind:le value:"900" |
process.thread.Ext.call_stack_summary | eq |
| field:"process.thread.Ext.call_stack_summary" kind:eq value:"ntdll.dll|kernelbase.dll|user32.dll|ntdll.dll" |
user.id | in |
| field:"user.id" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
dll.code_signature.status | wildcard | trusted, errorCode_endpoint* | excludes:dll.code_signature.status field:"dll.code_signature.status" value:"trusted" field:"dll.code_signature.status" value:"errorCode_endpoint*" |
dll.path | starts_with | ?:\Program Files\, ?:\Program Files (x86)\, ?:\Windows\System32\ | excludes:dll.path field:"dll.path" value:"?:\Program Files\" field:"dll.path" value:"?:\Program Files (x86)\" field:"dll.path" value:"?:\Windows\System32\" |
Potential Process Injection via PowerShell
#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
| Tactic | Techniques |
|---|---|
| Execution | |
| Stealth |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.category | eq |
| field:"event.category" kind:eq value:"process" |
powershell.file.script_block_text | in |
| field:"ScriptBlockText" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
file.directory | in | C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads, C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\SenseCM | excludes: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
#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
| Tactic | Techniques |
|---|---|
| Execution | |
| Persistence |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | in |
| field:"event.type" kind:in |
file.Ext.header_bytes | wildcard |
| field:"file.Ext.header_bytes" kind:wildcard |
file.extension | wildcard |
| field:"file.extension" kind:wildcard value:"pth" |
file.path | wildcard |
| field:"TargetFilename" kind:wildcard value:"*site-packages*" |
file.size | ge |
| field:"file.size" kind:ge value:"30000" |
Registry Modification via WMI StdRegProv
#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
| Tactic | Techniques |
|---|---|
| Execution | |
| Persistence | |
| Defense Impairment |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
process.Ext.api.name | eq |
| field:"process.Ext.api.name" kind:eq value:"IWbemServices::ExecMethod" |
process.Ext.api.parameters.operation | wildcard |
| field:"process.Ext.api.parameters.operation" kind:wildcard value:"*StdRegProv::SetStringValue*" |
process.executable | ne |
| field:"Image" kind:ne value:"C:\Program Files (x86)\GreenwayTR\GMTGC.exe" |
user.id | ne |
| field:"user.id" kind:ne value:"S-1-5-18" |
Exclusions
The rule actively suppresses these predicates.
Renice or Ulimit Execution from Unusual Parent
#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
| Tactic | Techniques |
|---|---|
| Execution |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq value:"-c" |
process.command_line | wildcard |
| field:"CommandLine" kind:wildcard |
process.name | in |
| field:"process_basename" kind:in |
process.parent.executable | is_not_null | field:"ParentImage" kind:is_not_null | |
process.parent.executable | wildcard |
| field:"ParentImage" kind:wildcard |
process.parent.name | wildcard |
| field:"parent_process_basename" kind:wildcard value:".*" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.parent.command_line | in | /bin/sh /usr/bin/byobu-status tmux_right, runc init | excludes: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.executable | wildcard | /tmp/newroot/*, /tmp/vmis.*/vmware-installer/vmis-launcher, /tmp/baum/easybuild/*, /tmp/wbrashear/easybuild/*, /tmp/par-*/temp-*/nbsu | excludes:process.parent.executable |
process.parent.name | in | java, make, python3.10.real | excludes: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
#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
| Tactic | Techniques |
|---|---|
| Execution |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.Ext.effective_parent.executable | ne |
| 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.exists | eq |
| field:"process.code_signature.exists" kind:eq value:"false" |
process.code_signature.trusted | eq |
| field:"process.code_signature.trusted" kind:eq value:"false" |
process.name | in |
| field:"process_basename" kind:in |
process.parent.name | eq |
| field:"parent_process_basename" kind:eq value:"expect" |
Suspicious Execution from a PDF Documents
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard value:"?:\Users\*\AppData\Local\Temp\acrord*_sbx\*" |
process.executable | wildcard |
| field:"Image" kind:wildcard value:"?:\Users\*\AppData\Local\Temp\acrord*_sbx\*" |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
process.parent.args | wildcard |
| field:"process.parent.args" kind:wildcard value:"?:\Users\*\AppData\Local\Temp\acrord*_sbx\*" |
process.parent.name | wildcard |
| field:"parent_process_basename" kind:wildcard |
Suspicious JetBrains TeamCity Child Process
#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
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
process.parent.executable | wildcard |
| field:"ParentImage" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | eq | -ExecutionPolicy | excludes:process.args field:"process.args" value:"-ExecutionPolicy" |
process.args | wildcard | ?:\TeamCity\buildAgent\work\*.ps1 | excludes:process.args field:"process.args" value:"?:\TeamCity\buildAgent\work\*.ps1" |
process.name | eq | powershell.exe | excludes:process.name field:"process.name" value:"powershell.exe" |
process.args | eq | /-c | excludes:process.args field:"process.args" value:"/-c" |
process.args | eq | dir | excludes:process.args field:"process.args" value:"dir" |
process.name | eq | cmd.exe | excludes:process.name field:"process.name" value:"cmd.exe" |
Suspicious Memory Mapping from a Windows Installer
#Identifies suspicious API calls from a Windows Installer module. This behavior is consistent with code injection attacks.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
process.Ext.api.name | in |
| field:"process.Ext.api.name" kind:in |
process.Ext.api.parameters.protection | in |
| field:"process.Ext.api.parameters.protection" kind:in |
process.Ext.api.parameters.size | ge |
| field:"process.Ext.api.parameters.size" kind:ge value:"100000" |
process.parent.executable | wildcard |
| field:"ParentImage" kind:wildcard value:"C:\Windows\Sys?????\msiexec.exe" |
Transacted File Activity via an Unsigned DLL
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
dll.Ext.device.product_id | wildcard |
| field:"dll.Ext.device.product_id" kind:wildcard |
dll.Ext.relative_file_creation_time | lt |
| field:"dll.Ext.relative_file_creation_time" kind:lt value:"500" |
dll.Ext.relative_file_name_modify_time | lt |
| field:"dll.Ext.relative_file_name_modify_time" kind:lt value:"500" |
event.action | eq |
| field:"EventType" kind:eq |
process.pid | ne |
| field:"process_id" kind:ne value:"4" |
process.thread.Ext.call_stack_summary | contains |
| field:"process.thread.Ext.call_stack_summary" kind:contains |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
dll.code_signature.status | eq | trusted | excludes:dll.code_signature.status field:"dll.code_signature.status" value:"trusted" |