Detection rules › Elastic

Elastic rules: 23

Active Directory Data Collection via LDAP

#
Source
github.com/elastic/protections-artifacts

In an Active Directory LDAP query, (objectGUID=*) is a search filter that evaluates to TRUE for every object in the directory, meaning it will return all objects. This may indicate an attempt to dump AD database using tools such as ADExplorer for offline analysis or exfiltration.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
In an Active Directory LDAP query, (objectGUID=*) is a search filter that evaluates to TRUE for every object in the
directory, meaning it will return all objects. This may indicate an attempt to dump AD database using tools such as
ADExplorer for offline analysis or exfiltration.
"""
id = "e79d5328-16fc-45ea-8179-ea2746042af6"
license = "Elastic License v2"
name = "Active Directory Data Collection via LDAP"
os_list = ["windows"]
reference = ["https://learn.microsoft.com/en-us/windows/win32/adschema/a-objectguid"]
version = "1.0.3"

query = '''
api where process.Ext.api.name == "ldap_search" and process.Ext.api.parameters.search_filter : ("(objectGUID=?)", "objectGUID=?")
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1069"
name = "Permission Groups Discovery"
reference = "https://attack.mitre.org/techniques/T1069/"
[[threat.technique.subtechnique]]
id = "T1069.002"
name = "Domain Groups"
reference = "https://attack.mitre.org/techniques/T1069/002/"


[[threat.technique]]
id = "T1087"
name = "Account Discovery"
reference = "https://attack.mitre.org/techniques/T1087/"
[[threat.technique.subtechnique]]
id = "T1087.002"
name = "Domain Account"
reference = "https://attack.mitre.org/techniques/T1087/002/"


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

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

[[threat.technique]]
id = "T1615"
name = "Group Policy Discovery"
reference = "https://attack.mitre.org/techniques/T1615/"


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

[internal]
min_endpoint_version = "9.1.0"

Stages and Predicates

Stage 1: api

api where process.Ext.api.name == "ldap_search" and process.Ext.api.parameters.search_filter : ("(objectGUID=?)", "objectGUID=?")

Indicators

These rows show field, operator, and value matches.

AWS Bedrock Unauthorized Resource-Based Policy Modification Attempt

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

Detects failed, access-denied attempts to modify or delete resource-based access policies on AWS Bedrock resources via the PutResourcePolicy and DeleteResourcePolicy API calls. Resource-based policies govern which principals (including external accounts) may access Bedrock resources such as agents, knowledge bases, and custom models. A principal that is repeatedly denied when attempting to attach or remove these policies may be a compromised or under-privileged identity probing for the ability to grant external or cross-account access, or to weaken existing access controls. Unlike the companion rule that detects successful changes, this rule surfaces the attempt itself, which is a high-signal indicator of credential boundary-testing even though no change occurred.

Known False Positives

  • Access-denied errors can result from benign permission gaps: a newly created role or user whose IAM policy has not yet been provisioned, infrastructure-as-code pipelines running ahead of permission grants, or developers experimenting in non-production accounts. Verify whether the user identity, user agent, and source IP are expected to manage Bedrock resource policies in your environment. Recurring denials from known automation or onboarding workflows can be exempted from the rule.

MITRE ATT&CK Coverage

TacticTechniques
Persistence

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2026/06/04"
integration = ["aws"]
maturity = "production"
updated_date = "2026/06/04"

[rule]
author = ["Elastic"]
description = """
Detects failed, access-denied attempts to modify or delete resource-based access policies on AWS Bedrock resources via
the PutResourcePolicy and DeleteResourcePolicy API calls. Resource-based policies govern which principals (including
external accounts) may access Bedrock resources such as agents, knowledge bases, and custom models. A principal that is
repeatedly denied when attempting to attach or remove these policies may be a compromised or under-privileged identity
probing for the ability to grant external or cross-account access, or to weaken existing access controls. Unlike the
companion rule that detects successful changes, this rule surfaces the attempt itself, which is a high-signal indicator
of credential boundary-testing even though no change occurred.
"""
false_positives = [
    """
    Access-denied errors can result from benign permission gaps: a newly created role or user whose IAM policy has not
    yet been provisioned, infrastructure-as-code pipelines running ahead of permission grants, or developers
    experimenting in non-production accounts. Verify whether the user identity, user agent, and source IP are expected
    to manage Bedrock resource policies in your environment. Recurring denials from known automation or onboarding
    workflows can be exempted from the rule.
    """,
]
from = "now-6m"
index = ["logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS Bedrock Unauthorized Resource-Based Policy Modification Attempt"
note = """## Triage and analysis

### Investigating AWS Bedrock Unauthorized Resource-Based Policy Modification Attempt

AWS Bedrock resource-based policies control which principals can access Bedrock resources such as agents,
knowledge bases, and custom models. An adversary who has compromised a credential may attempt to attach a policy
that grants an external principal access for persistence or cross-account access, or delete a policy to break
existing access controls. This rule detects `PutResourcePolicy` and `DeleteResourcePolicy` calls that were denied
(`AccessDenied` / unauthorized), which indicates an identity attempting an action it is not permitted to perform —
a strong signal of boundary-testing by a compromised or under-privileged principal even though the change did not
take effect.

#### Possible investigation steps

- **Identify the actor and context**
  - Review `aws.cloudtrail.user_identity.arn`, `aws.cloudtrail.user_identity.type`,
    `aws.cloudtrail.user_identity.access_key_id`, `user_agent.original`, and `source.ip`.
  - Determine whether this identity has any legitimate reason to manage Bedrock resource policies. A denial for an
    identity that should never touch these APIs is more suspicious than one from an admin with a transient gap.
- **Assess the attempt**
  - Inspect `aws.cloudtrail.error_code` and `aws.cloudtrail.error_message` to confirm the denial reason.
  - For `PutResourcePolicy`, review `aws.cloudtrail.request_parameters` and
    `aws.cloudtrail.flattened.request_parameters` for the target resource ARN and the attempted policy document.
    Look for `Principal` values referencing external AWS account IDs, `"*"`, or unfamiliar roles.
- **Correlate activity**
  - Look for repeated denials across Bedrock or IAM APIs from the same identity, which can indicate permission
    enumeration or escalation attempts.
  - Check whether the identity later succeeded (e.g., after acquiring new permissions) on the same or related
    resources, and review any IAM changes in the surrounding window.

### False positive analysis

- **Permission gaps**: Newly provisioned roles/users or IaC pipelines running before policy grants are applied may
  generate transient denials. Validate against change tickets and known automation.
- **Exploration in non-production**: Developers testing in sandbox accounts may hit denials. Confirm the account and
  identity context.

### Response and remediation

- If the attempt is unexpected, treat the identity as potentially compromised: disable or rotate the credentials in
  `aws.cloudtrail.user_identity.access_key_id` and review the actor's recent activity.
- Review all Bedrock and IAM activity from the same identity in the surrounding time window for successful access
  grants, permission changes, or other persistence attempts.
- Confirm least-privilege on `bedrock:PutResourcePolicy` and `bedrock:DeleteResourcePolicy`, and alert on both denied
  and successful calls.
"""
references = [
    "https://docs.aws.amazon.com/bedrock/latest/APIReference/API_PutResourcePolicy.html",
    "https://docs.aws.amazon.com/bedrock/latest/APIReference/API_DeleteResourcePolicy.html"
]
risk_score = 21
rule_id = "2e99477f-6099-48a9-ae0e-68801d97079c"
severity = "low"
tags = [
    "Domain: Cloud",
    "Domain: LLM",
    "Data Source: AWS",
    "Data Source: AWS CloudTrail",
    "Data Source: Amazon Web Services",
    "Data Source: Amazon Bedrock",
    "Use Case: Identity and Access Audit",
    "Resources: Investigation Guide",
    "Tactic: Persistence",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset: "aws.cloudtrail" and
    event.provider: "bedrock.amazonaws.com" and
    event.action: ("PutResourcePolicy" or "DeleteResourcePolicy") and
    event.outcome: "failure" and
    aws.cloudtrail.error_code: (
        "AccessDenied" or
        "AccessDeniedException"
    )
'''

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

[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

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

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user_agent.original",
    "source.ip",
    "aws.cloudtrail.user_identity.arn",
    "aws.cloudtrail.user_identity.type",
    "aws.cloudtrail.user_identity.access_key_id",
    "event.action",
    "event.provider",
    "event.outcome",
    "aws.cloudtrail.error_code",
    "cloud.account.id",
    "cloud.region",
    "aws.cloudtrail.request_parameters",
    "aws.cloudtrail.response_elements",
]

Stages and Predicates

Stage 1: query

data_stream.dataset: "aws.cloudtrail" and
    event.provider: "bedrock.amazonaws.com" and
    event.action: ("PutResourcePolicy" or "DeleteResourcePolicy") and
    event.outcome: "failure" and
    aws.cloudtrail.error_code: (
        "AccessDenied" or
        "AccessDeniedException"
    )

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
aws.cloudtrail.error_codein
  • AccessDenied corpus 3 (elastic 2, splunk 1)
  • AccessDeniedException corpus 2 (elastic 2)
field:"aws::errorCode" kind:in
data_stream.dataseteq
  • aws.cloudtrail corpus 143 (elastic 143)
field:"data_stream.dataset" kind:eq value:"aws.cloudtrail"
event.actionin
  • DeleteResourcePolicy corpus 2 (elastic 2)
  • PutResourcePolicy corpus 2 (elastic 2)
field:"EventType" kind:in
event.outcomeeq
  • failure corpus 14 (elastic 14)
field:"event.outcome" kind:eq value:"failure"
event.providereq
  • bedrock.amazonaws.com corpus 13 (elastic 13)
field:"Provider_Name" kind:eq value:"bedrock.amazonaws.com"

Azure Automation Runbook Created or Modified

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

Identifies when an Azure Automation runbook is created or modified. An adversary may create or modify an Azure Automation runbook to execute malicious code and maintain persistence in their target's environment.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2020/08/18"
integration = ["azure"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Identifies when an Azure Automation runbook is created or modified. An adversary may create or modify an Azure
Automation runbook to execute malicious code and maintain persistence in their target's environment.
"""
from = "now-9m"
index = ["logs-azure.activitylogs-*", "filebeat-*"]
language = "kuery"
license = "Elastic License v2"
name = "Azure Automation Runbook Created or Modified"
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 Azure Automation Runbook Created or Modified

Azure Automation Runbooks are scripts that automate tasks in cloud environments, enhancing operational efficiency. However, adversaries can exploit them to execute unauthorized code and maintain persistence. The detection rule monitors specific Azure activity logs for runbook creation or modification events, flagging successful operations to identify potential misuse. This helps in early detection of malicious activities, ensuring cloud security.

### Possible investigation steps

- Review the Azure activity logs to identify the specific runbook that was created or modified, focusing on the operation names: "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DRAFT/WRITE", "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE", or "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/PUBLISH/ACTION".
- Check the event.outcome field to confirm the operation was successful, as indicated by the values "Success" or "success".
- Identify the user or service principal that performed the operation by examining the relevant user identity fields in the activity logs.
- Investigate the content and purpose of the runbook by reviewing its script or configuration to determine if it contains any unauthorized or suspicious code.
- Correlate the runbook activity with other security events or alerts in the environment to identify any patterns or related malicious activities.
- Verify if the runbook changes align with recent legitimate administrative activities or if they were unexpected, which could indicate potential misuse.

### False positive analysis

- Routine updates or maintenance activities by authorized personnel can trigger alerts. To manage this, create exceptions for known maintenance windows or specific user accounts that regularly perform these tasks.
- Automated deployment processes that include runbook creation or modification might be flagged. Identify and exclude these processes by tagging them with specific identifiers in the logs.
- Integration with third-party tools that modify runbooks as part of their normal operation can result in false positives. Work with your IT team to whitelist these tools or their associated accounts.
- Frequent testing or development activities in non-production environments may cause alerts. Consider setting up separate monitoring rules or thresholds for these environments to reduce noise.
- Scheduled runbook updates for compliance or policy changes can be mistaken for suspicious activity. Document these schedules and adjust the detection rule to account for them, possibly by excluding specific operation names during these times.

### Response and remediation

- Immediately isolate the affected Azure Automation account to prevent further unauthorized runbook executions. This can be done by disabling the account or restricting its permissions temporarily.
- Review the modified or newly created runbooks to identify any malicious code or unauthorized changes. Remove or revert any suspicious modifications to ensure the integrity of the automation scripts.
- Conduct a thorough audit of recent activities associated with the affected Azure Automation account, focusing on identifying any unauthorized access or changes made by adversaries.
- Reset credentials and update access controls for the affected Azure Automation account to prevent further unauthorized access. Ensure that only authorized personnel have the necessary permissions to create or modify runbooks.
- Implement additional monitoring and alerting for Azure Automation activities, specifically focusing on runbook creation and modification events, to enhance early detection of similar threats in the future.
- Escalate the incident to the security operations team for further investigation and to determine if additional systems or accounts have been compromised.
- Document the incident, including all actions taken and findings, to improve response strategies and update incident response plans for future reference.

## Setup

The Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule."""
references = [
    "https://powerzure.readthedocs.io/en/latest/Functions/operational.html#create-backdoor",
    "https://github.com/hausec/PowerZure",
    "https://posts.specterops.io/attacking-azure-azure-ad-and-introducing-powerzure-ca70b330511a",
    "https://azure.microsoft.com/en-in/blog/azure-automation-runbook-management/",
]
risk_score = 21
rule_id = "16280f1e-57e6-4242-aa21-bb4d16f13b2f"
severity = "low"
tags = ["Domain: Cloud", "Data Source: Azure", "Use Case: Configuration Audit", "Tactic: Execution", "Resources: Investigation Guide"]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset:azure.activitylogs and
  azure.activitylogs.operation_name:
  (
    "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DRAFT/WRITE" or
    "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE" or
    "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/PUBLISH/ACTION"
  ) and
  event.outcome:(Success or success)
'''

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

[[rule.threat.technique]]
id = "T1648"
name = "Serverless Execution"
reference = "https://attack.mitre.org/techniques/T1648/"

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

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

[[rule.threat.technique]]
id = "T1053"
name = "Scheduled Task/Job"
reference = "https://attack.mitre.org/techniques/T1053/"

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

Stages and Predicates

Stage 1: query

data_stream.dataset:azure.activitylogs and
  azure.activitylogs.operation_name:
  (
    "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DRAFT/WRITE" or
    "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE" or
    "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/PUBLISH/ACTION"
  ) and
  event.outcome:(Success or success)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
azure.activitylogs.operation_namein
  • MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DRAFT/WRITE
  • MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/PUBLISH/ACTION
  • MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE
field:"azure.activitylogs.operation_name" kind:in
data_stream.dataseteq
  • azure.activitylogs corpus 38 (elastic 38)
field:"data_stream.dataset" kind:eq value:"azure.activitylogs"
event.outcomein
  • Success corpus 306 (elastic 306)
  • success corpus 306 (elastic 306)
field:"event.outcome" kind:in

Common Language Runtime Loaded via an Unsigned Module

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

Identifies the load of the Microsoft Common Language Runtime DLL CLR.dll from a recently dropped unsigned DLL.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = "Identifies the load of the Microsoft Common Language Runtime DLL CLR.dll from a recently dropped unsigned DLL."
id = "d8d90a1a-a912-4716-994b-26e24d363d76"
license = "Elastic License v2"
name = "Common Language Runtime Loaded via an Unsigned Module"
os_list = ["windows"]
reference = [
    "https://www.elastic.co/security-labs/upping-the-ante-detecting-in-memory-threats-with-kernel-call-stacks",
]
version = "1.0.20"

query = '''
sequence by process.entity_id with maxspan=1m
 [library where
  dll.Ext.relative_file_creation_time <= 300 and
  dll.code_signature.trusted  != true and not startswith~(dll.name, process.name) and
  dll.hash.sha256 : "??*" and dll.path : "?*" and
  (process.code_signature.subject_name : "Microsoft*" or process.code_signature.exists == false) and
  not dll.code_signature.status : ("trusted", "errorCode_endpoint*") and
  not process.executable : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*", "?:\\Windows\\System32\\DriverStore\\FileRepository\\*") and
  not dll.path : ("?:\\Windows\\assembly\\NativeImages_v*",
                  "?:\\Windows\\System32\\DriverStore\\FileRepository\\*",
                  "?:\\Windows\\SoftwareDistribution\\Download\\*",
                  "?:\\Windows\\WinSxS\\*",
                  "?:\\Program Files\\*",
                  "?:\\Program Files (x86)\\*") and
  not dll.hash.sha256 : "f51ff500ace815d2d2213fe961a2080f8b7da98474d7a7736a49961938e1028e"] as event0
 [library where dll.name : "clr.dll" and
  stringcontains~(process.thread.Ext.call_stack_summary, concat("mscoreei.dll|", event0.dll.name)) and
  not process.thread.Ext.call_stack_summary : "*mscoreei.dll|msi*.tmp|msi.dll*"]
'''

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

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

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


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

[internal]
min_endpoint_version = "8.10.0"

Stages and Predicates

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

Stage 1: library

[library where
  dll.Ext.relative_file_creation_time <= 300 and
  dll.code_signature.trusted  != true and not startswith~(dll.name, process.name) and
  dll.hash.sha256 : "??*" and dll.path : "?*" and
  (process.code_signature.subject_name : "Microsoft*" or process.code_signature.exists == false) and
  not dll.code_signature.status : ("trusted", "errorCode_endpoint*") and
  not process.executable : ("?:\\Program Files\\*", "?:\\Program Files (x86)\\*", "?:\\Windows\\System32\\DriverStore\\FileRepository\\*") and
  not dll.path : ("?:\\Windows\\assembly\\NativeImages_v*",
                  "?:\\Windows\\System32\\DriverStore\\FileRepository\\*",
                  "?:\\Windows\\SoftwareDistribution\\Download\\*",
                  "?:\\Windows\\WinSxS\\*",
                  "?:\\Program Files\\*",
                  "?:\\Program Files (x86)\\*") and
  not dll.hash.sha256 : "f51ff500ace815d2d2213fe961a2080f8b7da98474d7a7736a49961938e1028e"] as event0

Stage 2: library

[library where dll.name : "clr.dll" and
  stringcontains~(process.thread.Ext.call_stack_summary, concat("mscoreei.dll|", event0.dll.name)) and
  not process.thread.Ext.call_stack_summary : "*mscoreei.dll|msi*.tmp|msi.dll*"]

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
dll.code_signature.statuswildcardtrusted, errorCode_endpoint*excludes:dll.code_signature.status field:"dll.code_signature.status" value:"trusted" field:"dll.code_signature.status" value:"errorCode_endpoint*"
dll.hash.sha256eqf51ff500ace815d2d2213fe961a2080f8b7da98474d7a7736a49961938e1028eexcludes:dll.hash.sha256 field:"dll.hash.sha256" value:"f51ff500ace815d2d2213fe961a2080f8b7da98474d7a7736a49961938e1028e"
dll.namestarts_withprocess.nameexcludes:dll.name field:"dll.name" value:"process.name"
dll.pathstarts_with?:\Windows\assembly\NativeImages_v, ?:\Windows\System32\DriverStore\FileRepository\, ?:\Windows\SoftwareDistribution\Download\, ?:\Windows\WinSxS\, ?:\Program Files\, ?:\Program Files (x86)\excludes:dll.path
process.executablestarts_with?:\Program Files\, ?:\Program Files (x86)\, ?:\Windows\System32\DriverStore\FileRepository\excludes:process.executable field:"process.executable" value:"?:\Program Files\" field:"process.executable" value:"?:\Program Files (x86)\" field:"process.executable" value:"?:\Windows\System32\DriverStore\FileRepository\"
process.thread.Ext.call_stack_summarywildcard*mscoreei.dll|msi*.tmp|msi.dll*excludes:process.thread.Ext.call_stack_summary field:"process.thread.Ext.call_stack_summary" value:"*mscoreei.dll|msi*.tmp|msi.dll*"

Control Panel Process with Unusual Arguments

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

Identifies unusual instances of Control Panel with suspicious keywords or paths in the process command line value. Adversaries may abuse control.exe to proxy execution of malicious code.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2021/09/08"
integration = ["endpoint", "windows", "system", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike"]
maturity = "production"
updated_date = "2026/04/29"

[rule]
author = ["Elastic"]
description = """
Identifies unusual instances of Control Panel with suspicious keywords or paths in the process command line value.
Adversaries may abuse control.exe to proxy execution of malicious code.
"""
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 = "Control Panel Process with Unusual Arguments"
references = ["https://www.joesandbox.com/analysis/476188/1/html"]
risk_score = 73
rule_id = "416697ae-e468-4093-a93d-59661fa619ec"
severity = "high"
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",
    "Data Source: Crowdstrike",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.type == "start" and
  process.name : "control.exe" and
  process.command_line : (
    "*.jpg*", "*.png*",
    "*.gif*", "*.bmp*",
    "*.jpeg*", "*.TIFF*",
    "*.inf*", "*.cpl:*/*",
    "*../../..*",
    "*/AppData/Local/*",
    "*:\\Users\\Public\\*",
    "*\\AppData\\Local\\*"
)
'''

note = """## Triage and analysis

### Investigating Control Panel Process with Unusual Arguments

#### Possible investigation steps

- Which suspicious argument family did the alert preserve, and what does it imply?
  - Focus: `process.command_line` and `@timestamp`, identifying image or INF targets, ".cpl:" indirection, traversal (".."), "AppData\\Local", or "Users\\Public" fragments.
  - Implication: escalate when Control Panel points at non-applet content, user-writable paths, traversal, or URL-like ".cpl:" loading; lower suspicion only when the path and argument resolve to one recognized vendor applet, driver package, or support workflow.

- Is the alerting binary really the expected Control Panel executable?
  - Focus: `process.executable`, `process.pe.original_file_name`, `process.code_signature.subject_name`, `process.code_signature.trusted`, and `process.hash.sha256`.
  - Implication: escalate if "control.exe" is renamed, unsigned or untrusted, has an unfamiliar hash, or runs outside the Windows system path; Microsoft identity lowers masquerade risk but does not clear the arguments.

- Does the parent and user context fit this launch?
  - Focus: `process.parent.executable`, `process.parent.command_line`, `user.id`, and `user.name`.
  - Implication: Office, browser, script-host, archive-tool, remote-admin, or mismatched-user launches make the command abnormal; keep validating only when parent and user context fit the applet, driver, support, or lab workflow named by the command line.

- Did Control Panel hand off to follow-on execution?
  - Focus: child starts on the same `host.id` where `process.parent.entity_id` equals the alert `process.entity_id`; review child `process.executable`, `process.command_line`, and `process.pe.original_file_name`. $investigate_0
  - Implication: follow-on execution confirms proxy-abuse risk when the chain uses "rundll32.exe" or "Control_RunDLL", or spawns PowerShell, cmd, mshta, regsvr32, wscript, cscript, or another unexpected LOLBin; a clean stop at the expected applet or support component narrows scope.
  - Hint: if `process.entity_id` is absent, recover children with `host.id` + `process.pid` near `@timestamp`; treat ambiguity as unresolved.

- Did the referenced path contain staged or renamed payload content?
  - Focus: file events for `host.id` + `process.entity_id`, or `host.id` + `process.pid` near `@timestamp`; review `file.path`, `file.Ext.original.path`, `file.Ext.header_bytes`, and `file.Ext.windows.zone_identifier`. $investigate_1
  - Implication: escalate when file events show executable or script content, mismatched headers, recent renames, internet provenance, or payloads under "AppData\\Local" or "Users\\Public"; artifacts confined to the same recognized vendor package layout reduce file concern. Missing file telemetry is unresolved, not benign.

- Did the process or host contact delivery or command-and-control infrastructure?
  - Focus: DNS and connection events for `host.id` + `process.entity_id`, or `host.id` + `process.pid` near `@timestamp`; compare DNS `dns.question.name` and `dns.resolved_ip` with `destination.ip` and `destination.port`. $investigate_2
  - Implication: escalate when network events show the same process or host reaching rare external domains, payload hosts, or mismatched service ports after launch; urgency drops only when traffic stays limited to the same recognized vendor or internal service. Missing network telemetry is unresolved, not benign.
  - Hint: separate DNS events from connection events before correlating `dns.resolved_ip` to `destination.ip`.

- If local evidence is suspicious or unresolved, does related alert activity change the user or host scope?
  - Focus: alerts for the same `user.id` showing delivery, persistence, defense evasion, suspicious children, or other proxy-execution utilities such as "rundll32.exe", "mshta.exe", or "regsvr32.exe". $investigate_3
  - Hint: use the host pivot separately for the same patterns on `host.id`, especially when user context is absent or shared. $investigate_4
  - Implication: broaden scope when either pivot shows related delivery, persistence, proxy execution, or repeated suspicious Control Panel launches; keep local only when local evidence is explained and related alerts do not contradict it.

- Escalate when command intent plus any meaningful corroborator indicates proxy execution, staged payloads, unexpected child execution, suspicious destinations, or spread; close only when alert-local process evidence and supported recovery bind the exact activity to one recognized workflow with no contradictions; if evidence is mixed or visibility is incomplete, preserve artifacts and escalate.

### False positive analysis

- Vendor applets, printer/display drivers, hardware-management packages, support troubleshooting, or lab validation can trigger unusual Control Panel paths. Confirm `process.command_line` names the expected CPL or INF target, `process.executable` is the Microsoft system binary, `process.parent.executable` and `process.parent.command_line` match the installer or support component, `user.id` and `host.id` fit the endpoint or lab cohort, artifacts stay inside the vendor package layout, and no suspicious child process or unexpected external destination follows. Use package, change, or lab records only as corroboration; without them, close only when this case's telemetry binds the exact workflow. Treat it as a candidate exception until records or recurrence confirm stability.
- Before creating an exception, validate that the same `process.executable`, `process.parent.executable`, stable `process.command_line` pattern, `user.id`, and `host.id` recur across prior alerts from this rule. Build the exception from that minimum confirmed workflow pattern. Avoid exceptions on "control.exe" alone, on a file extension alone, or on a host alone.

### Response and remediation

- If confirmed benign, reverse any temporary containment and document the command, binary identity, parent workflow, account, host, artifact, and destination evidence that proved one recognized workflow. Create an exception only if that same workflow recurs across prior alerts from this rule.
- If suspicious but unconfirmed, preserve a case export with `process.command_line`, `process.entity_id`, parent and child lineage, referenced artifacts, and network indicators when available before containment. Apply reversible containment first, such as temporary egress restrictions or heightened monitoring on the affected `host.id` and `user.id`, and avoid deleting files or killing child processes until follow-on execution is scoped.
- Do not isolate or suspend based on the alert alone. Escalate suspicious-but-unconfirmed cases to host isolation or account action only when child-process, artifact, network, or related-alert evidence shows likely follow-on execution or broader exposure.
- If confirmed malicious, preserve the same process, artifact, and network evidence before destructive action. Isolate the endpoint to stop further execution while keeping telemetry available; if direct endpoint response is unavailable, hand off the preserved `host.id`, `user.id`, `process.entity_id`, and command-line evidence to the team that can isolate the host or suspend the account.
- After scoping related hosts, users, parent processes, command-line fragments, referenced paths, and follow-on children, quarantine or remove the malicious applets, DLLs, scripts, archives, or dropped artifacts identified during the investigation. Restore affected Control Panel or shell-association paths to the expected baseline and verify no persistence remains.
- Post-incident hardening: restrict document-, script-, and archive-driven launches of Control Panel on privileged or shared systems, retain any file or network telemetry that limited the case, and record the confirmed workflow or malicious artifact pattern for future triage.
"""

setup = """## Setup

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

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

### 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)
"""

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "host.name",
    "host.id",
    "user.name",
    "user.id",
    "process.entity_id",
    "process.pid",
    "process.executable",
    "process.command_line",
    "process.working_directory",
    "process.pe.original_file_name",
    "process.parent.entity_id",
    "process.parent.name",
    "process.parent.executable",
    "process.parent.command_line",
]

[transform]

[[transform.investigate]]
label = "Child process events for Control Panel"
description = ""
providers = [
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "File events for Control Panel"
description = ""
providers = [
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Network events for Control Panel"
description = ""
providers = [
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
    { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" }
  ],
  [
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" },
    { excluded = false, field = "event.category", queryType = "phrase", value = "dns", valueType = "string" }
  ]
]
relativeFrom = "now-1h"
relativeTo = "now"

[[transform.investigate]]
label = "Alerts associated with the user"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[transform.investigate]]
label = "Alerts associated with the host"
description = ""
providers = [
  [
    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
  ]
]
relativeFrom = "now-48h/h"
relativeTo = "now"

[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[[rule.threat.technique.subtechnique]]
id = "T1218.002"
name = "Control Panel"
reference = "https://attack.mitre.org/techniques/T1218/002/"

[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 : "control.exe" and
  process.command_line : (
    "*.jpg*", "*.png*",
    "*.gif*", "*.bmp*",
    "*.jpeg*", "*.TIFF*",
    "*.inf*", "*.cpl:*/*",
    "*../../..*",
    "*/AppData/Local/*",
    "*:\\Users\\Public\\*",
    "*\\AppData\\Local\\*"
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.command_linewildcard
  • *../../..*
  • *.TIFF* corpus 2 (elastic 2)
  • *.bmp* corpus 2 (elastic 2)
  • *.cpl:*/*
  • *.gif* corpus 2 (elastic 2)
  • *.inf*
  • *.jpeg* corpus 2 (elastic 2)
  • *.jpg* corpus 2 (elastic 2)
  • *.png* corpus 2 (elastic 2)
  • */AppData/Local/*
  • *:\Users\Public\* corpus 2 (elastic 2)
  • *\AppData\Local\*
field:"CommandLine" kind:wildcard
process.namewildcard
  • control.exe corpus 10 (elastic 8, splunk 2)
field:"process_basename" kind:wildcard value:"control.exe"

Elastic Security External Alerts

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

Generates a detection alert for each Elastic Security alert written to the configured indices. Enabling this rule allows you to immediately begin investigating Elastic Security alerts in the app.

Rule Body

[metadata]
creation_date = "2025/07/31"
integration = ["elastic_security"]
maturity = "production"
promotion = true
updated_date = "2025/10/17"

[rule]
author = ["Elastic"]
description = """
Generates a detection alert for each Elastic Security alert written to the configured indices. Enabling this rule allows
you to immediately begin investigating Elastic Security alerts in the app.
"""
from = "now-2m"
index = ["logs-elastic_security.alert-*"]
interval = "1m"
language = "kuery"
license = "Elastic License v2"
max_signals = 1000
name = "Elastic Security External Alerts"
note = """## Triage and analysis

### Investigating Elastic Security External Alerts

The Elastic Security integration facilitates transferring security alert data from another Elasticsearch instance to your own, enabling threats to be investigated in a centralized manner.

### Possible investigation steps

- Correlate the alert with recent activity on the affected endpoint to identify any unusual or suspicious behavior patterns.
- Check for any additional alerts or logs related to the same endpoint or user to determine if this is part of a broader attack or isolated incident.
- Investigate the source and destination IP addresses involved in the alert to assess if they are known to be malicious or associated with previous threats.
- Analyze any files or processes flagged in the alert to determine if they are legitimate or potentially malicious, using threat intelligence sources if necessary.
- Consult the Elastic Security investigation guide and resources tagged in the alert for specific guidance on handling similar threats.

### False positive analysis

- Alerts triggered by routine software updates or patches can be false positives. Review the context of the alert to determine if it aligns with scheduled maintenance activities.
- Legitimate administrative tools or scripts may trigger alerts. Identify and whitelist these tools if they are verified as non-threatening.
- Frequent alerts from known safe applications or processes can be excluded by creating exceptions for these specific behaviors in the Elastic Security configuration.
- Network scanning or monitoring tools used by IT teams might be flagged. Ensure these tools are documented and excluded from triggering alerts if they are part of regular operations.
- User behavior that is consistent with their role but triggers alerts should be reviewed. If deemed non-malicious, adjust the rule to exclude these specific user actions.

### Response and remediation

- Isolate the affected endpoint immediately to prevent lateral movement and further compromise within the network.
- Analyze the specific alert details to identify the nature of the threat and any associated indicators of compromise (IOCs).
- Remove or quarantine any malicious files or processes identified by the Elastic Security alert to neutralize the threat.
- Apply relevant security patches or updates to address any exploited vulnerabilities on the affected endpoint.
- Conduct a thorough scan of the network to identify any additional endpoints that may have been compromised or are exhibiting similar behavior.
- Document the incident and escalate to the appropriate security team or management if the threat is part of a larger attack campaign or if additional resources are needed for remediation.
- Review and update endpoint protection policies and configurations to enhance detection and prevention capabilities against similar threats in the future.
"""
references = ["https://docs.elastic.co/en/integrations/elastic_security"]
risk_score = 47
rule_id = "720fc1aa-e195-4a1d-81d8-04edfe5313ed"
rule_name_override = "kibana.alert.rule.name"
setup = """## Setup

### Elastic Security Alert Integration
This rule is designed to capture alert events generated by the Elastic Security integration and promote them as Elastic detection alerts.

To capture Elastic Security alerts, install and configure the Elastic Security integration to ingest alert events into the `logs-elastic_security.alert-*` index pattern.

If this rule is enabled alongside the External Alerts promotion rule (UUID: eb079c62-4481-4d6e-9643-3ca499df7aaa), you may receive duplicate alerts for the same Elastic Security events. Consider adding a rule exception for the External Alert rule to exclude data_stream.dataset:elastic_security.alert to avoid receiving duplicate alerts.

### Additional notes

For information on troubleshooting the maximum alerts warning please refer to this [guide](https://www.elastic.co/guide/en/security/current/alerts-ui-monitor.html#troubleshoot-max-alerts).
"""
severity = "medium"
tags = [
    "Data Source: Elastic Security",
    "Use Case: Threat Detection",
    "Resources: Investigation Guide",
    "Promotion: External Alerts",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
event.kind: alert and data_stream.dataset: elastic_security.alert
'''


[[rule.risk_score_mapping]]
field = "event.risk_score"
operator = "equals"
value = ""

[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "low"
value = "21"

[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "medium"
value = "47"

[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "high"
value = "73"

[[rule.severity_mapping]]
field = "event.severity"
operator = "equals"
severity = "critical"
value = "99"


Stages and Predicates

Stage 1: query

event.kind: alert and data_stream.dataset: elastic_security.alert

Indicators

These rows show field, operator, and value matches.

Elevated Apple Script Execution via Unsigned Parent

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

Identifies execution of the Apple script interpreter (osascript) without a password prompt with administrator privileges and from unsigned or untrusted parent process.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[rule]
description = """
Identifies execution of the Apple script interpreter (osascript) without a password prompt with administrator privileges
and from unsigned or untrusted parent process.
"""
id = "f17c8dcf-d65f-479a-b047-3558233f774e"
license = "Elastic License v2"
name = "Elevated Apple Script Execution via Unsigned Parent"
os_list = ["macos"]
reference = ["https://discussions.apple.com/thread/2266150"]
version = "1.0.26"

query = '''
sequence with maxspan=1m
 [process where event.action == "exec" and
  (process.code_signature.trusted == false or process.code_signature.exists == false)] by process.entity_id
 [process where event.action == "exec" and (process.name in ("osascript", "sh", "bash", "zsh", "dash", "csh", "tcsh", "ksh", "tclsh", "fish") or process.name like "tclsh*") and
  process.command_line like~ "*osascript*with administrator privileges*"] by process.parent.entity_id
'''

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

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

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


[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1548"
name = "Abuse Elevation Control Mechanism"
reference = "https://attack.mitre.org/techniques/T1548/"


[threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

[internal]
min_endpoint_version = "8.1.0"

Stages and Predicates

Ordered sequence: each step below must occur in order within 1m, correlated by process.entity_id, process.parent.entity_id.

Stage 1: process

[process where event.action == "exec" and
  (process.code_signature.trusted == false or process.code_signature.exists == false)] by process.entity_id

Stage 2: process

[process where event.action == "exec" and (process.name in ("osascript", "sh", "bash", "zsh", "dash", "csh", "tcsh", "ksh", "tclsh", "fish") or process.name like "tclsh*") and
  process.command_line like~ "*osascript*with administrator privileges*"] by process.parent.entity_id

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec corpus 547 (elastic 547)
field:"EventType" kind:eq value:"exec"
process.code_signature.existseq
  • false transforms: boolean corpus 118 (elastic 118)
field:"process.code_signature.exists" kind:eq value:"false"
process.code_signature.trustedeq
  • false transforms: boolean corpus 114 (elastic 114)
field:"process.code_signature.trusted" kind:eq value:"false"
process.command_linewildcard
  • *osascript*with administrator privileges*
field:"CommandLine" kind:wildcard value:"*osascript*with administrator privileges*"
process.namein
  • bash corpus 181 (elastic 181)
  • csh corpus 148 (elastic 148)
  • dash corpus 150 (elastic 150)
  • fish corpus 151 (elastic 151)
  • ksh corpus 149 (elastic 149)
  • osascript corpus 12 (elastic 12)
  • sh corpus 180 (elastic 180)
  • tclsh corpus 28 (elastic 28)
  • tcsh corpus 145 (elastic 145)
  • zsh corpus 180 (elastic 180)
field:"process_basename" kind:in
process.namewildcard
  • tclsh* corpus 23 (elastic 23)
field:"process_basename" kind:wildcard value:"tclsh*"

Entra ID OAuth Phishing via First-Party Microsoft Application

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

Detects potentially suspicious OAuth authorization activity in Microsoft Entra ID where first-party Microsoft applications from the FOCI (Family of Client IDs) group request access to Microsoft Graph or legacy Azure AD resources. Developer tools like Azure CLI, Visual Studio Code, and Azure PowerShell accessing these resources are flagged, as they are commonly abused in phishing campaigns like ConsentFix. Additionally, any FOCI family application accessing the deprecated Windows Azure Active Directory resource is flagged since this API is rarely used legitimately and attackers target it for stealth. First-party apps are trusted by default in all tenants and cannot be blocked, making them ideal for OAuth phishing attacks.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2025/04/23"
integration = ["azure"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Detects potentially suspicious OAuth authorization activity in Microsoft Entra ID where first-party Microsoft
applications from the FOCI (Family of Client IDs) group request access to Microsoft Graph or legacy Azure AD resources.
Developer tools like Azure CLI, Visual Studio Code, and Azure PowerShell accessing these resources are flagged, as they
are commonly abused in phishing campaigns like ConsentFix. Additionally, any FOCI family application accessing the
deprecated Windows Azure Active Directory resource is flagged since this API is rarely used legitimately and attackers
target it for stealth. First-party apps are trusted by default in all tenants and cannot be blocked, making them ideal
for OAuth phishing attacks.
"""
from = "now-9m"
index = ["filebeat-*", "logs-azure.signinlogs-*"]
language = "kuery"
license = "Elastic License v2"
name = "Entra ID OAuth Phishing via First-Party Microsoft Application"
note = """## Triage and analysis

### Investigating Entra ID OAuth Phishing via First-Party Microsoft Application

This rule detects OAuth authorization activity where FOCI (Family of Client IDs) applications access Microsoft Graph or legacy Azure AD resources. Adversaries exploit these trusted first-party apps in phishing campaigns like ConsentFix to steal authorization codes and exchange them for tokens from attacker infrastructure. Because first-party apps are pre-consented and cannot be blocked, attackers use them to bypass consent prompts and access user data without triggering typical OAuth alerts.

The rule uses split detection logic: developer tools (Azure CLI, VSCode, PowerShell) accessing either Graph or legacy AAD are flagged, while any FOCI app accessing legacy AAD is flagged since this deprecated API is rarely used legitimately and attackers target it for stealth.

### Possible investigation steps

- Review `azure.signinlogs.properties.user_principal_name` to identify the affected user and determine if they are a high-value target (privileged roles, executives, IT admins).
- Analyze `source.ip` and `source.geo.*` for geographic anomalies. ConsentFix attackers exchange codes from different IPs than the victim's location.
- Check `azure.signinlogs.properties.app_display_name` to confirm which first-party application was used. Azure CLI or PowerShell access by non-developers is suspicious.
- Examine `azure.signinlogs.properties.resource_id` to identify the target resource. Legacy AAD (`00000002-0000-0000-c000-000000000000`) access is unusual for most users.
- Review `azure.signinlogs.properties.is_interactive` - non-interactive sign-ins shortly after interactive ones from different IPs indicate token replay.
- Correlate with other sign-in events using `azure.signinlogs.properties.session_id` to identify the full OAuth flow sequence.
- Pivot to `azure.graphactivitylogs` to search for subsequent Graph API activity from the same session or user from unusual locations.
- Check `azure.auditlogs` for device registration events around the same timeframe, which may indicate persistence attempts.

### False positive analysis

- Developers or IT administrators legitimately using Azure CLI, PowerShell, or VS Code to access Microsoft Graph or Azure AD.
- Enterprise automation or CI/CD pipelines using these tools with user-delegated permissions.
- Users working from multiple locations (VPN, travel) may show different IPs.
- Consider excluding known developer machines, managed devices, or specific user groups that regularly use these tools.
- Maintain an allowlist of expected source IPs tied to corporate infrastructure or developer environments.

### Response and remediation

- Contact the user immediately to confirm if they initiated the OAuth flow and used the detected application.
- If unauthorized, revoke all refresh tokens for the user via Microsoft Entra ID portal or PowerShell.
- Review the user's recent Microsoft Graph activity (email access, file downloads, Teams messages) for signs of data exfiltration.
- Block the source IP if confirmed malicious.
- Check for any devices registered during this session via `azure.auditlogs` and remove unauthorized device registrations.
- Implement Conditional Access policies to restrict OAuth flows for these applications to compliant devices only.
- Educate users about OAuth phishing and the risks of pasting authorization codes into websites.
"""
references = [
    "https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/reference-azure-monitor-sign-ins-log-schema",
    "https://www.volexity.com/blog/2025/04/22/phishing-for-codes-russian-threat-actors-target-microsoft-365-oauth-workflows/",
    "https://pushsecurity.com/blog/consentfix",
    "https://github.com/secureworks/family-of-client-ids-research",
]
risk_score = 47
rule_id = "14fa0285-fe78-4843-ac8e-f4b481f49da9"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Data Source: Azure",
    "Data Source: Microsoft Entra ID",
    "Data Source: Microsoft Entra ID Sign-in Logs",
    "Use Case: Identity and Access Audit",
    "Resources: Investigation Guide",
    "Tactic: Initial Access",

]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset: "azure.signinlogs" and
event.action: "Sign-in activity" and
event.outcome: "success" and
(
  (
    azure.signinlogs.properties.app_id: (
      "aebc6443-996d-45c2-90f0-388ff96faa56" or
      "04b07795-8ddb-461a-bbee-02f9e1bf7b46" or
      "1950a258-227b-4e31-a9cf-717495945fc2"
    ) and (
      azure.signinlogs.properties.resource_id: ("00000003-0000-0000-c000-000000000000" or "00000002-0000-0000-c000-000000000000") or
      azure.signinlogs.properties.resource_display_name: ("Microsoft Graph" or "Windows Azure Active Directory")
    )
  ) or
  (
    azure.signinlogs.properties.app_id: (
      "00b41c95-dab0-4487-9791-b9d2c32c80f2" or
      "1fec8e78-bce4-4aaf-ab1b-5451cc387264" or
      "26a7ee05-5602-4d76-a7ba-eae8b7b67941" or
      "27922004-5251-4030-b22d-91ecd9a37ea4" or
      "4813382a-8fa7-425e-ab75-3b753aab3abb" or
      "ab9b8c07-8f02-4f72-87fa-80105867a763" or
      "872cd9fa-d31f-45e0-9eab-6e460a02d1f1" or
      "af124e86-4e96-495a-b70a-90f90ab96707" or
      "2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8" or
      "844cca35-0656-46ce-b636-13f48b0eecbd" or
      "87749df4-7ccf-48f8-aa87-704bad0e0e16" or
      "cf36b471-5b44-428c-9ce7-313bf84528de" or
      "0ec893e0-5785-4de6-99da-4ed124e5296c" or
      "22098786-6e16-43cc-a27d-191a01a1e3b5" or
      "4e291c71-d680-4d0e-9640-0a3358e31177" or
      "57336123-6e14-4acc-8dcf-287b6088aa28" or
      "57fcbcfa-7cee-4eb1-8b25-12d2030b4ee0" or
      "66375f6b-983f-4c2c-9701-d680650f588f" or
      "a40d7d7d-59aa-447e-a655-679a4107e548" or
      "a569458c-7f2b-45cb-bab9-b7dee514d112" or
      "b26aadf8-566f-4478-926f-589f601d9c74" or
      "c0d2a505-13b8-4ae0-aa9e-cddd5eab0b12" or
      "d326c1ce-6cc6-4de2-bebc-4591e5e13ef0" or
      "e9c51622-460d-4d3d-952d-966a5b1da34c" or
      "eb539595-3fe1-474e-9c1d-feb3625d1be5" or
      "ecd6b820-32c2-49b6-98a6-444530e5a77a" or
      "f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" or
      "f44b1140-bc5e-48c6-8dc0-5cf5a53c0e34" or
      "be1918be-3fe3-4be9-b32b-b542fc27f02e" or
      "cab96880-db5b-4e15-90a7-f3f1d62ffe39" or
      "d7b530a4-7680-4c23-a8bf-c52c121d2e87" or
      "dd47d17a-3194-4d86-bfd5-c6ae6f5651e3" or
      "e9b154d0-7658-433b-bb25-6b8e0a8a7c59"
    ) and (
      azure.signinlogs.properties.resource_id: "00000002-0000-0000-c000-000000000000" or
      azure.signinlogs.properties.resource_display_name: "Windows Azure Active Directory"
    )
  )
)
'''


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

[[rule.threat.technique]]
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"

[[rule.threat.technique.subtechnique]]
id = "T1078.004"
name = "Cloud Accounts"
reference = "https://attack.mitre.org/techniques/T1078/004/"

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

[[rule.threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"

[[rule.threat.technique]]
id = "T1199"
name = "Trusted Relationship"
reference = "https://attack.mitre.org/techniques/T1199/"

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

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

[[rule.threat.technique]]
id = "T1528"
name = "Steal Application Access Token"
reference = "https://attack.mitre.org/techniques/T1528/"

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

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

[[rule.threat.technique]]
id = "T1550"
name = "Use Alternate Authentication Material"
reference = "https://attack.mitre.org/techniques/T1550/"

[[rule.threat.technique.subtechnique]]
id = "T1550.001"
name = "Application Access Token"
reference = "https://attack.mitre.org/techniques/T1550/001/"

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

Stages and Predicates

Stage 1: query

data_stream.dataset: "azure.signinlogs" and
event.action: "Sign-in activity" and
event.outcome: "success" and
(
  (
    azure.signinlogs.properties.app_id: (
      "aebc6443-996d-45c2-90f0-388ff96faa56" or
      "04b07795-8ddb-461a-bbee-02f9e1bf7b46" or
      "1950a258-227b-4e31-a9cf-717495945fc2"
    ) and (
      azure.signinlogs.properties.resource_id: ("00000003-0000-0000-c000-000000000000" or "00000002-0000-0000-c000-000000000000") or
      azure.signinlogs.properties.resource_display_name: ("Microsoft Graph" or "Windows Azure Active Directory")
    )
  ) or
  (
    azure.signinlogs.properties.app_id: (
      "00b41c95-dab0-4487-9791-b9d2c32c80f2" or
      "1fec8e78-bce4-4aaf-ab1b-5451cc387264" or
      "26a7ee05-5602-4d76-a7ba-eae8b7b67941" or
      "27922004-5251-4030-b22d-91ecd9a37ea4" or
      "4813382a-8fa7-425e-ab75-3b753aab3abb" or
      "ab9b8c07-8f02-4f72-87fa-80105867a763" or
      "872cd9fa-d31f-45e0-9eab-6e460a02d1f1" or
      "af124e86-4e96-495a-b70a-90f90ab96707" or
      "2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8" or
      "844cca35-0656-46ce-b636-13f48b0eecbd" or
      "87749df4-7ccf-48f8-aa87-704bad0e0e16" or
      "cf36b471-5b44-428c-9ce7-313bf84528de" or
      "0ec893e0-5785-4de6-99da-4ed124e5296c" or
      "22098786-6e16-43cc-a27d-191a01a1e3b5" or
      "4e291c71-d680-4d0e-9640-0a3358e31177" or
      "57336123-6e14-4acc-8dcf-287b6088aa28" or
      "57fcbcfa-7cee-4eb1-8b25-12d2030b4ee0" or
      "66375f6b-983f-4c2c-9701-d680650f588f" or
      "a40d7d7d-59aa-447e-a655-679a4107e548" or
      "a569458c-7f2b-45cb-bab9-b7dee514d112" or
      "b26aadf8-566f-4478-926f-589f601d9c74" or
      "c0d2a505-13b8-4ae0-aa9e-cddd5eab0b12" or
      "d326c1ce-6cc6-4de2-bebc-4591e5e13ef0" or
      "e9c51622-460d-4d3d-952d-966a5b1da34c" or
      "eb539595-3fe1-474e-9c1d-feb3625d1be5" or
      "ecd6b820-32c2-49b6-98a6-444530e5a77a" or
      "f05ff7c9-f75a-4acd-a3b5-f4b6a870245d" or
      "f44b1140-bc5e-48c6-8dc0-5cf5a53c0e34" or
      "be1918be-3fe3-4be9-b32b-b542fc27f02e" or
      "cab96880-db5b-4e15-90a7-f3f1d62ffe39" or
      "d7b530a4-7680-4c23-a8bf-c52c121d2e87" or
      "dd47d17a-3194-4d86-bfd5-c6ae6f5651e3" or
      "e9b154d0-7658-433b-bb25-6b8e0a8a7c59"
    ) and (
      azure.signinlogs.properties.resource_id: "00000002-0000-0000-c000-000000000000" or
      azure.signinlogs.properties.resource_display_name: "Windows Azure Active Directory"
    )
  )
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
azure.signinlogs.properties.app_idin
  • 00b41c95-dab0-4487-9791-b9d2c32c80f2 corpus 2 (elastic 2)
  • 04b07795-8ddb-461a-bbee-02f9e1bf7b46 corpus 3 (elastic 3)
  • 0ec893e0-5785-4de6-99da-4ed124e5296c corpus 2 (elastic 2)
  • 1950a258-227b-4e31-a9cf-717495945fc2 corpus 3 (elastic 3)
  • 1fec8e78-bce4-4aaf-ab1b-5451cc387264 corpus 2 (elastic 2)
  • 22098786-6e16-43cc-a27d-191a01a1e3b5 corpus 2 (elastic 2)
  • 26a7ee05-5602-4d76-a7ba-eae8b7b67941 corpus 2 (elastic 2)
  • 27922004-5251-4030-b22d-91ecd9a37ea4 corpus 2 (elastic 2)
  • 2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8 corpus 2 (elastic 2)
  • 4813382a-8fa7-425e-ab75-3b753aab3abb corpus 2 (elastic 2)
  • 4e291c71-d680-4d0e-9640-0a3358e31177 corpus 2 (elastic 2)
  • 57336123-6e14-4acc-8dcf-287b6088aa28 corpus 2 (elastic 2)
  • 57fcbcfa-7cee-4eb1-8b25-12d2030b4ee0 corpus 2 (elastic 2)
  • 66375f6b-983f-4c2c-9701-d680650f588f corpus 2 (elastic 2)
  • 844cca35-0656-46ce-b636-13f48b0eecbd corpus 2 (elastic 2)
  • 872cd9fa-d31f-45e0-9eab-6e460a02d1f1 corpus 3 (elastic 3)
  • 87749df4-7ccf-48f8-aa87-704bad0e0e16 corpus 2 (elastic 2)
  • a40d7d7d-59aa-447e-a655-679a4107e548 corpus 2 (elastic 2)
  • a569458c-7f2b-45cb-bab9-b7dee514d112 corpus 2 (elastic 2)
  • ab9b8c07-8f02-4f72-87fa-80105867a763 corpus 2 (elastic 2)
  • aebc6443-996d-45c2-90f0-388ff96faa56 corpus 3 (elastic 3)
  • af124e86-4e96-495a-b70a-90f90ab96707 corpus 2 (elastic 2)
  • b26aadf8-566f-4478-926f-589f601d9c74 corpus 2 (elastic 2)
  • be1918be-3fe3-4be9-b32b-b542fc27f02e corpus 2 (elastic 2)
  • c0d2a505-13b8-4ae0-aa9e-cddd5eab0b12 corpus 2 (elastic 2)
  • cab96880-db5b-4e15-90a7-f3f1d62ffe39 corpus 2 (elastic 2)
  • cf36b471-5b44-428c-9ce7-313bf84528de corpus 2 (elastic 2)
  • d326c1ce-6cc6-4de2-bebc-4591e5e13ef0 corpus 2 (elastic 2)
  • d7b530a4-7680-4c23-a8bf-c52c121d2e87 corpus 2 (elastic 2)
  • dd47d17a-3194-4d86-bfd5-c6ae6f5651e3 corpus 2 (elastic 2)
  • e9b154d0-7658-433b-bb25-6b8e0a8a7c59 corpus 2 (elastic 2)
  • e9c51622-460d-4d3d-952d-966a5b1da34c corpus 2 (elastic 2)
  • eb539595-3fe1-474e-9c1d-feb3625d1be5 corpus 2 (elastic 2)
  • ecd6b820-32c2-49b6-98a6-444530e5a77a corpus 2 (elastic 2)
  • f05ff7c9-f75a-4acd-a3b5-f4b6a870245d corpus 2 (elastic 2)
  • f44b1140-bc5e-48c6-8dc0-5cf5a53c0e34 corpus 2 (elastic 2)
field:"azure_ad::app_id" kind:in
azure.signinlogs.properties.resource_display_nameeq
  • Windows Azure Active Directory
field:"azure_ad::resource_display_name" kind:eq value:"Windows Azure Active Directory"
azure.signinlogs.properties.resource_display_namein
  • Microsoft Graph
  • Windows Azure Active Directory
field:"azure_ad::resource_display_name" kind:in
azure.signinlogs.properties.resource_ideq
  • 00000002-0000-0000-c000-000000000000 corpus 2 (elastic 2)
field:"azure_ad::resource_id" kind:eq value:"00000002-0000-0000-c000-000000000000"
azure.signinlogs.properties.resource_idin
  • 00000002-0000-0000-c000-000000000000 corpus 2 (elastic 2)
  • 00000003-0000-0000-c000-000000000000 corpus 5 (elastic 5)
field:"azure_ad::resource_id" kind:in
data_stream.dataseteq
  • azure.signinlogs corpus 26 (elastic 26)
field:"data_stream.dataset" kind:eq value:"azure.signinlogs"
event.actioneq
  • Sign-in activity corpus 7 (elastic 7)
field:"EventType" kind:eq value:"Sign-in activity"
event.outcomeeq
  • success corpus 306 (elastic 306)
field:"event.outcome" kind:eq value:"success"

File Cloned by Unsigned or Untrusted Process

#
Source
github.com/elastic/protections-artifacts

Detects when a file is cloned by an unsigned or untrusted process. Cloning of files is highly abnormal but especially so when done by an unsigned or untrusted process to duplicate a file or payload via api call.

MITRE ATT&CK Coverage

TacticTechniques
Execution

Rule Body

[rule]
description = """
Detects when a file is cloned by an unsigned or untrusted process. Cloning of files is highly abnormal but especially so
when done by an unsigned or untrusted process to duplicate a file or payload via api call.
"""
id = "aac13c8f-fd32-43c8-b71c-85019ad6fe50"
license = "Elastic License v2"
name = "File Cloned by Unsigned or Untrusted Process"
os_list = ["macos"]
version = "1.0.4"

query = '''
file where event.action == "clone" and 
 (process.code_signature.exists == false or process.code_signature.trusted == false)
'''

min_endpoint_version = "8.11.1"
optional_actions = []
[[actions]]
action = "kill_process"
field = "Effective_process.executable"
state = 0

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1559"
name = "Inter-Process Communication"
reference = "https://attack.mitre.org/techniques/T1559/"


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

[internal]
min_endpoint_version = "8.11.1"

Stages and Predicates

Stage 1: file

file where event.action == "clone" and 
 (process.code_signature.exists == false or process.code_signature.trusted == false)

Indicators

These rows show field, operator, and value matches.

GitHub Owner Role Granted To User

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

This rule detects when a member is granted the organization owner role of a GitHub organization. This role provides admin level privileges. Any new owner role should be investigated to determine its validity. Unauthorized owner roles could indicate compromise within your organization and provide unlimited access to data and settings.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2023/09/11"
integration = ["github"]
maturity = "production"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
This rule detects when a member is granted the organization owner role of a GitHub organization. This role provides
admin level privileges. Any new owner role should be investigated to determine its validity. Unauthorized owner roles
could indicate compromise within your organization and provide unlimited access to data and settings.
"""
from = "now-9m"
index = ["logs-github.audit-*"]
language = "eql"
license = "Elastic License v2"
name = "GitHub Owner Role Granted To User"
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 GitHub Owner Role Granted To User

In GitHub organizations, the owner role grants comprehensive administrative privileges, enabling full control over repositories, settings, and data. Adversaries may exploit this by elevating privileges to maintain persistence or exfiltrate data. The detection rule monitors audit logs for changes in member roles to 'admin', signaling potential unauthorized access or privilege escalation attempts, thus aiding in early threat identification.

### Possible investigation steps

- Review the audit logs for the specific event where the member's role was changed to 'admin' to identify the user who made the change and the user who received the new role.
- Verify the legitimacy of the role change by contacting the user who was granted the owner role and the user who performed the action to confirm if the change was authorized.
- Check the organization's recent activity logs for any unusual or suspicious actions performed by the user who was granted the owner role, such as changes to repository settings or data access.
- Investigate any recent changes in the organization's membership or permissions that could indicate a broader compromise or unauthorized access.
- Assess the potential impact of the role change by identifying sensitive repositories or data that the new owner role could access, and determine if any data exfiltration or unauthorized changes have occurred.

### False positive analysis

- Role changes due to organizational restructuring or legitimate promotions can trigger alerts. Regularly update the list of expected role changes to minimize unnecessary alerts.
- Automated scripts or integrations that manage user roles might inadvertently trigger the rule. Identify and whitelist these scripts to prevent false positives.
- Temporary role assignments for project-specific tasks can be mistaken for unauthorized access. Implement a process to document and pre-approve such temporary changes.
- Changes made by trusted administrators during routine audits or maintenance may be flagged. Maintain a log of scheduled maintenance activities to cross-reference with alerts.
- Onboarding processes that involve granting admin roles to new employees can generate alerts. Ensure that onboarding procedures are documented and known exceptions are configured in the detection system.

### Response and remediation

- Immediately revoke the owner role from the user account identified in the alert to prevent further unauthorized access or changes.
- Conduct a thorough review of recent activities performed by the user with the elevated privileges to identify any unauthorized changes or data access.
- Reset the credentials and enforce multi-factor authentication for the affected user account to secure it against further compromise.
- Notify the security team and relevant stakeholders about the potential breach and involve them in the investigation and remediation process.
- Review and update access control policies to ensure that owner roles are granted only through a formal approval process and are regularly audited.
- Implement additional monitoring and alerting for changes to high-privilege roles within the organization to detect similar threats in the future."""
risk_score = 47
rule_id = "9b343b62-d173-4cfd-bd8b-e6379f964ca4"
severity = "medium"
tags = [
    "Domain: Cloud",
    "Use Case: Threat Detection",
    "Use Case: UEBA",
    "Tactic: Persistence",
    "Data Source: Github",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
iam where data_stream.dataset == "github.audit" and event.action == "org.update_member" and github.permission == "admin"
'''


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

[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.003"
name = "Additional Cloud Roles"
reference = "https://attack.mitre.org/techniques/T1098/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 = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"

[[rule.threat.technique.subtechnique]]
id = "T1098.003"
name = "Additional Cloud Roles"
reference = "https://attack.mitre.org/techniques/T1098/003/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

Stages and Predicates

Stage 1: iam

iam where data_stream.dataset == "github.audit" and event.action == "org.update_member" and github.permission == "admin"

Indicators

These rows show field, operator, and value matches.

Google Workspace User Organizational Unit Changed

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

Users in Google Workspace are typically assigned a specific organizational unit that grants them permissions to certain services and roles that are inherited from this organizational unit. Adversaries may compromise a valid account and change which organizational account the user belongs to which then could allow them to inherit permissions to applications and resources inaccessible prior to.

Known False Positives

  • Google Workspace administrators may change which organizational unit a user belongs to as a result of internal role adjustments.

MITRE ATT&CK Coverage

Telemetry Coverage

Rules Detecting the Same Action

These rules filter on the same operation.

Rule Body

[metadata]
creation_date = "2022/09/06"
integration = ["google_workspace"]
maturity = "production"
updated_date = "2026/05/22"

[rule]
author = ["Elastic"]
description = """
Users in Google Workspace are typically assigned a specific organizational unit that grants them permissions to certain
services and roles that are inherited from this organizational unit. Adversaries may compromise a valid account and
change which organizational account the user belongs to which then could allow them to inherit permissions to
applications and resources inaccessible prior to.
"""
false_positives = [
    """
    Google Workspace administrators may change which organizational unit a user belongs to as a result of internal role
    adjustments.
    """,
]
from = "now-130m"
index = ["filebeat-*", "logs-google_workspace.admin-*"]
interval = "10m"
language = "kuery"
license = "Elastic License v2"
name = "Google Workspace User Organizational Unit Changed"
note = """## Triage and analysis

### Investigating Google Workspace User Organizational Unit Changed

An organizational unit is a group that an administrator can create in the Google Admin console to apply settings to a specific set of users for Google Workspace. By default, all users are placed in the top-level (parent) organizational unit. Child organizational units inherit the settings from the parent but can be changed to fit the needs of the child organizational unit.

Permissions and privileges for users are often inherited from the organizational unit they are placed in. Therefore, if a user is changed to a separate organizational unit, they will inherit all privileges and permissions. User accounts may have unexpected privileges when switching organizational units that would allow a threat actor to gain a stronger foothold within the organization. The principle of least privileged (PoLP) should be followed when users are switched to different groups in Google Workspace.

This rule identifies when a user has been moved to a different organizational unit.

### Possible investigation steps

- Identify the associated user accounts by reviewing `user.name` or `user.email` fields in the alert.
  - The `user.target.email` field contains the user that had their assigned organizational unit switched.
- Identify the user's previously assigned unit and new organizational unit by checking the `google_workspace.admin.org_unit.name` and `google_workspace.admin.new_value` fields.
- Identify Google Workspace applications whose settings were explicitly set for this organizational unit.
    - Search for `event.action` is `CREATE_APPLICATION_SETTING` where `google_workspace.admin.org_unit.name` is the new organizational unit.
- After identifying the involved user, verify administrative privileges are scoped properly to allow changing user organizational units.
- Identify if the user account was recently created by searching for `event.action: CREATE_USER`.
  - Add `user.email` with the target user account that recently had their organizational unit changed.
- Filter on `user.name` or `user.target.email` of the user who took this action and review the last 48 hours of activity for anything that may indicate a compromise.

### False positive analysis

- After identifying the user account that changed another user's organizational unit, verify the action was intentional.
- Verify whether the target user who received this update is expected to inherit privileges from the new organizational unit.
- Review potential maintenance notes or organizational changes. They might explain why a user's organization was changed.

### Response and remediation

- Initiate the incident response process based on the outcome of the triage.
- Disable or limit the account during the investigation and response.
- Identify the possible impact of the incident and prioritize accordingly; the following actions can help you gain context:
    - Identify the account role in the cloud environment.
    - Assess the criticality of affected services and servers.
    - Work with your IT team to identify and minimize the impact on users.
    - Identify if the attacker is moving laterally and compromising other accounts, servers, or services.
    - Identify any regulatory or legal ramifications related to this activity.
- Investigate credential exposure on systems compromised or used by the attacker to ensure all compromised accounts are identified. Reset passwords or delete API keys as needed to revoke the attacker's access to the environment. Work with your IT teams to minimize the impact on business operations during these actions.
- Review the permissions assigned to the implicated user to ensure that the least privilege principle is being followed.
- Implement security best practices [outlined](https://support.google.com/a/answer/7587183) by Google.
- Determine the initial vector abused by the attacker and take action to prevent reinfection via 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

The Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.

### Important Information Regarding Google Workspace Event Lag Times
- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.
- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.
- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.
- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).
- See the following references for further information:
  - https://support.google.com/a/answer/7061566
  - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-google_workspace.html"""
references = [
    "https://support.google.com/a/answer/6328701?hl=en#",
    "https://www.elastic.co/security-labs/google-workspace-attack-surface-part-one",
    "https://www.elastic.co/security-labs/google-workspace-attack-surface-part-two",
]
risk_score = 21
rule_id = "cc6a8a20-2df2-11ed-8378-f661ea17fbce"
severity = "low"
tags = [
    "Domain: Cloud",
    "Data Source: Google Workspace",
    "Use Case: Configuration Audit",
    "Tactic: Persistence",
    "Tactic: Privilege Escalation",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
data_stream.dataset:"google_workspace.admin" and google_workspace.event.type:"USER_SETTINGS" and event.action:"MOVE_USER_TO_ORG_UNIT"
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"
[[rule.threat.technique.subtechnique]]
id = "T1098.003"
name = "Additional Cloud Roles"
reference = "https://attack.mitre.org/techniques/T1098/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 = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"
[[rule.threat.technique.subtechnique]]
id = "T1098.003"
name = "Additional Cloud Roles"
reference = "https://attack.mitre.org/techniques/T1098/003/"



[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "user.name",
    "user.email",
    "source.ip",
    "google_workspace.actor.type",
    "user.target.email",
    "google_workspace.admin.org_unit.name",
    "google_workspace.admin.new_value",
    "event.action",
    "cloud.account.id",
]

Stages and Predicates

Stage 1: query

data_stream.dataset:"google_workspace.admin" and google_workspace.event.type:"USER_SETTINGS" and event.action:"MOVE_USER_TO_ORG_UNIT"

Indicators

These rows show field, operator, and value matches.

Linux External IP Address Discovery via Curl

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

Detects applications making a curl request to a known public IP address lookup web service. Malware tends to perform this action to assess potential targets.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2026/07/02"
integration = ["endpoint", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/07/06"

[rule]
author = ["Elastic"]
description = """
Detects applications making a curl request to a known public IP address lookup web service. Malware tends to perform this 
action to assess potential targets.
"""
from = "now-9m"
index = [
        "logs-endpoint.events.process*",
        "logs-sentinel_one_cloud_funnel.*",
]
language = "eql"
license = "Elastic License v2"
name = "Linux External IP Address Discovery via Curl"
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 Linux External IP Address Discovery via Curl

This rule flags a Linux process that uses curl to contact public IP lookup sites, a common way malware learns the host’s internet-facing address before choosing follow-on actions. An attacker who gains shell access on a server or container may run curl against services like ifconfig.me or ipify, then use the returned address to verify outbound reachability, tailor command-and-control, or decide whether the system sits behind cloud or NAT infrastructure.

### Possible investigation steps

- Trace the full process ancestry and nearby commands to determine whether the curl execution came from an interactive shell, scheduled task, deployment script, container entrypoint, or an unexpected program launched from a writable path.
- Review the invoked URL, arguments, working directory, and any captured output to determine whether the request was a one-off connectivity check or part of a broader script performing follow-on discovery, download, or beaconing.
- Correlate the activity with the initiating account, TTY/session details, recent SSH and sudo events, and change records to quickly separate approved administrator troubleshooting from suspicious post-compromise behavior.
- Pivot to surrounding network activity from the same host to identify repeated lookups, subsequent outbound connections to unfamiliar infrastructure, or signs of staging and command-and-control immediately after the public IP query.
- Inspect the parent script or binary on disk for recent creation or modification, unusual persistence mechanisms, and prevalence on peer systems to assess whether the behavior is tied to malware, a rogue change, or benign automation.

### False positive analysis

- Legitimate startup, login-banner, or scheduled maintenance scripts may use curl to learn the host’s public IP for configuration or status display, so verify the parent script or service path is expected, recently approved, and consistently seen at boot or on a routine schedule.
- An administrator or engineer may manually run curl to a public IP lookup site during troubleshooting or deployment validation, so confirm the initiating user, TTY or session context, and shell history align with authorized activity and that no suspicious follow-on commands occurred.

### Response and remediation

- Isolate the affected Linux host or container from the network immediately, allow only a secured management path, and preserve volatile evidence such as the running parent process, shell history, and the script or binary that launched curl.
- Terminate the malicious process chain and remove persistence by inspecting and cleaning cron jobs, systemd unit files, rc.local, user shell profiles, container entrypoints, SSH authorized_keys, and any attacker files staged in writable locations such as /tmp, /var/tmp, or /dev/shm.
- Rotate credentials and secrets exposed to the compromised system, including SSH keys, API tokens, cloud instance credentials, and application secrets found in scripts, environment files, or shell history.
- Restore the asset to a known-good state by rebuilding from a trusted image or clean backup and validating startup scripts, packages, and container images before returning the system to production.
- Escalate to incident response and broaden scoping across peer systems if the IP lookup was followed by downloads, reverse shells, new outbound connections to unfamiliar infrastructure, or if the same parent script, binary, or persistence artifact appears on multiple hosts.
- Harden the environment by restricting outbound curl access to approved destinations, blocking public IP lookup services where not needed, limiting execution from writable directories, and adding detections for unexpected systemd, cron, and shell-profile modifications.
"""
risk_score = 21
rule_id = "996e2e09-087e-4e99-a3cc-a9225d24ba3d"
setup = """## Setup

This rule requires data coming in from one of the following integrations:
- Elastic Defend

### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.

#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).

#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "low"
tags = [
  "Domain: Endpoint",
  "OS: Linux",
  "Use Case: Threat Detection",
  "Tactic: Discovery",
  "Data Source: Elastic Defend",
  "Data Source: SentinelOne",
  "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "linux" and event.type == "start" and event.action in ("exec", "start") and
process.name == "curl" and (
  process.parent.name like ".*" or process.parent.executable like (
    "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/opt/*",  "/etc/*", "./*", "/run/user/*", "/var/run/user/*",
    "/usr/bin/*", "/bin/*", "/usr/local/bin/*", "/sbin/*", "/usr/sbin/*", "/usr/local/sbin/*",
    "/usr/lib/*", "/usr/local/lib/*", "/lib/*", "/lib64/*", "/usr/lib64/*", "/usr/local/lib64/*"
  )
) and
process.command_line like~ (
  "*ip-api.com*", "*checkip.dyndns.org*", "*api.ipify.org*", "*whatismyip.akamai.com*", "*bot.whatismyipaddress.com*",
  "*ifcfg.me*", "*ifconfig.me*", "*ident.me*", "*ipof.in*", "*ip.tyk.nu*", "*icanhazip.com*", "*curlmyip.com*",
  "*wgetip.com*", "*eth0.me*", "*ipecho.net*", "*ip.appspot.com*", "*api.myip.com*", "*geoiptool.com*", "*api.2ip.ua*",
  "*api.ip.sb*", "*ipinfo.io*", "*checkip.amazonaws.com*", "*wtfismyip.com*", "*iplogger.*", "*freegeoip.net*",
  "*freegeoip.app*", "*geoplugin.net*", "*myip.dnsomatic.com*", "*www.geoplugin.net*",
  "*api64.ipify.org*", "*ip4.seeip.org*", "*.geojs.io*", "*portmap.io*", "*api.db-ip.com*",
  "*geolocation-db.com*", "*httpbin.org*", "*myip.opendns.com*", "*ipv4.icanhazip.com*", "*ipv6.icanhazip.com*"
) and
not (
  process.parent.name in ("jamf", "make") or
  process.parent.name in (".", "./alert_api_call.sh", "nvim", "teleport") or
  process.parent.executable like (
    "/usr/local/bin/teleport", "/usr/local/bin/current_ip", "/tmp/go-build*", "/usr/bin/neofetch",
    "/usr/bin/show-location-info", "/opt/tpot/bin/myip.sh", "/usr/sbin/sshd", "/tmp/newroot/var/quest/kace/scripts/*",
    "./Linux_Inventory_Sheets.sh", "/opt/qvm/bin/update_info_qsuite", "/usr/lib/check_mk_agent/local/public_ip_check",
    "/opt/teleport/system/bin/teleport", "/opt/Elastic/Endpoint/elastic-endpoint", "/etc/update-motd.d/motd.sh",
    "/opt/coe/cadence/IC231/tools.lnx86/cda/bin/64bit/cda.exe", "/etc/update-motd.d/10-armbian-header",
    "/opt/saltstack/salt/bin/python*", "/usr/bin/python*", "/usr/local/bin/detect-external-ip"
  ) or
  process.parent.args in ("/var/www/html/admin/modules/leucoalarm/scripts/system.php", "/etc/cont-init.d/50-ddns") or
  (
    process.parent.executable == "/usr/bin/java" and
    process.args like "/opt/streamsets-datacollector/libexec/bootstrap-libs/*"
  ) or
  process.parent.command_line == "runc init" or
  (
    process.parent.executable == "/usr/bin/busybox" and
    (process.parent.command_line == "sh /etc/cont-init.d/50-ddns" or process.working_directory == "/opt/outline-server")
  )
)
'''

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

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

  [[rule.threat.technique]]
  name = "System Network Configuration Discovery"
  id = "T1016"
  reference = "https://attack.mitre.org/techniques/T1016/"

Stages and Predicates

Stage 1: process

process where host.os.type == "linux" and event.type == "start" and event.action in ("exec", "start") and
process.name == "curl" and (
  process.parent.name like ".*" or process.parent.executable like (
    "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/opt/*",  "/etc/*", "./*", "/run/user/*", "/var/run/user/*",
    "/usr/bin/*", "/bin/*", "/usr/local/bin/*", "/sbin/*", "/usr/sbin/*", "/usr/local/sbin/*",
    "/usr/lib/*", "/usr/local/lib/*", "/lib/*", "/lib64/*", "/usr/lib64/*", "/usr/local/lib64/*"
  )
) and
process.command_line like~ (
  "*ip-api.com*", "*checkip.dyndns.org*", "*api.ipify.org*", "*whatismyip.akamai.com*", "*bot.whatismyipaddress.com*",
  "*ifcfg.me*", "*ifconfig.me*", "*ident.me*", "*ipof.in*", "*ip.tyk.nu*", "*icanhazip.com*", "*curlmyip.com*",
  "*wgetip.com*", "*eth0.me*", "*ipecho.net*", "*ip.appspot.com*", "*api.myip.com*", "*geoiptool.com*", "*api.2ip.ua*",
  "*api.ip.sb*", "*ipinfo.io*", "*checkip.amazonaws.com*", "*wtfismyip.com*", "*iplogger.*", "*freegeoip.net*",
  "*freegeoip.app*", "*geoplugin.net*", "*myip.dnsomatic.com*", "*www.geoplugin.net*",
  "*api64.ipify.org*", "*ip4.seeip.org*", "*.geojs.io*", "*portmap.io*", "*api.db-ip.com*",
  "*geolocation-db.com*", "*httpbin.org*", "*myip.opendns.com*", "*ipv4.icanhazip.com*", "*ipv6.icanhazip.com*"
) and
not (
  process.parent.name in ("jamf", "make") or
  process.parent.name in (".", "./alert_api_call.sh", "nvim", "teleport") or
  process.parent.executable like (
    "/usr/local/bin/teleport", "/usr/local/bin/current_ip", "/tmp/go-build*", "/usr/bin/neofetch",
    "/usr/bin/show-location-info", "/opt/tpot/bin/myip.sh", "/usr/sbin/sshd", "/tmp/newroot/var/quest/kace/scripts/*",
    "./Linux_Inventory_Sheets.sh", "/opt/qvm/bin/update_info_qsuite", "/usr/lib/check_mk_agent/local/public_ip_check",
    "/opt/teleport/system/bin/teleport", "/opt/Elastic/Endpoint/elastic-endpoint", "/etc/update-motd.d/motd.sh",
    "/opt/coe/cadence/IC231/tools.lnx86/cda/bin/64bit/cda.exe", "/etc/update-motd.d/10-armbian-header",
    "/opt/saltstack/salt/bin/python*", "/usr/bin/python*", "/usr/local/bin/detect-external-ip"
  ) or
  process.parent.args in ("/var/www/html/admin/modules/leucoalarm/scripts/system.php", "/etc/cont-init.d/50-ddns") or
  (
    process.parent.executable == "/usr/bin/java" and
    process.args like "/opt/streamsets-datacollector/libexec/bootstrap-libs/*"
  ) or
  process.parent.command_line == "runc init" or
  (
    process.parent.executable == "/usr/bin/busybox" and
    (process.parent.command_line == "sh /etc/cont-init.d/50-ddns" or process.working_directory == "/opt/outline-server")
  )
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actionin
  • exec
  • start
field:"EventType" kind:in
event.typeeq
  • start
field:"event.type" kind:eq value:"start"
process.command_linewildcard
  • *.geojs.io*
  • *api.2ip.ua*
  • *api.db-ip.com*
  • *api.ip.sb*
  • *api.ipify.org*
  • *api.myip.com*
  • *api64.ipify.org*
  • *bot.whatismyipaddress.com*
  • *checkip.amazonaws.com*
  • *checkip.dyndns.org*
  • *curlmyip.com*
  • *eth0.me*
  • *freegeoip.app*
  • *freegeoip.net*
  • *geoiptool.com*
  • *geolocation-db.com*
  • *geoplugin.net*
  • *httpbin.org*
  • *icanhazip.com*
  • *ident.me*
  • *ifcfg.me*
  • *ifconfig.me*
  • *ip-api.com*
  • *ip.appspot.com*
  • *ip.tyk.nu*
  • *ip4.seeip.org*
  • *ipecho.net*
  • *ipinfo.io*
  • *iplogger.*
  • *ipof.in*
  • *ipv4.icanhazip.com*
  • *ipv6.icanhazip.com*
  • *myip.dnsomatic.com*
  • *myip.opendns.com*
  • *portmap.io*
  • *wgetip.com*
  • *whatismyip.akamai.com*
  • *wtfismyip.com*
  • *www.geoplugin.net*
field:"CommandLine" kind:wildcard
process.nameeq
  • curl
field:"process_basename" kind:eq value:"curl"
process.parent.executablewildcard
  • ./*
  • /bin/*
  • /dev/shm/*
  • /etc/*
  • /lib/*
  • /lib64/*
  • /opt/*
  • /run/user/*
  • /sbin/*
  • /tmp/*
  • /usr/bin/*
  • /usr/lib/*
  • /usr/lib64/*
  • /usr/local/bin/*
  • /usr/local/lib/*
  • /usr/local/lib64/*
  • /usr/local/sbin/*
  • /usr/sbin/*
  • /var/run/user/*
  • /var/tmp/*
field:"ParentImage" kind:wildcard
process.parent.namewildcard
  • .*
field:"parent_process_basename" kind:wildcard value:".*"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.parent.command_lineeqsh /etc/cont-init.d/50-ddnsexcludes:process.parent.command_line field:"process.parent.command_line" value:"sh /etc/cont-init.d/50-ddns"
process.working_directoryeq/opt/outline-serverexcludes:process.working_directory field:"process.working_directory" value:"/opt/outline-server"
process.parent.executableeq/usr/bin/busyboxexcludes:process.parent.executable field:"process.parent.executable" value:"/usr/bin/busybox"
process.argsstarts_with/opt/streamsets-datacollector/libexec/bootstrap-libs/excludes:process.args field:"process.args" value:"/opt/streamsets-datacollector/libexec/bootstrap-libs/"
process.parent.executableeq/usr/bin/javaexcludes:process.parent.executable field:"process.parent.executable" value:"/usr/bin/java"
process.parent.argsin/etc/cont-init.d/50-ddns, /var/www/html/admin/modules/leucoalarm/scripts/system.phpexcludes:process.parent.args field:"process.parent.args" value:"/etc/cont-init.d/50-ddns" field:"process.parent.args" value:"/var/www/html/admin/modules/leucoalarm/scripts/system.php"
process.parent.command_lineeqrunc initexcludes:process.parent.command_line field:"process.parent.command_line" value:"runc init"
process.parent.executablewildcard/usr/local/bin/teleport, /usr/local/bin/current_ip, /tmp/go-build*, /usr/bin/neofetch, /usr/bin/show-location-info, /opt/tpot/bin/myip.sh, /usr/sbin/sshd, /tmp/newroot/var/quest/kace/scripts/*, ./Linux_Inventory_Sheets.sh, /opt/qvm/bin/update_info_qsuite, /usr/lib/check_mk_agent/local/public_ip_check, /opt/teleport/system/bin/teleport, /opt/Elastic/Endpoint/elastic-endpoint, /etc/update-motd.d/motd.sh, /opt/coe/cadence/IC231/tools.lnx86/cda/bin/64bit/cda.exe, /etc/update-motd.d/10-armbian-header, /opt/saltstack/salt/bin/python*, /usr/bin/python*, /usr/local/bin/detect-external-ipexcludes:process.parent.executable
process.parent.namein., ./alert_api_call.sh, nvim, teleportexcludes:process.parent.name
process.parent.nameinjamf, makeexcludes:process.parent.name field:"process.parent.name" value:"jamf" field:"process.parent.name" value:"make"

Multiple Rare Elastic Defend Behavior Rules by Host

#
Status
production
Severity
critical
Time window
1h
Group by
host.id, rule.name
Author
Elastic
Source
github.com/elastic/detection-rules

Identifies hosts that triggered multiple distinct Elastic Defend behavior rules, while reducing false positives by considering only behavior rules that appear on a single host globally (via INLINE STATS). Hosts with two or more such rare behavior rules are more likely to be compromised and warrant prioritized triage.

Rule Body

[metadata]
creation_date = "2026/02/19"
maturity = "production"
min_stack_comments = "ES|QL inline stats became generally available in 9.3.0"
min_stack_version = "9.3.0"
updated_date = "2026/04/10"

[rule]
author = ["Elastic"]
description = """
Identifies hosts that triggered multiple distinct Elastic Defend behavior rules, while reducing false positives by
considering only behavior rules that appear on a single host globally (via INLINE STATS). Hosts with two or more
such rare behavior rules are more likely to be compromised and warrant prioritized triage.
"""
from = "now-60m"
interval = "30m"
language = "esql"
license = "Elastic License v2"
name = "Multiple Rare Elastic Defend Behavior Rules by Host"
risk_score = 99
rule_id = "c4f7a2b1-5d8e-4c3a-9b6e-2f1a0d8c7e5b"
severity = "critical"
tags = ["Use Case: Threat Detection", "Rule Type: Higher-Order Rule", "Resources: Investigation Guide", "Data Source: Elastic Defend"]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-endpoint.alerts-* metadata _id
| where data_stream.dataset == "endpoint.alerts" and event.code == "behavior"
| INLINE STATS hosts = COUNT_DISTINCT(host.id) BY rule.name
// excludes rules triggering on multiple hosts to reduce potential FPs
| where hosts == 1
| stats Esql.rule_name_count_distinct = COUNT_DISTINCT(rule.name),
        Esql.rule_name_values = VALUES(rule.name),
        Esql.process_executable_values = VALUES(process.executable),
        Esql.process_parent_executable_values = VALUES(process.parent.executable),
        Esql.process_command_line_values = VALUES(process.command_line),
		Esql.process_parent_command_line_values = VALUES(process.parent.command_line),
        Esql.process_hash_sha256_values = VALUES(process.hash.sha256), 
		Esql.file_path_values = VALUES(file.path),
        Esql.dll_path_values = VALUES(dll.path),
        Esql.dll_hash_sha256_values = VALUES(dll.hash.sha256), 
		Esql.user_name_values = VALUES(user.name) by host.id
// at least 2 unique rules
| where Esql.rule_name_count_distinct >= 2
// populate fields to use in rule exceptions
| eval process.hash.sha256 = MV_FIRST(Esql.process_hash_sha256_values),
       process.executable = MV_FIRST(Esql.process_executable_values),
       process.parent.executable = MV_FIRST(Esql.process_parent_executable_values),
       process.command_line = MV_FIRST(Esql.process_command_line_values),
       user.name = MV_FIRST(Esql.user_name_values)
| Keep host.id, user.name, process.executable, process.parent.executable, process.hash.sha256, process.command_line, Esql.*
'''
note = """## Triage and analysis

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

### Investigating Multiple Rare Elastic Defend Behavior Rules by Host

This rule correlates Elastic Defend behavior alerts by host and applies a global prevalence filter: only behavior rules that fire on a single host in the lookback window are considered. Hosts that trigger two or more such rare behavior rules are flagged, as this pattern is more likely to indicate real compromise than commonly seen behavior rules.

### Possible investigation steps

- Review the listed behavior rule names and the associated process command lines (and parent command lines) to understand what actions triggered the alerts.
- Identify the user(s) associated with the activity and confirm whether the behavior is expected for that role or host.
- Correlate with other endpoint and network data for the host (process, network, file events) to assess scope and persistence.
- Compare timestamps of the alerts to determine if activity is part of a single campaign or staged execution.

### False positive analysis

- The global prevalence filter (rules seen on only one host) reduces noise from behavior rules that fire widely (e.g., common software or policy). If legitimate single-host tools or scripts trigger multiple rare behavior rules, consider documenting and excluding known-good rule names or hosts.
- Development or testing hosts may exhibit multiple rare behaviors; consider lowering severity or excluding those hosts if appropriate.

### Response and remediation

- Isolate the host if triage indicates compromise, then follow standard incident response procedures.
- Collect and preserve artifacts (process hashes, command lines, files) for further analysis.
- Escalate to the security team for full investigation and potential containment or eradication actions.
"""
references = [
"https://www.elastic.co/docs/reference/query-languages/esql/commands/inlinestats-by", 
"https://github.com/elastic/protections-artifacts/tree/main/behavior"
]

Stages and Predicates

Stage 1: from

from logs-endpoint.alerts-* metadata _id

Stage 2: where

| where data_stream.dataset == "endpoint.alerts" and event.code == "behavior"

Stage 3: inline_stats

| INLINE STATS hosts = COUNT_DISTINCT(host.id) BY rule.name

Stage 4: where

| where hosts == 1

Stage 5: stats

| stats Esql.rule_name_count_distinct = COUNT_DISTINCT(rule.name),
        Esql.rule_name_values = VALUES(rule.name),
        Esql.process_executable_values = VALUES(process.executable),
        Esql.process_parent_executable_values = VALUES(process.parent.executable),
        Esql.process_command_line_values = VALUES(process.command_line),
		Esql.process_parent_command_line_values = VALUES(process.parent.command_line),
        Esql.process_hash_sha256_values = VALUES(process.hash.sha256),
		Esql.file_path_values = VALUES(file.path),
        Esql.dll_path_values = VALUES(dll.path),
        Esql.dll_hash_sha256_values = VALUES(dll.hash.sha256),
		Esql.user_name_values = VALUES(user.name) by host.id

Stage 6: where

| where Esql.rule_name_count_distinct >= 2

Stage 7: eval

| eval process.hash.sha256 = MV_FIRST(Esql.process_hash_sha256_values),
       process.executable = MV_FIRST(Esql.process_executable_values),
       process.parent.executable = MV_FIRST(Esql.process_parent_executable_values),
       process.command_line = MV_FIRST(Esql.process_command_line_values),
       user.name = MV_FIRST(Esql.user_name_values)

Stage 8: keep

| Keep host.id, user.name, process.executable, process.parent.executable, process.hash.sha256, process.command_line, Esql.*

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
host.idKEEP host.id
user.nameKEEP user.name
process.executableKEEP process.executable
process.parent.executableKEEP process.parent.executable
process.hash.sha256KEEP process.hash.sha256
process.command_lineKEEP process.command_line
Esql.*KEEP Esql.*

Network Connection via Registration Utility

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

Identifies the native Windows tools regsvr32.exe, regsvr64.exe, RegSvcs.exe, or RegAsm.exe making a network connection. This may be indicative of an attacker bypassing allowlists or running arbitrary scripts via a signed Microsoft binary.

Known False Positives

  • Security testing may produce events like this. Activity of this kind performed by non-engineers and ordinary users is unusual.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

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

[transform]
[[transform.osquery]]
label = "Osquery - Retrieve DNS Cache"
query = "SELECT * FROM dns_cache"

[[transform.osquery]]
label = "Osquery - Retrieve All Services"
query = "SELECT description, display_name, name, path, pid, service_type, start_type, status, user_account FROM services"

[[transform.osquery]]
label = "Osquery - Retrieve Services Running on User Accounts"
query = """
SELECT description, display_name, name, path, pid, service_type, start_type, status, user_account FROM services WHERE
NOT (user_account LIKE '%LocalSystem' OR user_account LIKE '%LocalService' OR user_account LIKE '%NetworkService' OR
user_account == null)
"""

[[transform.osquery]]
label = "Osquery - Retrieve Service Unsigned Executables with Virustotal Link"
query = """
SELECT concat('https://www.virustotal.com/gui/file/', sha1) AS VtLink, name, description, start_type, status, pid,
services.path FROM services JOIN authenticode ON services.path = authenticode.path OR services.module_path =
authenticode.path JOIN hash ON services.path = hash.path WHERE authenticode.result != 'trusted'
"""


[rule]
author = ["Elastic"]
description = """
Identifies the native Windows tools regsvr32.exe, regsvr64.exe, RegSvcs.exe, or RegAsm.exe making a network connection.
This may be indicative of an attacker bypassing allowlists or running arbitrary scripts via a signed Microsoft binary.
"""
false_positives = [
    """
    Security testing may produce events like this. Activity of this kind performed by non-engineers and ordinary users
    is unusual.
    """,
]
from = "now-9m"
index = [
    "winlogbeat-*",
    "logs-endpoint.events.process-*",
    "logs-endpoint.events.network-*",
    "logs-windows.sysmon_operational-*",
]
language = "eql"
license = "Elastic License v2"
name = "Network Connection via Registration Utility"
note = """## Triage and analysis

### Investigating Network Connection via Registration Utility

By examining the specific traits of Windows binaries -- such as process trees, command lines, network connections, registry modifications, and so on -- it's possible to establish a baseline of normal activity. Deviations from this baseline can indicate malicious activity such as masquerading, and deserve further investigation.

This rule looks for the execution of `regsvr32.exe`, `RegAsm.exe`, or `RegSvcs.exe` utilities followed by a network connection to an external address. Attackers can abuse utilities to execute malicious files or masquerade as those utilities in order to bypass detections and evade defenses.

> **Note**:
> This investigation guide uses the [Osquery Markdown Plugin](https://www.elastic.co/guide/en/security/current/invest-guide-run-osquery.html) introduced in Elastic Stack version 8.5.0. Older Elastic Stack versions will display unrendered Markdown in this guide.

#### Possible investigation steps

- Investigate other alerts associated with the user/host during the past 48 hours.
- 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.
  - Investigate any abnormal behavior by the subject process such as network connections, registry or file modifications, and any spawned child processes.
  - Investigate the file digital signature and process original filename, if suspicious, treat it as potential malware.
- Investigate the target host that the signed binary is communicating with.
  - Check if the domain is newly registered or unexpected.
  - Check the reputation of the domain or IP address.
- Assess whether this behavior is prevalent in the environment by looking for similar occurrences across hosts.
- Examine the host for derived artifacts that indicate suspicious activities:
  - Analyze the process executable using a private sandboxed analysis system.
  - Observe and collect information about the following activities in both the sandbox and the alert subject host:
    - Attempts to contact external domains and addresses.
      - Use the Elastic Defend network events to determine domains and addresses contacted by the subject process by filtering by the process' `process.entity_id`.
      - Examine the DNS cache for suspicious or anomalous entries.
        - $osquery_0
    - Use the Elastic Defend registry events to examine registry keys accessed, modified, or created by the related processes in the process tree.
    - Examine the host services for suspicious or anomalous entries.
      - $osquery_1
      - $osquery_2
      - $osquery_3
  - Retrieve the files' SHA-256 hash values using the PowerShell `Get-FileHash` cmdlet and search for the existence and reputation of the hashes in resources like VirusTotal, Hybrid-Analysis, CISCO Talos, Any.run, etc.

### False positive analysis

- If this activity is expected and noisy in your environment, consider adding exceptions — preferably with a combination of destination IP address and command line conditions.

### Response and remediation

- Initiate the incident response process based on the outcome of the triage.
- Isolate the involved host to prevent further post-compromise behavior.
- If the triage identified malware, search the environment for additional compromised hosts.
  - Implement temporary network rules, procedures, and segmentation to contain the malware.
  - Stop suspicious processes.
  - Immediately block the identified indicators of compromise (IoCs).
  - Inspect the affected systems for additional malware backdoors like reverse shells, reverse proxies, or droppers that attackers could use to reinfect the system.
- Remove and block malicious artifacts identified during triage.
- Run a full antimalware scan. This may reveal additional artifacts left in the system, persistence mechanisms, and malware components.
- 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:

- [Sysmon Event ID 1 - Process Creation](https://ela.st/sysmon-event-1-setup)
- [Sysmon Event ID 3 - Network Connection](https://ela.st/sysmon-event-3-setup)
"""

references = ["https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml"]
risk_score = 21
rule_id = "fb02b8d3-71ee-4af1-bacd-215d23f17efa"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Tactic: Defense Evasion",
    "Resources: Investigation Guide",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
]
type = "eql"

query = '''
sequence by process.entity_id
  [process where host.os.type == "windows" and event.type == "start" and
   process.name : ("regsvr32.exe", "RegAsm.exe", "RegSvcs.exe") and
   not (
         (?process.Ext.token.integrity_level_name : "System" or ?winlog.event_data.IntegrityLevel : "System") and
         (process.parent.name : "msiexec.exe" or process.parent.executable : ("C:\\Program Files (x86)\\*.exe", "C:\\Program Files\\*.exe"))
       )
   ]
  [network where host.os.type == "windows" and process.name : ("regsvr32.exe", "RegAsm.exe", "RegSvcs.exe")  and
   not cidrmatch(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24",
       "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32",
       "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.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") and network.protocol != "dns"]
'''


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

[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[[rule.threat.technique.subtechnique]]
id = "T1218.009"
name = "Regsvcs/Regasm"
reference = "https://attack.mitre.org/techniques/T1218/009/"

[[rule.threat.technique.subtechnique]]
id = "T1218.010"
name = "Regsvr32"
reference = "https://attack.mitre.org/techniques/T1218/010/"



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

Stages and Predicates

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

Stage 1: process

[process where host.os.type == "windows" and event.type == "start" and
   process.name : ("regsvr32.exe", "RegAsm.exe", "RegSvcs.exe") and
   not (
         (?process.Ext.token.integrity_level_name : "System" or ?winlog.event_data.IntegrityLevel : "System") and
         (process.parent.name : "msiexec.exe" or process.parent.executable : ("C:\\Program Files (x86)\\*.exe", "C:\\Program Files\\*.exe"))
       )
   ]

Stage 2: network

[network where host.os.type == "windows" and process.name : ("regsvr32.exe", "RegAsm.exe", "RegSvcs.exe")  and
   not cidrmatch(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24",
       "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32",
       "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.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") and network.protocol != "dns"]

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
network.protocolne
  • dns corpus 3 (elastic 3)
field:"DestinationPortName" kind:ne value:"dns"
process.namewildcard
  • RegAsm.exe corpus 25 (elastic 24, splunk 1)
  • RegSvcs.exe corpus 22 (elastic 21, splunk 1)
  • regsvr32.exe corpus 74 (elastic 69, splunk 5)
field:"process_basename" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.Ext.token.integrity_level_nameeqSystemexcludes:process.Ext.token.integrity_level_name field:"process.Ext.token.integrity_level_name" value:"System"
winlog.event_data.IntegrityLeveleqSystemexcludes:winlog.event_data.IntegrityLevel field:"winlog.event_data.IntegrityLevel" value:"System"
process.parent.executablewildcardC:\Program Files (x86)\*.exe, C:\Program Files\*.exeexcludes:process.parent.executable field:"process.parent.executable" value:"C:\Program Files (x86)\*.exe" field:"process.parent.executable" value:"C:\Program Files\*.exe"
process.parent.nameeqmsiexec.exeexcludes:process.parent.name field:"process.parent.name" value:"msiexec.exe"
destination.ipcidr_match10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.0.0/29, 192.0.0.8/32, 192.0.0.9/32, 192.0.0.10/32, 192.0.0.170/32, 192.0.0.171/32, 192.0.2.0/24, 192.31.196.0/24, 192.52.193.0/24, 192.168.0.0/16, 192.88.99.0/24, 224.0.0.0/4, 100.64.0.0/10, 192.175.48.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4, ::1, FE80::/10, FF00::/8excludes:destination.ip

Okta AiTM Session Cookie Replay

#

Payload Decoded via CertUtil

#
Source
github.com/elastic/protections-artifacts

Identifies when attempts to decode file or information using the Microsoft built-in CertUtil utility. malware droppers may leverage this technique to deobfuscate embedded malicious resources.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies when attempts to decode file or information using the Microsoft built-in CertUtil utility. malware droppers
may leverage this technique to deobfuscate embedded malicious resources.
"""
id = "dbc72ac5-a004-45de-916d-e8aac82c4789"
license = "Elastic License v2"
name = "Payload Decoded via CertUtil"
os_list = ["windows"]
reference = ["https://lolbas-project.github.io/lolbas/Binaries/Certutil/"]
version = "1.0.5"

query = '''
process where event.action == "start" and
 (process.name : "certutil.exe" or process.pe.original_file_name == "CertUtil.exe") and
 process.args : ("-decode", "-decodehex") and
 not (user.id : "S-1-5-18" and process.args : "-decode" and
      process.parent.args : "?:\\ProgramData\\CentraStage\\AEMAgent\\Temp\\*.bat") and
 not (user.id : "S-1-5-18" and process.command_line : "certutil  -decode getSignatureInfo.base64 getSignatureInfo.ps1 ") and
 not process.command_line :
              ("certutil  -f -decode C:\\WINDOWS\\Temp\\csat\\csat_dwnldr.txt C:\\WINDOWS\\Temp\\csat\\csat_dwnldr.exe",
               "certutil  -decode \"c:\\HVworking\\checkSignature.base64\" \"c:\\HVworking\\checkSignature.bat\"")
'''

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

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1027"
name = "Obfuscated Files or Information"
reference = "https://attack.mitre.org/techniques/T1027/"

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


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

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.action == "start" and
 (process.name : "certutil.exe" or process.pe.original_file_name == "CertUtil.exe") and
 process.args : ("-decode", "-decodehex") and
 not (user.id : "S-1-5-18" and process.args : "-decode" and
      process.parent.args : "?:\\ProgramData\\CentraStage\\AEMAgent\\Temp\\*.bat") and
 not (user.id : "S-1-5-18" and process.command_line : "certutil  -decode getSignatureInfo.base64 getSignatureInfo.ps1 ") and
 not process.command_line :
              ("certutil  -f -decode C:\\WINDOWS\\Temp\\csat\\csat_dwnldr.txt C:\\WINDOWS\\Temp\\csat\\csat_dwnldr.exe",
               "certutil  -decode \"c:\\HVworking\\checkSignature.base64\" \"c:\\HVworking\\checkSignature.bat\"")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • start corpus 388 (elastic 388)
field:"EventType" kind:eq value:"start"
process.argswildcard
  • -decode corpus 2 (elastic 2)
  • -decodehex
field:"process.args" kind:wildcard
process.namewildcard
  • certutil.exe corpus 45 (elastic 39, splunk 6)
field:"process_basename" kind:wildcard value:"certutil.exe"
process.pe.original_file_nameeq
  • CertUtil.exe corpus 5 (elastic 5)
field:"OriginalFileName" kind:eq value:"CertUtil.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argseq-decodeexcludes:process.args field:"process.args" value:"-decode"
process.parent.argswildcard?:\ProgramData\CentraStage\AEMAgent\Temp\*.batexcludes:process.parent.args field:"process.parent.args" value:"?:\ProgramData\CentraStage\AEMAgent\Temp\*.bat"
user.ideqS-1-5-18excludes:user.id field:"user.id" value:"S-1-5-18"
process.command_lineeqcertutil -decode getSignatureInfo.base64 getSignatureInfo.ps1 excludes:process.command_line field:"process.command_line" value:"certutil -decode getSignatureInfo.base64 getSignatureInfo.ps1 "
process.command_lineeqcertutil -f -decode C:\WINDOWS\Temp\csat\csat_dwnldr.txt C:\WINDOWS\Temp\csat\csat_dwnldr.exe, certutil -decode "c:\HVworking\checkSignature.base64" "c:\HVworking\checkSignature.bat"excludes:process.command_line

Potential Linux Tunneling and/or Port Forwarding

#
Source
github.com/elastic/protections-artifacts

This rule monitors for a set of Linux utilities that can be used for tunneling and port forwarding. Attackers can leverage tunneling and port forwarding techniques to bypass network defenses, establish hidden communication channels, and gain unauthorized access to internal resources, facilitating data exfiltration, lateral movement, and remote control.

MITRE ATT&CK Coverage

TacticTechniques
Command & Control

Rule Body

[rule]
description = """
This rule monitors for a set of Linux utilities that can be used for tunneling and port forwarding. Attackers can
leverage tunneling and port forwarding techniques to bypass network defenses, establish hidden communication channels,
and gain unauthorized access to internal resources, facilitating data exfiltration, lateral movement, and remote
control.
"""
id = "a5cfaae1-ee03-40f3-af2a-25a23f2abebf"
license = "Elastic License v2"
name = "Potential Linux Tunneling and/or Port Forwarding"
os_list = ["linux"]
reference = [
    "https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-commands/",
    "https://attack.mitre.org/techniques/T1572/",
    "https://www.trendmicro.com/tr_tr/research/26/c/dissecting-a-warlock-attack.html",
    "https://github.com/P001water/yuze",
    "https://flare.io/learn/resources/blog/teampcp-cloud-native-ransomware",
    "https://blog.bitsadmin.com/living-off-the-foreign-land-windows-as-offensive-platform",
    "https://book.hacktricks.xyz/generic-methodologies-and-resources/tunneling-and-port-forwarding",
    "https://github.com/erebe/wstunnel",
]
version = "1.0.8"

query = '''
process where event.type == "start" and event.action == "exec" and (
  (
    // Tunneling and/or Port Forwarding via process command line
    (
      process.command_line regex """.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}:[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}.*"""
    ) or
    // gost
    (
      process.name == "gost" and process.args like~ ("-L*", "-C*", "-R*")
    ) or
    // ngrok
    (
      process.name == "ngrok" and process.args in ("http", "https", "tcp", "tls") and
      not (process.executable like "/scratch/project/*/tools/ngrok/ngrok" and process.command_line like "*127.0.0.1*")
    ) or
    // earthworm
    (
      process.args == "-s" and process.args == "-d" and process.args == "rssocks"
    ) or
    // chisel
    (
      process.name like~ "chisel*" and process.args in ("client", "server")
    ) or
    // vscode
    (
      process.name == "code" and process.args == "tunnel" and
      not (
        process.args == "kill" or
        (process.executable like "/scratch/user/*/.vscode/code" and process.args == "-cli-data-dir")
      )
    ) or
    // QEMU
    (
      process.name like ("qemu-system-*", ".qemu-system-*") and
      process.args == "-netdev" and process.args like "*socket*" and (
        (
          process.args == "-nographic" and process.command_line like~ "*connect=*" and process.command_line like~ "*restrict=off*"
        ) or
        (
          process.command_line like~ "*hostfwd=*" and
          /* Common uses of hostfwd */
          not process.command_line like "*hostfwd=tcp::*-:22*"
        )
      )
    ) or
    // yuze
    (
      (
        process.args == "proxy" and process.args == "-l" and process.args_count >= 4
      ) or
      (
        process.args == "fwd" and process.args == "-l" and process.args == "-f" and process.args_count >= 6 and
        process.command_line regex """.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}.*"""
      ) or
      (
        process.args == "reverse" and (
          (
            process.args == "-s" and process.args == "-l" and process.args_count >= 6
          ) or
          (
            process.args == "-c" and process.args_count >= 4 and
            process.command_line regex """.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}.*"""
          )
        )
      )
    ) or
    // Common tunneling tools 
    (
      process.name in~ (
        "iodine", "iodined", "dnscat", "hans", "hans-ubuntu", "ptunnel-ng", "ssf", "3proxy", "wstunnel", "pivotnacci",
        "frps", "proxychains", "yuze"
      )
    )
  )
) and
not (
  (
    process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "mksh") and
    process.args like "ssh*"
  ) or
  process.parent.args == "/usr/bin/crun" or
  process.executable in (
    "/usr/bin/podman", "/usr/bin/crontab", "/usr/bin/rg", "/usr/bin/ssh", "/usr/bin/autossh", "/usr/local/bin/rtk", "/usr/lib/autossh/autossh"
  ) or
  process.parent.executable in (
    "/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
    "/usr/share/antigravity/resources/app/extensions/antigravity/bin/language_server_linux_x64"
  ) or
  process.parent.executable like "/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl" or
  process.executable like ("/tmp/.mount_cursor*/ripgrep/bin/rg", "/home/*/.local/bin/code", "/home/*/.local/bin/rtk", "/home/*/.cursor-server/bin/linux-x64/*") or
  process.parent.command_line == "runc init" or
  process.args == "/usr/bin/autossh" or
  (
    process.parent.executable == "/opt/rancher-desktop/resources/resources/linux/lima/bin/limactl" and
    process.executable == "/usr/bin/qemu-system-x86_64"
  ) or
  (
    process.executable == "/usr/bin/gssh-agent" and
    process.command_line like "/usr/bin/python3 /usr/bin/gssh-agent /usr/bin/ssh -N -o BatchMode=yes *" and
    process.args in ("-L", "-R") and
    process.args like "127.0.0.1:*:127.0.0.1:*"
  ) or
  process.parent.executable like "/home/linuxbrew/.linuxbrew/Caskroom/codex/*/bin/codex" or
  process.parent.command_line like "*/home/*/.claude/*shell-snapshots/snapshot*" or
  (process.executable == "/usr/bin/qemu-system-x86_64" and process.parent.command_line == "bash /run/entry.sh")
)
'''

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

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1572"
name = "Protocol Tunneling"
reference = "https://attack.mitre.org/techniques/T1572/"


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

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action == "exec" and (
  (
    (
      process.command_line regex """.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}:[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}.*"""
    ) or
    (
      process.name == "gost" and process.args like~ ("-L*", "-C*", "-R*")
    ) or
    (
      process.name == "ngrok" and process.args in ("http", "https", "tcp", "tls") and
      not (process.executable like "/scratch/project/*/tools/ngrok/ngrok" and process.command_line like "*127.0.0.1*")
    ) or
    (
      process.args == "-s" and process.args == "-d" and process.args == "rssocks"
    ) or
    (
      process.name like~ "chisel*" and process.args in ("client", "server")
    ) or
    (
      process.name == "code" and process.args == "tunnel" and
      not (
        process.args == "kill" or
        (process.executable like "/scratch/user/*/.vscode/code" and process.args == "-cli-data-dir")
      )
    ) or
    (
      process.name like ("qemu-system-*", ".qemu-system-*") and
      process.args == "-netdev" and process.args like "*socket*" and (
        (
          process.args == "-nographic" and process.command_line like~ "*connect=*" and process.command_line like~ "*restrict=off*"
        ) or
        (
          process.command_line like~ "*hostfwd=*" and
          not process.command_line like "*hostfwd=tcp::*-:22*"
        )
      )
    ) or
    (
      (
        process.args == "proxy" and process.args == "-l" and process.args_count >= 4
      ) or
      (
        process.args == "fwd" and process.args == "-l" and process.args == "-f" and process.args_count >= 6 and
        process.command_line regex """.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}.*"""
      ) or
      (
        process.args == "reverse" and (
          (
            process.args == "-s" and process.args == "-l" and process.args_count >= 6
          ) or
          (
            process.args == "-c" and process.args_count >= 4 and
            process.command_line regex """.*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}.*"""
          )
        )
      )
    ) or
    (
      process.name in~ (
        "iodine", "iodined", "dnscat", "hans", "hans-ubuntu", "ptunnel-ng", "ssf", "3proxy", "wstunnel", "pivotnacci",
        "frps", "proxychains", "yuze"
      )
    )
  )
) and
not (
  (
    process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "mksh") and
    process.args like "ssh*"
  ) or
  process.parent.args == "/usr/bin/crun" or
  process.executable in (
    "/usr/bin/podman", "/usr/bin/crontab", "/usr/bin/rg", "/usr/bin/ssh", "/usr/bin/autossh", "/usr/local/bin/rtk", "/usr/lib/autossh/autossh"
  ) or
  process.parent.executable in (
    "/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
    "/usr/share/antigravity/resources/app/extensions/antigravity/bin/language_server_linux_x64"
  ) or
  process.parent.executable like "/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl" or
  process.executable like ("/tmp/.mount_cursor*/ripgrep/bin/rg", "/home/*/.local/bin/code", "/home/*/.local/bin/rtk", "/home/*/.cursor-server/bin/linux-x64/*") or
  process.parent.command_line == "runc init" or
  process.args == "/usr/bin/autossh" or
  (
    process.parent.executable == "/opt/rancher-desktop/resources/resources/linux/lima/bin/limactl" and
    process.executable == "/usr/bin/qemu-system-x86_64"
  ) or
  (
    process.executable == "/usr/bin/gssh-agent" and
    process.command_line like "/usr/bin/python3 /usr/bin/gssh-agent /usr/bin/ssh -N -o BatchMode=yes *" and
    process.args in ("-L", "-R") and
    process.args like "127.0.0.1:*:127.0.0.1:*"
  ) or
  process.parent.executable like "/home/linuxbrew/.linuxbrew/Caskroom/codex/*/bin/codex" or
  process.parent.command_line like "*/home/*/.claude/*shell-snapshots/snapshot*" or
  (process.executable == "/usr/bin/qemu-system-x86_64" and process.parent.command_line == "bash /run/entry.sh")
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • exec
field:"EventType" kind:eq value:"exec"
event.typeeq
  • start
field:"event.type" kind:eq value:"start"
process.argseq
  • -c
  • -d
  • -f
  • -l
  • -netdev
  • -nographic
  • -s
  • fwd
  • proxy
  • reverse
  • rssocks
  • tunnel
field:"process.args" kind:eq
process.argsin
  • client
  • http
  • https
  • server
  • tcp
  • tls
field:"process.args" kind:in
process.argswildcard
  • *socket*
  • -C*
  • -L*
  • -R*
field:"process.args" kind:wildcard
process.args_countge
  • 4 transforms: number
  • 6 transforms: number
field:"process.args_count" kind:ge
process.command_lineregex_match
  • .*[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}:[0-9]{1,5}.*
  • .*[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}:[0-9]{1,5}:[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}:[0-9]{1,5}.*
field:"CommandLine" kind:regex_match
process.command_linewildcard
  • *connect=*
  • *hostfwd=*
  • *restrict=off*
field:"CommandLine" kind:wildcard
process.nameeq
  • code
  • gost
  • ngrok
field:"process_basename" kind:eq
process.namein
  • 3proxy
  • dnscat
  • frps
  • hans
  • hans-ubuntu
  • iodine
  • iodined
  • pivotnacci
  • proxychains
  • ptunnel-ng
  • ssf
  • wstunnel
  • yuze
field:"process_basename" kind:in
process.namewildcard
  • .qemu-system-*
  • chisel*
  • qemu-system-*
field:"process_basename" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argsin-L, -Rexcludes:process.args field:"process.args" value:"-L" field:"process.args" value:"-R"
process.argswildcard127.0.0.1:*:127.0.0.1:*excludes:process.args field:"process.args" value:"127.0.0.1:*:127.0.0.1:*"
process.command_linestarts_with/usr/bin/python3 /usr/bin/gssh-agent /usr/bin/ssh -N -o BatchMode=yes excludes:process.command_line field:"process.command_line" value:"/usr/bin/python3 /usr/bin/gssh-agent /usr/bin/ssh -N -o BatchMode=yes "
process.executableeq/usr/bin/gssh-agentexcludes:process.executable field:"process.executable" value:"/usr/bin/gssh-agent"
process.argsstarts_withsshexcludes:process.args field:"process.args" value:"ssh"
process.nameinbash, csh, dash, fish, ksh, mksh, sh, tcsh, zshexcludes:process.name
process.executableeq/usr/bin/qemu-system-x86_64excludes:process.executable field:"process.executable" value:"/usr/bin/qemu-system-x86_64"
process.parent.command_lineeqbash /run/entry.shexcludes:process.parent.command_line field:"process.parent.command_line" value:"bash /run/entry.sh"
process.parent.executableeq/opt/rancher-desktop/resources/resources/linux/lima/bin/limactlexcludes:process.parent.executable field:"process.parent.executable" value:"/opt/rancher-desktop/resources/resources/linux/lima/bin/limactl"
process.argseq/usr/bin/autosshexcludes:process.args field:"process.args" value:"/usr/bin/autossh"
process.executablein/usr/bin/autossh, /usr/bin/crontab, /usr/bin/podman, /usr/bin/rg, /usr/bin/ssh, /usr/lib/autossh/autossh, /usr/local/bin/rtkexcludes:process.executable
process.executablewildcard/tmp/.mount_cursor*/ripgrep/bin/rg, /home/*/.local/bin/code, /home/*/.local/bin/rtk, /home/*/.cursor-server/bin/linux-x64/*excludes:process.executable
process.parent.argseq/usr/bin/crunexcludes:process.parent.args field:"process.parent.args" value:"/usr/bin/crun"
process.parent.command_lineeqrunc initexcludes:process.parent.command_line field:"process.parent.command_line" value:"runc init"
process.parent.command_linewildcard*/home/*/.claude/*shell-snapshots/snapshot*excludes:process.parent.command_line field:"process.parent.command_line" value:"*/home/*/.claude/*shell-snapshots/snapshot*"
process.parent.executablein/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex, /usr/share/antigravity/resources/app/extensions/antigravity/bin/language_server_linux_x64excludes:process.parent.executable field:"process.parent.executable" value:"/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex" field:"process.parent.executable" value:"/usr/share/antigravity/resources/app/extensions/antigravity/bin/language_server_linux_x64"
process.parent.executablewildcard/home/linuxbrew/.linuxbrew/Caskroom/codex/*/bin/codexexcludes:process.parent.executable field:"process.parent.executable" value:"/home/linuxbrew/.linuxbrew/Caskroom/codex/*/bin/codex"
process.parent.executablewildcard/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-muslexcludes:process.parent.executable field:"process.parent.executable" value:"/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl"

Potential PlugX Registry Modification

#
Source
github.com/elastic/protections-artifacts

Identifies registry modification that matches on PlugX Trojan known registry configuration patterns such as C&C version, Run key persistence value and internet status on the victim machine. PlugX is a known RAT (Remote Access Trojan) malware family that is around since 2008 and is used as a backdoor to control the victim's machine fully.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies registry modification that matches on PlugX Trojan known registry configuration patterns such as C&C version,
Run key persistence value and internet status on the victim machine. PlugX is a known RAT (Remote Access Trojan) malware
family that is around since 2008 and is used as a backdoor to control the victim's machine fully.
"""
id = "7a201712-9f3c-4f40-b4fc-2418a44b8ecb"
license = "Elastic License v2"
name = "Potential PlugX Registry Modification"
os_list = ["windows"]
reference = [
    "https://www.avira.com/en/blog/new-wave-of-plugx-targets-hong-kong",
    "https://www.welivesecurity.com/2022/03/23/mustang-panda-hodur-old-tricks-new-korplug-variant/",
    "https://malpedia.caad.fkie.fraunhofer.de/details/win.plugx",
]
version = "1.0.28"

query = '''
registry where

  /* PlugX store C&C server version in ms-pu sub values */
 registry.path : ("HK*\\Software\\CLASSES\\ms-pu\\PROXY*", "HK*\\Software\\CLASSES\\ms-pu\\CLSID*") or

  /* PlugX Persist via Run key with specific program args */
 (registry.path : "HK*\\CurrentVersion\\Run\\*" and
  not process.executable : ("?:\\Windows\\System32\\msiexec.exe", "?:\\Windows\\regedit.exe") and
  (registry.data.strings regex ".+exe. [0-9]{2,3}" or registry.data.strings : ("*.exe? -app", "*.exe? -net"))) or

  /* PlugX store internet status in Version value */
  (registry.path : "HK*\\System\\*ControlSet*\\Control\\Network\\Version" and registry.data.strings : "1")
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1547"
name = "Boot or Logon Autostart Execution"
reference = "https://attack.mitre.org/techniques/T1547/"
[[threat.technique.subtechnique]]
id = "T1547.001"
name = "Registry Run Keys / Startup Folder"
reference = "https://attack.mitre.org/techniques/T1547/001/"



[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/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1219"
name = "Remote Access Tools"
reference = "https://attack.mitre.org/techniques/T1219/"


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

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: registry

registry where
 registry.path : ("HK*\\Software\\CLASSES\\ms-pu\\PROXY*", "HK*\\Software\\CLASSES\\ms-pu\\CLSID*") or
 (registry.path : "HK*\\CurrentVersion\\Run\\*" and
  not process.executable : ("?:\\Windows\\System32\\msiexec.exe", "?:\\Windows\\regedit.exe") and
  (registry.data.strings regex ".+exe. [0-9]{2,3}" or registry.data.strings : ("*.exe? -app", "*.exe? -net"))) or
  (registry.path : "HK*\\System\\*ControlSet*\\Control\\Network\\Version" and registry.data.strings : "1")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
registry.data.stringsregex_match
  • .+exe. [0-9]{2,3}
field:"Details" kind:regex_match value:".+exe. [0-9]{2,3}"
registry.data.stringswildcard
  • *.exe? -app
  • *.exe? -net
  • 1 corpus 16 (elastic 14, splunk 2)
field:"Details" kind:wildcard
registry.pathwildcard
  • HK*\CurrentVersion\Run\*
  • HK*\Software\CLASSES\ms-pu\CLSID*
  • HK*\Software\CLASSES\ms-pu\PROXY*
  • HK*\System\*ControlSet*\Control\Network\Version
field:"TargetObject" kind:wildcard

Potential Sudo Privilege Escalation via CVE-2019-14287

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

This rule monitors for the execution of a suspicious sudo command that is leveraged in CVE-2019-14287 to escalate privileges to root. Sudo does not verify the presence of the designated user ID and proceeds to execute using a user ID that can be chosen arbitrarily. By using the sudo privileges, the command "sudo -u#-1" translates to an ID of 0, representing the root user. This exploit may work for sudo versions prior to v1.28.

MITRE ATT&CK Coverage

Rule Body

[metadata]
creation_date = "2023/08/30"
integration = ["endpoint", "auditd_manager", "crowdstrike", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/03/24"

[rule]
author = ["Elastic"]
description = """
This rule monitors for the execution of a suspicious sudo command that is leveraged in CVE-2019-14287 to escalate
privileges to root. Sudo does not verify the presence of the designated user ID and proceeds to execute using a user ID
that can be chosen arbitrarily. By using the sudo privileges, the command "sudo -u#-1" translates to an ID of 0,
representing the root user. This exploit may work for sudo versions prior to v1.28.
"""
from = "now-9m"
index = [
    "auditbeat-*",
    "endgame-*",
    "logs-auditd_manager.auditd-*",
    "logs-crowdstrike.fdr*",
    "logs-endpoint.events.process*",
    "logs-sentinel_one_cloud_funnel.*",
]
language = "eql"
license = "Elastic License v2"
name = "Potential Sudo Privilege Escalation via CVE-2019-14287"
note = """## Triage and analysis

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

### Investigating Potential Sudo Privilege Escalation via CVE-2019-14287

CVE-2019-14287 exploits a flaw in certain sudo versions, allowing users to execute commands as root by bypassing user ID verification. Attackers can misuse this to gain unauthorized root access, posing significant security risks. The detection rule identifies suspicious sudo commands indicative of this exploit, focusing on specific command patterns that translate to root execution, thereby alerting security teams to potential privilege escalation attempts.

### Possible investigation steps

- Review the alert details to confirm the presence of the suspicious command pattern "sudo -u#-1" in the process arguments, as this is indicative of the CVE-2019-14287 exploit attempt.
- Identify the user account associated with the process execution to determine if the user should have legitimate access to execute commands with elevated privileges.
- Examine the process execution timeline to identify any preceding or subsequent suspicious activities that might indicate a broader attack or compromise.
- Check the version of sudo installed on the affected system to verify if it is vulnerable to CVE-2019-14287, specifically versions prior to v1.28.
- Investigate the source IP address and hostname of the affected system to assess if it is part of a larger attack pattern or if there are other systems potentially compromised.
- Review system logs and audit trails for any additional unauthorized access attempts or privilege escalation activities around the time of the alert.
- If possible, isolate the affected system to prevent further unauthorized access while conducting a more thorough forensic analysis.

### False positive analysis

- Legitimate administrative tasks using sudo with unconventional user ID arguments may trigger the rule. Review the context of the command execution to determine if it aligns with expected administrative activities.
- Automated scripts or maintenance tools that use sudo with arbitrary user IDs for testing or configuration purposes might be flagged. Identify and document these scripts, then create exceptions in the monitoring system to exclude them from alerts.
- Development environments where developers have elevated privileges for testing purposes could generate false positives. Ensure that such environments are well-documented and consider excluding them from this specific rule if they consistently trigger alerts.
- Security tools or monitoring systems that simulate attacks for testing detection capabilities may inadvertently trigger this rule. Coordinate with security teams to whitelist these tools or adjust their configurations to prevent unnecessary alerts.

### Response and remediation

- Immediately isolate the affected system from the network to prevent further unauthorized access or lateral movement by the attacker.
- Terminate any suspicious processes identified with the command pattern "sudo -u#-1" to halt any ongoing unauthorized activities.
- Conduct a thorough review of system logs and sudo logs to identify any additional unauthorized access attempts or successful privilege escalations.
- Reset passwords and review user accounts on the affected system to ensure no unauthorized accounts have been created or existing accounts have been compromised.
- Apply patches or upgrade sudo to a version later than v1.28 to mitigate the vulnerability exploited by CVE-2019-14287.
- Monitor the network for any signs of data exfiltration or further exploitation attempts, using enhanced logging and alerting mechanisms.
- Report the incident to the appropriate internal security team or external authorities if required, providing them with detailed findings and actions taken."""
references = ["https://www.exploit-db.com/exploits/47502"]
risk_score = 73
rule_id = "8af5b42f-8d74-48c8-a8d0-6d14b4197288"
setup = """## Setup

This rule requires data coming in from Elastic Defend.

### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.

#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).

#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "high"
tags = [
    "Domain: Endpoint",
    "OS: Linux",
    "Use Case: Threat Detection",
    "Tactic: Privilege Escalation",
    "Data Source: Elastic Defend",
    "Use Case: Vulnerability",
    "Data Source: Elastic Endgame",
    "Data Source: Auditd Manager",
    "Data Source: Crowdstrike",
    "Data Source: SentinelOne",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "linux" and event.type == "start" and
  event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
  process.name == "sudo" and process.args == "-u#-1"
'''

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

[[rule.threat.technique]]
id = "T1068"
name = "Exploitation for Privilege Escalation"
reference = "https://attack.mitre.org/techniques/T1068/"

[[rule.threat.technique]]
id = "T1548"
name = "Abuse Elevation Control Mechanism"
reference = "https://attack.mitre.org/techniques/T1548/"

[[rule.threat.technique.subtechnique]]
id = "T1548.003"
name = "Sudo and Sudo Caching"
reference = "https://attack.mitre.org/techniques/T1548/003/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

Stages and Predicates

Stage 1: process

process where host.os.type == "linux" and event.type == "start" and
  event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
  process.name == "sudo" and process.args == "-u#-1"

Indicators

These rows show field, operator, and value matches.

Privileged Container Creation with Host Directory Mount

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

This rule detects the creation of privileged containers that mount host directories into the container's filesystem. Such configurations can be exploited by attackers to escape the container isolation and gain access to the host system, potentially leading to privilege escalation and lateral movement within the environment.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2025/11/27"
integration = ["endpoint", "auditd_manager", "crowdstrike", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/03/24"

[rule]
author = ["Elastic"]
description = """
This rule detects the creation of privileged containers that mount host directories into the container's filesystem.
Such configurations can be exploited by attackers to escape the container isolation and gain access to the host system,
potentially leading to privilege escalation and lateral movement within the environment.
"""
from = "now-9m"
index = [
    "auditbeat-*",
    "endgame-*",
    "logs-auditd_manager.auditd-*",
    "logs-crowdstrike.fdr*",
    "logs-endpoint.events.process*",
    "logs-sentinel_one_cloud_funnel.*",
]
language = "eql"
license = "Elastic License v2"
name = "Privileged Container Creation with Host Directory Mount"
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 Privileged Container Creation with Host Directory Mount

This rule flags creation of a privileged container that bind-mounts host directories into the container filesystem, breaking isolation and granting direct access to host files and devices. An attacker on a compromised node starts a privileged container via the runtime, bind-mounts the host root (/:) inside it, then chroots and alters critical files or services to seize host control, persist, and pivot.

### Possible investigation steps

- Retrieve the full process tree and execution context (user, controlling TTY, parent, remote source IP) to identify who initiated the container and whether it aligns with a sanctioned change.
- Run runtime introspection to confirm the container’s mounts and privileges (e.g., docker ps/inspect or CRI equivalents), capturing the container ID, exact hostPath mappings, image, entrypoint, and start time.
- If orchestrated, correlate with Kubernetes events and kubelet logs at the same timestamp to find any Pod using privileged: true with hostPath volumes, recording the namespace, service account, controller, and requestor.
- Review audit and file integrity telemetry after container start for host-impacting actions such as chroot into the mount, nsenter into host namespaces, or writes to critical paths (/etc/passwd, /etc/sudoers, /root/.ssh, /var/lib/kubelet, and systemd unit directories).
- Assess image provenance and intent by resolving the image digest and registry, reviewing history/entrypoint for post-start tooling, and validating with service owners or allowlists whether this privileged host-mount is expected on this node.

### False positive analysis

- An administrator uses docker run --privileged with -v /:/host during a break-glass or troubleshooting session to edit host files or restart services, matching the pattern but aligned with an approved maintenance procedure.
- Automated provisioning or upgrade workflows intentionally start a privileged container that bind-mounts / to apply system configuration, install packages, or manage kernel modules during node bootstrap, producing an expected event.

### Response and remediation

- Immediately stop and remove the privileged container by its ID using docker, cordon the node to prevent scheduling, and temporarily disable the Docker/CRI socket to block further privileged runs.
- Preserve forensic artifacts (docker inspect output, container image and filesystem, bash history, /var/log) and remediate by diffing and restoring critical paths (/etc, /root/.ssh, /etc/systemd/system, /var/lib/kubelet), removing rogue users, SSH keys, and systemd units.
- Rotate credentials potentially exposed by the host mount (SSH keys, kubelet certs, cloud tokens under /var/lib/kubelet or /root), patch the container runtime, and uncordon or rejoin the node only after verifying privileged runs and host-root mounts are blocked.
- Escalate to incident response if the mount included "/" or if evidence shows chroot or nsenter into host namespaces or writes to /etc/passwd, /etc/sudoers, or systemd unit files, and initiate host reimage and broader fleet scoping.
- Enforce controls that deny --privileged and hostPath of "/" via admission policy (Pod Security Standards, Kyverno, OPA Gatekeeper), drop CAP_SYS_ADMIN with seccomp/AppArmor, enable Docker userns-remap and no-new-privileges, and restrict membership in the docker group.
- Establish a break-glass approval workflow and an allowlist for legitimate host mounts, enable file integrity monitoring on /etc and kubelet directories, and add runtime rules to alert and block future docker run -v /:/host attempts."""
references = [
    "https://www.elastic.co/blog/shai-hulud-worm-npm-supply-chain-compromise",
    "https://socket.dev/blog/shai-hulud-strikes-again-v2",
    "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack",
    "https://unit42.paloaltonetworks.com/container-escape-techniques/",
]
risk_score = 73
rule_id = "d1f310cb-5921-4d37-bbdf-cfdab7a6df9c"
setup = """## Setup
This rule requires data coming in from Elastic Defend.
### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.
#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
#### The following steps should be executed in order to add the Elastic Defend integration on a Linux System:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/8.10/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "high"
tags = [
    "Domain: Endpoint",
    "Domain: Container",
    "OS: Linux",
    "OS: macOS",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Data Source: Elastic Defend",
    "Data Source: Elastic Endgame",
    "Data Source: Auditd Manager",
    "Data Source: Crowdstrike",
    "Data Source: SentinelOne",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where event.type == "start" and event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.name == "docker" and process.args == "--privileged" and process.args == "run" and
process.args == "-v" and process.args like "/:/*" and
not (
  (process.args == "aktosecurity/mirror-api-logging:k8s_ebpf" and process.args == "akto-api-security-traffic-collector") or
  (process.args like "goharbor/prepare:*" and process.args in ("/:/hostfs", "/:/hostfs/"))
)
'''

[[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]]
id = "T1609"
name = "Container Administration Command"
reference = "https://attack.mitre.org/techniques/T1609/"

[[rule.threat.technique]]
id = "T1610"
name = "Deploy Container"
reference = "https://attack.mitre.org/techniques/T1610/"

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

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

[[rule.threat.technique]]
id = "T1611"
name = "Escape to Host"
reference = "https://attack.mitre.org/techniques/T1611/"

[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
process.name == "docker" and process.args == "--privileged" and process.args == "run" and
process.args == "-v" and process.args like "/:/*" and
not (
  (process.args == "aktosecurity/mirror-api-logging:k8s_ebpf" and process.args == "akto-api-security-traffic-collector") or
  (process.args like "goharbor/prepare:*" and process.args in ("/:/hostfs", "/:/hostfs/"))
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actionin
  • ProcessRollup2 corpus 119 (elastic 119)
  • exec corpus 180 (elastic 180)
  • exec_event corpus 135 (elastic 135)
  • executed corpus 85 (elastic 85)
  • process_started corpus 77 (elastic 77)
  • start corpus 157 (elastic 157)
field:"EventType" kind:in
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.argseq
  • --privileged corpus 2 (elastic 2)
  • -v corpus 2 (elastic 2)
  • run corpus 7 (elastic 7)
field:"process.args" kind:eq
process.argswildcard
  • /:/* corpus 2 (elastic 2)
field:"process.args" kind:wildcard value:"/:/*"
process.nameeq
  • docker corpus 4 (elastic 4)
field:"process_basename" kind:eq value:"docker"

Exclusions

The rule actively suppresses these predicates.

Sensitive File Access - Remote Desktop Connection Manager

#
Source
github.com/elastic/protections-artifacts

Identifies an unusual process accessing Remote Desktop Connection Manager settings file. Adversaries may search and steal credentials from administration utilities configuration files.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Identifies an unusual process accessing Remote Desktop Connection Manager settings file. Adversaries may search and
steal credentials from administration utilities configuration files.
"""
id = "934232e5-66d3-4e80-a4ee-a9f1b7d2a7bc"
license = "Elastic License v2"
name = "Sensitive File Access - Remote Desktop Connection Manager"
os_list = ["windows"]
reference = [
    "http://www.harmj0y.net/blog/redteaming/operational-guidance-for-offensive-user-dpapi-abuse/",
    "https://smsagent.blog/2017/01/26/decrypting-remote-desktop-connection-manager-passwords-with-powershell/",
]
version = "1.0.33"

query = '''
file where event.type == "access" and event.outcome == "success" and
    /* domain user RID */
    user.id : ("S-1-5-21*", "S-1-12-*") and process.pid != 4 and
    file.path : "?:\\Users\\*\\AppData\\Local\\*\\Remote Desktop Connection Manager\\RDCMan.settings" and
    not process.executable :
                    ("?:\\Program Files (x86)\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.exe",
                     "?:\\Program Files\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.exe") and
    not (process.name : ("RDCMan.exe", "RDCMan-x86.exe", "RemoteDesktopManager.exe") and process.code_signature.subject_name like "Microsoft *" and process.code_signature.trusted == true) and
    not (process.code_signature.subject_name == "Fortinet, Inc." and process.code_signature.trusted == true)
'''

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"
[[threat.technique.subtechnique]]
id = "T1552.001"
name = "Credentials In Files"
reference = "https://attack.mitre.org/techniques/T1552/001/"



[threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1021"
name = "Remote Services"
reference = "https://attack.mitre.org/techniques/T1021/"
[[threat.technique.subtechnique]]
id = "T1021.001"
name = "Remote Desktop Protocol"
reference = "https://attack.mitre.org/techniques/T1021/001/"



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

[internal]
min_endpoint_version = "8.0.0"

Stages and Predicates

Stage 1: file

file where event.type == "access" and event.outcome == "success" and
    user.id : ("S-1-5-21*", "S-1-12-*") and process.pid != 4 and
    file.path : "?:\\Users\\*\\AppData\\Local\\*\\Remote Desktop Connection Manager\\RDCMan.settings" and
    not process.executable :
                    ("?:\\Program Files (x86)\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.exe",
                     "?:\\Program Files\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.exe") and
    not (process.name : ("RDCMan.exe", "RDCMan-x86.exe", "RemoteDesktopManager.exe") and process.code_signature.subject_name like "Microsoft *" and process.code_signature.trusted == true) and
    not (process.code_signature.subject_name == "Fortinet, Inc." and process.code_signature.trusted == true)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.outcomeeq
  • success corpus 82 (elastic 82)
field:"event.outcome" kind:eq value:"success"
event.typeeq
  • access corpus 9 (elastic 9)
field:"event.type" kind:eq value:"access"
file.pathwildcard
  • ?:\Users\*\AppData\Local\*\Remote Desktop Connection Manager\RDCMan.settings corpus 2 (elastic 2)
field:"TargetFilename" kind:wildcard value:"?:\Users\*\AppData\Local\*\Remote Desktop Connection Manager\RDCMan.settings"
process.pidne
  • 4 transforms: number corpus 44 (elastic 44)
field:"process_id" kind:ne value:"4"
user.idwildcard
  • S-1-12-* corpus 25 (elastic 25)
  • S-1-5-21* corpus 26 (elastic 26)
field:"user.id" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

Shared Memory File Turned Executable by Suspicious Parent

#
Source
github.com/elastic/protections-artifacts

Detects when a file located in the shared memory directory is made executable using chmod via an abnormal or suspicious parent process. Malware will often drop a second stage payload or file and will need to make it executable before invoking it.

MITRE ATT&CK Coverage

Rule Body

[rule]
description = """
Detects when a file located in the shared memory directory is made executable using chmod via an abnormal or suspicious
parent process. Malware will often drop a second stage payload or file and will need to make it executable before
invoking it.
"""
id = "742037b3-3ef6-4a33-84ed-b26fc6ae322c"
license = "Elastic License v2"
name = "Shared Memory File Turned Executable by Suspicious Parent"
os_list = ["linux"]
version = "1.0.12"

query = '''
process where event.type == "start" and event.action == "exec" and process.name == "chmod" and
process.args in ("4755", "755", "777", "0777", "+x", "a+x") and
process.args like "/dev/shm/*" and process.parent.executable != null and
not (
  (
    process.parent.executable == "/etc/init.d/nagios" and
    process.args in ("/dev/shm/tmp", "/dev/shm/var", "/dev/shm/checkresults")
  ) or
  process.parent.executable == "./install-attachment-registration-manager.sh" or
  process.parent.command_line == "runc init" or
  (
    process.working_directory like "/tmp/selfgz*" and
    process.parent.args ==  "./install-attachment-registration-manager.sh" and
    process.command_line == "chmod 777 /dev/shm/check-point"
  )
)
'''

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

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1222"
name = "File and Directory Permissions Modification"
reference = "https://attack.mitre.org/techniques/T1222/"
[[threat.technique.subtechnique]]
id = "T1222.002"
name = "Linux and Mac File and Directory Permissions Modification"
reference = "https://attack.mitre.org/techniques/T1222/002/"


[[threat.technique]]
id = "T1564"
name = "Hide Artifacts"
reference = "https://attack.mitre.org/techniques/T1564/"


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

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.type == "start" and event.action == "exec" and process.name == "chmod" and
process.args in ("4755", "755", "777", "0777", "+x", "a+x") and
process.args like "/dev/shm/*" and process.parent.executable != null and
not (
  (
    process.parent.executable == "/etc/init.d/nagios" and
    process.args in ("/dev/shm/tmp", "/dev/shm/var", "/dev/shm/checkresults")
  ) or
  process.parent.executable == "./install-attachment-registration-manager.sh" or
  process.parent.command_line == "runc init" or
  (
    process.working_directory like "/tmp/selfgz*" and
    process.parent.args ==  "./install-attachment-registration-manager.sh" and
    process.command_line == "chmod 777 /dev/shm/check-point"
  )
)

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

Shellcode Behavior via .NET Core

#
Source
github.com/elastic/protections-artifacts

Identifies the call of code injection related Windows API with suspicious parameters that align with shellcode allocation from a Managed .NET application.

MITRE ATT&CK Coverage

TacticTechniques
Stealth

Rule Body

[rule]
description = """
Identifies the call of code injection related Windows API with suspicious parameters that align with shellcode
allocation from a Managed .NET application.
"""
id = "d084c509-0222-49a2-b908-c9c3510f0f97"
license = "Elastic License v2"
name = "Shellcode Behavior via .NET Core"
os_list = ["windows"]
version = "1.0.3"

query = '''
api where
(
 (process.Ext.api.behaviors == "allocate_shellcode" and process.Ext.api.parameters.size >= 100000 and
  process.Ext.api.metadata.target_address_name == "Unbacked" and
  process.Ext.api.name in ("VirtualAlloc", "VirtualProtect", "MapViewOfFile", "MapViewOfFile2")) or

  (process.Ext.api.name == "SetThreadContext" and process.Ext.api.behaviors == "shellcode")
) and
process.thread.Ext.call_stack_final_user_module.name == "Unbacked" and
 (
  process.thread.Ext.call_stack_final_user_module.protection_provenance == "system.core.ni.dll" or
  process.thread.Ext.call_stack_final_user_module.protection_provenance_path like "c:\\windows\\assembly\\nativeimages_*\\system.core.ni.dll"
  )
  and not process.thread.Ext.call_stack_summary like ("*|Unbacked|clr.dll|*", "*Unbacked|mscorlib.ni.dll|*")
'''

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

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


[threat.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.behaviors == "allocate_shellcode" and process.Ext.api.parameters.size >= 100000 and
  process.Ext.api.metadata.target_address_name == "Unbacked" and
  process.Ext.api.name in ("VirtualAlloc", "VirtualProtect", "MapViewOfFile", "MapViewOfFile2")) or

  (process.Ext.api.name == "SetThreadContext" and process.Ext.api.behaviors == "shellcode")
) and
process.thread.Ext.call_stack_final_user_module.name == "Unbacked" and
 (
  process.thread.Ext.call_stack_final_user_module.protection_provenance == "system.core.ni.dll" or
  process.thread.Ext.call_stack_final_user_module.protection_provenance_path like "c:\\windows\\assembly\\nativeimages_*\\system.core.ni.dll"
  )
  and not process.thread.Ext.call_stack_summary like ("*|Unbacked|clr.dll|*", "*Unbacked|mscorlib.ni.dll|*")

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

Splunk Enterprise PostgreSQL Backup-to-Restore Potential RCE Sequence

#
Status
production
Severity
medium
Time window
19m
Group by
destination.ip, source.ip
Author
Elastic
Source
github.com/elastic/detection-rules

Detects a POST to the Splunk Enterprise PostgreSQL backup endpoint followed by a POST to the restore endpoint from the same client to the same host within a 15-minute window. This sequence is unusual and can align with the public CVE-2026-20253 pre-authentication RCE chain, where an attacker stages a database dump via the backup path and executes attacker-controlled SQL via the restore path.

Known False Positives

  • Legitimate PostgreSQL recovery operations performed by Splunk administrators through the backup and restore API. These should be rare and originate from known management networks. If such operations occur in your environment, scope exceptions by source IP or approved management network rather than suppressing the rule entirely.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

[metadata]
creation_date = "2026/06/15"
integration = ["network_traffic", "zeek", "suricata"]
maturity = "production"
updated_date = "2026/06/24"

[rule]
author = ["Elastic"]
description = """
Detects a POST to the Splunk Enterprise PostgreSQL backup endpoint followed by a POST to the restore endpoint from the
same client to the same host within a 15-minute window. This sequence is unusual and can align with the public
CVE-2026-20253 pre-authentication RCE chain, where an attacker stages a database dump via the backup path and executes
attacker-controlled SQL via the restore path.
"""
false_positives = [
    """
    Legitimate PostgreSQL recovery operations performed by Splunk administrators through the backup and restore API.
    These should be rare and originate from known management networks. If such operations occur in your environment,
    scope exceptions by source IP or approved management network rather than suppressing the rule entirely.
    """,
]
from = "now-19m"
language = "esql"
license = "Elastic License v2"
max_signals = 5
name = "Splunk Enterprise PostgreSQL Backup-to-Restore Potential RCE Sequence"
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 Splunk Enterprise PostgreSQL Backup-to-Restore Potential RCE Sequence

This rule fires when the same source IP sends a POST to both the `/backup` and `/restore` recovery
endpoints on the same Splunk host within 15 minutes. This two-step sequence is unusual and aligns with
the watchTowr CVE-2026-20253 RCE chain: the backup request can place an attacker-controlled
PostgreSQL dump on the Splunk filesystem (using `backupFile` path traversal or absolute path
injection), and the restore request can load that dump and execute attacker-controlled SQL through the
local PostgreSQL instance. A backup-plus-restore pair from an unrecognized source IP on a production
Splunk host should be investigated as potential exploitation.

### Possible investigation steps

- Review `http.response.status_code` for both requests. A `400` on the backup step indicates the
  sidecar handler was reached (the request parsed but failed), consistent with a vulnerable host.
- Check whether the backup request body (if captured by a WAF or proxy) contains `hostaddr=`,
  `host=`, or `passfile=` in the `database` field, or path traversal (`../`) or absolute paths
  in the `backupFile` field. These are the connection-string injection and file-placement artifacts
  specific to this exploit chain.
- Correlate with host telemetry on the Splunk server: look for new or modified files under
  `/opt/splunk/etc/apps/`, `/opt/splunk/var/packages/`, or `/tmp/` around the time of the requests.
- Check for Splunk process execution of `pg_dump` or `pg_restore` with unusual arguments,
  particularly connection strings containing external hostnames or IP addresses.
- Check for outbound network connections from the Splunk host to external PostgreSQL services
  (port 5432 or similar) following the backup request — this indicates successful connection-string
  injection causing the server to pivot to an attacker-controlled database.
- Verify whether the target Splunk host is running an affected version (10.0.0–10.0.6 or
  10.2.0–10.2.3). Splunk Enterprise 10.4 and Splunk Cloud are not affected.

### False positive analysis

- Authorized administrative recovery operations using the sidecar API. These should originate from
  known management IPs; create exceptions for approved management network ranges.
- Red-team or vulnerability management tooling that runs a full backup-to-restore probe as part of
  a CVE-2026-20253 exposure check.

### Response and remediation

- Treat a confirmed backup-and-restore sequence from an unrecognized source as active exploitation.
  Isolate the Splunk host from the network immediately and preserve forensic state.
- Examine the Splunk host for new or modified files, scheduled tasks, and PostgreSQL extension
  objects that may have been placed by the restore step.
- Patch Splunk Enterprise to an unaffected version (SVD-2026-0603). There is no vendor-provided
  workaround; patching is the only mitigation.
- Block Splunk Web port (default 8000) at the perimeter and restrict access to management networks
  while patching is in progress.
"""
references = [
    "https://nvd.nist.gov/vuln/detail/CVE-2026-20253",
    "https://advisory.splunk.com/advisories/SVD-2026-0603",
    "https://labs.watchtowr.com/why-use-app-level-auth-when-every-database-has-auth-splunk-enterprise-cve-2026-20253-pre-auth-rce/",
    "https://attack.mitre.org/techniques/T1190/",
]
risk_score = 47
rule_id = "7c7d2a89-b7e9-4e8d-bbf2-5a782fdcc803"
setup = """## Setup

This rule requires HTTP request metadata with `url.path` and `http.request.method` populated from
one of the following sources visible to the sensor without TLS decryption:
- Zeek (`logs-zeek.http*`) where Splunk Web traffic is cleartext or the sensor is downstream of TLS
  termination.
- Suricata (`logs-suricata.eve*`) in the same deployment conditions
- Elastic Agent `network_traffic` integration (`logs-network_traffic.http*`) with HTTP parsing enabled

Splunk Web listens on TCP port 8000 by default (`web.conf` `httpport`), which is included in the
default Network Packet Capture/Packetbeat HTTP port list. Add any custom Splunk Web `httpport` value
to the HTTP protocol configuration. Splunk's management service defaults to TCP port 8089
(`mgmtHostPort`) and commonly uses TLS; add 8089 only if management/API traffic is directly exposed or
visible to the sensor after decryption. If the PostgreSQL sidecar is directly exposed or monitored
locally on TCP port 5435, add port 5435 as an HTTP port as well. Zeek and Suricata can identify
plaintext HTTP on non-standard ports through protocol detection when their HTTP analyzers are enabled.
For TLS deployments, the sensor must observe decrypted HTTP, sit downstream of TLS termination, or use
proxy or load balancer logs that expose the HTTP path, method, and status code.

The rule uses a 19-minute lookback and verifies that the first and last matching recovery events are
no more than 15 minutes apart. Ensure `event.ingested` is populated and `timestamp_override` is set.
"""
severity = "medium"
tags = [
    "Domain: Network",
    "Use Case: Threat Detection",
    "Use Case: Vulnerability",
    "Use Case: Network Security Monitoring",
    "Tactic: Initial Access",
    "Data Source: Network Packet Capture",
    "Data Source: Network Traffic",
    "Data Source: Zeek",
    "Data Source: Suricata",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-network_traffic.http*, logs-zeek.http*, logs-suricata.eve*
| where http.request.method == "POST"
  and (
    url.path like "*splunkd/__raw/v1/postgres/recovery/*" or
    url.path like "/v1/postgres/recovery/*"
  )
| eval Esql.is_backup = case(url.path like "*/backup", 1, 0)
| eval Esql.is_restore = case(url.path like "*/restore", 1, 0)
| stats
    Esql.backup_count = SUM(Esql.is_backup),
    Esql.restore_count = SUM(Esql.is_restore),
    Esql.first_seen = MIN(@timestamp),
    Esql.last_seen = MAX(@timestamp),
    Esql.statuses = VALUES(http.response.status_code)
  by source.ip, destination.ip
| eval Esql.duration_minutes = DATE_DIFF("minute", Esql.first_seen, Esql.last_seen)
| where Esql.backup_count >= 1 and Esql.restore_count >= 1
  and Esql.duration_minutes <= 15
| keep source.ip, destination.ip, Esql.*
'''


[[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-network_traffic.http*, logs-zeek.http*, logs-suricata.eve*

Stage 2: where

| where http.request.method == "POST"
  and (
    url.path like "*splunkd/__raw/v1/postgres/recovery/*" or
    url.path like "/v1/postgres/recovery/*"
  )

Stage 3: eval

| eval Esql.is_backup = case(url.path like "*/backup", 1, 0)
Esql.is_backup =
ifurl.path like "*/backup"1
else0

Stage 4: eval

| eval Esql.is_restore = case(url.path like "*/restore", 1, 0)
Esql.is_restore =
ifurl.path like "*/restore"1
else0

Stage 5: stats

| stats
    Esql.backup_count = SUM(Esql.is_backup),
    Esql.restore_count = SUM(Esql.is_restore),
    Esql.first_seen = MIN(@timestamp),
    Esql.last_seen = MAX(@timestamp),
    Esql.statuses = VALUES(http.response.status_code)
  by source.ip, destination.ip

Stage 6: eval

| eval Esql.duration_minutes = DATE_DIFF("minute", Esql.first_seen, Esql.last_seen)

Stage 7: where

| where Esql.backup_count >= 1 and Esql.restore_count >= 1
  and Esql.duration_minutes <= 15

Stage 8: keep

| keep source.ip, destination.ip, Esql.*

Indicators

These rows show field, operator, and value matches.

Output Fields

These fields are emitted when the rule matches.

FieldSource
source.ipKEEP source.ip
destination.ipKEEP destination.ip
Esql.*KEEP Esql.*

Splunk Enterprise PostgreSQL Recovery Endpoint Injection Artifacts

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

Detects CVE-2026-20253 exploit artifacts against the Splunk Enterprise PostgreSQL sidecar recovery endpoints via complementary signals. Where endpoint or Network Packet Capture request-body logging is available, the rule matches PostgreSQL connection-string injection keywords, suspicious backupFile destinations, and known filesystem artifacts used to pivot from backup/restore primitives to file write or RCE. It also detects vulnerable recovery endpoint probing and empty-password Basic auth credentials observed in public exploit tooling.

Known False Positives

  • Authorized red-team or penetration testing tooling exercising the CVE-2026-20253 exploit chain. Legitimate Splunk user activity should not produce PostgreSQL connection-string keywords, suspicious filesystem targets, empty Basic auth credentials, or unauthenticated 400 responses on the recovery endpoints.

MITRE ATT&CK Coverage

TacticTechniques
Initial Access

Rule Body

[metadata]
creation_date = "2026/06/15"
integration = ["endpoint", "network_traffic", "zeek", "suricata", "azure", "gcp"]
maturity = "production"
updated_date = "2026/06/15"

[rule]
author = ["Elastic"]
description = """
Detects CVE-2026-20253 exploit artifacts against the Splunk Enterprise PostgreSQL sidecar recovery endpoints via
complementary signals. Where endpoint or Network Packet Capture request-body logging is available, the rule matches
PostgreSQL connection-string injection keywords, suspicious `backupFile` destinations, and known filesystem artifacts
used to pivot from backup/restore primitives to file write or RCE. It also detects vulnerable recovery endpoint probing
and empty-password Basic auth credentials observed in public exploit tooling.
"""
false_positives = [
    """
    Authorized red-team or penetration testing tooling exercising the CVE-2026-20253 exploit chain. Legitimate Splunk
    user activity should not produce PostgreSQL connection-string keywords, suspicious filesystem targets, empty Basic
    auth credentials, or unauthenticated 400 responses on the recovery endpoints.
    """,
]
from = "now-9m"
index = [
    "logs-endpoint.events.network*",
    "logs-network_traffic.http*",
    "logs-zeek.http*",
    "logs-suricata.eve*",
    "logs-azure.application_gateway*",
    "logs-gcp.loadbalancing_logs*",
]
language = "kuery"
license = "Elastic License v2"
name = "Splunk Enterprise PostgreSQL Recovery Endpoint Injection Artifacts"
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 Splunk Enterprise PostgreSQL Recovery Endpoint Injection Artifacts

This rule fires on distinct signals from the CVE-2026-20253 exploit chain and closely related recovery endpoint abuse:

**Body injection** (endpoint/WAF/proxy sources): A POST to the recovery endpoints with a body
containing PostgreSQL connection-string keywords (`hostaddr=`, `host=`, `port=`, `passfile=`,
`dbname=`, `user=`, `password=`, `sslmode=`, or `service=`), `backupFile` path traversal, suspicious
absolute destinations (`/tmp/`, `/var/tmp/`, `/dev/shm/`, `/opt/splunk/etc/apps/`, cron paths, or SSH
authorized keys), or known filesystem artifacts (`.pgpass`, `/opt/splunk/etc/apps/`). The `database`
JSON field is passed directly to `pg_dump` or `pg_restore` as a connection string, so
attacker-supplied keywords override the hardcoded local configuration. The `backupFile` parameter
controls the dump file path, enabling arbitrary file placement.

**Auth credential artifact** (Zeek sources): A POST to the recovery endpoints with an empty password
in the HTTP Basic auth header (`url.password : ""`). The exploit passes the Basic auth username
directly to `pg_dump` or `pg_restore` as a PostgreSQL username — any value works, so this branch does
not filter on specific usernames.

**Vulnerable endpoint probing**: A POST to `/v1/postgres/recovery/backup` or
`/v1/postgres/recovery/restore` returning HTTP 400. Public probes use this response distinction because
vulnerable handlers parse the request and return 400, while patched or protected paths return 401.

### Possible investigation steps

- Check `http.response.status_code`. A `400` indicates the request reached the vulnerable sidecar
  handler; a `401` indicates access was blocked or the host is patched. A `400` on the backup or
  restore path is consistent with probing, and a `400` with injection content in the body is a
  high-confidence indicator of active exploitation.
- Identify which injection artifact triggered the rule:
  - `hostaddr=` or `host=` in `database` → server-side database pivot; check for outbound connections
    from the Splunk host to port 5432 or the attacker-supplied `port=` value.
  - `port=`, `user=`, `password=`, `sslmode=`, or `service=` in `database` → generic libpq connection
    string smuggling; review the full body for remote database or credential manipulation.
  - `passfile=/opt/splunk/var/packages/data/postgres/.pgpass` → local PostgreSQL credential reuse;
    this exact string is the public restore-chain artifact from watchTowr.
  - `backupFile` with `../` traversal or suspicious absolute paths (`/tmp/`, `/var/tmp/`, `/dev/shm/`,
    `/opt/splunk/etc/apps/`, cron paths, or SSH authorized keys) → arbitrary file placement; check for
    new or modified files at those paths.
  - `dbname=template1` with `passfile=` → the published two-stage restore payload.
- Correlate with host telemetry: new files under `/opt/splunk/etc/apps/`, `/opt/splunk/var/packages/`,
  or `/tmp/` created around the request time.
- Check for outbound PostgreSQL connections from the Splunk host following any `hostaddr=` or `host=`
  injection (see companion rule "Splunk Enterprise PostgreSQL Backup-to-Restore Potential RCE Sequence").
- Verify whether the target Splunk host is running an affected version (10.0.0-10.0.6 or
  10.2.0-10.2.3). Splunk Enterprise 10.4 and Splunk Cloud are not affected.

### False positive analysis

- No legitimate Splunk user workflow sends PostgreSQL connection-string keywords or filesystem paths
  to these recovery endpoints. This rule has very low false positive potential when the path filter
  is in scope.

### Response and remediation

- Any confirmed body injection on the recovery endpoints should be treated as active exploitation.
  Isolate the Splunk host immediately and preserve forensic state.
- Check for files placed by `backupFile` traversal and SQL objects loaded by the restore step.
- Patch Splunk Enterprise to an unaffected version. There is no vendor-provided workaround for
  CVE-2026-20253.
"""
references = [
    "https://nvd.nist.gov/vuln/detail/CVE-2026-20253",
    "https://advisory.splunk.com/advisories/SVD-2026-0603",
    "https://labs.watchtowr.com/why-use-app-level-auth-when-every-database-has-auth-splunk-enterprise-cve-2026-20253-pre-auth-rce/",
    "https://attack.mitre.org/techniques/T1190/",
]
risk_score = 73
rule_id = "2a7823db-0bc2-48f6-aa2f-e6aef233c6dc"
setup = """## Setup

This rule covers two detection paths with different telemetry requirements:

**Body injection branch** (`http.request.body.content`): Populated by:
- Elastic Defend (`logs-endpoint.events.network*`) on the Splunk host, capturing HTTP network
  events at the endpoint level
- Network Packet Capture (`logs-network_traffic.http*`) with HTTP body capture enabled for the
  Splunk recovery paths

Avoid enabling broad request-body logging without masking or filtering — bodies can contain
credentials and PII. Scope capture to specific URL paths (e.g., `*/splunkd/*`) where possible.

**Auth artifact branch** (`url.password`, `url.username`): Populated by:
- Zeek (`logs-zeek.http*`) - parses HTTP Basic auth headers natively, no additional configuration

**Vulnerable endpoint probing branch** (`http.response.status_code`): Populated by Network Packet
Capture, Zeek, Suricata, Azure Application Gateway, and GCP Load Balancing where HTTP response
metadata is visible to the sensor.

Splunk Web listens on TCP port 8000 by default (`web.conf` `httpport`), which is included in the
default Network Packet Capture/Packetbeat HTTP port list. Add any custom Splunk Web `httpport` value
to the HTTP protocol configuration. Splunk's management service defaults to TCP port 8089
(`mgmtHostPort`) and commonly uses TLS; add 8089 only if management/API traffic is directly exposed or
visible to the sensor after decryption. If the PostgreSQL sidecar is directly exposed or monitored
locally on TCP port 5435, add port 5435 as an HTTP port as well. Zeek and Suricata can identify
plaintext HTTP on non-standard ports through protocol detection when their HTTP analyzers are enabled.
For TLS deployments, the sensor must observe decrypted HTTP, sit downstream of TLS termination, or use
proxy or load balancer logs that expose the HTTP path, method, and status code. Body-content detection
still requires request-body capture for the Splunk recovery paths.

Use the companion rule "Splunk Enterprise PostgreSQL Backup-to-Restore Potential RCE Sequence" for detections that work without
request-body capture or auth header logging.
"""
severity = "high"
tags = [
    "Domain: Network",
    "Use Case: Threat Detection",
    "Use Case: Vulnerability",
    "Use Case: Network Security Monitoring",
    "Tactic: Initial Access",
    "Data Source: Azure",
    "Data Source: Elastic Defend",
    "Data Source: GCP",
    "Data Source: Google Cloud Platform",
    "Data Source: Network Packet Capture",
    "Data Source: Network Traffic",
    "Data Source: Zeek",
    "Data Source: Suricata",
    "Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"

query = '''
http.request.method:POST and
url.path:("*splunkd/__raw/v1/postgres/recovery/*" or "/v1/postgres/recovery/*") and
(
  http.request.body.content:(
    "*\"backupFile\"*../*" or
    "*\"backupFile\"*/dev/shm/*" or
    "*\"backupFile\"*/etc/cron*" or
    "*\"backupFile\"*/home/*/.ssh/*" or
    "*\"backupFile\"*/opt/splunk/bin/scripts/*" or
    "*\"backupFile\"*/opt/splunk/etc/apps/*" or
    "*\"backupFile\"*/root/*" or
    "*\"backupFile\"*/tmp/*" or
    "*\"backupFile\"*/var/tmp/*" or
    "*\"backupFile\"*authorized_keys*" or
    "*\"database\"*dbname=*" or
    "*\"database\"*host=*" or
    "*\"database\"*hostaddr=*" or
    "*\"database\"*passfile=*" or
    "*\"database\"*password=*" or
    "*\"database\"*port=*" or
    "*\"database\"*service=*" or
    "*\"database\"*sslmode=*" or
    "*\"database\"*user=*" or
    "*/opt/splunk/etc/apps/*" or
    "*/opt/splunk/var/packages/data/postgres/.pgpass*"
  ) or
  data_stream.dataset:zeek.http and url.password:"" or
  data_stream.dataset:(azure.application_gateway or gcp.loadbalancing_logs or network_traffic.http or suricata.eve or zeek.http) and
  url.path:(
    "*splunkd/__raw/v1/postgres/recovery/backup" or
    "*splunkd/__raw/v1/postgres/recovery/restore" or
    /v1/postgres/recovery/backup or
    /v1/postgres/recovery/restore
  ) and
  http.response.status_code:400
)
'''


[[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: query

http.request.method:POST and
url.path:("*splunkd/__raw/v1/postgres/recovery/*" or "/v1/postgres/recovery/*") and
(
  http.request.body.content:(
    "*\"backupFile\"*../*" or
    "*\"backupFile\"*/dev/shm/*" or
    "*\"backupFile\"*/etc/cron*" or
    "*\"backupFile\"*/home/*/.ssh/*" or
    "*\"backupFile\"*/opt/splunk/bin/scripts/*" or
    "*\"backupFile\"*/opt/splunk/etc/apps/*" or
    "*\"backupFile\"*/root/*" or
    "*\"backupFile\"*/tmp/*" or
    "*\"backupFile\"*/var/tmp/*" or
    "*\"backupFile\"*authorized_keys*" or
    "*\"database\"*dbname=*" or
    "*\"database\"*host=*" or
    "*\"database\"*hostaddr=*" or
    "*\"database\"*passfile=*" or
    "*\"database\"*password=*" or
    "*\"database\"*port=*" or
    "*\"database\"*service=*" or
    "*\"database\"*sslmode=*" or
    "*\"database\"*user=*" or
    "*/opt/splunk/etc/apps/*" or
    "*/opt/splunk/var/packages/data/postgres/.pgpass*"
  ) or
  data_stream.dataset:zeek.http and url.password:"" or
  data_stream.dataset:(azure.application_gateway or gcp.loadbalancing_logs or network_traffic.http or suricata.eve or zeek.http) and
  url.path:(
    "*splunkd/__raw/v1/postgres/recovery/backup" or
    "*splunkd/__raw/v1/postgres/recovery/restore" or
    /v1/postgres/recovery/backup or
    /v1/postgres/recovery/restore
  ) and
  http.response.status_code:400
)

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
data_stream.dataseteq
  • zeek.http
field:"data_stream.dataset" kind:eq value:"zeek.http"
data_stream.datasetin
  • azure.application_gateway
  • gcp.loadbalancing_logs
  • network_traffic.http
  • suricata.eve
  • zeek.http
field:"data_stream.dataset" kind:in
http.request.body.contentin
  • *"backupFile"*../*
  • *"backupFile"*/dev/shm/*
  • *"backupFile"*/etc/cron*
  • *"backupFile"*/home/*/.ssh/*
  • *"backupFile"*/opt/splunk/bin/scripts/*
  • *"backupFile"*/opt/splunk/etc/apps/*
  • *"backupFile"*/root/*
  • *"backupFile"*/tmp/*
  • *"backupFile"*/var/tmp/*
  • *"backupFile"*authorized_keys*
  • *"database"*dbname=*
  • *"database"*host=*
  • *"database"*hostaddr=*
  • *"database"*passfile=*
  • *"database"*password=*
  • *"database"*port=*
  • *"database"*service=*
  • *"database"*sslmode=*
  • *"database"*user=*
  • */opt/splunk/etc/apps/*
  • */opt/splunk/var/packages/data/postgres/.pgpass*
field:"http.request.body.content" kind:in
http.request.methodeq
  • POST
field:"http.request.method" kind:eq value:"POST"
http.response.status_codeeq
  • 400
field:"http.response.status_code" kind:eq value:"400"
url.pathin
  • *splunkd/__raw/v1/postgres/recovery/*
  • *splunkd/__raw/v1/postgres/recovery/backup
  • *splunkd/__raw/v1/postgres/recovery/restore
  • /v1/postgres/recovery/*
  • /v1/postgres/recovery/backup
  • /v1/postgres/recovery/restore
field:"url.path" kind:in

Suspicious Execution via MSIEXEC

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

Identifies suspicious execution of the built-in Windows Installer, msiexec.exe, to install a package from usual paths or parent process. Adversaries may abuse msiexec.exe to launch malicious local MSI files.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
creation_date = "2023/09/26"
integration = ["endpoint", "windows"]
maturity = "production"
updated_date = "2025/03/20"

[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Identifies suspicious execution of the built-in Windows Installer, msiexec.exe, to install a package from usual paths or
parent process. Adversaries may abuse msiexec.exe to launch malicious local MSI files.
"""
from = "now-119m"
index = ["logs-endpoint.events.process-*", "winlogbeat-*", "logs-windows.*", "endgame-*"]
interval = "60m"
language = "eql"
license = "Elastic License v2"
name = "Suspicious Execution via MSIEXEC"
references = [
    "https://lolbas-project.github.io/lolbas/Binaries/Msiexec/",
    "https://www.guardicore.com/labs/purple-fox-rootkit-now-propagates-as-a-worm/",
]
risk_score = 21
rule_id = "708c9d92-22a3-4fe0-b6b9-1f861c55502d"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Defense Evasion",
    "Rule Type: BBR",
    "Data Source: Elastic Defend",
    "Data Source: Elastic Endgame",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where host.os.type == "windows" and event.action == "start" and
  process.name : "msiexec.exe" and user.id : ("S-1-5-21*", "S-1-12-*") and process.parent.executable != null and
  (
    (process.args : "/i" and process.args : ("/q", "/quiet") and process.args_count == 4 and
     process.args : ("?:\\Users\\*", "?:\\ProgramData\\*") and
     not process.parent.executable : ("?:\\Program Files (x86)\\*.exe",
                                      "?:\\Program Files\\*.exe",
                                      "?:\\Windows\\explorer.exe",
                                      "?:\\Users\\*\\Desktop\\*",
                                      "?:\\Users\\*\\Downloads\\*",
                                      "?:\\programdata\\*")) or

    (process.args_count == 1 and not process.parent.executable : ("?:\\Windows\\explorer.exe", "?:\\Windows\\SysWOW64\\explorer.exe")) or

    (process.args : "/i" and process.args : ("/q", "/quiet") and process.args_count == 4 and
     (process.parent.args : "Schedule" or process.parent.name : "wmiprvse.exe" or
     process.parent.executable : "?:\\Users\\*\\AppData\\*" or
     (process.parent.name : ("powershell.exe", "cmd.exe") and length(process.parent.command_line) >= 200))) or

    (process.args : "/i" and process.args : ("/q", "/quiet") and process.args_count == 4 and
     ?process.working_directory : "?:\\" and process.parent.name : ("cmd.exe", "powershell.exe"))
  ) and

  /* noisy pattern */
  not (process.parent.executable : "?:\\Users\\*\\AppData\\Local\\Temp\\*" and ?process.parent.args_count >= 2 and
       process.args : "?:\\Users\\*\\AppData\\Local\\Temp\\*\\*.msi") and

  not process.args : ("?:\\Program Files (x86)\\*", "?:\\Program Files\\*")
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[[rule.threat.technique.subtechnique]]
id = "T1218.007"
name = "Msiexec"
reference = "https://attack.mitre.org/techniques/T1218/007/"



[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.action == "start" and
  process.name : "msiexec.exe" and user.id : ("S-1-5-21*", "S-1-12-*") and process.parent.executable != null and
  (
    (process.args : "/i" and process.args : ("/q", "/quiet") and process.args_count == 4 and
     process.args : ("?:\\Users\\*", "?:\\ProgramData\\*") and
     not process.parent.executable : ("?:\\Program Files (x86)\\*.exe",
                                      "?:\\Program Files\\*.exe",
                                      "?:\\Windows\\explorer.exe",
                                      "?:\\Users\\*\\Desktop\\*",
                                      "?:\\Users\\*\\Downloads\\*",
                                      "?:\\programdata\\*")) or
    (process.args_count == 1 and not process.parent.executable : ("?:\\Windows\\explorer.exe", "?:\\Windows\\SysWOW64\\explorer.exe")) or
    (process.args : "/i" and process.args : ("/q", "/quiet") and process.args_count == 4 and
     (process.parent.args : "Schedule" or process.parent.name : "wmiprvse.exe" or
     process.parent.executable : "?:\\Users\\*\\AppData\\*" or
     (process.parent.name : ("powershell.exe", "cmd.exe") and length(process.parent.command_line) >= 200))) or
    (process.args : "/i" and process.args : ("/q", "/quiet") and process.args_count == 4 and
     ?process.working_directory : "?:\\" and process.parent.name : ("cmd.exe", "powershell.exe"))
  ) and
  not (process.parent.executable : "?:\\Users\\*\\AppData\\Local\\Temp\\*" and ?process.parent.args_count >= 2 and
       process.args : "?:\\Users\\*\\AppData\\Local\\Temp\\*\\*.msi") and
  not process.args : ("?:\\Program Files (x86)\\*", "?:\\Program Files\\*")

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.actioneq
  • start corpus 388 (elastic 388)
field:"EventType" kind:eq value:"start"
process.argswildcard
  • /i corpus 4 (elastic 4)
  • /q corpus 7 (elastic 7)
  • /quiet corpus 5 (elastic 5)
  • ?:\ProgramData\* corpus 3 (elastic 3)
  • ?:\Users\* corpus 4 (elastic 4)
field:"process.args" kind:wildcard
process.args_counteq
  • 1 transforms: number corpus 50 (elastic 50)
  • 4 transforms: number corpus 6 (elastic 6)
field:"process.args_count" kind:eq
process.namewildcard
  • msiexec.exe corpus 45 (elastic 40, splunk 5)
field:"process_basename" kind:wildcard value:"msiexec.exe"
process.parent.argswildcard
  • Schedule corpus 4 (elastic 4)
field:"process.parent.args" kind:wildcard value:"Schedule"
process.parent.executableis_not_null
  • (no value, null check)
field:"ParentImage" kind:is_not_null
process.parent.executablewildcard
  • ?:\Users\*\AppData\* corpus 4 (elastic 4)
field:"ParentImage" kind:wildcard value:"?:\Users\*\AppData\*"
process.parent.namewildcard
  • cmd.exe corpus 37 (elastic 32, splunk 4, kusto 1)
  • powershell.exe corpus 37 (elastic 35, splunk 1, kusto 1)
  • wmiprvse.exe corpus 24 (elastic 19, splunk 5)
field:"parent_process_basename" kind:wildcard
process.working_directorywildcard
  • ?:\ corpus 8 (elastic 8)
field:"CurrentDirectory" kind:wildcard value:"?:\"
user.idwildcard
  • S-1-12-* corpus 25 (elastic 25)
  • S-1-5-21* corpus 26 (elastic 26)
field:"user.id" kind:wildcard

Exclusions

The rule actively suppresses these predicates.

Suspicious Recursive File Deletion via Built-In Utilities

#
Source
github.com/elastic/protections-artifacts

Identifies suspicious use of the Linux rm command to recursively delete user home files and directories. Certain ransomware families abuse this built-in utility to delete user files and important system files after their encryption process is complete.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[rule]
description = """
Identifies suspicious use of the Linux rm command to recursively delete user home files and directories. Certain
ransomware families abuse this built-in utility to delete user files and important system files after their encryption
process is complete.
"""
id = "15019d7c-42e6-4cf7-88b0-0c3a6963e6f5"
license = "Elastic License v2"
name = "Suspicious Recursive File Deletion via Built-In Utilities"
os_list = ["linux", "macos"]
reference = [
    "https://www.trendmicro.com/en_us/research/21/f/bash-ransomware-darkradiation-targets-red-hat--and-debian-based-linux-distributions.html",
]
version = "1.0.28"

query = '''
process where event.action == "exec" and

 /* recursive file deletion and multiple directories passed for deletion */
 process.name == "rm" and process.args == "-rf" and process.args_count >= 10 and

 /* encrypting users home or docker folders */
 process.args : ("/home/*", "/var/lib/docker/*") and process.parent.name == "xargs"
'''

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

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

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1485"
name = "Data Destruction"
reference = "https://attack.mitre.org/techniques/T1485/"

[[threat.technique]]
id = "T1565"
name = "Data Manipulation"
reference = "https://attack.mitre.org/techniques/T1565/"


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

[internal]
min_endpoint_version = "7.15.0"

Stages and Predicates

Stage 1: process

process where event.action == "exec" and
 process.name == "rm" and process.args == "-rf" and process.args_count >= 10 and
 process.args : ("/home/*", "/var/lib/docker/*") and process.parent.name == "xargs"

Indicators

These rows show field, operator, and value matches.

System Information Discovery via Windows Command Shell

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

Identifies the execution of discovery commands to enumerate system information, files, and folders using the Windows Command Shell.

MITRE ATT&CK Coverage

Telemetry Coverage

Rule Body

[metadata]
bypass_bbr_timing = true
creation_date = "2022/11/01"
integration = ["endpoint", "windows", "system"]
maturity = "production"
updated_date = "2025/03/20"

[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Identifies the execution of discovery commands to enumerate system information, files, and folders using the Windows
Command Shell.
"""
from = "now-9m"
index = [
    "endgame-*",
    "logs-endpoint.events.process-*",
    "logs-system.security*",
    "logs-windows.*",
    "winlogbeat-*",
]
language = "eql"
license = "Elastic License v2"
name = "System Information Discovery via Windows Command Shell"
note = """## Triage and analysis

### Investigating System Information Discovery via Windows Command Shell

After successfully compromising an environment, attackers may try to gain situational awareness to plan their next steps. This can happen by running commands to enumerate network resources, users, connections, files, and installed security software.

This rule identifies commands to enumerate system information, files, and folders using the Windows Command Shell.

#### 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.
- Investigate other alerts associated with the user/host during the past 48 hours.
- Investigate any abnormal account behavior, such as command executions, file creations or modifications, and network connections.

### False positive analysis

- Discovery activities are not inherently malicious if they occur in isolation. As long as the analyst did not identify suspicious activity related to the user or host, such alerts can be dismissed.

### 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.
- 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.
- Run a full antimalware scan. This may reveal additional artifacts left in the system, persistence mechanisms, and malware components.
- Determine the initial vector abused by the attacker and take action to prevent reinfection through the same vector.
- Using the incident response data, update logging and audit policies to improve the mean time to detect (MTTD) and the mean time to respond (MTTR).
"""
risk_score = 21
rule_id = "d68e95ad-1c82-4074-a12a-125fe10ac8ba"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Discovery",
    "Tactic: Execution",
    "Resources: Investigation Guide",
    "Data Source: Elastic Defend",
    "Rule Type: BBR",
    "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 : "cmd.exe" and process.args : "/c" and process.args : ("set", "dir") and
  not process.parent.executable : (
    "?:\\Program Files\\*",
    "?:\\Program Files (x86)\\*",
    "?:\\PROGRA~1\\*",
    "?:\\TeamCity\\jre\\bin\\java.exe"
  ) and
  not process.args : (
    "*\\db\\rabbit@*", "*/db/rabbit@*",
    "*rabbitmq/db/*", "*RabbitMQ\\db*"
  ) and
  not process.parent.args : "*C:\\Program Files (x86)\\Tanium\\Tanium Client\\TPython\\TPython.bat*"
'''


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

[[rule.threat.technique]]
id = "T1083"
name = "File and Directory Discovery"
reference = "https://attack.mitre.org/techniques/T1083/"


[rule.threat.tactic]
id = "TA0007"
name = "Discovery"
reference = "https://attack.mitre.org/tactics/TA0007/"
[[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.003"
name = "Windows Command Shell"
reference = "https://attack.mitre.org/techniques/T1059/003/"



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

Stages and Predicates

Stage 1: process

process where host.os.type == "windows" and event.type == "start" and
  process.name : "cmd.exe" and process.args : "/c" and process.args : ("set", "dir") and
  not process.parent.executable : (
    "?:\\Program Files\\*",
    "?:\\Program Files (x86)\\*",
    "?:\\PROGRA~1\\*",
    "?:\\TeamCity\\jre\\bin\\java.exe"
  ) and
  not process.args : (
    "*\\db\\rabbit@*", "*/db/rabbit@*",
    "*rabbitmq/db/*", "*RabbitMQ\\db*"
  ) and
  not process.parent.args : "*C:\\Program Files (x86)\\Tanium\\Tanium Client\\TPython\\TPython.bat*"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
event.typeeq
  • start corpus 1036 (elastic 1036)
field:"event.type" kind:eq value:"start"
process.argswildcard
  • /c corpus 7 (elastic 7)
  • dir
  • set corpus 5 (elastic 5)
field:"process.args" kind:wildcard
process.namewildcard
  • cmd.exe corpus 122 (elastic 93, splunk 29)
field:"process_basename" kind:wildcard value:"cmd.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.argsmatch\db\rabbit@, /db/rabbit@, rabbitmq/db/, RabbitMQ\dbexcludes:process.args
process.parent.argsmatchC:\Program Files (x86)\Tanium\Tanium Client\TPython\TPython.batexcludes:process.parent.args field:"process.parent.args" value:"C:\Program Files (x86)\Tanium\Tanium Client\TPython\TPython.bat"
process.parent.executablewildcard?:\Program Files\*, ?:\Program Files (x86)\*, ?:\PROGRA~1\*, ?:\TeamCity\jre\bin\java.exeexcludes:process.parent.executable

Back to all Elastic rules