Detection rules › Elastic
Elastic rules: 39
Attempt to Clear Kernel Ring Buffer
#Monitors for the deletion of the kernel ring buffer events through dmesg. Attackers may clear kernel ring buffer events to evade detection after installing a Linux kernel module (LKM). This activity is commonly observed by intrusions that leverage kernel-level rootkits to maintain persistence on a compromised host.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth | |
| Defense Impairment |
Rule Body
[metadata]
creation_date = "2023/10/24"
integration = ["endpoint", "auditd_manager", "crowdstrike", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/06/01"
[rule]
author = ["Elastic"]
description = """
Monitors for the deletion of the kernel ring buffer events through dmesg. Attackers may clear kernel ring buffer events
to evade detection after installing a Linux kernel module (LKM). This activity is commonly observed by intrusions that
leverage kernel-level rootkits to maintain persistence on a compromised host.
"""
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 = "Attempt to Clear Kernel Ring Buffer"
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 Attempt to Clear Kernel Ring Buffer
The kernel ring buffer logs system messages, crucial for diagnosing issues. Adversaries may clear these logs using the `dmesg -c` command to hide traces of malicious activities, such as installing unauthorized kernel modules. The detection rule identifies this behavior by monitoring the execution of `dmesg` with specific arguments, flagging potential evasion attempts for further investigation.
### Possible investigation steps
- Review the process execution details to confirm the presence of the `dmesg -c` command, focusing on the process name and arguments to ensure the alert is valid.
- Investigate the user account associated with the execution of the `dmesg -c` command to determine if it is a known and authorized user or potentially compromised.
- Check for any recent installations or modifications of Linux kernel modules (LKMs) on the host to identify unauthorized changes that may coincide with the log clearing attempt.
- Examine other system logs and security alerts around the same timeframe to identify any suspicious activities or patterns that may indicate a broader attack or compromise.
- Assess the host's network activity for any unusual outbound connections or data exfiltration attempts that could suggest further malicious intent.
### False positive analysis
- Routine system maintenance activities may trigger the rule if administrators use the dmesg -c command to clear logs for legitimate purposes. To handle this, create exceptions for known maintenance scripts or processes that regularly execute this command.
- Automated scripts or monitoring tools that include dmesg -c as part of their log management routine can cause false positives. Identify these scripts and exclude them from the rule by specifying their process IDs or user accounts.
- Development and testing environments where kernel modules are frequently installed and removed might generate alerts. Consider excluding these environments from the rule or adjusting the risk score to reflect the lower threat level in these contexts.
- System administrators may use dmesg -c during troubleshooting to clear logs and view new messages. Document these activities and create exceptions for specific user accounts or roles that perform this task regularly.
### Response and remediation
- Immediately isolate the affected system from the network to prevent further malicious activity or lateral movement.
- Conduct a thorough review of the system to identify any unauthorized kernel modules or other suspicious changes, and remove them if found.
- Restore the system from a known good backup if unauthorized changes are detected and cannot be easily reversed.
- Review and update access controls and permissions to ensure that only authorized users have the ability to execute commands like `dmesg -c`.
- Implement enhanced monitoring and logging for the affected system to detect any future attempts to clear the kernel ring buffer or similar evasion tactics.
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine if additional systems are affected.
- Conduct a post-incident review to identify gaps in detection and response, and update security policies and procedures to prevent recurrence."""
risk_score = 73
rule_id = "2724808c-ba5d-48b2-86d2-0002103df753"
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 = "high"
tags = [
"Domain: Endpoint",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Data Source: Elastic Defend",
"Data Source: Elastic Endgame",
"Data Source: Auditd Manager",
"Data Source: Crowdstrike",
"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", "ProcessRollup2", "executed", "process_started") and
process.name == "dmesg" and process.args in ("-c", "-C", "--clear", "--read-clear")
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1070"
name = "Indicator Removal"
reference = "https://attack.mitre.org/techniques/T1070/"
[[rule.threat.technique.subtechnique]]
id = "T1070.002"
name = "Clear Linux or Mac System Logs"
reference = "https://attack.mitre.org/techniques/T1070/002/"
[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"
[[rule.threat.technique.subtechnique]]
id = "T1562.001"
name = "Disable or Modify Tools"
reference = "https://attack.mitre.org/techniques/T1562/001/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
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 == "dmesg" and process.args in ("-c", "-C", "--clear", "--read-clear")
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 | in |
| field:"process.args" kind:in |
process.name | eq |
| field:"process_basename" kind:eq value:"dmesg" |
AWS EC2 Role GetCallerIdentity from New Source AS Organization
#Identifies the first time an EC2 instance role session calls AWS STS GetCallerIdentity from a given source autonomous system (AS) organization name within the lookback window. Adversaries who steal instance role credentials often verify them with GetCallerIdentity from infrastructure outside your normal egress paths. Baseline learning on the pairing of identity and source network reduces noise from stable NAT or AWS-classified egress compared to alerting on every call from a non-Amazon ASN.
Known False Positives
- New EC2 workloads, NAT or egress changes, ISP renumbering, or GeoIP database updates can change `source.as.organization.name` for the same logical path. Roles that legitimately call STS from many networks (for example, developer-exported temporary credentials) may also produce alerts. Tune using role ARN, account, or user agent where appropriate.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
Rule Body
[metadata]
creation_date = "2026/04/03"
integration = ["aws"]
maturity = "production"
updated_date = "2026/04/03"
[rule]
author = ["Elastic"]
description = """
Identifies the first time an EC2 instance role session calls AWS STS GetCallerIdentity from a given source autonomous
system (AS) organization name within the lookback window. Adversaries who steal instance role credentials often verify
them with GetCallerIdentity from infrastructure outside your normal egress paths. Baseline learning on the pairing of
identity and source network reduces noise from stable NAT or AWS-classified egress compared to alerting on every call
from a non-Amazon ASN.
"""
false_positives = [
"""
New EC2 workloads, NAT or egress changes, ISP renumbering, or GeoIP database updates can change
`source.as.organization.name` for the same logical path. Roles that legitimately call STS from many networks (for
example, developer-exported temporary credentials) may also produce alerts. Tune using role ARN, account, or user
agent where appropriate.
""",
]
from = "now-6m"
index = ["filebeat-*", "logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS EC2 Role GetCallerIdentity from New Source AS Organization"
note = """## Triage and analysis
### Investigating AWS EC2 Role GetCallerIdentity from New Source AS Organization
The `GetCallerIdentity` API returns details about the IAM principal owning the credentials. It requires no IAM permissions and is commonly used to validate stolen or exported credentials.
EC2 instance role sessions appear in CloudTrail as `AssumedRole` with a session identifier matching an instance id (for example, `arn:aws:sts::account:assumed-role/role-name/i-0123456789abcdef0`). This complements the rule **AWS STS GetCallerIdentity API Called for the First Time**, which excludes `AssumedRole`. Here, a **New Terms** condition applies to the combination of `aws.cloudtrail.user_identity.arn` and `source.as.organization.name` over a 10-day history window. The first observation of that pair triggers an alert, which suppresses repeated noise when the same role keeps using the same stable egress AS organization (for example, the same NAT or provider label).
#### Possible investigation steps
- Confirm the assumed-role ARN and instance id; map the instance to an account, VPC, and expected egress (NAT gateway, IGW, proxy).
- Compare `source.as.organization.name` and `source.ip` to historical CloudTrail for the same role session or role.
- Review `user_agent.original` for tooling inconsistent with the instance (for example, unexpected OS or CLI version).
- Correlate with other alerts from the same `aws.cloudtrail.user_identity.access_key_id` or instance over the prior 48 hours.
### False positive analysis
- New instances or roles calling GetCallerIdentity once per new AS label are expected to alert once per new term until the baseline ages in.
- Missing or changing GeoIP enrichment can alter `source.as.organization.name`; ensure the field is populated consistently.
### Response and remediation
- If credentials are suspected stolen, revoke the session by stopping the instance, removing the role from the instance profile, or tightening trust and permissions; rotate any long-lived secrets the instance could access.
- Scope follow-on API activity from the same access key id and investigate the initial access vector (SSRF, IMDS abuse, malware).
### Additional information
- [GetCallerIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html)
"""
references = [
"https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html",
"https://detectioninthe.cloud/ttps/discovery/sts_get_caller_identity",
]
risk_score = 47
rule_id = "b2f8c4e1-6a73-4f1e-9c2d-8e5b0a1d3f7c"
severity = "medium"
tags = [
"Domain: Cloud",
"Domain: Identity",
"Data Source: AWS",
"Data Source: Amazon Web Services",
"Data Source: AWS STS",
"Use Case: Identity and Access Audit",
"Use Case: Threat Detection",
"Tactic: Discovery",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
event.dataset: "aws.cloudtrail"
and event.provider: "sts.amazonaws.com"
and event.action: "GetCallerIdentity"
and event.outcome: "success"
and aws.cloudtrail.user_identity.type: "AssumedRole"
and user.id: *\:i-*
and source.as.organization.name:(* and not (AMAZON* or Amazon* or Google* or "MongoDB, Inc."))
'''
[rule.investigation_fields]
field_names = [
"@timestamp",
"user.name",
"user_agent.original",
"source.ip",
"source.as.organization.name",
"aws.cloudtrail.user_identity.arn",
"aws.cloudtrail.user_identity.type",
"aws.cloudtrail.user_identity.access_key_id",
"event.action",
"event.outcome",
"cloud.account.id",
"cloud.region",
]
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1087"
name = "Account Discovery"
reference = "https://attack.mitre.org/techniques/T1087/"
[[rule.threat.technique.subtechnique]]
id = "T1087.004"
name = "Cloud Account"
reference = "https://attack.mitre.org/techniques/T1087/004/"
[rule.threat.tactic]
id = "TA0007"
name = "Discovery"
reference = "https://attack.mitre.org/tactics/TA0007/"
[rule.new_terms]
field = "new_terms_fields"
value = ["source.as.organization.name", "user.id"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-10d"
Stages and Predicates
Stage 1: new_terms
event.dataset: "aws.cloudtrail"
and event.provider: "sts.amazonaws.com"
and event.action: "GetCallerIdentity"
and event.outcome: "success"
and aws.cloudtrail.user_identity.type: "AssumedRole"
and user.id: *\:i-*
and source.as.organization.name:(* and not (AMAZON* or Amazon* or Google* or "MongoDB, Inc."))
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
aws.cloudtrail.user_identity.type | eq |
| field:"aws::userIdentity.type" kind:eq value:"AssumedRole" |
event.action | eq |
| field:"EventType" kind:eq value:"GetCallerIdentity" |
event.dataset | eq |
| field:"event.dataset" kind:eq value:"aws.cloudtrail" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
event.provider | eq |
| field:"Provider_Name" kind:eq value:"sts.amazonaws.com" |
source.as.organization.name | is_not_null | field:"source.as.organization.name" kind:is_not_null | |
user.id | wildcard |
| field:"user.id" kind:wildcard value:"*:i-*" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
source.as.organization.name | eq | MongoDB, Inc. | excludes:source.as.organization.name field:"source.as.organization.name" value:"MongoDB, Inc." |
source.as.organization.name | starts_with | AMAZON | excludes:source.as.organization.name field:"source.as.organization.name" value:"AMAZON" |
source.as.organization.name | starts_with | Amazon | excludes:source.as.organization.name field:"source.as.organization.name" value:"Amazon" |
source.as.organization.name | starts_with | Google | excludes:source.as.organization.name field:"source.as.organization.name" value:"Google" |
AWS SSM Session Manager Child Process Execution
#Identifies process start events where the parent process is the AWS Systems Manager (SSM) Session Manager worker. Session Manager provides interactive shell access to EC2 instances and hybrid nodes without bastion hosts or open inbound ports. Adversaries abuse it for remote execution and lateral movement using legitimate AWS credentials and IAM permissions. This rule surfaces endpoint execution occurring under that worker for visibility and hunting. Expect noise from authorized administrative sessions.
Known False Positives
- Legitimate operators using AWS Systems Manager Session Manager to administer instances will spawn child processes under the session worker. Tune with host, user, or command-line exclusions for known automation and break-glass workflows.
- The SSM agent may invoke short-lived utilities (for example identity or environment probes) during session setup. Additional exclusions may be required in your environment.
MITRE ATT&CK Coverage
Telemetry Coverage
Rule Body
[metadata]
creation_date = "2026/04/03"
integration = ["endpoint", "auditd_manager", "crowdstrike", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/06/01"
[rule]
author = ["Elastic"]
description = """
Identifies process start events where the parent process is the AWS Systems Manager (SSM) Session Manager worker.
Session Manager provides interactive shell access to EC2 instances and hybrid nodes without bastion hosts or open inbound ports.
Adversaries abuse it for remote execution and lateral movement using legitimate AWS credentials and IAM permissions.
This rule surfaces endpoint execution occurring under that worker for visibility and hunting. Expect noise from authorized
administrative sessions.
"""
false_positives = [
"""
Legitimate operators using AWS Systems Manager Session Manager to administer instances will spawn child processes
under the session worker. Tune with host, user, or command-line exclusions for known automation and break-glass
workflows.
""",
"""
The SSM agent may invoke short-lived utilities (for example identity or environment probes) during session setup.
Additional exclusions may be required in your environment.
""",
]
from = "now-9m"
index = [
"logs-endpoint.events.process*",
"auditbeat-*",
"logs-auditd_manager.auditd-*",
"logs-crowdstrike.fdr*",
"logs-sentinel_one_cloud_funnel.*"
]
language = "kuery"
license = "Elastic License v2"
name = "AWS SSM Session Manager Child Process Execution"
note = """## Triage and analysis
### Investigating AWS SSM Session Manager Child Process Execution
AWS Systems Manager Session Manager starts a session worker process on the endpoint; commands and shells you run in the
session appear as child processes of that worker. The same mechanism is used for authorized administration and for
adversary activity when IAM credentials or instance roles allow `ssm:StartSession` (or related) abuse.
### Possible investigation steps
- Confirm whether the host is an EC2 instance or managed node that legitimately uses Session Manager.
- Review `process.command_line`, `process.executable`, `process.user.name`, and `user.name` for the child process to
judge intent (reconnaissance, download, credential access, persistence, etc.).
- Correlate timing with AWS CloudTrail for `StartSession`, `ResumeSession`, or related SSM API calls and the IAM
principal that initiated the session.
- Pivot on the same `host.id` or instance identifier for other alerts or SSM activity in the same window.
### False positive analysis
- Routine interactive or automated administration via Session Manager is expected to match this rule by design.
- Prefer exclusions tied to stable attributes (approved IAM roles, automation service accounts, known script paths)
rather than broad process-name allowlists unless validated.
### Response and remediation
- If activity is unauthorized: revoke or rotate exposed IAM credentials, review SSM and VPC endpoints policies, and
terminate suspicious sessions from the AWS console or API.
- Isolate the instance if compromise is suspected and perform endpoint forensics following your incident response
playbook.
"""
references = [
"https://www.mitiga.io/blog/abusing-the-amazon-web-services-ssm-agent-as-a-remote-access-trojan",
"https://hackingthe.cloud/aws/post_exploitation/run_shell_commands_on_ec2/",
"https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html",
]
risk_score = 47
rule_id = "cf2b8cf5-3364-4396-b551-42aae9b6d37e"
severity = "medium"
tags = [
"Domain: Endpoint",
"Domain: Cloud",
"OS: Linux",
"OS: Windows",
"OS: macOS",
"Use Case: Threat Detection",
"Tactic: Execution",
"Data Source: Elastic Defend",
"Data Source: Auditd Manager",
"Data Source: Crowdstrike",
"Data Source: SentinelOne",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
event.category: "process" and event.action : ("exec" or "exec_event" or "start" or "ProcessRollup2" or "executed" or "process_started") and
(
process.parent.name:("ssm-session-worker.exe" or "ssm-session-worker" or "ssm-document-worker.exe" or "ssm-document-worker") or
(process.name : "powershell.exe" and process.args : *awsrunPowerShellScript*) or
(process.name : ("dash" or "sh" or "bash") and process.args : *awsrunShellScript*) or
(process.parent.name : "powershell.exe" and process.parent.args : *awsrunPowerShellScript*) or
(process.parent.name : ("dash" or "sh" or "bash") and process.parent.args : *awsrunShellScript*)
) and
not (process.name : "powershell.exe" and process.args :("$str.Substring($str.length" or *Convert-GuidToCompressedGuid* or get-wmiobject* or $wmi_proc* or *win32_quickfixengineering* or Get-wmiobject* or *Get-Service* or *Get-WmiObject* or *System32\\ntoskrnl.exe* or *GET-WMIOBJECT*)) and
not process.executable : ("/usr/bin/lscpu" or "/usr/bin/snap" or "/usr/bin/rpm" or "/usr/bin/dpkg-query" or /snap/snapd/*/usr/bin/snap or "/usr/bin/id" or "C:\\Program Files\\Amazon\\SSM\\Plugins\\SessionManagerShell\\winpty-agent.exe" or /var/lib/amazon/ssm/update/amazon-ssm-agent-updater/*/updater or C\:\\ProgramData\\Amazon\\SSM\\Update\\amazon-ssm-agent-updater\\*\\updater.exe) and
not (process.name : (dash or bash or sh or _script.sh) and process.args : /var/lib/amazon/ssm/*/document/orchestration/*/_script.sh) and
process.command_line :(* and not (*ssm-user or */invokeInspectorSsmPluginLinux/_script.sh or */checkExclusionPreference/_script.sh or *\\createUpdateFolder\\_script.ps1 or */checkProvisioningEligibility/_script.sh or */install/_script.sh or */uninstall/_script.sh))
'''
[[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]]
name = "Unix Shell"
id = "T1059.004"
reference = "https://attack.mitre.org/techniques/T1059/004/"
[[rule.threat.technique.subtechnique]]
id = "T1059.001"
name = "PowerShell"
reference = "https://attack.mitre.org/techniques/T1059/001/"
[[rule.threat.technique]]
id = "T1651"
name = "Cloud Administration Command"
reference = "https://attack.mitre.org/techniques/T1651/"
[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
Stages and Predicates
Stage 1: query
event.category: "process" and event.action : ("exec" or "exec_event" or "start" or "ProcessRollup2" or "executed" or "process_started") and
(
process.parent.name:("ssm-session-worker.exe" or "ssm-session-worker" or "ssm-document-worker.exe" or "ssm-document-worker") or
(process.name : "powershell.exe" and process.args : *awsrunPowerShellScript*) or
(process.name : ("dash" or "sh" or "bash") and process.args : *awsrunShellScript*) or
(process.parent.name : "powershell.exe" and process.parent.args : *awsrunPowerShellScript*) or
(process.parent.name : ("dash" or "sh" or "bash") and process.parent.args : *awsrunShellScript*)
) and
not (process.name : "powershell.exe" and process.args :("$str.Substring($str.length" or *Convert-GuidToCompressedGuid* or get-wmiobject* or $wmi_proc* or *win32_quickfixengineering* or Get-wmiobject* or *Get-Service* or *Get-WmiObject* or *System32\\ntoskrnl.exe* or *GET-WMIOBJECT*)) and
not process.executable : ("/usr/bin/lscpu" or "/usr/bin/snap" or "/usr/bin/rpm" or "/usr/bin/dpkg-query" or /snap/snapdupdater or C\:\\ProgramData\\Amazon\\SSM\\Update\\amazon-ssm-agent-updater\\*\\updater.exe) and
not (process.name : (dash or bash or sh or _script.sh) and process.args : /var/lib/amazon/ssm_script.sh) and
process.command_line :(* and not (*ssm-user or */invokeInspectorSsmPluginLinux/_script.sh or */checkExclusionPreference/_script.sh or *\\createUpdateFolder\\_script.ps1 or */checkProvisioningEligibility/_script.sh or */install/_script.sh or */uninstall/_script.sh))
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | in |
| field:"EventType" kind:in |
event.category | eq |
| field:"event.category" kind:eq value:"process" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.command_line | is_not_null | field:"CommandLine" kind:is_not_null | |
process.name | eq |
| field:"process_basename" kind:eq value:"powershell.exe" |
process.name | in |
| field:"process_basename" kind:in |
process.parent.args | wildcard |
| field:"process.parent.args" kind:wildcard |
process.parent.name | eq |
| field:"parent_process_basename" kind:eq value:"powershell.exe" |
process.parent.name | in |
| field:"parent_process_basename" kind:in |
Exclusions
The rule actively suppresses these predicates.
Azure Storage Anonymous Blob Access to Unusual Resource
#Identifies the first time an Azure Storage resource receives an anonymous data-plane read (GetBlob and related Get or List operations). Anonymous requests are used to probe public containers and to test stolen blob URLs before a SAS is appended. First-seen resource ID keeps volume down while still covering WireServer-related probes of status or extension blobs.
Known False Positives
- Intentionally public containers (static websites, public datasets) generate anonymous GetBlob and ListBlobs. Baseline those storage accounts and exclude `azure.resource.id` after review.
- Internet-wide scanners will produce first-seen anonymous access on newly created or newly logged accounts. Confirm whether the account is meant to be public.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery | |
| Collection |
Rule Body
[metadata]
creation_date = "2026/08/17"
integration = ["azure"]
maturity = "production"
updated_date = "2026/08/17"
[rule]
author = ["Elastic"]
description = """
Identifies the first time an Azure Storage resource receives an anonymous data-plane read (GetBlob and related Get or
List operations). Anonymous requests are used to probe public containers and to test stolen blob URLs before a SAS is
appended. First-seen resource ID keeps volume down while still covering WireServer-related probes of status or extension
blobs.
"""
false_positives = [
"""
Intentionally public containers (static websites, public datasets) generate anonymous GetBlob and ListBlobs.
Baseline those storage accounts and exclude `azure.resource.id` after review.
""",
"""
Internet-wide scanners will produce first-seen anonymous access on newly created or newly logged accounts. Confirm
whether the account is meant to be public.
""",
]
from = "now-9m"
index = ["logs-azure.platformlogs-*"]
language = "kuery"
license = "Elastic License v2"
name = "Azure Storage Anonymous Blob Access to Unusual Resource"
note = """## Triage and analysis
### Investigating Azure Storage Anonymous Blob Access to Unusual Resource
StorageRead platform logs record `AuthenticationType` as Anonymous when no SAS, OAuth, or account key is presented.
A first-seen `azure.resource.id` (typically the blob service
`/subscriptions/.../storageAccounts/<account>/blobServices/default`) means this resource has not had anonymous Get or
List traffic in the history window.
WireServer SAS-replay chains often start with an anonymous GetBlob (HTTP 409/403) against the same object, then a
SAS 200. This rule does not require guest-agent path strings; those lab container names are not production
observables.
`source.ip` is often empty. Use `source.address` (`ip:port`).
### Possible investigation steps
- Review `event.action`, `azure.platformlogs.statusCode`, and `azure.platformlogs.uri`.
- HTTP 200 with Anonymous means the container or blob is publicly readable. HTTP 409/403 is a probe.
- Identify the account from `azure.resource.id` / `azure.resource.name` and check whether public access is intended.
- Search for SAS-authenticated GetBlob to the same account from the same source shortly after.
- If the URI contains `/$system/` or `md-hdd-`, correlate with WireServer access on VMs in the subscription.
### False positive analysis
- Public blob websites and CDN origins. Exclude the `azure.resource.id` for approved public accounts.
- New accounts that enable StorageRead for the first time will alert on the first scanner hit.
### Response and remediation
- Disable anonymous public access on accounts that should be private.
- If a follow-on SAS read exists, revoke that SAS and review how the URL was obtained.
- Keep StorageRead diagnostic logs enabled on storage accounts of interest.
"""
references = [
"https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/storagebloblogs",
"https://learn.microsoft.com/en-us/azure/storage/blobs/anonymous-read-access-prevent",
"https://cybercx.com.au/blog/azure-ssrf-metadata/",
"https://www.netspi.com/blog/technical-blog/cloud-pentesting/decrypting-vm-extension-settings-with-azure-wireserver/",
]
risk_score = 47
rule_id = "eabaf807-e710-4f0f-8943-8d1b436d834a"
setup = """#### Required Azure Storage Diagnostic Logs
Enable StorageRead diagnostic logs on Azure Storage Accounts and stream them to the Event Hub used by the Azure
integration. Anonymous vs SAS is `azure.platformlogs.identity.type`.
"""
severity = "medium"
tags = [
"Domain: Cloud",
"Data Source: Azure",
"Data Source: Azure Platform Logs",
"Platform: Azure",
"Service: Azure Storage",
"Use Case: Threat Detection",
"Tactic: Discovery",
"Tactic: Collection",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
data_stream.dataset: azure.platformlogs and
azure.platformlogs.identity.type: Anonymous and
event.action: (
GetBlob or GetBlobMetadata or GetBlobProperties or GetBlockList or
GetPageRanges or QueryBlobContents or ListBlobs or
GetContainerProperties or GetContainerMetadata or GetContainerAcl
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1580"
name = "Cloud Infrastructure Discovery"
reference = "https://attack.mitre.org/techniques/T1580/"
[rule.threat.tactic]
id = "TA0007"
name = "Discovery"
reference = "https://attack.mitre.org/tactics/TA0007/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1530"
name = "Data from Cloud Storage"
reference = "https://attack.mitre.org/techniques/T1530/"
[rule.threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"
[rule.new_terms]
field = "new_terms_fields"
value = ["azure.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.platformlogs and
azure.platformlogs.identity.type: Anonymous and
event.action: (
GetBlob or GetBlobMetadata or GetBlobProperties or GetBlockList or
GetPageRanges or QueryBlobContents or ListBlobs or
GetContainerProperties or GetContainerMetadata or GetContainerAcl
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
azure.platformlogs.identity.type | eq |
| field:"azure.platformlogs.identity.type" kind:eq value:"Anonymous" |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"azure.platformlogs" |
event.action | in |
| field:"EventType" kind:in |
DNS to Commonly Abused Web Services
#Adversaries may implement command and control (C2) communications that use common web services to hide their activity. This attack technique is typically targeted at an organization and uses web services common to the victim network, which allows the adversary to blend into legitimate traffic activity. These popular services are typically targeted since they have most likely been used before compromise, which helps malicious traffic blend in.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control | |
| Exfiltration |
Rule Body
[metadata]
bypass_bbr_timing = true
creation_date = "2026/05/04"
integration = ["endpoint"]
maturity = "production"
min_stack_version = "9.3.0"
min_stack_comments = "DNS for Linux support was introduced in 9.3.0"
updated_date = "2026/05/26"
[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Adversaries may implement command and control (C2) communications that use common web services to hide their activity.
This attack technique is typically targeted at an organization and uses web services common to the victim network, which
allows the adversary to blend into legitimate traffic activity. These popular services are typically targeted since they
have most likely been used before compromise, which helps malicious traffic blend in.
"""
from = "now-9m"
index = ["logs-endpoint.events.network-*"]
language = "eql"
license = "Elastic License v2"
name = "DNS to Commonly Abused Web Services"
risk_score = 21
rule_id = "8248323e-f888-4134-a26f-37a6362f7231"
severity = "low"
tags = [
"Domain: Endpoint",
"Domain: Network",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Command and Control",
"Tactic: Exfiltration",
"Data Source: Elastic Defend",
"Rule Type: BBR",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
network where host.os.type == "linux" and dns.question.name != null and process.name != null and
dns.question.name like~ (
/* Google services */
"drive.google.com", "docs.google.com", "script.google.com", "script.googleusercontent.com",
"*googleapis.com", "calendar.app.google*",
/* Dropbox */
"api.dropboxapi.com", "content.dropboxapi.com", "*dl.dropboxusercontent.com",
/* Microsoft / OneDrive / SharePoint */
"api.onedrive.com", "*.onedrive.org", "onedrive.live.com", "*files.1drv.com", "graph.microsoft.com",
"*.sharepoint.com", "login.live.com", "g.live.com",
/* Slack */
"*slack.com", "slack-redir.net", "slack-files.com",
/* Discord */
"discord.com", "cdn.discordapp.com", "discordapp.com",
/* Telegram */
"api.telegram.org", "t.me",
/* Azure / Cloud storage */
"apis.azureedge.net", "*.blob.core.windows.net", "*.blob.storage.azure.net", "*azurewebsites.net",
/* GitHub / Dev hosting */
"api.github.com", "raw.githubusercontent.*", "gist.githubusercontent.com", "rawcdn.githack.*",
"*.notabug.org",
/* Developer tunnels / reverse proxies */
"*.devtunnels.ms", "*global.rel.tunnels.api.visualstudio.com", "*.ngrok.io", "*.ngrok-free.app",
"*.portmap.*", "serveo.net", "*localtunnel.me", "*pagekite.me", "*.trycloudflare.com",
/* AWS */
"*s3.amazonaws.com",
/* Paste services */
"pastebin.*", "paste4btc.com", "paste.ee", "ghostbin.com", "paste.nrecom.net", "zerobin.net",
"controlc.com", "pastecode.dev", "paste.rs", "hastebin.com", "dpaste.org", "dpaste.com", "0bin.net",
"paste.ofcode.org", "paste.wakas.org", "nopaste.net",
/* File sharing / exfiltration */
"filebin.net", "file.io", "transfer.sh", "*.gofile.io", "workupload.com", "*upload.ee", "*anonfiles.com",
"api.anonfile.com", "*bayfiles.com", "*bublup.com", "*dropfiles.org", "*dropmefiles.com", "*easyupload.io",
"*filetransfer.io", "*sendspace.com", "*share.riseup.net", "*temp.sh", "*tempsend.com", "*ufile.io",
"*send.now", "*send.cm", "*sendit.sh", "*pixeldrain.com", "*megaupload.com", "*mediafire.com",
"*bashupload.com", "*bujang.online", "mediafire.zip", "*.4shared.com", "filecloud.me", "*.pcloud.com",
"*catbox.moe",
/* CDN / hosting / generic file infra */
"*cdnmegafiles.com", "www.uplooder.net", "?.top4top.io", "top4top.io", "*.b-cdn.net", "cdn*.space",
"i.ibb.co", "i.imgur.com",
/* Webhooks / testing / bins */
"webhook.site", "run.mocky.io", "mockbin.org", "requestbin.net",
/* Public hosting / misc infra */
"*.publicvm.com", "*.blogspot.com", "*infinityfreeapp.com", "free.keep.sh", "*.aternos.me",
"*hosting-profi.de",
/* IP / network utilities */
"api.mylnikov.org", "ipbase.com", "*.getmyip.com", "myexternalip.com", "*.geojs.io",
"*api.2ip.ua", "*api.db-ip.com", "*api.ip.sb", "*api.ipify.org", "*api.myip.com",
"*api.npoint.io", "*api64.ipify.org", "*bot.whatismyipaddress.com", "*checkip.amazonaws.com",
"*checkip.dyndns.org", "*curlmyip.com", "*eth0.me", "*freegeoip.app", "*freegeoip.net",
"*freeipapi.com", "*geoiptool.com", "*geolocation-db.com", "*httpbin.org",
"*icanhazip.com", "*ident.me", "*ifcfg.me", "*ifconfig.me", "*inet-ip.info", "*ip-api.com",
"*ip.appspot.com", "*ip.tyk.nu", "*ip4.seeip.org", "*ipecho.net", "*ipinfo.io", "*iplogger.*",
"*ipof.in", "*ipwho.is", "*ipwhois.app", "*ipv4.icanhazip.com", "*ipv6.icanhazip.com",
"*myip.dnsomatic.com", "*myip.ipip.net", "*myip.opendns.com", "*portmap.io", "*wgetip.com",
"*whatismyip.akamai.com", "*wtfismyip.com",
/* Social / platforms */
"mbasic.facebook.com", "*.zulipchat.com", "stackoverflow.com",
/* Package hosting */
"files.pythonhosted.org",
/* Databases / backend platforms */
"*.supabase.co", "*.elastic-cloud.com", "*.cloud.es.io",
/* Misc / suspicious */
"*up.freeo*.space", "*icp0.io", "updates.peer2profit.com", "meacz.gq", "rwrd.org", "lobfile.com",
"ftpupload.net", "the.earth.li",
/* URL shorteners */
"*shorturl.at", "*tinyurl.com", "*bit.ly", "*cutt.ly", "*is.gd", "*rebrand.ly", "*rebrandly.com",
"*adf.ly", "*rb.gy", "tiny.one", "t.ly", "urlz.fr", "rentry.co",
/* Crypto mining pools */
"*.nicehash.com", "stratum*.nicehash.com",
"*.2miners.com", "*.moneroocean.stream", "*.supportxmr.com",
"*.nanopool.org", "*.f2pool.com", "*.poolbinance.com",
"*.antpool.com", "*.viabtc.com", "*.braiins.com", "*.slushpool.com",
/* Decentralized */
"ipfs.io", "*.ipfs.io", "dweb.link", "*.dweb.link",
"*.ipfs.dweb.link", "*.ipns.dweb.link",
"gateway.pinata.cloud", "*.mypinata.cloud",
"web3.storage", "*.web3.storage",
"nftstorage.link", "*.nftstorage.link",
"arweave.net", "*.arweave.net",
"ar.io", "*.ar.io",
"ic0.app", "*.ic0.app",
"icp0.io", "*.icp0.io",
"*.storjshare.io"
) and
not process.executable like (
"/opt/google-cloud-ops-agent/subagents/fluent-bit/bin/fluent-bit", "/usr/lib/systemd/systemd-resolved",
"/opt/Elastic/Agent/data/elastic-agent-*/components/elastic-otel-collector", "/usr/bin/dockerd",
"/usr/bin/google_osconfig_agent", "/snap/firefox/*/usr/lib/firefox/firefox", "/usr/bin/warp-svc",
"/var/lib/docker/overlay2/*/merged/usr/local/bin/node", "/snap/chromium/*/usr/lib/chromium-browser/chrome",
"/opt/google-cloud-ops-agent/subagents/opentelemetry-collector/otelopscol", "/usr/local/bin/rclone",
"/var/lib/elastic-agent/data/elastic-agent-*/components/elastic-otel-collector", "/opt/google/chrome/chrome",
"/usr/bin/pihole-FTL"
)
'''
[[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.technique]]
id = "T1090"
name = "Proxy"
reference = "https://attack.mitre.org/techniques/T1090/"
[[rule.threat.technique.subtechnique]]
id = "T1090.002"
name = "External Proxy"
reference = "https://attack.mitre.org/techniques/T1090/002/"
[[rule.threat.technique]]
id = "T1102"
name = "Web Service"
reference = "https://attack.mitre.org/techniques/T1102/"
[[rule.threat.technique.subtechnique]]
id = "T1102.001"
name = "Dead Drop Resolver"
reference = "https://attack.mitre.org/techniques/T1102/001/"
[[rule.threat.technique.subtechnique]]
id = "T1102.002"
name = "Bidirectional Communication"
reference = "https://attack.mitre.org/techniques/T1102/002/"
[[rule.threat.technique]]
id = "T1568"
name = "Dynamic Resolution"
reference = "https://attack.mitre.org/techniques/T1568/"
[[rule.threat.technique.subtechnique]]
id = "T1568.002"
name = "Domain Generation Algorithms"
reference = "https://attack.mitre.org/techniques/T1568/002/"
[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1567"
name = "Exfiltration Over Web Service"
reference = "https://attack.mitre.org/techniques/T1567/"
[[rule.threat.technique.subtechnique]]
id = "T1567.001"
name = "Exfiltration to Code Repository"
reference = "https://attack.mitre.org/techniques/T1567/001/"
[[rule.threat.technique.subtechnique]]
id = "T1567.002"
name = "Exfiltration to Cloud Storage"
reference = "https://attack.mitre.org/techniques/T1567/002/"
[[rule.threat.technique.subtechnique]]
id = "T1567.003"
name = "Exfiltration to Text Storage Sites"
reference = "https://attack.mitre.org/techniques/T1567/003/"
[rule.threat.tactic]
id = "TA0010"
name = "Exfiltration"
reference = "https://attack.mitre.org/tactics/TA0010/"
Stages and Predicates
Stage 1: network
network where host.os.type == "linux" and dns.question.name != null and process.name != null and
dns.question.name like~ (
"drive.google.com", "docs.google.com", "script.google.com", "script.googleusercontent.com",
"*googleapis.com", "calendar.app.google*",
"api.dropboxapi.com", "content.dropboxapi.com", "*dl.dropboxusercontent.com",
"api.onedrive.com", "*.onedrive.org", "onedrive.live.com", "*files.1drv.com", "graph.microsoft.com",
"*.sharepoint.com", "login.live.com", "g.live.com",
"*slack.com", "slack-redir.net", "slack-files.com",
"discord.com", "cdn.discordapp.com", "discordapp.com",
"api.telegram.org", "t.me",
"apis.azureedge.net", "*.blob.core.windows.net", "*.blob.storage.azure.net", "*azurewebsites.net",
"api.github.com", "raw.githubusercontent.*", "gist.githubusercontent.com", "rawcdn.githack.*",
"*.notabug.org",
"*.devtunnels.ms", "*global.rel.tunnels.api.visualstudio.com", "*.ngrok.io", "*.ngrok-free.app",
"*.portmap.*", "serveo.net", "*localtunnel.me", "*pagekite.me", "*.trycloudflare.com",
"*s3.amazonaws.com",
"pastebin.*", "paste4btc.com", "paste.ee", "ghostbin.com", "paste.nrecom.net", "zerobin.net",
"controlc.com", "pastecode.dev", "paste.rs", "hastebin.com", "dpaste.org", "dpaste.com", "0bin.net",
"paste.ofcode.org", "paste.wakas.org", "nopaste.net",
"filebin.net", "file.io", "transfer.sh", "*.gofile.io", "workupload.com", "*upload.ee", "*anonfiles.com",
"api.anonfile.com", "*bayfiles.com", "*bublup.com", "*dropfiles.org", "*dropmefiles.com", "*easyupload.io",
"*filetransfer.io", "*sendspace.com", "*share.riseup.net", "*temp.sh", "*tempsend.com", "*ufile.io",
"*send.now", "*send.cm", "*sendit.sh", "*pixeldrain.com", "*megaupload.com", "*mediafire.com",
"*bashupload.com", "*bujang.online", "mediafire.zip", "*.4shared.com", "filecloud.me", "*.pcloud.com",
"*catbox.moe",
"*cdnmegafiles.com", "www.uplooder.net", "?.top4top.io", "top4top.io", "*.b-cdn.net", "cdn*.space",
"i.ibb.co", "i.imgur.com",
"webhook.site", "run.mocky.io", "mockbin.org", "requestbin.net",
"*.publicvm.com", "*.blogspot.com", "*infinityfreeapp.com", "free.keep.sh", "*.aternos.me",
"*hosting-profi.de",
"api.mylnikov.org", "ipbase.com", "*.getmyip.com", "myexternalip.com", "*.geojs.io",
"*api.2ip.ua", "*api.db-ip.com", "*api.ip.sb", "*api.ipify.org", "*api.myip.com",
"*api.npoint.io", "*api64.ipify.org", "*bot.whatismyipaddress.com", "*checkip.amazonaws.com",
"*checkip.dyndns.org", "*curlmyip.com", "*eth0.me", "*freegeoip.app", "*freegeoip.net",
"*freeipapi.com", "*geoiptool.com", "*geolocation-db.com", "*httpbin.org",
"*icanhazip.com", "*ident.me", "*ifcfg.me", "*ifconfig.me", "*inet-ip.info", "*ip-api.com",
"*ip.appspot.com", "*ip.tyk.nu", "*ip4.seeip.org", "*ipecho.net", "*ipinfo.io", "*iplogger.*",
"*ipof.in", "*ipwho.is", "*ipwhois.app", "*ipv4.icanhazip.com", "*ipv6.icanhazip.com",
"*myip.dnsomatic.com", "*myip.ipip.net", "*myip.opendns.com", "*portmap.io", "*wgetip.com",
"*whatismyip.akamai.com", "*wtfismyip.com",
"mbasic.facebook.com", "*.zulipchat.com", "stackoverflow.com",
"files.pythonhosted.org",
"*.supabase.co", "*.elastic-cloud.com", "*.cloud.es.io",
"*up.freeo*.space", "*icp0.io", "updates.peer2profit.com", "meacz.gq", "rwrd.org", "lobfile.com",
"ftpupload.net", "the.earth.li",
"*shorturl.at", "*tinyurl.com", "*bit.ly", "*cutt.ly", "*is.gd", "*rebrand.ly", "*rebrandly.com",
"*adf.ly", "*rb.gy", "tiny.one", "t.ly", "urlz.fr", "rentry.co",
"*.nicehash.com", "stratum*.nicehash.com",
"*.2miners.com", "*.moneroocean.stream", "*.supportxmr.com",
"*.nanopool.org", "*.f2pool.com", "*.poolbinance.com",
"*.antpool.com", "*.viabtc.com", "*.braiins.com", "*.slushpool.com",
"ipfs.io", "*.ipfs.io", "dweb.link", "*.dweb.link",
"*.ipfs.dweb.link", "*.ipns.dweb.link",
"gateway.pinata.cloud", "*.mypinata.cloud",
"web3.storage", "*.web3.storage",
"nftstorage.link", "*.nftstorage.link",
"arweave.net", "*.arweave.net",
"ar.io", "*.ar.io",
"ic0.app", "*.ic0.app",
"icp0.io", "*.icp0.io",
"*.storjshare.io"
) and
not process.executable like (
"/opt/google-cloud-ops-agent/subagents/fluent-bit/bin/fluent-bit", "/usr/lib/systemd/systemd-resolved",
"/opt/Elastic/Agent/data/elastic-agent-*/components/elastic-otel-collector", "/usr/bin/dockerd",
"/usr/bin/google_osconfig_agent", "/snap/firefox/*/usr/lib/firefox/firefox", "/usr/bin/warp-svc",
"/var/lib/docker/overlay2/*/merged/usr/local/bin/node", "/snap/chromium/*/usr/lib/chromium-browser/chrome",
"/opt/google-cloud-ops-agent/subagents/opentelemetry-collector/otelopscol", "/usr/local/bin/rclone",
"/var/lib/elastic-agent/data/elastic-agent-*/components/elastic-otel-collector", "/opt/google/chrome/chrome",
"/usr/bin/pihole-FTL"
)
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.name | is_not_null | field:"process_basename" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.executable | wildcard | /opt/google-cloud-ops-agent/subagents/fluent-bit/bin/fluent-bit, /usr/lib/systemd/systemd-resolved, /opt/Elastic/Agent/data/elastic-agent-*/components/elastic-otel-collector, /usr/bin/dockerd, /usr/bin/google_osconfig_agent, /snap/firefox/*/usr/lib/firefox/firefox, /usr/bin/warp-svc, /var/lib/docker/overlay2/*/merged/usr/local/bin/node, /snap/chromium/*/usr/lib/chromium-browser/chrome, /opt/google-cloud-ops-agent/subagents/opentelemetry-collector/otelopscol, /usr/local/bin/rclone, /var/lib/elastic-agent/data/elastic-agent-*/components/elastic-otel-collector, /opt/google/chrome/chrome, /usr/bin/pihole-FTL | excludes:process.executable |
Execution via Internet Explorer Exporter
#Identifies the execution of the built-in Windows program, ExtExport, which can be used for execution via side-loading a malicious DLL with one of the following names: mozcrt19.dll, mozsqlite3.dll, or sqlite.dll.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[rule]
description = """
Identifies the execution of the built-in Windows program, ExtExport, which can be used for execution via side-loading a
malicious DLL with one of the following names: mozcrt19.dll, mozsqlite3.dll, or sqlite.dll.
"""
id = "e13a65b7-f46f-4c7f-85cf-7e59170071fa"
license = "Elastic License v2"
name = "Execution via Internet Explorer Exporter"
os_list = ["windows"]
reference = ["https://lolbas-project.github.io/lolbas/Binaries/Extexport/"]
version = "1.0.31"
query = '''
sequence by user.id with maxspan=5m
[file where event.action != "deletion" and
file.name : ("sqlite3.dll", "mozcrt19.dll", "mozsqlite3.dll") and
not file.path : ("?:\\Program Files (x86)\\*.dll", "?:\\Program Files\\*.dll")]
[process where event.action == "start" and process.pe.original_file_name : "extexport.exe" and
not process.executable : ("?:\\Program Files (x86)\\Internet Explorer\\ExtExport.exe",
"?:\\Program Files\\Internet Explorer\\ExtExport.exe")]
'''
min_endpoint_version = "7.15.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
[[optional_actions]]
action = "rollback"
field = "process.entity_id"
state = 1
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 5m, correlated by user.id.
Stage 1: file
[file where event.action != "deletion" and
file.name : ("sqlite3.dll", "mozcrt19.dll", "mozsqlite3.dll") and
not file.path : ("?:\\Program Files (x86)\\*.dll", "?:\\Program Files\\*.dll")]
Stage 2: process
[process where event.action == "start" and process.pe.original_file_name : "extexport.exe" and
not process.executable : ("?:\\Program Files (x86)\\Internet Explorer\\ExtExport.exe",
"?:\\Program Files\\Internet Explorer\\ExtExport.exe")]
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" |
file.name | wildcard |
| field:"file.name" kind:wildcard |
process.pe.original_file_name | wildcard |
| field:"OriginalFileName" kind:wildcard value:"extexport.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
file.path | wildcard | ?:\Program Files (x86)\*.dll, ?:\Program Files\*.dll | excludes:file.path field:"file.path" value:"?:\Program Files (x86)\*.dll" field:"file.path" value:"?:\Program Files\*.dll" |
process.executable | eq | ?:\Program Files (x86)\Internet Explorer\ExtExport.exe, ?:\Program Files\Internet Explorer\ExtExport.exe | excludes:process.executable field:"process.executable" value:"?:\Program Files (x86)\Internet Explorer\ExtExport.exe" field:"process.executable" value:"?:\Program Files\Internet Explorer\ExtExport.exe" |
GKE Unusual Sensitive Workload Modification
#Detects the first occurrence of create or patch activity against sensitive GKE workloads (DaemonSets, Deployments, or CronJobs) from an unusual combination of user agent, source IP, and user identity, which may indicate privilege escalation or unauthorized access within the cluster.
Known False Positives
- Emergency kubectl changes, VPN or workstation migrations, and CI runner rotation can produce new user agent, source IP, and username combinations for authorized operators. Baseline expected automation before tuning.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- Direct Interactive Kubernetes API Request by Unusual Utilities (Elastic)
- GKE Sensitive RBAC Change Followed by Workload Modification (Elastic)
- Kubernetes Cron Job Created or Modified (Panther)
- Kubernetes Cron Job Created or Modified (Panther)
- Kubernetes Cron Job Creation (Splunk)
- Kubernetes CronJob Created or Modified (Panther)
- Kubernetes CronJob/Job Modification (Sigma)
- Kubernetes DaemonSet Created (Panther)
Rule Body
[metadata]
creation_date = "2026/07/10"
integration = ["gcp"]
maturity = "production"
updated_date = "2026/07/10"
[rule]
author = ["Elastic"]
description = """
Detects the first occurrence of create or patch activity against sensitive GKE workloads (DaemonSets, Deployments, or
CronJobs) from an unusual combination of user agent, source IP, and user identity, which may indicate privilege
escalation or unauthorized access within the cluster.
"""
false_positives = [
"""
Emergency kubectl changes, VPN or workstation migrations, and CI runner rotation can produce new user agent, source
IP, and username combinations for authorized operators. Baseline expected automation before tuning.
""",
]
from = "now-6m"
index = ["logs-gcp.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "GKE Unusual Sensitive Workload Modification"
note = """## Triage and analysis
### Investigating GKE Unusual Sensitive Workload Modification
This new-terms rule alerts on the first create or patch of a DaemonSet, Deployment, or CronJob from a new combination of
`user_agent.original`, `source.ip`, and `client.user.email`.
### Possible investigation steps
- Review the audit request for image, command, service account, and privileged settings changes.
- Attribute the actor to its backing identity and validate whether the source network is expected.
- Correlate with RBAC, secret, or exec activity from the same identity.
### False positive analysis
- Legitimate on-call changes from new workstations or updated kubectl versions are common in lab clusters.
### Response and remediation
- Roll back unauthorized workload changes, revoke the credential used, and tighten RBAC on workload controllers.
"""
setup = "The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule."
references = [
"https://heilancoos.github.io/research/2025/12/16/kubernetes.html#overly-permissive-role-based-access-control",
"https://flare.io/learn/resources/blog/teampcp-cloud-native-ransomware",
]
risk_score = 21
rule_id = "8d97dfa3-3c51-45fb-8621-bde800c47b22"
severity = "low"
tags = [
"Domain: Cloud",
"Domain: Kubernetes",
"Data Source: GCP",
"Data Source: Google Cloud Platform",
"Use Case: Threat Detection",
"Tactic: Privilege Escalation",
"Tactic: Persistence",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
data_stream.dataset:gcp.audit and service.name:k8s.io and event.outcome:success and user_agent.original:* and client.user.email:(* and not system\:*) and source.ip:* and event.action:(io.k8s.apps.v1.daemonsets.create or io.k8s.apps.v1.daemonsets.patch or io.k8s.apps.v1.deployments.create or io.k8s.apps.v1.deployments.patch or io.k8s.batch.v1.cronjobs.create or io.k8s.batch.v1.cronjobs.patch)
'''
[rule.new_terms]
field = "new_terms_fields"
value = ["user_agent.original", "source.ip", "client.user.email"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"
[[rule.threat.technique.subtechnique]]
id = "T1098.006"
name = "Additional Container Cluster Roles"
reference = "https://attack.mitre.org/techniques/T1098/006/"
[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"
[[rule.threat.technique.subtechnique]]
id = "T1098.006"
name = "Additional Container Cluster Roles"
reference = "https://attack.mitre.org/techniques/T1098/006/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[rule.investigation_fields]
field_names = [
"@timestamp",
"client.user.email",
"source.ip",
"user_agent.original",
"event.action",
"event.outcome",
"gcp.audit.resource_name",
"gcp.audit.request",
"data_stream.namespace",
]
Stages and Predicates
Stage 1: new_terms
data_stream.dataset:gcp.audit and service.name:k8s.io and event.outcome:success and user_agent.original:* and client.user.email:(* and not system\:*) and source.ip:* and event.action:(io.k8s.apps.v1.daemonsets.create or io.k8s.apps.v1.daemonsets.patch or io.k8s.apps.v1.deployments.create or io.k8s.apps.v1.deployments.patch or io.k8s.batch.v1.cronjobs.create or io.k8s.batch.v1.cronjobs.patch)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
client.user.email | is_not_null | field:"client.user.email" kind:is_not_null | |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"gcp.audit" |
event.action | in |
| field:"EventType" kind:in |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
service.name | eq |
| field:"ServiceName" kind:eq value:"k8s.io" |
source.ip | is_not_null | field:"src_ip" kind:is_not_null | |
user_agent.original | is_not_null | field:"aws::userAgent" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
client.user.email | starts_with | system: | excludes:client.user.email field:"client.user.email" value:"system:" |
High Number of Okta User Password Reset or Unlock Attempts
#Identifies a high number of Okta user password reset or account unlock attempts. An adversary may attempt to obtain unauthorized access to Okta user accounts using these methods and attempt to blend in with normal activity in their target's environment and evade detection.
Known False Positives
- The number of Okta user password reset or account unlock attempts will likely vary between organizations. To fit this rule to their organization, users can duplicate this rule and edit the schedule and threshold values in the new rule.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Persistence | |
| Stealth |
Telemetry Coverage
Rule Body
[metadata]
creation_date = "2020/08/19"
integration = ["okta"]
maturity = "production"
updated_date = "2026/04/10"
[rule]
author = ["Elastic", "@BenB196", "Austin Songer"]
description = """
Identifies a high number of Okta user password reset or account unlock attempts. An adversary may attempt to obtain
unauthorized access to Okta user accounts using these methods and attempt to blend in with normal activity in their
target's environment and evade detection.
"""
false_positives = [
"""
The number of Okta user password reset or account unlock attempts will likely vary between organizations. To fit
this rule to their organization, users can duplicate this rule and edit the schedule and threshold values in the new
rule.
""",
]
from = "now-60m"
index = ["filebeat-*", "logs-okta*"]
language = "kuery"
license = "Elastic License v2"
name = "High Number of Okta User Password Reset or Unlock Attempts"
note = """## Triage and analysis
### Investigating High Number of Okta User Password Reset or Unlock Attempts
This rule is designed to detect a suspiciously high number of password reset or account unlock attempts in Okta. Excessive password resets or account unlocks can be indicative of an attacker's attempt to gain unauthorized access to an account.
#### Possible investigation steps:
- Identify the actor associated with the excessive attempts. The `okta.actor.alternate_id` field can be used for this purpose.
- Determine the client used by the actor. You can look at `okta.client.device`, `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.ip_chain.ip`, and `okta.client.geographical_context`.
- Review the `okta.outcome.result` and `okta.outcome.reason` fields to understand the outcome of the password reset or unlock attempts.
- Review the event actions associated with these attempts. Look at the `event.action` field and filter for actions related to password reset and account unlock attempts.
- Check for other similar patterns of behavior from the same actor or IP address. If there is a high number of failed login attempts before the password reset or unlock attempts, this may suggest a brute force attack.
- Also, look at the times when these attempts were made. If these were made during off-hours, it could further suggest an adversary's activity.
### False positive analysis:
- This alert might be a false positive if there are legitimate reasons for a high number of password reset or unlock attempts. This could be due to the user forgetting their password or account lockouts due to too many incorrect attempts.
- Check the actor's past behavior. If this is their usual behavior and they have a valid reason for it, then it might be a false positive.
### Response and remediation:
- If unauthorized attempts are confirmed, initiate the incident response process.
- Reset the user's password and enforce MFA re-enrollment, if applicable.
- Block the IP address or device used in the attempts, if they appear suspicious.
- If the attack was facilitated by a particular technique, ensure your systems are patched or configured to prevent such techniques.
- Consider a security review of your Okta policies and rules to ensure they follow security best practices.
## Setup
The Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.
"""
references = [
"https://developer.okta.com/docs/reference/api/system-log/",
"https://developer.okta.com/docs/reference/api/event-types/",
"https://www.elastic.co/security-labs/testing-okta-visibility-and-detection-dorothy",
"https://www.elastic.co/security-labs/monitoring-okta-threats-with-elastic-security",
"https://www.elastic.co/security-labs/starter-guide-to-understanding-okta",
]
risk_score = 47
rule_id = "e90ee3af-45fc-432e-a850-4a58cf14a457"
severity = "medium"
tags = [
"Use Case: Identity and Access Audit",
"Data Source: Okta",
"Tactic: Defense Evasion",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "threshold"
query = '''
data_stream.dataset:okta.system and
event.action:(system.email.account_unlock.sent_message or system.email.password_reset.sent_message or
system.sms.send_account_unlock_message or system.sms.send_password_reset_message or
system.voice.send_account_unlock_call or system.voice.send_password_reset_call or
user.account.unlock_token)
'''
[[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.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[[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.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[[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.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[rule.threshold]
field = ["okta.actor.alternate_id"]
value = 5
Stages and Predicates
Stage 1: query
data_stream.dataset:okta.system and
event.action:(system.email.account_unlock.sent_message or system.email.password_reset.sent_message or
system.sms.send_account_unlock_message or system.sms.send_password_reset_message or
system.voice.send_account_unlock_call or system.voice.send_password_reset_call or
user.account.unlock_token)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"okta.system" |
event.action | in |
| field:"EventType" kind:in |
Kubernetes User Exec into Pod
#This rule detects a user attempt to establish a shell session into a pod using the 'exec' command. Using the 'exec' command in a pod allows a user to establish a temporary shell session and execute any process/commands in the pod. An adversary may call bash to gain a persistent interactive shell which will allow access to any data the pod has permissions to, including secrets.
Known False Positives
- An administrator may need to exec into a pod for a legitimate reason like debugging purposes. Containers built from Linux and Windows OS images, tend to include debugging utilities. In this case, an admin may choose to run commands inside a specific container with kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}. For example, the following command can be used to look at logs from a running Cassandra pod: kubectl exec cassandra --cat /var/log/cassandra/system.log . Additionally, the -i and -t arguments might be used to run a shell connected to the terminal: kubectl exec -i -t cassandra -- sh
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Kubernetes | get-pods-exec: get pods/exec |
| Kubernetes | create-pods-exec: create pods/exec |
Rules Detecting the Same Action
These rules filter on the same operation.
- Azure AKS Attempted User Exec into Pod (Elastic)
- Container With A hostPath Mount Created (Sigma)
- Creation Of Pod In System Namespace (Sigma)
- Direct Interactive Kubernetes API Request by Unusual Utilities (Elastic)
- Exec into Pod (Panther)
- GCP Break-glass Container Workload Deployed (Sigma)
- GCP K8s Pod Attached To Node Host Network (Panther)
- GCP K8S Pod Create Or Modify Host Path Volume Mount (Panther)
Rule Body
[metadata]
creation_date = "2022/05/17"
integration = ["kubernetes"]
maturity = "production"
updated_date = "2026/04/10"
[rule]
author = ["Elastic"]
description = """
This rule detects a user attempt to establish a shell session into a pod using the 'exec' command. Using the 'exec'
command in a pod allows a user to establish a temporary shell session and execute any process/commands in the pod. An
adversary may call bash to gain a persistent interactive shell which will allow access to any data the pod has
permissions to, including secrets.
"""
false_positives = [
"""
An administrator may need to exec into a pod for a legitimate reason like debugging purposes. Containers built from
Linux and Windows OS images, tend to include debugging utilities. In this case, an admin may choose to run commands
inside a specific container with kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ...
${ARGN}. For example, the following command can be used to look at logs from a running Cassandra pod: kubectl exec
cassandra --cat /var/log/cassandra/system.log . Additionally, the -i and -t arguments might be used to run a shell
connected to the terminal: kubectl exec -i -t cassandra -- sh
""",
]
index = ["logs-kubernetes.audit_logs-*"]
language = "eql"
license = "Elastic License v2"
name = "Kubernetes User Exec into Pod"
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 Kubernetes User Exec into Pod
Kubernetes allows users to execute commands within a pod using the 'exec' command, facilitating temporary shell sessions for legitimate management tasks. However, adversaries can exploit this to gain unauthorized access, potentially exposing sensitive data. The detection rule identifies such misuse by monitoring audit logs for specific patterns, such as allowed 'exec' actions on pods, indicating possible malicious activity.
### Possible investigation steps
- Review the Kubernetes audit logs to identify the user who executed the 'exec' command by examining the event.dataset field for "kubernetes.audit_logs".
- Check the kubernetes.audit.annotations.authorization_k8s_io/decision field to confirm that the action was allowed and determine if the user had legitimate access.
- Investigate the kubernetes.audit.objectRef.resource and kubernetes.audit.objectRef.subresource fields to verify that the action involved a pod and the 'exec' subresource.
- Analyze the context of the pod involved, including its purpose and the data it has access to, to assess the potential impact of the unauthorized access.
- Correlate the event with other logs or alerts to identify any suspicious patterns or repeated unauthorized access attempts by the same user or IP address.
- Review the user's activity history to determine if there are other instances of unusual or unauthorized access attempts within the Kubernetes environment.
### False positive analysis
- Routine administrative tasks by DevOps teams can trigger the rule when they use 'exec' for legitimate management purposes. To handle this, create exceptions for specific user accounts or roles that are known to perform these tasks regularly.
- Automated scripts or tools that use 'exec' for monitoring or maintenance can also cause false positives. Identify these scripts and whitelist their associated service accounts or IP addresses.
- Scheduled jobs or cron tasks that require 'exec' to perform updates or checks within pods may be flagged. Exclude these by setting up time-based exceptions for known maintenance windows.
- Development environments where frequent testing and debugging occur using 'exec' can lead to alerts. Implement environment-specific exclusions to reduce noise from non-production clusters.
### Response and remediation
- Immediately isolate the affected pod to prevent further unauthorized access or data exposure. This can be done by applying network policies or temporarily scaling down the pod.
- Review the audit logs to identify the user or service account responsible for the 'exec' command and assess whether the access was legitimate or unauthorized.
- Revoke or adjust permissions for the identified user or service account to prevent further unauthorized 'exec' actions. Ensure that only necessary permissions are granted following the principle of least privilege.
- Conduct a thorough investigation of the pod's environment to identify any potential data exposure or tampering. Check for unauthorized changes to configurations, secrets, or data within the pod.
- If unauthorized access is confirmed, rotate any exposed secrets or credentials that the pod had access to, and update any affected systems or services.
- Escalate the incident to the security operations team for further analysis and to determine if additional systems or pods have been compromised.
- Enhance monitoring and alerting for similar 'exec' actions in the future by ensuring that audit logs are continuously reviewed and that alerts are configured to notify the security team of any suspicious activity.
## Setup
The Kubernetes Fleet integration with Audit Logs enabled or similarly structured data is required to be compatible with this rule."""
references = [
"https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/",
"https://kubernetes.io/docs/tasks/debug/debug-application/get-shell-running-container/",
]
risk_score = 47
rule_id = "14de811c-d60f-11ec-9fd7-f661ea17fbce"
severity = "medium"
tags = [
"Data Source: Kubernetes",
"Domain: Kubernetes",
"Use Case: Threat Detection",
"Tactic: Execution",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
any where data_stream.dataset == "kubernetes.audit_logs" and kubernetes.audit.verb in ("get", "create") and
kubernetes.audit.objectRef.subresource == "exec" and kubernetes.audit.stage in ("ResponseComplete", "ResponseStarted") and
kubernetes.audit.level == "Request" and `kubernetes.audit.annotations.authorization_k8s_io/decision` == "allow" and
not (
(kubernetes.audit.objectRef.namespace == "trident" and kubernetes.audit.objectRef.name like "trident-controller-*") or
(kubernetes.audit.objectRef.namespace == "vuls" and kubernetes.audit.requestURI like "/api/v1/namespaces/vuls/pods/vuls-*/exec?command=sh&command=-c&command=*+%2Fvuls%2Fresults*") or
(kubernetes.audit.objectRef.namespace == "git-runners" and kubernetes.audit.requestURI like (
"/api/v1/namespaces/git-runners/pods/runner-*/exec?command=sh&command=-c&command=if+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbusybox%2Fsh+%5D%3B+then%0A%09exec+%2Fbusybox%2Fsh+%0Aelse%0A%09echo+shell+not+found%0A%09exit+1%0Afi%0A%0A&container=*&container=*&stderr=true&stdin=true&stdout=true",
"/api/v1/namespaces/git-runners/pods/runner-*/exec?command=gitlab-runner-helper&command=read-logs&command=--path&command=%2Flogs-*%2Foutput.log&command=--offset&command=0&command=--wait-file-timeout&command=1m0s&container=*&container=*&stderr=true&stdout=true"
)) or
(kubernetes.audit.objectRef.namespace == "elasticsearch-cluster" and kubernetes.audit.requestURI like (
"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stdin=true&stdout=true&tty=true",
"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stderr=true&stdout=true",
"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=kibana&stderr=true&stdout=true"
)) or
(kubernetes.audit.objectRef.namespace == "kube-system" and kubernetes.audit.requestURI like (
"/api/v1/namespaces/kube-system/pods/*/exec?command=%2Fproxy-agent&command=--help&container=konnectivity-agent&stderr=true&stdout=true",
"api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=endpoint&command=list&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true",
"/api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=status&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true",
"/api/v1/namespaces/kube-system/pods/*/exec?command=sh&command=-c&command=clear%3B+%28bash+%7C%7C+ash+%7C%7C+sh%29&container=*&stdin=true&stdout=true&tty=true"
))
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1609"
name = "Container Administration Command"
reference = "https://attack.mitre.org/techniques/T1609/"
[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
Stages and Predicates
Stage 1: any
any where data_stream.dataset == "kubernetes.audit_logs" and kubernetes.audit.verb in ("get", "create") and
kubernetes.audit.objectRef.subresource == "exec" and kubernetes.audit.stage in ("ResponseComplete", "ResponseStarted") and
kubernetes.audit.level == "Request" and `kubernetes.audit.annotations.authorization_k8s_io/decision` == "allow" and
not (
(kubernetes.audit.objectRef.namespace == "trident" and kubernetes.audit.objectRef.name like "trident-controller-*") or
(kubernetes.audit.objectRef.namespace == "vuls" and kubernetes.audit.requestURI like "/api/v1/namespaces/vuls/pods/vuls-*/exec?command=sh&command=-c&command=*+%2Fvuls%2Fresults*") or
(kubernetes.audit.objectRef.namespace == "git-runners" and kubernetes.audit.requestURI like (
"/api/v1/namespaces/git-runners/pods/runner-*/exec?command=sh&command=-c&command=if+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbusybox%2Fsh+%5D%3B+then%0A%09exec+%2Fbusybox%2Fsh+%0Aelse%0A%09echo+shell+not+found%0A%09exit+1%0Afi%0A%0A&container=*&container=*&stderr=true&stdin=true&stdout=true",
"/api/v1/namespaces/git-runners/pods/runner-*/exec?command=gitlab-runner-helper&command=read-logs&command=--path&command=%2Flogs-*%2Foutput.log&command=--offset&command=0&command=--wait-file-timeout&command=1m0s&container=*&container=*&stderr=true&stdout=true"
)) or
(kubernetes.audit.objectRef.namespace == "elasticsearch-cluster" and kubernetes.audit.requestURI like (
"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stdin=true&stdout=true&tty=true",
"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stderr=true&stdout=true",
"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=kibana&stderr=true&stdout=true"
)) or
(kubernetes.audit.objectRef.namespace == "kube-system" and kubernetes.audit.requestURI like (
"/api/v1/namespaces/kube-system/pods/*/exec?command=%2Fproxy-agent&command=--help&container=konnectivity-agent&stderr=true&stdout=true",
"api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=endpoint&command=list&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true",
"/api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=status&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true",
"/api/v1/namespaces/kube-system/pods/*/exec?command=sh&command=-c&command=clear%3B+%28bash+%7C%7C+ash+%7C%7C+sh%29&container=*&stdin=true&stdout=true&tty=true"
))
)
Indicators
These rows show field, operator, and value matches.
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
kubernetes.audit.objectRef.name | starts_with | trident-controller- | excludes:kubernetes.audit.objectRef.name field:"kubernetes.audit.objectRef.name" value:"trident-controller-" |
kubernetes.audit.objectRef.namespace | eq | trident | excludes:kubernetes.audit.objectRef.namespace field:"kubernetes.audit.objectRef.namespace" value:"trident" |
kubernetes.audit.objectRef.namespace | eq | elasticsearch-cluster | excludes:kubernetes.audit.objectRef.namespace field:"kubernetes.audit.objectRef.namespace" value:"elasticsearch-cluster" |
kubernetes.audit.requestURI | wildcard | /api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stdin=true&stdout=true&tty=true, /api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stderr=true&stdout=true, /api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=kibana&stderr=true&stdout=true | excludes:kubernetes.audit.requestURI field:"kubernetes.audit.requestURI" value:"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stdin=true&stdout=true&tty=true" field:"kubernetes.audit.requestURI" value:"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stderr=true&stdout=true" field:"kubernetes.audit.requestURI" value:"/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=kibana&stderr=true&stdout=true" |
kubernetes.audit.objectRef.namespace | eq | git-runners | excludes:kubernetes.audit.objectRef.namespace field:"kubernetes.audit.objectRef.namespace" value:"git-runners" |
kubernetes.audit.requestURI | wildcard | /api/v1/namespaces/git-runners/pods/runner-*/exec?command=sh&command=-c&command=if+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbusybox%2Fsh+%5D%3B+then%0A%09exec+%2Fbusybox%2Fsh+%0Aelse%0A%09echo+shell+not+found%0A%09exit+1%0Afi%0A%0A&container=*&container=*&stderr=true&stdin=true&stdout=true, /api/v1/namespaces/git-runners/pods/runner-*/exec?command=gitlab-runner-helper&command=read-logs&command=--path&command=%2Flogs-*%2Foutput.log&command=--offset&command=0&command=--wait-file-timeout&command=1m0s&container=*&container=*&stderr=true&stdout=true | excludes:kubernetes.audit.requestURI field:"kubernetes.audit.requestURI" value:"/api/v1/namespaces/git-runners/pods/runner-*/exec?command=sh&command=-c&command=if+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbusybox%2Fsh+%5D%3B+then%0A%09exec+%2Fbusybox%2Fsh+%0Aelse%0A%09echo+shell+not+found%0A%09exit+1%0Afi%0A%0A&container=*&container=*&stderr=true&stdin=true&stdout=true" field:"kubernetes.audit.requestURI" value:"/api/v1/namespaces/git-runners/pods/runner-*/exec?command=gitlab-runner-helper&command=read-logs&command=--path&command=%2Flogs-*%2Foutput.log&command=--offset&command=0&command=--wait-file-timeout&command=1m0s&container=*&container=*&stderr=true&stdout=true" |
kubernetes.audit.objectRef.namespace | eq | kube-system | excludes:kubernetes.audit.objectRef.namespace field:"kubernetes.audit.objectRef.namespace" value:"kube-system" |
kubernetes.audit.requestURI | wildcard | /api/v1/namespaces/kube-system/pods/*/exec?command=%2Fproxy-agent&command=--help&container=konnectivity-agent&stderr=true&stdout=true, api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=endpoint&command=list&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true, /api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=status&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true, /api/v1/namespaces/kube-system/pods/*/exec?command=sh&command=-c&command=clear%3B+%28bash+%7C%7C+ash+%7C%7C+sh%29&container=*&stdin=true&stdout=true&tty=true | excludes:kubernetes.audit.requestURI |
kubernetes.audit.objectRef.namespace | eq | vuls | excludes:kubernetes.audit.objectRef.namespace field:"kubernetes.audit.objectRef.namespace" value:"vuls" |
kubernetes.audit.requestURI | wildcard | /api/v1/namespaces/vuls/pods/vuls-*/exec?command=sh&command=-c&command=*+%2Fvuls%2Fresults* | excludes:kubernetes.audit.requestURI field:"kubernetes.audit.requestURI" value:"/api/v1/namespaces/vuls/pods/vuls-*/exec?command=sh&command=-c&command=*+%2Fvuls%2Fresults*" |
Manual Memory Password Searching Activity
#This rule detects the use of the 'strings' command to search for passwords in memory. Attackers may leverage this technique to extract sensitive information from memory. This behavior should not happen by default, and should be investigated thoroughly.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Rule Body
[rule]
description = """
This rule detects the use of the 'strings' command to search for passwords in memory. Attackers may leverage this
technique to extract sensitive information from memory. This behavior should not happen by default, and should be
investigated thoroughly.
"""
id = "e3d9bd45-315f-47a6-8675-475e2d3f29ff"
license = "Elastic License v2"
name = "Manual Memory Password Searching Activity"
os_list = ["linux"]
reference = ["https://github.com/controlplaneio/truffleproc", "https://github.com/hajzer/bash-memory-dump"]
version = "1.0.3"
query = '''
process where event.type == "start" and event.action == "exec" and process.name == "strings" and process.args == "/dev/mem"
'''
min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1003"
name = "OS Credential Dumping"
reference = "https://attack.mitre.org/techniques/T1003/"
[[threat.technique.subtechnique]]
id = "T1003.007"
name = "Proc Filesystem"
reference = "https://attack.mitre.org/techniques/T1003/007/"
[threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Stage 1: process
process where event.type == "start" and event.action == "exec" and process.name == "strings" and process.args == "/dev/mem"
Indicators
These rows show field, operator, and value matches.
Multiple Alerts on a Host Exhibiting CPU Spike
#This rule correlates multiple security alerts from a host exhibiting unusually high CPU utilization 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/02/26"
[rule]
author = ["Elastic"]
description = """
This rule correlates multiple security alerts from a host exhibiting unusually high CPU utilization 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 = "Multiple Alerts on a Host 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 = 99
rule_id = "b7f77c3c-1bcb-4afc-9ace-49357007947b"
severity = "critical"
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
// hosts with more than 90% total CPU use
cpu_metrics_host_ids = CASE(_index like ".ds-metrics-system.cpu-*" and system.cpu.total.norm.pct >= 0.9, host.id, null),
// hosts with high severity security alerts
alerts_host_ids = CASE(_index like ".internal.alerts-security.*" and kibana.alert.rule.name is not null and host.id is not null and kibana.alert.risk_score >= 73, host.id, null)
| stats host_with_cpu_spike = COUNT_DISTINCT(cpu_metrics_host_ids),
host_with_alerts = COUNT_DISTINCT(alerts_host_ids),
Esql.max_cpu_pct = MAX(system.cpu.total.norm.pct),
Esql.unique_alerts_count = COUNT_DISTINCT(kibana.alert.rule.name),
Esql.unique_process_count = COUNT_DISTINCT(process.entity_id),
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 host.id
// at least 3 unique high severity alerts and from a host with 90% CPU use
| where host_with_cpu_spike > 0 and host_with_alerts > 0 and Esql.unique_alerts_count >= 3
| 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),
host.name = MV_FIRST(host_name),
user.name = MV_FIRST(user_name)
| KEEP user.name, host.name, host.id, process.*, Esql.*
'''
note = """## Triage and analysis
### Investigating Multiple Alerts on a Host Exhibiting CPU Spike
This rule identifies hosts that both triggered multiple security alerts and exhibited unusually high CPU utilization on the
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 host was flagged by the detection alerts.
- Examine the involved process name, command line, and SHA-256 hash to determine whether those processes are 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_host_ids = CASE(_index like ".ds-metrics-system.cpu-*" and system.cpu.total.norm.pct >= 0.9, host.id, null),
alerts_host_ids = CASE(_index like ".internal.alerts-security.*" and kibana.alert.rule.name is not null and host.id is not null and kibana.alert.risk_score >= 73, host.id, null)
alerts_host_ids =_index like ".internal.alerts-security.*" and kibana.alert.rule.name is not null and host.id is not null and kibana.alert.risk_score >= 73host.idnullcpu_metrics_host_ids =_index like ".ds-metrics-system.cpu-*" and system.cpu.total.norm.pct >= 0.9host.idnullStage 4: stats
| stats host_with_cpu_spike = COUNT_DISTINCT(cpu_metrics_host_ids),
host_with_alerts = COUNT_DISTINCT(alerts_host_ids),
Esql.max_cpu_pct = MAX(system.cpu.total.norm.pct),
Esql.unique_alerts_count = COUNT_DISTINCT(kibana.alert.rule.name),
Esql.unique_process_count = COUNT_DISTINCT(process.entity_id),
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 host.id
Stage 5: where
| where host_with_cpu_spike > 0 and host_with_alerts > 0 and Esql.unique_alerts_count >= 3
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),
host.name = MV_FIRST(host_name),
user.name = MV_FIRST(user_name)
Stage 7: keep
| KEEP user.name, host.name, host.id, process.*, Esql.*
Indicators
These rows show field, operator, and value matches.
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.name | KEEP host.name |
host.id | KEEP host.id |
process.* | KEEP process.* |
Esql.* | KEEP Esql.* |
Multiple Elastic Defend Alerts from a Single Process Tree
#Detects multiple Elastic Defend EDR alerts originating from the same process tree, indicating coordinated malicious activity. Analysts can use this to prioritize triage and response, as these hosts are more likely to be compromised.
Rule Body
[metadata]
creation_date = "2025/12/31"
maturity = "production"
updated_date = "2025/12/31"
[rule]
author = ["Elastic"]
description = """
Detects multiple Elastic Defend EDR alerts originating from the same process tree, indicating coordinated malicious activity.
Analysts can use this to prioritize triage and response, as these hosts are more likely to be compromised.
"""
from = "now-9m"
interval = "8m"
language = "esql"
license = "Elastic License v2"
name = "Multiple Elastic Defend Alerts from a Single Process Tree"
references = [
"https://github.com/elastic/protections-artifacts/tree/main/yara/rules",
"https://github.com/elastic/protections-artifacts/tree/main/behavior"
]
risk_score = 73
rule_id = "25a4207c-5c05-4680-904c-6e3411b275fa"
severity = "high"
tags = ["Use Case: Threat Detection", "Rule Type: Higher-Order Rule", "Resources: Investigation Guide", "Data Source: Elastic Defend"]
timestamp_override = "event.ingested"
type = "esql"
query = '''
from logs-endpoint.alerts-*
// process.Ext.ancestry is an array of all unique process IDs ancestors of the alert actor process ID
| where event.code in ("malicious_file", "memory_signature", "shellcode_thread", "behavior") and
agent.id is not null and not rule.name in ("Multi.EICAR.Not-a-virus") and process.Ext.ancestry is not null
// aggregate alerts by process.Ext.ancestry and agent.id
| stats Esql.alerts_count = COUNT(*),
Esql.rule_name_distinct_count = COUNT_DISTINCT(rule.name),
Esql.event_code_distinct_count = COUNT_DISTINCT(event.code),
Esql.process_id_distinct_count = COUNT_DISTINCT(process.entity_id),
Esql.message_values = VALUES(message),
Esql.user_name_values = VALUES(user.name),
Esql.threat_tactic_name_values = VALUES(threat.tactic.name),
Esql.threat_technique_name_values = VALUES(threat.technique.name),
Esql.process_command_line_values = VALUES(process.command_line),
Esql.process_parent_executable_values = values(process.parent.executable),
Esql.file_path_values = VALUES(file.path),
Esql.file_hash_sha256_values = VALUES(file.hash.sha256),
Esql.process_hash_sha256_values = VALUES(process.hash.sha256),
Esql.dns_question_name_values = VALUES(dns.question.name) by process.Ext.ancestry, agent.id
// filter for at least 3 unique process IDs and 2 or more alert types or rule names.
| where Esql.process_id_distinct_count >= 3 and (Esql.rule_name_distinct_count >= 2 or Esql.event_code_distinct_count >= 2)
// keep unique values
| stats Esql.alert_names = values(Esql.message_values),
Esql.alerts_process_cmdline_values = VALUES(Esql.process_command_line_values),
Esql.alerts_user_names = VALUES(Esql.user_name_values),
Esql.alerts_mitre_tactics = values(Esql.threat_tactic_name_values),
Esql.alerts_mitre_techniques = VALUES(Esql.threat_technique_name_values),
Esql.alerts_process_parent_executable = values(Esql.process_parent_executable_values),
Esql.alerts_file_paths = VALUES(Esql.file_path_values),
Esql.alerts_file_hash_sha256 = VALUES(Esql.file_hash_sha256_values),
Esql.alerts_process_hash_sha256 = VALUES(Esql.process_hash_sha256_values),
Esql.alerts_dns_question_names = VALUES(Esql.dns_question_name_values) by agent.id
| keep Esql.*, agent.id
'''
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 Multiple Elastic Defend Alerts from a Single Process Tree
Detects multiple Elastic Defend EDR alerts originating from the same process tree, indicating coordinated malicious activity.
### Possible investigation steps
- Review the alert details to identify the specific host involved and the different alerts that triggered.
- Examine the timeline of the alerts to understand the sequence of events and determine the root cause.
- Correlate the alert data with other logs and telemetry from the host, such as process creation, network connections, and file modifications, to gather additional context.
- Check for any indicators of compromise (IOCs) associated with the alerts, such as suspicious IP addresses, domains, or file hashes, and search for these across the network.
- Assess the impact and scope of the potential compromise by determining if other hosts or systems have similar alerts or related activity.
### False positive analysis
- Security tools running on the host might generate multiple alerts from same process tree.
- Automated scripts or batch processes can mimic adversarial behavior. Analyze and whitelist these processes if they are verified as non-threatening.
- Frequent alerts from development or testing environments can be misleading. Consider excluding these environments from the rule or applying a different risk score.
### Response and remediation
- Isolate the affected host from the network immediately to prevent further lateral movement by the adversary.
- Conduct a thorough forensic analysis of the host to identify the specific vulnerabilities exploited and gather evidence of the attack phases involved.
- Remove any identified malicious software or unauthorized access tools from the host, ensuring all persistence mechanisms are eradicated.
- Apply security patches and updates to the host to address any exploited vulnerabilities and prevent similar attacks.
- Restore the host from a known good backup if necessary, ensuring that the backup is free from compromise.
- Monitor the host and network for any signs of re-infection or further suspicious activity, using enhanced logging and alerting based on the identified attack patterns.
- Escalate the incident to the appropriate internal or external cybersecurity teams for further investigation and potential legal action if the attack is part of a larger campaign."""
Stages and Predicates
Stage 1: from
from logs-endpoint.alerts-*
Stage 2: where
| where event.code in ("malicious_file", "memory_signature", "shellcode_thread", "behavior") and
agent.id is not null and not rule.name in ("Multi.EICAR.Not-a-virus") and process.Ext.ancestry is not null
Stage 3: stats
| stats Esql.alerts_count = COUNT(*),
Esql.rule_name_distinct_count = COUNT_DISTINCT(rule.name),
Esql.event_code_distinct_count = COUNT_DISTINCT(event.code),
Esql.process_id_distinct_count = COUNT_DISTINCT(process.entity_id),
Esql.message_values = VALUES(message),
Esql.user_name_values = VALUES(user.name),
Esql.threat_tactic_name_values = VALUES(threat.tactic.name),
Esql.threat_technique_name_values = VALUES(threat.technique.name),
Esql.process_command_line_values = VALUES(process.command_line),
Esql.process_parent_executable_values = values(process.parent.executable),
Esql.file_path_values = VALUES(file.path),
Esql.file_hash_sha256_values = VALUES(file.hash.sha256),
Esql.process_hash_sha256_values = VALUES(process.hash.sha256),
Esql.dns_question_name_values = VALUES(dns.question.name) by process.Ext.ancestry, agent.id
Stage 4: where
| where Esql.process_id_distinct_count >= 3 and (Esql.rule_name_distinct_count >= 2 or Esql.event_code_distinct_count >= 2)
Stage 5: stats
| stats Esql.alert_names = values(Esql.message_values),
Esql.alerts_process_cmdline_values = VALUES(Esql.process_command_line_values),
Esql.alerts_user_names = VALUES(Esql.user_name_values),
Esql.alerts_mitre_tactics = values(Esql.threat_tactic_name_values),
Esql.alerts_mitre_techniques = VALUES(Esql.threat_technique_name_values),
Esql.alerts_process_parent_executable = values(Esql.process_parent_executable_values),
Esql.alerts_file_paths = VALUES(Esql.file_path_values),
Esql.alerts_file_hash_sha256 = VALUES(Esql.file_hash_sha256_values),
Esql.alerts_process_hash_sha256 = VALUES(Esql.process_hash_sha256_values),
Esql.alerts_dns_question_names = VALUES(Esql.dns_question_name_values) by agent.id
Stage 6: keep
| keep Esql.*, agent.id
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Esql.event_code_distinct_count | ge |
| field:"Esql.event_code_distinct_count" kind:ge value:"2" |
Esql.process_id_distinct_count | ge |
| field:"Esql.process_id_distinct_count" kind:ge value:"3" |
Esql.rule_name_distinct_count | ge |
| field:"Esql.rule_name_distinct_count" kind:ge value:"2" |
agent.id | is_not_null | field:"agent.id" kind:is_not_null | |
event.code | in |
| field:"EventID" kind:in |
process.Ext.ancestry | is_not_null | field:"process.Ext.ancestry" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
rule.name | eq | Multi.EICAR.Not-a-virus | excludes:rule.name field:"rule.name" value:"Multi.EICAR.Not-a-virus" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Esql.* | KEEP Esql.* |
agent.id | KEEP agent.id |
Netcat Reverse Shell via Busybox
#This rule detects the creation of a reverse shell through netcat using Busybox. Attackers may spawn reverse shells to establish persistence onto a target system. By proxying the execution through Busybox, attackers may attempt to evade detection.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Stealth | |
| Command & Control |
Rule Body
[rule]
description = """
This rule detects the creation of a reverse shell through netcat using Busybox. Attackers may spawn reverse shells to
establish persistence onto a target system. By proxying the execution through Busybox, attackers may attempt to evade
detection.
"""
id = "332a8018-6615-4d2d-aeff-61e85e5ae77b"
license = "Elastic License v2"
name = "Netcat Reverse Shell via Busybox"
os_list = ["linux"]
version = "1.0.9"
query = '''
sequence by process.entity_id with maxspan=5s
[process where event.type == "start" and event.action == "exec" and process.name == "busybox" and
process.command_line like ("* nc *", "* netcat *", "* ncat *") and not process.command_line like "*-*z*"]
[network where event.type == "start" and event.action == "connection_attempted" and process.name == "busybox" and
not (destination.ip == null or destination.ip == "0.0.0.0" or 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.168.0.0/16", "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"
)
)
]
'''
min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
tree = true
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
tree = true
[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0
tree = true
[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 1
tree = true
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1071"
name = "Application Layer Protocol"
reference = "https://attack.mitre.org/techniques/T1071/"
[threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 5s, correlated by process.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and process.name == "busybox" and
process.command_line like ("* nc *", "* netcat *", "* ncat *") and not process.command_line like "*-*z*"]
Stage 2: network
[network where event.type == "start" and event.action == "connection_attempted" and process.name == "busybox" and
not (destination.ip == null or destination.ip == "0.0.0.0" or 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.168.0.0/16", "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"
)
)
]
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.command_line | wildcard |
| field:"CommandLine" kind:wildcard |
process.name | eq |
| field:"process_basename" kind:eq value:"busybox" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.command_line | wildcard | *-*z* | excludes:process.command_line field:"process.command_line" value:"*-*z*" |
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.168.0.0/16, 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 |
destination.ip | eq | 0.0.0.0 | excludes:destination.ip field:"destination.ip" value:"0.0.0.0" |
destination.ip | is_null | excludes:destination.ip |
Potential Privilege Escalation via Rogue WinRM
#Identifies a privilege escalation attempt via impersonation using RogueWinRM. RogueWinRM is a local privilege escalation exploit that allows to escalate from a Service account (with SeImpersonatePrivilege) to Local System account if the WinRM service is not running.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Rule Body
[rule]
description = """
Identifies a privilege escalation attempt via impersonation using RogueWinRM. RogueWinRM is a local privilege escalation
exploit that allows to escalate from a Service account (with SeImpersonatePrivilege) to Local System account if the
WinRM service is not running.
"""
id = "33962262-436f-43d7-86e9-06dbddfffb5d"
license = "Elastic License v2"
name = "Potential Privilege Escalation via Rogue WinRM"
os_list = ["windows"]
reference = [
"https://decoder.cloud/2019/12/06/we-thought-they-were-potatoes-but-they-were-beans/",
"https://github.com/antonioCoco/RogueWinRM",
]
version = "1.0.31"
query = '''
sequence with maxspan=1m
[network where process.pid != 4 and event.action == "disconnect_received" and
/* localhost connection via WinRM default listening port */
destination.port == 5985 and source.port >= 49152 and
destination.address : ("127.*", "::1") and source.address : ("127.*", "::1") and
not process.executable : "?:\\Windows\\System32\\svchost.exe" and user.id != "S-1-5-18"] by process.entity_id
[process where event.action == "start" and user.id == "S-1-5-18" and
/* started via seclogon service */
process.parent.Ext.real.pid > 0 and
not process.executable : "?:\\Windows\\System32\\WerFault.exe"] by process.parent.entity_id
'''
min_endpoint_version = "7.15.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
[[optional_actions]]
action = "rollback"
field = "process.entity_id"
state = 1
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1134"
name = "Access Token Manipulation"
reference = "https://attack.mitre.org/techniques/T1134/"
[[threat.technique.subtechnique]]
id = "T1134.001"
name = "Token Impersonation/Theft"
reference = "https://attack.mitre.org/techniques/T1134/001/"
[[threat.technique.subtechnique]]
id = "T1134.002"
name = "Create Process with Token"
reference = "https://attack.mitre.org/techniques/T1134/002/"
[threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 1m, correlated by process.entity_id, process.parent.entity_id.
Stage 1: network
[network where process.pid != 4 and event.action == "disconnect_received" and
destination.port == 5985 and source.port >= 49152 and
destination.address : ("127.*", "::1") and source.address : ("127.*", "::1") and
not process.executable : "?:\\Windows\\System32\\svchost.exe" and user.id != "S-1-5-18"] by process.entity_id
Stage 2: process
[process where event.action == "start" and user.id == "S-1-5-18" and
process.parent.Ext.real.pid > 0 and
not process.executable : "?:\\Windows\\System32\\WerFault.exe"] by process.parent.entity_id
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
destination.address | wildcard |
| field:"destination.address" kind:wildcard |
destination.port | eq |
| field:"DestinationPort" kind:eq value:"5985" |
event.action | eq |
| field:"EventType" kind:eq |
process.parent.Ext.real.pid | gt |
| field:"process.parent.Ext.real.pid" kind:gt value:"0" |
process.pid | ne |
| field:"process_id" kind:ne value:"4" |
source.address | wildcard |
| field:"aws::sourceIPAddress" kind:wildcard |
source.port | ge |
| field:"SourcePort" kind:ge value:"49152" |
user.id | eq |
| field:"user.id" kind:eq value:"S-1-5-18" |
user.id | ne |
| field:"user.id" kind:ne value:"S-1-5-18" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.executable | eq | ?:\Windows\System32\svchost.exe | excludes:process.executable field:"process.executable" value:"?:\Windows\System32\svchost.exe" |
process.executable | eq | ?:\Windows\System32\WerFault.exe | excludes:process.executable field:"process.executable" value:"?:\Windows\System32\WerFault.exe" |
Potential SIP Bypass via the ShoveService
#Identifies the use of the Shove service to modify a SIP protected resource. A malicious application may be able to modify protected parts of the file system by spawning the shov process with the -X|x options (used to communicate with the system XPC service and removed by Apple in recent versions).
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Telemetry Coverage
Rule Body
[rule]
description = """
Identifies the use of the Shove service to modify a SIP protected resource. A malicious application may be able to
modify protected parts of the file system by spawning the shov process with the -X|x options (used to communicate with
the system XPC service and removed by Apple in recent versions).
"""
id = "7dea8cfc-92db-4081-9a5d-85ead8cedd5f"
license = "Elastic License v2"
name = "Potential SIP Bypass via the ShoveService"
os_list = ["macos"]
reference = [
"https://jhftss.github.io/CVE-2022-26712-The-POC-For-SIP-Bypass-Is-Even-Tweetable/",
"https://support.apple.com/en-us/HT213256",
]
version = "1.0.23"
query = '''
process where event.action == "exec" and
(process.name == "shove" or process.code_signature.signing_id like "com.apple.shove") and process.args == "-x"
'''
min_endpoint_version = "8.1.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1068"
name = "Exploitation for Privilege Escalation"
reference = "https://attack.mitre.org/techniques/T1068/"
[threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
[internal]
min_endpoint_version = "8.1.0"
Stages and Predicates
Stage 1: process
process where event.action == "exec" and
(process.name == "shove" or process.code_signature.signing_id like "com.apple.shove") and process.args == "-x"
Indicators
These rows show field, operator, and value matches.
Security Account Manager (SAM) Registry Access
#Identifies attempts to read the Security Account Manager database through the registry, which adversaries can use to recover password hashes for local accounts.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Rule Body
[rule]
description = """
Identifies attempts to read the Security Account Manager database through the registry, which adversaries can use to
recover password hashes for local accounts.
"""
id = "b6e8c090-f0ec-4c4c-af00-55ac2a9f9b41"
license = "Elastic License v2"
name = "Security Account Manager (SAM) Registry Access"
os_list = ["windows"]
reference = [
"https://adsecurity.org/?page_id=1821",
"https://github.com/gentilkiwi/mimikatz/wiki/module-~-lsadump",
]
version = "1.0.41"
query = '''
sequence by process.entity_id
[process where event.action == "start" and
not process.executable : ("?:\\Program Files\\*.exe", "?:\\Program Files (x86)\\*.exe") and
not (process.name : "cscript.exe" and process.command_line : "*Tanium*collectAdInfo.vbs*" and
process.Ext.token.integrity_level_name == "system") and
not (process.executable : "?:\\Windows\\Provisioning\\Autopilot\\DiagonsticAnalysis.pif" and
process.args : "?:\\Windows\\Provisioning\\Microsoft-Desktop-Provisioning-Diagnostic.dat") and
not (process.parent.executable : "?:\\Program Files\\Rapid7\\Insight Agent\\components\\insight_agent\\*\\ir_agent.exe" and process.name : "reg.exe") and
not (process.executable : "?:\\Windows\\System32\\backgroundTaskHost.exe" and
process.parent.executable : "C:\\Windows\\System32\\svchost.exe" and process.parent.args : "DcomLaunch" and
process.args : "-ServerName:BackgroundTaskHost.WebAccountProvider") and
not process.hash.sha256 : "52f145a4ccc0f540a130bedbf04370a842daff1ee8d8361c75a8e0d21a88cf5a" and
not (process.executable : ("?:\\Windows\\SysWOW64\\msiexec.exe", "?:\\windows\\system32\\msiexec.exe") and
process.parent.executable : "?:\\windows\\sys*\\msiexec.exe" and process.args : "-Embedding" and process.parent.args : "/V") and
not (process.code_signature.trusted == true and
process.code_signature.subject_name : ("Trend Micro, Inc.", "Komodo Laboratories LLC", "Speckled Jay LLC", "Tenable Inc.", "HCL America Inc.",
"Kaspersky Lab*", "Check Point Software Technologies Ltd.", "AO Kaspersky Lab", "HCL America Inc.",
"Kaspersky Lab JSC", "SentinelOne Inc.", "Nicholas Anderson", "Urs Beckmann")) and
not process.hash.sha256 :
("8016595ed2344c5322ea8eac1ffd490994417b5c4c745668aa5731ba9129e9fd",
"f7e5566741042ce7a10cf2847279a0dd845ea813fdcb090cd4ee2359584c1496",
"c9283a6b825629e698915b5d948f669c325ea1eb5310a6ff03c640a77e5d6b46",
"c9a91e8404a48a24254be9e127e23a40804f9c01674044bf37148e1b68a16814",
"c80b04c122161c6b762d8c1dd3aa20391d870d43f53150aecd7a9265b3955e45") and
not (process.name == "powershell.exe" and process.parent.name == "cmd.exe" and
process.parent.args == "'HKLM:\\SECURITY\\SAM\\Domains\\Account\\'" and
process.parent.args == "System.Security.Principal.SecurityIdentifier($_.SID)).Translate([System.Security.Principal.NTAccount]).Value") and
not (process.name == "cscript.exe" and process.parent.executable : "C:\\Program Files\\ansible\\GTS\\jre\\bin\\java.exe")
]
[registry where event.action == "query" and
registry.path : "HKLM\\SAM\\SAM\\Domains\\Account\\*" and
/*
encrypted password LM/NT bytes are stored in V regval
under Account\Users key, to reduce noise we exclude following exact reg paths
*/
not registry.path : ("HKLM\\SAM\\SAM\\Domains\\Account\\Users",
"HKLM\\SAM\\SAM\\Domains\\Account\\Users\\Names",
"HKLM\\SAM\\SAM\\Domains\\Account",
"HKLM\\SAM\\SAM\\Domains\\Account\\Aliases\\*") and
/* LogonUI.exe legitimately reads SAM for user account display on the logon screen */
not (process.executable : "?:\\Windows\\System32\\LogonUI.exe" and
registry.value : ("UserDontShowInLogonUI", "JC_PREV_V"))
]
until [process where event.action == "end"]
'''
min_endpoint_version = "7.15.0"
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.technique.subtechnique]]
id = "T1003.002"
name = "Security Account Manager"
reference = "https://attack.mitre.org/techniques/T1003/002/"
[threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Ordered sequence: each step below must occur in order, correlated by process.entity_id.
Stage 1: process
[process where event.action == "start" and
not process.executable : ("?:\\Program Files\\*.exe", "?:\\Program Files (x86)\\*.exe") and
not (process.name : "cscript.exe" and process.command_line : "*Tanium*collectAdInfo.vbs*" and
process.Ext.token.integrity_level_name == "system") and
not (process.executable : "?:\\Windows\\Provisioning\\Autopilot\\DiagonsticAnalysis.pif" and
process.args : "?:\\Windows\\Provisioning\\Microsoft-Desktop-Provisioning-Diagnostic.dat") and
not (process.parent.executable : "?:\\Program Files\\Rapid7\\Insight Agent\\components\\insight_agent\\*\\ir_agent.exe" and process.name : "reg.exe") and
not (process.executable : "?:\\Windows\\System32\\backgroundTaskHost.exe" and
process.parent.executable : "C:\\Windows\\System32\\svchost.exe" and process.parent.args : "DcomLaunch" and
process.args : "-ServerName:BackgroundTaskHost.WebAccountProvider") and
not process.hash.sha256 : "52f145a4ccc0f540a130bedbf04370a842daff1ee8d8361c75a8e0d21a88cf5a" and
not (process.executable : ("?:\\Windows\\SysWOW64\\msiexec.exe", "?:\\windows\\system32\\msiexec.exe") and
process.parent.executable : "?:\\windows\\sys*\\msiexec.exe" and process.args : "-Embedding" and process.parent.args : "/V") and
not (process.code_signature.trusted == true and
process.code_signature.subject_name : ("Trend Micro, Inc.", "Komodo Laboratories LLC", "Speckled Jay LLC", "Tenable Inc.", "HCL America Inc.",
"Kaspersky Lab*", "Check Point Software Technologies Ltd.", "AO Kaspersky Lab", "HCL America Inc.",
"Kaspersky Lab JSC", "SentinelOne Inc.", "Nicholas Anderson", "Urs Beckmann")) and
not process.hash.sha256 :
("8016595ed2344c5322ea8eac1ffd490994417b5c4c745668aa5731ba9129e9fd",
"f7e5566741042ce7a10cf2847279a0dd845ea813fdcb090cd4ee2359584c1496",
"c9283a6b825629e698915b5d948f669c325ea1eb5310a6ff03c640a77e5d6b46",
"c9a91e8404a48a24254be9e127e23a40804f9c01674044bf37148e1b68a16814",
"c80b04c122161c6b762d8c1dd3aa20391d870d43f53150aecd7a9265b3955e45") and
not (process.name == "powershell.exe" and process.parent.name == "cmd.exe" and
process.parent.args == "'HKLM:\\SECURITY\\SAM\\Domains\\Account\\'" and
process.parent.args == "System.Security.Principal.SecurityIdentifier($_.SID)).Translate([System.Security.Principal.NTAccount]).Value") and
not (process.name == "cscript.exe" and process.parent.executable : "C:\\Program Files\\ansible\\GTS\\jre\\bin\\java.exe")
]
Stage 2: registry
[registry where event.action == "query" and
registry.path : "HKLM\\SAM\\SAM\\Domains\\Account\\*" and
/*
encrypted password LM/NT bytes are stored in V regval
under Account\Users key, to reduce noise we exclude following exact reg paths
*/
not registry.path : ("HKLM\\SAM\\SAM\\Domains\\Account\\Users",
"HKLM\\SAM\\SAM\\Domains\\Account\\Users\\Names",
"HKLM\\SAM\\SAM\\Domains\\Account",
"HKLM\\SAM\\SAM\\Domains\\Account\\Aliases\\*") and
not (process.executable : "?:\\Windows\\System32\\LogonUI.exe" and
registry.value : ("UserDontShowInLogonUI", "JC_PREV_V"))
]
Until: process
until [process where event.action == "end"]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq |
registry.path | wildcard |
| field:"TargetObject" kind:wildcard value:"HKLM\SAM\SAM\Domains\Account\*" |
Exclusions
The rule actively suppresses these predicates.
Suspicious Curl User Agent
#Detects curl commands using the "cur1" user agent string, associated with BlueNoroff/Lazarus Group campaigns. This deliberate misspelling is a reliable indicator of nation-state attacks targeting cryptocurrency sectors.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry Coverage
Rule Body
[rule]
description = """
Detects curl commands using the "cur1" user agent string, associated with BlueNoroff/Lazarus Group campaigns. This
deliberate misspelling is a reliable indicator of nation-state attacks targeting cryptocurrency sectors.
"""
id = "e26e47b7-ec35-4060-8b35-32d01fae159e"
license = "Elastic License v2"
name = "Suspicious Curl User Agent"
os_list = ["macos"]
reference = ["https://www.huntress.com/blog/inside-bluenoroff-web3-intrusion-analysis"]
version = "1.0.3"
query = '''
process where event.type == "start" and event.action == "exec" and process.name == "curl" and
(process.args like~ "cur1-*" or process.command_line : "*cur1-*")
'''
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 = "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
Stage 1: process
process where event.type == "start" and event.action == "exec" and process.name == "curl" and
(process.args like~ "cur1-*" or process.command_line : "*cur1-*")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard value:"cur1-*" |
process.command_line | wildcard |
| field:"CommandLine" kind:wildcard value:"*cur1-*" |
process.name | eq |
| field:"process_basename" kind:eq value:"curl" |
Suspicious DLL Loaded for Persistence or Privilege Escalation
#Identifies the loading of a non Microsoft signed DLL that is missing on a default Windows install (phantom DLL) or one that can be loaded from a different location by a native Windows process. This may be abused to persist or elevate privileges via privileged file write vulnerabilities.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[metadata]
creation_date = "2020/01/07"
integration = ["endpoint", "windows"]
maturity = "production"
updated_date = "2026/01/02"
[rule]
author = ["Elastic"]
description = """
Identifies the loading of a non Microsoft signed DLL that is missing on a default Windows install (phantom DLL) or one
that can be loaded from a different location by a native Windows process. This may be abused to persist or elevate
privileges via privileged file write vulnerabilities.
"""
from = "now-9m"
index = ["winlogbeat-*", "logs-endpoint.events.library-*", "logs-windows.sysmon_operational-*"]
language = "eql"
license = "Elastic License v2"
name = "Suspicious DLL Loaded for Persistence or Privilege Escalation"
note = """## Triage and analysis
### Investigating Suspicious DLL Loaded for Persistence or Privilege Escalation
Attackers can execute malicious code by abusing missing modules that processes try to load, enabling them to escalate privileges or gain persistence. This rule identifies the loading of a non-Microsoft-signed DLL that is missing on a default Windows installation or one that can be loaded from a different location by a native Windows process.
#### Possible investigation steps
- Examine the DLL signature and identify the process that created it.
- Investigate any abnormal behaviors by the process such as network connections, registry or file modifications, and any spawned child processes.
- Investigate other alerts associated with the user/host during the past 48 hours.
- Retrieve the DLL and determine if it is malicious:
- Use a private sandboxed malware analysis system to perform analysis.
- Observe and collect information about the following activities:
- Attempts to contact external domains and addresses.
- File and registry access, modification, and creation activities.
- Service creation and launch activities.
- Scheduled task creation.
- Use the PowerShell Get-FileHash cmdlet to get the files' SHA-256 hash values.
- Search for the existence and reputation of the hashes in resources like VirusTotal, Hybrid-Analysis, CISCO Talos, Any.run, etc.
### False positive analysis
- This activity is unlikely to happen legitimately. Any activity that triggered the alert and is not inherently malicious must be monitored by the security team.
### Response and remediation
- Initiate the incident response process based on the outcome of the triage.
- Isolate the involved host to prevent further post-compromise behavior.
- If the triage identified malware, search the environment for additional compromised hosts.
- Implement temporary network rules, procedures, and segmentation to contain the malware.
- Stop suspicious processes.
- Immediately block the identified indicators of compromise (IoCs).
- Inspect the affected systems for additional malware backdoors like reverse shells, reverse proxies, or droppers that attackers could use to reinfect the system.
- Remove and block malicious artifacts identified during triage.
- Run a full antimalware scan. This may reveal additional artifacts left in the system, persistence mechanisms, and malware components.
- 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.
- 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://itm4n.github.io/windows-dll-hijacking-clarified/",
"http://remoteawesomethoughts.blogspot.com/2019/05/windows-10-task-schedulerservice.html",
"https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html",
"https://shellz.club/2020/10/16/edgegdi-dll-for-persistence-and-lateral-movement.html",
"https://windows-internals.com/faxing-your-way-to-system/",
"http://waleedassar.blogspot.com/2013/01/wow64logdll.html",
]
risk_score = 73
rule_id = "bfeaf89b-a2a7-48a3-817f-e41829dc61ee"
setup = """## Setup
If enabling an EQL rule on a non-elastic-agent index (such as beats) for versions <8.2,
events will not define `event.ingested` and default fallback for EQL rules was not added until version 8.2.
Hence for this rule to work effectively, users will need to add a custom ingest pipeline to populate
`event.ingested` to @timestamp.
For more details on adding a custom ingest pipeline refer - https://www.elastic.co/guide/en/fleet/current/data-streams-pipeline-tutorial.html
"""
severity = "high"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Persistence",
"Tactic: Privilege Escalation",
"Tactic: Defense Evasion",
"Resources: Investigation Guide",
"Data Source: Elastic Defend",
"Data Source: Sysmon",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
any where host.os.type == "windows" and
(
/* Elastic Defend DLL load events */
(event.category == "library" and
(
?dll.name : ("wlbsctrl.dll", "wbemcomn.dll", "WptsExtensions.dll", "Tsmsisrv.dll", "TSVIPSrv.dll", "Msfte.dll", "wow64log.dll", "WindowsCoreDeviceInfo.dll", "Ualapi.dll", "wlanhlp.dll", "phoneinfo.dll", "EdgeGdi.dll", "cdpsgshims.dll", "windowsperformancerecordercontrol.dll", "diagtrack_win.dll", "TPPCOIPW32.dll", "tpgenlic.dll", "thinmon.dll", "fxsst.dll", "msTracer.dll") or
(?dll.path : "?:\\Windows\\*\\oci.dll" and process.executable : "?:\\Windows\\*.exe")
)
and (?dll.code_signature.trusted == false or ?dll.code_signature.exists == false or (?dll.code_signature.trusted == true and not ?dll.code_signature.subject_name : ("Microsoft Windows", "Microsoft Corporation", "Microsoft Windows Publisher"))
))
or
/* Sysmon DLL load events */
((event.category == "process" and event.action like "Image loaded*") and file.code_signature.status != "Valid" and
file.name : ("wlbsctrl.dll", "wbemcomn.dll", "WptsExtensions.dll", "Tsmsisrv.dll", "TSVIPSrv.dll", "Msfte.dll", "wow64log.dll", "WindowsCoreDeviceInfo.dll", "Ualapi.dll", "wlanhlp.dll", "phoneinfo.dll", "EdgeGdi.dll", "cdpsgshims.dll", "windowsperformancerecordercontrol.dll", "diagtrack_win.dll", "TPPCOIPW32.dll", "tpgenlic.dll", "thinmon.dll", "fxsst.dll", "msTracer.dll") and
not file.hash.sha256 in
("6e837794fc282446906c36d681958f2f6212043fc117c716936920be166a700f",
"b14e4954e8cca060ffeb57f2458b6a3a39c7d2f27e94391cbcea5387652f21a4",
"c258d90acd006fa109dc6b748008edbb196d6168bc75ace0de0de54a4db46662",
"254e5053ac04b7623e86234077876388e0b10c3ac5c3f4e4e86292b62571bfb0"))
) and not
(
?dll.path : (
"?:\\Windows\\System32\\wbemcomn.dll",
"?:\\Windows\\SysWOW64\\wbemcomn.dll",
"?:\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"?:\\Windows\\System32\\wlanhlp.dll",
"\\Device\\HarddiskVolume?\\Windows\\SysWOW64\\wbemcomn.dll",
"\\Device\\HarddiskVolume?\\Windows\\System32\\wbemcomn.dll",
"\\Device\\HarddiskVolume?\\Windows\\SysWOW64\\wlanhlp.dll",
"\\Device\\HarddiskVolume?\\Windows\\System32\\wlanhlp.dll",
"\\Device\\HarddiskVolume?\\Windows\\SysWOW64\\windowsperformancerecordercontrol.dll",
"\\Device\\HarddiskVolume?\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"\\Device\\vmsmb\\VSMB-{*}\\os\\windows\\system32\\*.dll",
"C:\\Windows\\WinSxS\\amd64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll",
"C:\\Windows\\WinSxS\\wow64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll",
"C:\\Windows\\WinSxS\\amd64_microsoft-windows-coresystem-wpr_*\\windowsperformancerecordercontrol.dll"
) or
file.path : (
"?:\\Windows\\System32\\wbemcomn.dll",
"?:\\Windows\\SysWOW64\\wbemcomn.dll",
"?:\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"?:\\Windows\\System32\\wlanhlp.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\wbemcomn.dll",
"\\Device\\vmsmb\\VSMB-{*}\\os\\windows\\system32\\*.dll",
"C:\\Windows\\WinSxS\\amd64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll",
"C:\\Windows\\WinSxS\\wow64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll"
) or
?dll.code_signature.status like "errorCode_endpoint*"
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"
[[rule.threat.technique.subtechnique]]
id = "T1574.001"
name = "DLL"
reference = "https://attack.mitre.org/techniques/T1574/001/"
[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 = "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.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"
[[rule.threat.technique.subtechnique]]
id = "T1574.001"
name = "DLL"
reference = "https://attack.mitre.org/techniques/T1574/001/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
Stages and Predicates
Stage 1: any
any where host.os.type == "windows" and
(
(event.category == "library" and
(
?dll.name : ("wlbsctrl.dll", "wbemcomn.dll", "WptsExtensions.dll", "Tsmsisrv.dll", "TSVIPSrv.dll", "Msfte.dll", "wow64log.dll", "WindowsCoreDeviceInfo.dll", "Ualapi.dll", "wlanhlp.dll", "phoneinfo.dll", "EdgeGdi.dll", "cdpsgshims.dll", "windowsperformancerecordercontrol.dll", "diagtrack_win.dll", "TPPCOIPW32.dll", "tpgenlic.dll", "thinmon.dll", "fxsst.dll", "msTracer.dll") or
(?dll.path : "?:\\Windows\\*\\oci.dll" and process.executable : "?:\\Windows\\*.exe")
)
and (?dll.code_signature.trusted == false or ?dll.code_signature.exists == false or (?dll.code_signature.trusted == true and not ?dll.code_signature.subject_name : ("Microsoft Windows", "Microsoft Corporation", "Microsoft Windows Publisher"))
))
or
((event.category == "process" and event.action like "Image loaded*") and file.code_signature.status != "Valid" and
file.name : ("wlbsctrl.dll", "wbemcomn.dll", "WptsExtensions.dll", "Tsmsisrv.dll", "TSVIPSrv.dll", "Msfte.dll", "wow64log.dll", "WindowsCoreDeviceInfo.dll", "Ualapi.dll", "wlanhlp.dll", "phoneinfo.dll", "EdgeGdi.dll", "cdpsgshims.dll", "windowsperformancerecordercontrol.dll", "diagtrack_win.dll", "TPPCOIPW32.dll", "tpgenlic.dll", "thinmon.dll", "fxsst.dll", "msTracer.dll") and
not file.hash.sha256 in
("6e837794fc282446906c36d681958f2f6212043fc117c716936920be166a700f",
"b14e4954e8cca060ffeb57f2458b6a3a39c7d2f27e94391cbcea5387652f21a4",
"c258d90acd006fa109dc6b748008edbb196d6168bc75ace0de0de54a4db46662",
"254e5053ac04b7623e86234077876388e0b10c3ac5c3f4e4e86292b62571bfb0"))
) and not
(
?dll.path : (
"?:\\Windows\\System32\\wbemcomn.dll",
"?:\\Windows\\SysWOW64\\wbemcomn.dll",
"?:\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"?:\\Windows\\System32\\wlanhlp.dll",
"\\Device\\HarddiskVolume?\\Windows\\SysWOW64\\wbemcomn.dll",
"\\Device\\HarddiskVolume?\\Windows\\System32\\wbemcomn.dll",
"\\Device\\HarddiskVolume?\\Windows\\SysWOW64\\wlanhlp.dll",
"\\Device\\HarddiskVolume?\\Windows\\System32\\wlanhlp.dll",
"\\Device\\HarddiskVolume?\\Windows\\SysWOW64\\windowsperformancerecordercontrol.dll",
"\\Device\\HarddiskVolume?\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"\\Device\\vmsmb\\VSMB-{*}\\os\\windows\\system32\\*.dll",
"C:\\Windows\\WinSxS\\amd64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll",
"C:\\Windows\\WinSxS\\wow64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll",
"C:\\Windows\\WinSxS\\amd64_microsoft-windows-coresystem-wpr_*\\windowsperformancerecordercontrol.dll"
) or
file.path : (
"?:\\Windows\\System32\\wbemcomn.dll",
"?:\\Windows\\SysWOW64\\wbemcomn.dll",
"?:\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"?:\\Windows\\System32\\wlanhlp.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\windowsperformancerecordercontrol.dll",
"C:\\ProgramData\\docker\\windowsfilter\\*\\Files\\Windows\\System32\\wbemcomn.dll",
"\\Device\\vmsmb\\VSMB-{*}\\os\\windows\\system32\\*.dll",
"C:\\Windows\\WinSxS\\amd64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll",
"C:\\Windows\\WinSxS\\wow64_microsoft-windows-wmi-core-wbemcomn-dll_*\\wbemcomn.dll"
) or
?dll.code_signature.status like "errorCode_endpoint*"
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
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 |
dll.name | wildcard |
| field:"dll.name" kind:wildcard |
dll.path | wildcard |
| field:"ImageLoaded" kind:wildcard value:"?:\Windows\*\oci.dll" |
event.action | wildcard |
| field:"EventType" kind:wildcard value:"Image loaded*" |
event.category | eq |
| field:"event.category" kind:eq |
file.code_signature.status | ne |
| field:"SignatureStatus" kind:ne value:"Valid" |
file.name | wildcard |
| field:"file.name" kind:wildcard |
process.executable | wildcard |
| field:"Image" kind:wildcard value:"?:\Windows\*.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
dll.code_signature.status | starts_with | errorCode_endpoint | excludes:dll.code_signature.status field:"dll.code_signature.status" value:"errorCode_endpoint" |
dll.path | wildcard | ?:\Windows\System32\wbemcomn.dll, ?:\Windows\SysWOW64\wbemcomn.dll, ?:\Windows\System32\windowsperformancerecordercontrol.dll, ?:\Windows\System32\wlanhlp.dll, \Device\HarddiskVolume?\Windows\SysWOW64\wbemcomn.dll, \Device\HarddiskVolume?\Windows\System32\wbemcomn.dll, \Device\HarddiskVolume?\Windows\SysWOW64\wlanhlp.dll, \Device\HarddiskVolume?\Windows\System32\wlanhlp.dll, \Device\HarddiskVolume?\Windows\SysWOW64\windowsperformancerecordercontrol.dll, \Device\HarddiskVolume?\Windows\System32\windowsperformancerecordercontrol.dll, C:\ProgramData\docker\windowsfilter\*\Files\Windows\System32\windowsperformancerecordercontrol.dll, \Device\vmsmb\VSMB-{*}\os\windows\system32\*.dll, C:\Windows\WinSxS\amd64_microsoft-windows-wmi-core-wbemcomn-dll_*\wbemcomn.dll, C:\Windows\WinSxS\wow64_microsoft-windows-wmi-core-wbemcomn-dll_*\wbemcomn.dll, C:\Windows\WinSxS\amd64_microsoft-windows-coresystem-wpr_*\windowsperformancerecordercontrol.dll | excludes:dll.path |
file.path | wildcard | ?:\Windows\System32\wbemcomn.dll, ?:\Windows\SysWOW64\wbemcomn.dll, ?:\Windows\System32\windowsperformancerecordercontrol.dll, ?:\Windows\System32\wlanhlp.dll, C:\ProgramData\docker\windowsfilter\*\Files\Windows\System32\windowsperformancerecordercontrol.dll, C:\ProgramData\docker\windowsfilter\*\Files\Windows\System32\wbemcomn.dll, \Device\vmsmb\VSMB-{*}\os\windows\system32\*.dll, C:\Windows\WinSxS\amd64_microsoft-windows-wmi-core-wbemcomn-dll_*\wbemcomn.dll, C:\Windows\WinSxS\wow64_microsoft-windows-wmi-core-wbemcomn-dll_*\wbemcomn.dll | excludes:file.path |
Suspicious DLLRegisterServer Execution via MSIEXEC
#Identifies the execution of the built-in Windows Installer, MSIEXEC, to execute code via calling the exported function DLLRegisterServer from a suspicious module.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[rule]
description = """
Identifies the execution of the built-in Windows Installer, MSIEXEC, to execute code via calling the exported function
DLLRegisterServer from a suspicious module.
"""
id = "ed77616c-8f97-472b-bb15-532af004e82a"
license = "Elastic License v2"
name = "Suspicious DLLRegisterServer Execution via MSIEXEC"
os_list = ["windows"]
reference = [
"https://lolbas-project.github.io/lolbas/Binaries/Msiexec/",
"https://www.elastic.co/security-labs/Hunting-for-Suspicious-Windows-Libraries-for-Execution-and-Evasion",
]
version = "1.0.25"
query = '''
process where event.action == "start" and
process.pe.original_file_name : "msiexec.exe" and process.args : ("/z", "/y", "-y", "-z") and
not process.args : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*") and
not process.Ext.token.integrity_level_name == "system" and
not (process.parent.executable : "?:\\Windows\\Sys*\\msiexec.exe" and process.parent.args : "/V") and
not (process.args : "?:\\windows\\system32\\nise.dll" and process.parent.executable : "?:\\Windows\\System32\\runonce.exe")
'''
min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[[threat.technique.subtechnique]]
id = "T1218.007"
name = "Msiexec"
reference = "https://attack.mitre.org/techniques/T1218/007/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Stage 1: process
process where event.action == "start" and
process.pe.original_file_name : "msiexec.exe" and process.args : ("/z", "/y", "-y", "-z") and
not process.args : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*") and
not process.Ext.token.integrity_level_name == "system" and
not (process.parent.executable : "?:\\Windows\\Sys*\\msiexec.exe" and process.parent.args : "/V") and
not (process.args : "?:\\windows\\system32\\nise.dll" and process.parent.executable : "?:\\Windows\\System32\\runonce.exe")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.pe.original_file_name | wildcard |
| field:"OriginalFileName" kind:wildcard value:"msiexec.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | eq | ?:\windows\system32\nise.dll | excludes:process.args field:"process.args" value:"?:\windows\system32\nise.dll" |
process.parent.executable | eq | ?:\Windows\System32\runonce.exe | excludes:process.parent.executable field:"process.parent.executable" value:"?:\Windows\System32\runonce.exe" |
process.parent.args | eq | /V | excludes:process.parent.args field:"process.parent.args" value:"/V" |
process.parent.executable | wildcard | ?:\Windows\Sys*\msiexec.exe | excludes:process.parent.executable field:"process.parent.executable" value:"?:\Windows\Sys*\msiexec.exe" |
process.Ext.token.integrity_level_name | eq | system | excludes:process.Ext.token.integrity_level_name field:"process.Ext.token.integrity_level_name" value:"system" |
process.args | starts_with | ?:\Program Files\, ?:\Program Files (x86)\ | excludes:process.args field:"process.args" value:"?:\Program Files\" field:"process.args" value:"?:\Program Files (x86)\" |
Suspicious Vault Client Image Load
#Identifies when the Credential Vault Client library is loaded by an unusual process. Adversaries may acquire credentials from Vault files.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Rule Body
[rule]
description = """
Identifies when the Credential Vault Client library is loaded by an unusual process. Adversaries may acquire credentials
from Vault files.
"""
id = "048737fe-80d6-4462-aa80-ffeed853103e"
license = "Elastic License v2"
name = "Suspicious Vault Client Image Load"
os_list = ["windows"]
reference = [
"https://docs.microsoft.com/en-us/uwp/api/windows.security.credentials.passwordvault.retrieve?view=winrt-22000",
]
version = "1.0.35"
query = '''
sequence by process.entity_id with maxspan=1m
[process where event.action == "start" and
(
(process.executable : "?:\\Windows\\Microsoft.NET\\*.exe" and
not process.executable : "?:\\Windows\\Microsoft.NET\\Framework64\\*\\dfsvc.exe") or
(process.name : ("mshta.exe", "notepad.exe", "msbuild.exe", "regasm.exe", "notepad.exe") and
not process.args : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*", "\\\\*")) or
(process.name : "rundll32.exe" and process.args : "?:\\Users\\*\\AppData\\*" and
not process.args : ("url.dll,FileProtocolHandler", "cryptext.dll,CryptExtOpen*",
"?:\\WINDOWS\\system32\\mshtml.dll,PrintHTML", "shdocvw.dll,OpenURL")) or
(process.name : "rundll32.exe" and process.args_count == 1) or
(process.name : "powershell.exe" and process.args : ("-enc", "-ec", "-e", "*downloadstring*", "*Reflection.Assembly*")) or
(process.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk") and not process.executable : "C:\\*" and
not (process.name : "setup*.exe" and process.code_signature.trusted == true)) or
process.command_line : "\"{path}\""
) and
not (process.name : "powershell.exe" and
process.parent.executable :
("?:\\Program Files (x86)\\Dell\\UpdateService\\ServiceShell.exe",
"?:\\Windows\\System32\\wsl.exe",
"?:\\Windows\\Explorer.exe")) and
not (process.name : "ngen.exe" and process.parent.name : "NGenTask.exe") and
not (process.name : "notepad.exe" and process.parent.name : "explorer.exe") and
not (process.name : "calc.exe" and process.parent.executable : "?:\\Windows\\Explorer.exe") and
not process.parent.executable : ("?:\\Program Files (x86)\\Lenovo\\LeAppStore\\LeASPac.exe",
"?:\\Program Files\\Dell\\DellOptimizer\\DellOptimizer.exe",
"?:\\Program Files\\WindowsApps\\Microsoft.*.exe",
"?:\\Program Files (x86)\\LabTech Client\\LTClient.exe",
"?:\\Users\\*\\AppData\\Local\\StarlimsBridge\\StarlimsBridge.exe",
"?:\\ProgramData\\LogiShrd\\LogiOptions\\Software\\Current\\LogiOptionsMgr.exe",
"?:\\Program Files\\LogiOptionsPlus\\logioptionsplus_agent.exe",
"?:\\Program Files (x86)\\LogiOptionsPlus\\logioptionsplus_agent.exe",
"?:\\Windows\\System32\\DriverStore\\FileRepository\\*.exe",
"?:\\Windows\\Microsoft.NET\\Framework*\\NGenTask.exe",
"C:\\Program Files\\Microsoft OneDrive\\OneDrive.exe",
"C:\\Program Files\\Autodesk\\Desktop Connector\\DesktopConnector.Applications.Tray.exe") and
not (process.executable : "?:\\Windows\\system32\\notepad.exe" and
process.parent.executable :
("C:\\Program Files*\\Google\\Chrome\\Application\\chrome.exe",
"C:\\Program Files*\\Microsoft\\Edge\\Application\\msedge.exe",
"C:\\Program Files*\\Microsoft Office\\root\\Office??\\OUTLOOK.EXE")) and
not (process.name : ("powershell.exe", "mshta.exe", "cvtres.exe") and
process.working_directory : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*",
"?:\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\Downloads\\")) and
not process.executable :
("?:\\Program Files\\WindowsApps\\Microsoft.WindowsNotepad_*\\Notepad\\Notepad.exe",
"?:\\Windows\\Microsoft.NET\\Framework*\\dw20.exe") and
not (process.name : ("rundll32.exe", "regsvr32.exe") and
process.args : ("?:\\Program Files (x86)\\*", "?:\\Program Files\\*",
"C:\\Windows\\System32\\FirewallControlPanel.dll,ShowNotificationDialog",
"C:\\Windows\\System32\\rundll32.exe C:\\Windows\\System32\\LogiLDA.dll,LogiFetch",
"C:\\Windows\\System32\\rundll32.exe shell32.dll, ShellExec_RunDLL *",
"C:\\WINDOWS\\system32\\rundll32.exe printui.dll,PrintUIEntryDPIAware*",
"cryptext.dll,CryptExtAddPFX")) and
not (process.name : "rundll32.exe" and
process.command_line :
("*MSI*.tmp*zzzzInvokeManagedCustomActionOutOfProc*",
"*\\AppData\\Local\\WebEx\\WebEx\\*\\atasctrl.dll,StartHostLauncher*",
"?:\\WINDOWS\\System32\\FirewallControlPanel.dll,ShowNotificationDialog")) and
not process.hash.sha256 :
("50d1713ef6353996d0fcb5548733e960b33bc220c2eccd3e4e1bff710c002610",
"bea033e778048748eb1c87bf57597f7f5449b6a15bac55ddc08263c57f7a1ca8",
"ced3768b028225aaf35bf7aa6efd5876751918c226a608b71494f521fbb242a9") and
not (process.executable : "?:\\Windows\\Microsoft.NET\\Framework*\\csc.exe" and process.parent.name : "powershell.exe" and
process.parent.command_line : "*\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\DataCollection*") and
not (process.executable : "?:\\Windows\\Microsoft.NET\\Framework64\\*\\mscorsvw.exe" and
process.parent.executable : "?:\\Windows\\Microsoft.NET\\Framework64\\*\\ngen.exe") and
not (process.parent.executable : ("C:\\Windows\\System32\\sihost.exe", "C:\\Windows\\System32\\OpenWith.exe") and
process.executable : "C:\\Windows\\System32\\notepad.exe" and process.args_count >= 2)
]
[library where dll.name : "vaultcli.dll"]
'''
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 = "T1555"
name = "Credentials from Password Stores"
reference = "https://attack.mitre.org/techniques/T1555/"
[[threat.technique.subtechnique]]
id = "T1555.004"
name = "Windows Credential Manager"
reference = "https://attack.mitre.org/techniques/T1555/004/"
[threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[internal]
min_endpoint_version = "8.4.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 1m, correlated by process.entity_id.
Stage 1: process
[process where event.action == "start" and
(
(process.executable : "?:\\Windows\\Microsoft.NET\\*.exe" and
not process.executable : "?:\\Windows\\Microsoft.NET\\Framework64\\*\\dfsvc.exe") or
(process.name : ("mshta.exe", "notepad.exe", "msbuild.exe", "regasm.exe", "notepad.exe") and
not process.args : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*", "\\\\*")) or
(process.name : "rundll32.exe" and process.args : "?:\\Users\\*\\AppData\\*" and
not process.args : ("url.dll,FileProtocolHandler", "cryptext.dll,CryptExtOpen*",
"?:\\WINDOWS\\system32\\mshtml.dll,PrintHTML", "shdocvw.dll,OpenURL")) or
(process.name : "rundll32.exe" and process.args_count == 1) or
(process.name : "powershell.exe" and process.args : ("-enc", "-ec", "-e", "*downloadstring*", "*Reflection.Assembly*")) or
(process.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk") and not process.executable : "C:\\*" and
not (process.name : "setup*.exe" and process.code_signature.trusted == true)) or
process.command_line : "\"{path}\""
) and
not (process.name : "powershell.exe" and
process.parent.executable :
("?:\\Program Files (x86)\\Dell\\UpdateService\\ServiceShell.exe",
"?:\\Windows\\System32\\wsl.exe",
"?:\\Windows\\Explorer.exe")) and
not (process.name : "ngen.exe" and process.parent.name : "NGenTask.exe") and
not (process.name : "notepad.exe" and process.parent.name : "explorer.exe") and
not (process.name : "calc.exe" and process.parent.executable : "?:\\Windows\\Explorer.exe") and
not process.parent.executable : ("?:\\Program Files (x86)\\Lenovo\\LeAppStore\\LeASPac.exe",
"?:\\Program Files\\Dell\\DellOptimizer\\DellOptimizer.exe",
"?:\\Program Files\\WindowsApps\\Microsoft.*.exe",
"?:\\Program Files (x86)\\LabTech Client\\LTClient.exe",
"?:\\Users\\*\\AppData\\Local\\StarlimsBridge\\StarlimsBridge.exe",
"?:\\ProgramData\\LogiShrd\\LogiOptions\\Software\\Current\\LogiOptionsMgr.exe",
"?:\\Program Files\\LogiOptionsPlus\\logioptionsplus_agent.exe",
"?:\\Program Files (x86)\\LogiOptionsPlus\\logioptionsplus_agent.exe",
"?:\\Windows\\System32\\DriverStore\\FileRepository\\*.exe",
"?:\\Windows\\Microsoft.NET\\Framework*\\NGenTask.exe",
"C:\\Program Files\\Microsoft OneDrive\\OneDrive.exe",
"C:\\Program Files\\Autodesk\\Desktop Connector\\DesktopConnector.Applications.Tray.exe") and
not (process.executable : "?:\\Windows\\system32\\notepad.exe" and
process.parent.executable :
("C:\\Program Files*\\Google\\Chrome\\Application\\chrome.exe",
"C:\\Program Files*\\Microsoft\\Edge\\Application\\msedge.exe",
"C:\\Program Files*\\Microsoft Office\\root\\Office??\\OUTLOOK.EXE")) and
not (process.name : ("powershell.exe", "mshta.exe", "cvtres.exe") and
process.working_directory : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*",
"?:\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\Downloads\\")) and
not process.executable :
("?:\\Program Files\\WindowsApps\\Microsoft.WindowsNotepad_*\\Notepad\\Notepad.exe",
"?:\\Windows\\Microsoft.NET\\Framework*\\dw20.exe") and
not (process.name : ("rundll32.exe", "regsvr32.exe") and
process.args : ("?:\\Program Files (x86)\\*", "?:\\Program Files\\*",
"C:\\Windows\\System32\\FirewallControlPanel.dll,ShowNotificationDialog",
"C:\\Windows\\System32\\rundll32.exe C:\\Windows\\System32\\LogiLDA.dll,LogiFetch",
"C:\\Windows\\System32\\rundll32.exe shell32.dll, ShellExec_RunDLL *",
"C:\\WINDOWS\\system32\\rundll32.exe printui.dll,PrintUIEntryDPIAware*",
"cryptext.dll,CryptExtAddPFX")) and
not (process.name : "rundll32.exe" and
process.command_line :
("*MSI*.tmp*zzzzInvokeManagedCustomActionOutOfProc*",
"*\\AppData\\Local\\WebEx\\WebEx\\*\\atasctrl.dll,StartHostLauncher*",
"?:\\WINDOWS\\System32\\FirewallControlPanel.dll,ShowNotificationDialog")) and
not process.hash.sha256 :
("50d1713ef6353996d0fcb5548733e960b33bc220c2eccd3e4e1bff710c002610",
"bea033e778048748eb1c87bf57597f7f5449b6a15bac55ddc08263c57f7a1ca8",
"ced3768b028225aaf35bf7aa6efd5876751918c226a608b71494f521fbb242a9") and
not (process.executable : "?:\\Windows\\Microsoft.NET\\Framework*\\csc.exe" and process.parent.name : "powershell.exe" and
process.parent.command_line : "*\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\DataCollection*") and
not (process.executable : "?:\\Windows\\Microsoft.NET\\Framework64\\*\\mscorsvw.exe" and
process.parent.executable : "?:\\Windows\\Microsoft.NET\\Framework64\\*\\ngen.exe") and
not (process.parent.executable : ("C:\\Windows\\System32\\sihost.exe", "C:\\Windows\\System32\\OpenWith.exe") and
process.executable : "C:\\Windows\\System32\\notepad.exe" and process.args_count >= 2)
]
Stage 2: library
[library where dll.name : "vaultcli.dll"]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
dll.name | wildcard |
| field:"dll.name" kind:wildcard value:"vaultcli.dll" |
event.action | eq |
| field:"EventType" kind:eq value:"start" |
process.Ext.device.product_id | wildcard |
| field:"process.Ext.device.product_id" kind:wildcard |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.args_count | eq |
| field:"process.args_count" kind:eq value:"1" |
process.command_line | wildcard |
| field:"CommandLine" kind:wildcard |
process.executable | wildcard |
| field:"Image" kind:wildcard value:"?:\Windows\Microsoft.NET\*.exe" |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
User Added to the Admin Group
#Identifies users being added to the admin group. This could be an indication of privilege escalation activity.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Rule Body
[metadata]
creation_date = "2024/09/12"
integration = ["jamf_protect"]
maturity = "production"
updated_date = "2026/05/06"
[transform]
[[transform.investigate]]
label = "Show events having the same responsible process"
providers = [
[
{ excluded = false, field = "host.hostname", queryType = "phrase", value = "{{host.hostname}}", valueType = "string" },
{ excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.group_leader.entity_id}}", valueType = "string" }
]
]
[[transform.investigate]]
label = "Show events having the same parent process"
providers = [
[
{ excluded = false, field = "host.hostname", queryType = "phrase", value = "{{host.hostname}}", valueType = "string" },
{ excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.parent.entity_id}}", valueType = "string" }
]
]
[rule]
author = ["Thijs Xhaflaire"]
description = "Identifies users being added to the admin group. This could be an indication of privilege\nescalation activity.\n"
from = "now-9m"
index = ["logs-jamf_protect*"]
language = "eql"
license = "Elastic License v2"
name = "User Added to the Admin Group"
note = """## Triage and analysis
To thoroughly investigate the actions that occurred **after a user was elevated to administrator**, it's essential to conduct a search on the Timeline. This allows you to review and understand the sequence of events that followed the elevation, helping to identify any potentially malicious or unauthorized activities that might have taken place. **Analyzing these actions is crucial for maintaining security and ensuring that the elevation was not exploited for harmful purposes.**
**Consider reviewing these actions:**
- Have persistency items been added?
- Is any software installed after elevation?
- Were any additional users created after elevation?
$investigate_0
$investigate_1
"""
references = [
"https://www.loobins.io/binaries/dscl/",
"https://managingosx.wordpress.com/2010/01/14/add-a-user-to-the-admin-group-via-command-line-3-0/",
]
risk_score = 21
rule_id = "04e65517-16e9-4fc4-b7f1-94dc21ecea0d"
setup = """## Setup
This rule requires data coming in from Jamf Protect.
### Jamf Protect Integration Setup
Jamf Protect is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events incoming events and send data to the Elastic.
#### Prerequisite Requirements:
- Fleet is required for Jamf Protect.
- 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 Jamf Protect integration:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Jamf Protect" and select the integration to see more details about it.
- Click "Add Jamf Protect".
- Configure the integration name.
- Click "Save and Continue".
"""
severity = "low"
tags = [
"Domain: Endpoint",
"OS: macOS",
"Use Case: Threat Detection",
"Tactic: Privilege Escalation",
"Data Source: Jamf Protect",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
configuration where host.os.type == "macos" and event.type == "change" and
event.action == "od_group_add" and group.name:"admin"
'''
[[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.003"
name = "Local Accounts"
reference = "https://attack.mitre.org/techniques/T1078/003/"
[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"
[[rule.threat.technique.subtechnique]]
id = "T1098.007"
name = "Additional Local or Domain Groups"
reference = "https://attack.mitre.org/techniques/T1098/007/"
[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
Stages and Predicates
Stage 1: configuration
configuration where host.os.type == "macos" and event.type == "change" and
event.action == "od_group_add" and group.name:"admin"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"od_group_add" |
event.type | eq |
| field:"event.type" kind:eq value:"change" |
group.name | wildcard |
| field:"group.name" kind:wildcard value:"admin" |