Detection rules › Elastic
Elastic rules: 2j
AWS Backup Recovery Point Deleted
#Identifies deletion of an AWS Backup recovery point via DeleteRecoveryPoint. A recovery point is a stored backup of a protected resource (EBS, RDS, DynamoDB, EFS, S3, and others). Deleting recovery points removes the ability to restore the associated data and is a core anti-recovery technique used in ransomware and data-destruction attacks to ensure victims cannot recover without paying or rebuilding. Routine lifecycle expirations are performed by the AWS Backup service itself; deletion by a non-service principal is rare and should be reviewed.
Known False Positives
- Backup, platform, or infrastructure-as-code teams may delete recovery points during retention cleanup, migration, or decommissioning. Verify the principal in "aws.cloudtrail.user_identity.arn", the affected recovery point and vault in "aws.cloudtrail.request_parameters", and whether the deletion aligns with an approved change. Known administration roles can be excluded after validation.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| AWS | CloudTrail event DeleteRecoveryPoint: Deletes the recovery point specified by a recovery point ID. |
Rule Body
[metadata]
creation_date = "2026/06/26"
integration = ["aws"]
maturity = "production"
updated_date = "2026/06/26"
[rule]
author = ["Elastic"]
description = """
Identifies deletion of an AWS Backup recovery point via DeleteRecoveryPoint. A recovery point is a stored backup of a
protected resource (EBS, RDS, DynamoDB, EFS, S3, and others). Deleting recovery points removes the ability to restore
the associated data and is a core anti-recovery technique used in ransomware and data-destruction attacks to ensure
victims cannot recover without paying or rebuilding. Routine lifecycle expirations are performed by the AWS Backup
service itself; deletion by a non-service principal is rare and should be reviewed.
"""
false_positives = [
"""
Backup, platform, or infrastructure-as-code teams may delete recovery points during retention cleanup, migration, or
decommissioning. Verify the principal in "aws.cloudtrail.user_identity.arn", the affected recovery point and vault
in "aws.cloudtrail.request_parameters", and whether the deletion aligns with an approved change. Known
administration roles can be excluded after validation.
""",
]
from = "now-6m"
index = ["logs-aws.cloudtrail-*"]
language = "kuery"
license = "Elastic License v2"
name = "AWS Backup Recovery Point Deleted"
note = """## Triage and analysis
### Investigating AWS Backup Recovery Point Deleted
AWS Backup recovery points are the restorable copies of protected resources. "DeleteRecoveryPoint" permanently removes a recovery point from its vault, eliminating the ability to restore that backup. Adversaries delete recovery points to inhibit recovery after data destruction or encryption, maximizing the impact of ransomware or sabotage. Because scheduled expirations are carried out by the AWS Backup service itself (excluded by this rule), a deletion by a user or role principal is uncommon and high-signal, especially when several recovery points are removed in a short window.
### Possible investigation steps
- Identify the actor in "aws.cloudtrail.user_identity.arn" and "aws.cloudtrail.user_identity.type", and review "source.ip", "source.as.organization.name", and "user_agent.original" for an unexpected origin.
- Identify the affected recovery point and vault from "aws.cloudtrail.request_parameters", and determine which resource and data it protected.
- Determine whether multiple recovery points or vaults were affected in the same window, indicating a broader anti-recovery effort.
- Correlate with adjacent destructive or evasion activity by the same principal, such as DeleteBackupVault, Vault Lock removal, KMS key deletion, or resource deletions.
### False positive analysis
- Retention cleanup, migration, or decommissioning may delete recovery points. Confirm the deletion is expected and exclude known administration roles on "aws.cloudtrail.user_identity.arn" after validation.
### Response and remediation
- If the deletion is unauthorized, treat it as a potential precursor to or part of a destructive attack: preserve remaining backups, enable Vault Lock where possible, and engage incident response.
- Rotate or restrict credentials for the principal if compromise is suspected, and restrict "backup:DeleteRecoveryPoint" to a small set of trusted administrators via IAM and SCPs.
### Additional information
- [DeleteRecoveryPoint API](https://docs.aws.amazon.com/aws-backup/latest/devguide/API_DeleteRecoveryPoint.html)
- [AWS Backup Vault Lock](https://docs.aws.amazon.com/aws-backup/latest/devguide/vault-lock.html)
"""
references = [
"https://docs.aws.amazon.com/aws-backup/latest/devguide/API_DeleteRecoveryPoint.html",
"https://docs.aws.amazon.com/aws-backup/latest/devguide/vault-lock.html",
]
risk_score = 73
rule_id = "042b35f3-afa6-4441-92b2-ef41976b48a3"
setup = """This rule requires AWS CloudTrail management events for AWS Backup and ingestion via the Elastic AWS CloudTrail integration. See https://docs.elastic.co/integrations/aws/cloudtrail."""
severity = "high"
tags = [
"Domain: Cloud",
"Data Source: AWS",
"Data Source: Amazon Web Services",
"Data Source: AWS Backup",
"Use Case: Threat Detection",
"Tactic: Impact",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
data_stream.dataset: "aws.cloudtrail"
and event.provider: "backup.amazonaws.com"
and event.action: "DeleteRecoveryPoint"
and event.outcome: "success"
and not aws.cloudtrail.user_identity.type: "AWSService"
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1490"
name = "Inhibit System Recovery"
reference = "https://attack.mitre.org/techniques/T1490/"
[rule.threat.tactic]
id = "TA0040"
name = "Impact"
reference = "https://attack.mitre.org/tactics/TA0040/"
[rule.investigation_fields]
field_names = [
"@timestamp",
"user.name",
"user_agent.original",
"source.ip",
"source.as.number",
"source.as.organization.name",
"aws.cloudtrail.user_identity.arn",
"aws.cloudtrail.user_identity.type",
"aws.cloudtrail.user_identity.access_key_id",
"event.action",
"event.outcome",
"cloud.account.id",
"cloud.region",
"aws.cloudtrail.request_parameters",
"aws.cloudtrail.response_elements",
]
Stages and Predicates
Stage 1: query
data_stream.dataset: "aws.cloudtrail"
and event.provider: "backup.amazonaws.com"
and event.action: "DeleteRecoveryPoint"
and event.outcome: "success"
and not aws.cloudtrail.user_identity.type: "AWSService"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"aws.cloudtrail" |
event.action | eq |
| field:"EventType" kind:eq value:"DeleteRecoveryPoint" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
event.provider | eq |
| field:"Provider_Name" kind:eq value:"backup.amazonaws.com" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
aws.cloudtrail.user_identity.type | eq | AWSService | excludes:aws.cloudtrail.user_identity.type field:"aws.cloudtrail.user_identity.type" value:"AWSService" |
Disabling User Account Control via Registry Modification
#User Account Control (UAC) can help mitigate the impact of malware on Windows hosts. With UAC, apps and tasks always run in the security context of a non-administrator account, unless an administrator specifically authorizes administrator-level access to the system. This rule identifies registry value changes to bypass User Access Control (UAC) protection.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation | |
| Defense Impairment |
Telemetry Coverage
Rule Body
[metadata]
creation_date = "2021/01/20"
integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike"]
maturity = "production"
updated_date = "2026/05/04"
[rule]
author = ["Elastic"]
description = """
User Account Control (UAC) can help mitigate the impact of malware on Windows hosts. With UAC, apps and tasks always run
in the security context of a non-administrator account, unless an administrator specifically authorizes
administrator-level access to the system. This rule identifies registry value changes to bypass User Access Control
(UAC) protection.
"""
from = "now-9m"
index = [
"winlogbeat-*",
"logs-endpoint.events.registry-*",
"logs-windows.sysmon_operational-*",
"endgame-*",
"logs-m365_defender.event-*",
"logs-sentinel_one_cloud_funnel.*",
"logs-crowdstrike.fdr*",
]
language = "eql"
license = "Elastic License v2"
name = "Disabling User Account Control via Registry Modification"
note = """## Triage and analysis
### Investigating Disabling User Account Control via Registry Modification
Windows User Account Control (UAC) allows a program to elevate its privileges (tracked as low to high integrity levels) to perform a task under administrator-level permissions, possibly by prompting the user for confirmation. UAC can deny an operation under high-integrity enforcement, or allow the user to perform the action if they are in the local administrators group and enter an administrator password when prompted.
For more information about the UAC and how it works, check the [official Microsoft docs page](https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/how-user-account-control-works).
Attackers may disable UAC to execute code directly in high integrity. This rule identifies registry value changes to bypass the UAC protection.
#### 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.
- Inspect the host for suspicious or abnormal behaviors in the alert timeframe.
- Investigate abnormal behaviors observed by the subject process such as network connections, registry or file modifications, and any spawned child processes.
- Analyze non-system processes executed with high integrity after UAC was disabled for unknown or suspicious processes.
- Retrieve the suspicious processes' executables and determine if they are malicious:
- Use a private sandboxed malware analysis system to perform analysis.
- Observe and collect information about the following activities:
- Attempts to contact external domains and addresses.
- File and registry access, modification, and creation activities.
- Service creation and launch activities.
- Scheduled tasks creation.
- Use the PowerShell `Get-FileHash` cmdlet to get the files' SHA-256 hash values.
- Search for the existence and reputation of the hashes in resources like VirusTotal, Hybrid-Analysis, CISCO Talos, Any.run, etc.
### False positive analysis
- This activity is unlikely to happen legitimately. Benign true positives (B-TPs) can be added as exceptions if necessary.
### 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.
- Restore UAC settings to the desired state.
- Run a full antimalware scan. This may reveal additional artifacts left in the system, persistence mechanisms, and malware components.
- Investigate credential exposure on systems compromised or used by the attacker to ensure all compromised accounts are identified. Reset passwords for these accounts and other potentially compromised credentials, such as email, business systems, and web services.
- Determine the initial vector abused by the attacker and take action to prevent reinfection through the same vector.
- Using the incident response data, update logging and audit policies to improve the mean time to detect (MTTD) and the mean time to respond (MTTR).
"""
setup = """## Setup
This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
Setup instructions: https://ela.st/install-elastic-defend
### Additional data sources
This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
- [CrowdStrike](https://ela.st/crowdstrike-integration)
- [Microsoft Defender XDR](https://ela.st/m365-defender)
- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
- [Sysmon Registry Events](https://ela.st/sysmon-event-reg-setup)
"""
references = [
"https://www.greyhathacker.net/?p=796",
"https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/user-account-control-group-policy-and-registry-key-settings",
"https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/user-account-control-overview",
"https://www.elastic.co/security-labs/dissecting-remcos-rat-part-four",
]
risk_score = 47
rule_id = "d31f183a-e5b1-451b-8534-ba62bca0b404"
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Privilege Escalation",
"Resources: Investigation Guide",
"Data Source: Elastic Endgame",
"Data Source: Elastic Defend",
"Data Source: Sysmon",
"Data Source: Microsoft Defender XDR",
"Data Source: SentinelOne",
"Data Source: Crowdstrike",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
registry where host.os.type == "windows" and event.type == "change" and
registry.value : ("EnableLUA", "ConsentPromptBehaviorAdmin", "PromptOnSecureDesktop") and
registry.data.strings : ("0", "0x00000000")
/*
Full registry key path omitted due to data source variations:
HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA
HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ConsentPromptBehaviorAdmin
HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\PromptOnSecureDesktop
*/
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1548"
name = "Abuse Elevation Control Mechanism"
reference = "https://attack.mitre.org/techniques/T1548/"
[[rule.threat.technique.subtechnique]]
id = "T1548.002"
name = "Bypass User Account Control"
reference = "https://attack.mitre.org/techniques/T1548/002/"
[rule.threat.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1112"
name = "Modify Registry"
reference = "https://attack.mitre.org/techniques/T1112/"
[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"
[[rule.threat.technique.subtechnique]]
id = "T1562.001"
name = "Disable or Modify Tools"
reference = "https://attack.mitre.org/techniques/T1562/001/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
Stages and Predicates
Stage 1: registry
registry where host.os.type == "windows" and event.type == "change" and
registry.value : ("EnableLUA", "ConsentPromptBehaviorAdmin", "PromptOnSecureDesktop") and
registry.data.strings : ("0", "0x00000000")
/*
Full registry key path omitted due to data source variations:
HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA
HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ConsentPromptBehaviorAdmin
HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\PromptOnSecureDesktop
*/
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"change" |
registry.data.strings | wildcard |
| field:"Details" kind:wildcard |
registry.value | wildcard |
| field:"registry_value_name" kind:wildcard |
Entra ID Global Administrator Role Assigned (PIM User)
#Identifies an Azure Active Directory (AD) Global Administrator role addition to a Privileged Identity Management (PIM) user account. PIM is a service that enables you to manage, control, and monitor access to important resources in an organization. Users who are assigned to the Global administrator role can read and modify any administrative setting in your Azure AD organization.
Known False Positives
- Global administrator additions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Global administrator additions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Telemetry Coverage
Rules Detecting the Same Action
These rules filter on the same operation.
- [Entra ID] Application Assigned Administrator Permissions Immediately After Obtaining Role Management Permissions (Kusto)
- [Entra ID] Mass Privileged Role Change Activity Detected (Kusto)
- [Entra ID] Privilege Elevation Request Denied (Kusto)
- [Entra ID] Privileged Role Assigned to a New User (Kusto)
- [Entra ID] Privileged Role Assigned to User (Kusto)
- Account Elevated to New Role (Kusto)
- Admin promotion after Role Management Application Permission Grant (Kusto)
- App Assigned To Azure RBAC/Microsoft Entra Role (Sigma)
Rule Body
[metadata]
creation_date = "2020/09/24"
integration = ["azure"]
maturity = "production"
updated_date = "2026/04/10"
[rule]
author = ["Elastic"]
description = """
Identifies an Azure Active Directory (AD) Global Administrator role addition to a Privileged Identity Management (PIM)
user account. PIM is a service that enables you to manage, control, and monitor access to important resources in an
organization. Users who are assigned to the Global administrator role can read and modify any administrative setting in
your Azure AD organization.
"""
false_positives = [
"""
Global administrator additions may be done by a system or network administrator. Verify whether the username,
hostname, and/or resource name should be making changes in your environment. Global administrator additions from
unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted
from the rule.
""",
]
index = ["logs-azure.auditlogs-*", "filebeat-*"]
language = "kuery"
license = "Elastic License v2"
name = "Entra ID Global Administrator Role Assigned (PIM 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 Entra ID Global Administrator Role Assigned (PIM User)
Azure AD's Global Administrator role grants extensive access, allowing users to modify any administrative setting. Privileged Identity Management (PIM) helps manage and monitor such access. Adversaries may exploit this by adding themselves or others to this role, gaining persistent control. The detection rule identifies suspicious role additions by monitoring specific audit logs, focusing on successful role assignments to PIM users, thus helping to flag potential unauthorized access attempts.
### Possible investigation steps
- Review the Azure audit logs to confirm the details of the role addition event, focusing on the event.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement fields.
- Identify the user account that was added to the Global Administrator role by examining the azure.auditlogs.properties.target_resources.*.display_name field.
- Check the event.outcome field to ensure the role addition was successful and not a failed attempt.
- Investigate the user account's recent activities and login history to determine if there are any anomalies or signs of compromise.
- Verify if the role addition aligns with any recent administrative changes or requests within the organization to rule out legitimate actions.
- Assess the potential impact of the role addition by reviewing the permissions and access levels granted to the user.
- If suspicious activity is confirmed, initiate a response plan to remove unauthorized access and secure the affected accounts.
### False positive analysis
- Routine administrative tasks may trigger alerts when legitimate IT staff are assigned the Global Administrator role for maintenance or updates. To manage this, create exceptions for known IT personnel or scheduled maintenance windows.
- Automated scripts or tools used for role assignments can cause false positives if they frequently add users to the Global Administrator role. Consider excluding these automated processes from monitoring or adjusting the detection rule to account for their activity.
- Temporary project-based role assignments might be flagged as suspicious. Implement a process to document and pre-approve such assignments, allowing for their exclusion from alerts.
- Training or onboarding sessions where new administrators are temporarily granted elevated access can result in false positives. Establish a protocol to notify the monitoring team of these events in advance, so they can be excluded from the detection rule.
### Response and remediation
- Immediately revoke the Global Administrator role from any unauthorized PIM user identified in the alert to prevent further unauthorized access.
- Conduct a thorough review of recent changes made by the affected account to identify any unauthorized modifications or suspicious activities.
- Reset the credentials of the compromised account and enforce multi-factor authentication (MFA) to secure the account against further unauthorized access.
- Notify the security team and relevant stakeholders about the incident for awareness and further investigation.
- Implement additional monitoring on the affected account and related systems to detect any further suspicious activities.
- Review and update access policies and role assignments in Azure AD to ensure that only necessary personnel have elevated privileges.
- Document the incident and response actions taken for future reference and to improve incident response procedures.
## Setup
The Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule."""
references = [
"https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles",
]
risk_score = 73
rule_id = "ed9ecd27-e3e6-4fd9-8586-7754803f7fc8"
severity = "high"
tags = ["Domain: Cloud", "Data Source: Azure", "Use Case: Identity and Access Audit", "Tactic: Persistence", "Resources: Investigation Guide"]
timestamp_override = "event.ingested"
type = "query"
query = '''
data_stream.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement and
azure.auditlogs.operation_name:("Add eligible member to role in PIM completed (permanent)" or
"Add member to role in PIM completed (timebound)") and
azure.auditlogs.properties.target_resources.*.display_name:"Global Administrator" and
event.outcome:(Success or success)
'''
[[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: query
data_stream.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement and
azure.auditlogs.operation_name:("Add eligible member to role in PIM completed (permanent)" or
"Add member to role in PIM completed (timebound)") and
azure.auditlogs.properties.target_resources.*.display_name:"Global Administrator" and
event.outcome:(Success or success)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
azure.auditlogs.operation_name | in |
| field:"azure_ad::activity_display_name" kind:in |
azure.auditlogs.properties.category | eq |
| field:"azure.auditlogs.properties.category" kind:eq value:"RoleManagement" |
azure.auditlogs.properties.target_resources.*.display_name | eq |
| field:"azure.auditlogs.properties.target_resources.*.display_name" kind:eq value:"Global Administrator" |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"azure.auditlogs" |
event.outcome | in |
| field:"event.outcome" kind:in |
Execution of a Downloaded Windows Script via Explorer
#Identifies execution of a Windows script that was downloaded from the internet, extracted via explorer and followed by spawning a child process or performing an outgoing network connection to the internet.
MITRE ATT&CK Coverage
Rule Body
[rule]
description = """
Identifies execution of a Windows script that was downloaded from the internet, extracted via explorer and followed by
spawning a child process or performing an outgoing network connection to the internet.
"""
id = "d8e8168f-3f1f-4e03-a069-a36879bde0f9"
license = "Elastic License v2"
name = "Execution of a Downloaded Windows Script via Explorer"
os_list = ["windows"]
version = "1.0.2"
query = '''
sequence with maxspan=5m
[file where event.action == "creation" and process.name : "explorer.exe" and
file.Ext.windows.zone_identifier == 3 and file.name : "*:Zone.Identifier" and file.path : "?:\\Users\\*" and
file.extension in~ ("js", "jse", "vbs", "vbe", "wsh", "hta", "chm", "msc")] as event0
[process where event.action == "start" and
process.name in~ ("wscript.exe", "mshta.exe", "hh.exe", "mmc.exe") and process.parent.name : "explorer.exe" and
(
/* substring used to remove Zone.Identifier from file.name */
stringcontains~(process.command_line, substring(event0.file.name, 0, length(event0.file.name) - 16)) or
stringcontains~(process.command_line, event0.file.name) or
startswith~(event0.file.path, process.working_directory)
)] as event1
[any where
/* script utility spawn a child process */
(event.category == "process" and event.action == "start" and
process.parent.name in~ ("wscript.exe", "mshta.exe", "hh.exe", "mmc.exe") and process.parent.entity_id == event1.process.entity_id) or
/* script utility perform an egress conn to the internet */
(event.category == "network" and event.action in ("disconnect_received", "connection_attempted") and
process.name in~ ("wscript.exe", "mshta.exe", "hh.exe", "mmc.exe") and
process.entity_id == event1.process.entity_id 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.88.99.0/24", "224.0.0.0/4",
"100.64.0.0/10", "192.168.0.0/16", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24",
"240.0.0.0/4", "::1", "FE80::/10", "FF00::/8"))]
'''
min_endpoint_version = "8.10.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
tree = true
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 2
tree = true
[[optional_actions]]
action = "rollback"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.005"
name = "Visual Basic"
reference = "https://attack.mitre.org/techniques/T1059/005/"
[[threat.technique.subtechnique]]
id = "T1059.007"
name = "JavaScript"
reference = "https://attack.mitre.org/techniques/T1059/007/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[[threat.technique.subtechnique]]
id = "T1218.001"
name = "Compiled HTML File"
reference = "https://attack.mitre.org/techniques/T1218/001/"
[[threat.technique.subtechnique]]
id = "T1218.005"
name = "Mshta"
reference = "https://attack.mitre.org/techniques/T1218/005/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "8.10.0"
Stages and Predicates
Stage 1: file
[file where event.action == "creation" and process.name : "explorer.exe" and
file.Ext.windows.zone_identifier == 3 and file.name : "*:Zone.Identifier" and file.path : "?:\\Users\\*" and
file.extension in~ ("js", "jse", "vbs", "vbe", "wsh", "hta", "chm", "msc")] as event0
Stage 2: process
[process where event.action == "start" and
process.name in~ ("wscript.exe", "mshta.exe", "hh.exe", "mmc.exe") and process.parent.name : "explorer.exe" and
(
stringcontains~(process.command_line, substring(event0.file.name, 0, length(event0.file.name) - 16)) or
stringcontains~(process.command_line, event0.file.name) or
startswith~(event0.file.path, process.working_directory)
)] as event1
Stage 3: any
[any where
(event.category == "process" and event.action == "start" and
process.parent.name in~ ("wscript.exe", "mshta.exe", "hh.exe", "mmc.exe") and process.parent.entity_id == event1.process.entity_id) or
(event.category == "network" and event.action in ("disconnect_received", "connection_attempted") and
process.name in~ ("wscript.exe", "mshta.exe", "hh.exe", "mmc.exe") and
process.entity_id == event1.process.entity_id 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.88.99.0/24", "224.0.0.0/4",
"100.64.0.0/10", "192.168.0.0/16", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24",
"240.0.0.0/4", "::1", "FE80::/10", "FF00::/8"))]
Indicators
These rows show field, operator, and value matches.
IBM QRadar External Alerts
#Generates a detection alert for each IBM QRadar offense written to the configured indices. Enabling this rule allows you to immediately begin investigating IBM QRadar offense alerts in the app.
Rule Body
[metadata]
creation_date = "2026/03/17"
integration = ["ibm_qradar"]
maturity = "production"
promotion = true
updated_date = "2026/03/17"
[rule]
author = ["Elastic"]
description = """
Generates a detection alert for each IBM QRadar offense written to the configured indices. Enabling this rule allows you
to immediately begin investigating IBM QRadar offense alerts in the app.
"""
from = "now-2m"
index = ["logs-ibm_qradar.offense-*"]
interval = "1m"
language = "kuery"
license = "Elastic License v2"
max_signals = 1000
name = "IBM QRadar External Alerts"
note = """## Triage and analysis
### Investigating IBM QRadar External Alerts
IBM QRadar is a Security Intelligence Platform that provides SIEM, log management, anomaly detection, and incident forensics. The rule promotes QRadar offense records as Elastic detection alerts, enabling analysts to investigate potential threats with full offense context including rule names, severity, and status.
### Possible investigation steps
- Review the offense details including rule name, description, and categories to understand the nature of the alert.
- Examine the offense severity and status (OPEN, HIDDEN, etc.) to prioritize investigation.
- Cross-reference the offense with QRadar console for additional context including contributing events and log sources.
- Investigate source and destination networks, device count, and event count associated with the offense.
- Consult the IBM QRadar investigation guide and resources tagged in the alert for specific guidance on handling similar threats.
### False positive analysis
- Offenses triggered by routine administrative activities or known maintenance can be false positives. Review the offense context and create exceptions for scheduled activities.
- Legitimate security testing or penetration testing may generate offenses. Coordinate with security teams to whitelist these during scheduled tests.
- Low-severity offenses from specific rules that are known to produce noise can be excluded by creating rule exceptions.
- Offenses from development or test environments may not require investigation. Consider excluding these environments if appropriate.
### Response and remediation
- Isolate affected systems if malicious activity is confirmed to prevent lateral movement.
- Review the offense details to identify compromised accounts, credentials, or systems and take appropriate remediation steps.
- Apply relevant security patches or updates to address any exploited vulnerabilities.
- Escalate to the security operations center (SOC) or incident response team for further analysis if the threat appears significant.
- Document the incident and update detection logic or exceptions based on findings.
"""
references = ["https://docs.elastic.co/en/integrations/ibm_qradar"]
risk_score = 47
rule_id = "d6702168-2be6-4d7d-a549-9bff67733df3"
rule_name_override = "rule.name"
setup = """## Setup
### IBM QRadar Offense Integration
This rule is designed to capture offense events generated by the IBM QRadar integration and promote them as Elastic detection alerts.
To capture IBM QRadar offenses, install and configure the IBM QRadar integration to ingest offense records into the `logs-ibm_qradar.offense-*` 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 QRadar events. Consider adding a rule exception for the External Alert rule to exclude data_stream.dataset:ibm_qradar.offense 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: IBM QRadar",
"Use Case: Threat Detection",
"Resources: Investigation Guide",
"Promotion: External Alerts",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
event.kind: alert and data_stream.dataset: ibm_qradar.offense
'''
[[rule.risk_score_mapping]]
field = "ibm_qradar.offense.magnitude"
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: ibm_qradar.offense
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"ibm_qradar.offense" |
event.kind | eq |
| field:"event.kind" kind:eq value:"alert" |
M365 Identity User Account Lockouts
#Detects a burst of Microsoft 365 user account lockouts within a short 5-minute window. A high number of IdsLocked login errors across multiple user accounts may indicate brute-force attempts for the same users resulting in lockouts.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Credential Access |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | PasswordLogonInitialAuthUsingPassword |
| Microsoft 365 | UserLoginFailed |
Rules Detecting the Same Action
These rules filter on the same operation.
- High Number of Login Failures from a single source (Splunk)
- M365 Identity User Brute Force Attempted (Elastic)
- O365 Excessive SSO logon errors (Splunk)
- O365 High Number Of Failed Authentications for User (Splunk)
- O365 Multi-Source Failed Authentications Spike (Splunk)
- O365 Multiple AppIDs and UserAgents Authentication Spike (Splunk)
- O365 Multiple Failed MFA Requests For User (Splunk)
- O365 Multiple Users Failing To Authenticate From Ip (Splunk)
Rule Body
[metadata]
creation_date = "2025/05/10"
integration = ["o365"]
maturity = "production"
updated_date = "2026/09/10"
[rule]
author = ["Elastic"]
description = """
Detects a burst of Microsoft 365 user account lockouts within a short 5-minute window. A high number of IdsLocked login
errors across multiple user accounts may indicate brute-force attempts for the same users resulting in lockouts.
"""
from = "now-9m"
interval = "8m"
language = "esql"
license = "Elastic License v2"
name = "M365 Identity User Account Lockouts"
note = """## Triage and Analysis
### Investigating M365 Identity User Account Lockouts
Detects a burst of Microsoft 365 user account lockouts within a short 5-minute window. A high number of IdsLocked login errors across multiple user accounts may indicate brute-force attempts for the same users resulting in lockouts.
This rule uses ESQL aggregations and thus has dynamically generated fields. Correlation of the values in the alert document may need to be performed to the original sign-in and Graph events for further context.
### Investigation Steps
- Review the `user_id_list`: Are specific naming patterns targeted (e.g., admin, helpdesk)?
- Examine `ip_list` and `source_orgs`: Look for suspicious ISPs or hosting providers.
- Check `duration_seconds`: A very short window with a high lockout rate often indicates automation.
- Confirm lockout policy thresholds with IAM or Entra ID admins. Did the policy trigger correctly?
- Use the `first_seen` and `last_seen` values to pivot into related authentication or audit logs.
- Correlate with any recent detection of password spraying or credential stuffing activity.
- Review the `request_type` field to identify which authentication methods were used (e.g., OAuth, SAML, etc.).
- Check for any successful logins from the same IP or ASN after the lockouts.
### False Positive Analysis
- Automated systems with stale credentials may cause repeated failed logins.
- Legitimate bulk provisioning or scripted tests could unintentionally cause account lockouts.
- Red team exercises or penetration tests may resemble the same lockout pattern.
- Some organizations may have a high volume of lockouts due to user behavior or legacy systems.
### Response Recommendations
- Notify affected users and confirm whether activity was expected or suspicious.
- Lock or reset credentials for impacted accounts.
- Block the source IP(s) or ASN temporarily using conditional access or firewall rules.
- Strengthen lockout and retry delay policies if necessary.
- Review the originating application(s) involved via `request_types`.
"""
references = [
"https://learn.microsoft.com/en-us/security/operations/incident-response-playbook-password-spray",
"https://learn.microsoft.com/en-us/purview/audit-log-detailed-properties",
"https://securityscorecard.com/research/massive-botnet-targets-m365-with-stealthy-password-spraying-attacks/",
"https://github.com/0xZDH/Omnispray",
"https://github.com/0xZDH/o365spray",
]
risk_score = 47
rule_id = "de67f85e-2d43-11f0-b8c9-f661ea17fbcc"
severity = "medium"
tags = [
"Domain: Cloud",
"Domain: SaaS",
"Data Source: Microsoft 365",
"Data Source: Microsoft 365 Audit Logs",
"Use Case: Threat Detection",
"Use Case: Identity and Access Audit",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
from logs-o365.audit-*
| mv_expand event.category
| eval
Esql.time_window_date_trunc = date_trunc(5 minutes, @timestamp)
| where
data_stream.dataset == "o365.audit" and
event.category == "authentication" and
event.provider in ("AzureActiveDirectory", "Exchange") and
event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword") and
to_lower(o365.audit.ExtendedProperties.RequestType) rlike "(oauth.*|.*login.*)" and
o365.audit.LogonError == "IdsLocked" and
to_lower(o365.audit.UserId) != "not available" and
o365.audit.Target.Type in ("0", "2", "6", "10") and
source.`as`.organization.name != "MICROSOFT-CORP-MSN-as-BLOCK"
| stats
Esql_priv.o365_audit_UserId_count_distinct = count_distinct(to_lower(o365.audit.UserId)),
Esql_priv.o365_audit_UserId_values = values(to_lower(o365.audit.UserId)),
Esql.source_ip_values = values(source.ip),
Esql.source_ip_count_distinct = count_distinct(source.ip),
Esql.source_as_organization_name_values = values(source.`as`.organization.name),
Esql.source_as_organization_name_count_distinct = count_distinct(source.`as`.organization.name),
Esql.source_geo_country_name_values = values(source.geo.country_name),
Esql.source_geo_country_name_count_distinct = count_distinct(source.geo.country_name),
Esql.o365_audit_ExtendedProperties_RequestType_values = values(to_lower(o365.audit.ExtendedProperties.RequestType)),
Esql.timestamp_first_seen = min(@timestamp),
Esql.timestamp_last_seen = max(@timestamp),
Esql.event_count = count(*)
by Esql.time_window_date_trunc
| eval
Esql.event_duration_seconds = date_diff("seconds", Esql.timestamp_first_seen, Esql.timestamp_last_seen)
| keep
Esql.time_window_date_trunc,
Esql_priv.o365_audit_UserId_count_distinct,
Esql_priv.o365_audit_UserId_values,
Esql.source_ip_values,
Esql.source_ip_count_distinct,
Esql.source_as_organization_name_values,
Esql.source_as_organization_name_count_distinct,
Esql.source_geo_country_name_values,
Esql.source_geo_country_name_count_distinct,
Esql.o365_audit_ExtendedProperties_RequestType_values,
Esql.timestamp_first_seen,
Esql.timestamp_last_seen,
Esql.event_count,
Esql.event_duration_seconds
| where
Esql_priv.o365_audit_UserId_count_distinct >= 10 and
Esql.event_count >= 10 and
Esql.event_duration_seconds <= 300
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1110"
name = "Brute Force"
reference = "https://attack.mitre.org/techniques/T1110/"
[[rule.threat.technique.subtechnique]]
id = "T1110.001"
name = "Password Guessing"
reference = "https://attack.mitre.org/techniques/T1110/001/"
[[rule.threat.technique.subtechnique]]
id = "T1110.003"
name = "Password Spraying"
reference = "https://attack.mitre.org/techniques/T1110/003/"
[[rule.threat.technique.subtechnique]]
id = "T1110.004"
name = "Credential Stuffing"
reference = "https://attack.mitre.org/techniques/T1110/004/"
[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 = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
[[rule.threat.technique.subtechnique]]
id = "T1078.004"
name = "Cloud Accounts"
reference = "https://attack.mitre.org/techniques/T1078/004/"
[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
Stages and Predicates
Stage 1: from
from logs-o365.audit-*
Stage 2: mv_expand
| mv_expand event.category
Stage 3: eval
| eval
Esql.time_window_date_trunc = date_trunc(5 minutes, @timestamp)
Stage 4: where
| where
data_stream.dataset == "o365.audit" and
event.category == "authentication" and
event.provider in ("AzureActiveDirectory", "Exchange") and
event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword") and
to_lower(o365.audit.ExtendedProperties.RequestType) rlike "(oauth.*|.*login.*)" and
o365.audit.LogonError == "IdsLocked" and
to_lower(o365.audit.UserId) != "not available" and
o365.audit.Target.Type in ("0", "2", "6", "10") and
source.`as`.organization.name != "MICROSOFT-CORP-MSN-as-BLOCK"
Stage 5: stats
| stats
Esql_priv.o365_audit_UserId_count_distinct = count_distinct(to_lower(o365.audit.UserId)),
Esql_priv.o365_audit_UserId_values = values(to_lower(o365.audit.UserId)),
Esql.source_ip_values = values(source.ip),
Esql.source_ip_count_distinct = count_distinct(source.ip),
Esql.source_as_organization_name_values = values(source.`as`.organization.name),
Esql.source_as_organization_name_count_distinct = count_distinct(source.`as`.organization.name),
Esql.source_geo_country_name_values = values(source.geo.country_name),
Esql.source_geo_country_name_count_distinct = count_distinct(source.geo.country_name),
Esql.o365_audit_ExtendedProperties_RequestType_values = values(to_lower(o365.audit.ExtendedProperties.RequestType)),
Esql.timestamp_first_seen = min(@timestamp),
Esql.timestamp_last_seen = max(@timestamp),
Esql.event_count = count(*)
by Esql.time_window_date_trunc
Stage 6: eval
| eval
Esql.event_duration_seconds = date_diff("seconds", Esql.timestamp_first_seen, Esql.timestamp_last_seen)
Stage 7: keep
| keep
Esql.time_window_date_trunc,
Esql_priv.o365_audit_UserId_count_distinct,
Esql_priv.o365_audit_UserId_values,
Esql.source_ip_values,
Esql.source_ip_count_distinct,
Esql.source_as_organization_name_values,
Esql.source_as_organization_name_count_distinct,
Esql.source_geo_country_name_values,
Esql.source_geo_country_name_count_distinct,
Esql.o365_audit_ExtendedProperties_RequestType_values,
Esql.timestamp_first_seen,
Esql.timestamp_last_seen,
Esql.event_count,
Esql.event_duration_seconds
Stage 8: where
| where
Esql_priv.o365_audit_UserId_count_distinct >= 10 and
Esql.event_count >= 10 and
Esql.event_duration_seconds <= 300
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Esql.event_count | ge |
| field:"Esql.event_count" kind:ge value:"10" |
Esql.event_duration_seconds | le |
| field:"Esql.event_duration_seconds" kind:le value:"300" |
Esql_priv.o365_audit_UserId_count_distinct | ge |
| field:"Esql_priv.o365_audit_UserId_count_distinct" kind:ge value:"10" |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"o365.audit" |
event.action | in |
| field:"EventType" kind:in |
event.category | eq |
| field:"event.category" kind:eq value:"authentication" |
event.provider | in |
| field:"Provider_Name" kind:in |
o365.audit.LogonError | eq |
| field:"m365::LogonError" kind:eq value:"IdsLocked" |
o365.audit.Target.Type | in |
| field:"m365::Target.Type" kind:in |
source.as.organization.name | ne |
| field:"source.as.organization.name" kind:ne value:"MICROSOFT-CORP-MSN-as-BLOCK" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Esql.time_window_date_trunc | KEEP Esql.time_window_date_trunc |
Esql_priv.o365_audit_UserId_count_distinct | KEEP Esql_priv.o365_audit_UserId_count_distinct |
Esql_priv.o365_audit_UserId_values | KEEP Esql_priv.o365_audit_UserId_values |
Esql.source_ip_values | KEEP Esql.source_ip_values |
Esql.source_ip_count_distinct | KEEP Esql.source_ip_count_distinct |
Esql.source_as_organization_name_values | KEEP Esql.source_as_organization_name_values |
Esql.source_as_organization_name_count_distinct | KEEP Esql.source_as_organization_name_count_distinct |
Esql.source_geo_country_name_values | KEEP Esql.source_geo_country_name_values |
Esql.source_geo_country_name_count_distinct | KEEP Esql.source_geo_country_name_count_distinct |
Esql.o365_audit_ExtendedProperties_RequestType_values | KEEP Esql.o365_audit_ExtendedProperties_RequestType_values |
Esql.timestamp_first_seen | KEEP Esql.timestamp_first_seen |
Esql.timestamp_last_seen | KEEP Esql.timestamp_last_seen |
Esql.event_count | KEEP Esql.event_count |
Esql.event_duration_seconds | KEEP Esql.event_duration_seconds |
M365 Potential AiTM UserLoggedIn via Office App (Tycoon2FA)
#Detects Microsoft 365 audit "UserLoggedIn" events consistent with Tycoon 2FA phishing-as-a-service (PhaaS) adversary-in-the-middle (AiTM) activity: the Microsoft Authentication Broker requesting access where the object identifier matches Microsoft Graph or Exchange Online, or the Office web client application authenticating to itself, combined with Node.js-style user agents (node, axios, undici). Tycoon 2FA bypasses MFA by relaying authentication and capturing session material, often targeting Microsoft 365 and Gmail. Baseline legitimate automation and developer tooling before tuning.
Known False Positives
- Legitimate Node.js or undici-based automation, health checks, or internal services that use the Microsoft Authentication Broker or the same first-party application IDs against Graph or Exchange may match. Developers using axios or undici with delegated flows can also resemble this pattern.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Credential Access |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | UserLoggedIn |
Rules Detecting the Same Action
These rules filter on the same operation.
- Azure Login Bypassing Conditional Access Policies (Sigma)
- Hunt for suspicious sign-in to Entra ID Using Extrnal Call Method (YARA-L)
- M365 Identity OAuth Flow by First-Party Microsoft App from Multiple IPs (Elastic)
- M365 Identity OAuth Flow by User Sign-in to Device Registration (Elastic)
- M365 Identity OAuth Phishing via First-Party Microsoft Application (Elastic)
- M365 Identity OAuth ROPC Grant via Legacy Authentication Client (Elastic)
- O365 AD PowerShell App Login Subsequent Activity (YARA-L)
- O365 Admin Login Activity To Uncommon Microsoft Cloud Apps (YARA-L)
Rule Body
[metadata]
creation_date = "2026/05/14"
integration = ["o365"]
maturity = "production"
updated_date = "2026/05/14"
[rule]
author = ["Elastic"]
description = """
Detects Microsoft 365 audit "UserLoggedIn" events consistent with Tycoon 2FA phishing-as-a-service (PhaaS)
adversary-in-the-middle (AiTM) activity: the Microsoft Authentication Broker requesting access where the object
identifier matches Microsoft Graph or Exchange Online, or the Office web client application authenticating to itself,
combined with Node.js-style user agents (node, axios, undici). Tycoon 2FA bypasses MFA by relaying authentication and
capturing session material, often targeting Microsoft 365 and Gmail. Baseline legitimate automation and developer
tooling before tuning.
"""
false_positives = [
"""
Legitimate Node.js or undici-based automation, health checks, or internal services that use the Microsoft
Authentication Broker or the same first-party application IDs against Graph or Exchange may match. Developers using
axios or undici with delegated flows can also resemble this pattern.
""",
]
from = "now-9m"
index = ["logs-o365.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "M365 Potential AiTM UserLoggedIn via Office App (Tycoon2FA)"
note = """## Triage and analysis
### Investigating M365 Potential AiTM UserLoggedIn via Office App (Tycoon2FA)
Review `o365.audit.UserId`, `user_agent.original`, `source.ip` or `o365.audit.ActorIpAddress`, and related Entra ID
sign-in logs (`azure.signinlogs`) for the same session or time window.
Confirm whether the account owner intentionally authenticated and whether Node.js-style user agents (node, axios, undici)
are expected for Microsoft Authentication Broker or Office web client flows in your environment.
### Possible investigation steps
- Correlate with `azure.signinlogs` for matching user principal name, IP, and session identifiers.
- Review Microsoft Graph or Exchange audit activity following the login for mailbox or data access anomalies.
- Hunt for other `UserLoggedIn` events from the same source with unusual user agents or rapid OAuth patterns.
### Response and remediation
- If malicious, revoke refresh tokens for the user, reset credentials per policy, and review conditional access outcomes.
- Block or monitor the source IP and escalate per incident procedures.
"""
references = ["https://any.run/malware-trends/tycoon/"]
risk_score = 73
rule_id = "275b972d-2fed-44fc-9214-08603b3318e3"
severity = "high"
tags = [
"Domain: Cloud",
"Domain: Identity",
"Domain: SaaS",
"Data Source: Microsoft 365",
"Data Source: Microsoft 365 Audit Logs",
"Use Case: Threat Detection",
"Threat: Tycoon2FA",
"Tactic: Initial Access",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
data_stream.dataset:"o365.audit" and event.category:"authentication" and event.action:"UserLoggedIn" and
(
(
o365.audit.ApplicationId:"29d9ed98-a469-4536-ade2-f981bc1d605e" and
o365.audit.ObjectId:(
"00000002-0000-0ff1-ce00-000000000000" or "00000003-0000-0000-c000-000000000000"
)
) or
(
o365.audit.ApplicationId:"4765445b-32c6-49b0-83e6-1d93765276ca" and
o365.audit.ObjectId:"4765445b-32c6-49b0-83e6-1d93765276ca"
)
) and user_agent.original:(node or axios* or undici)
'''
[rule.investigation_fields]
field_names = [
"@timestamp",
"o365.audit.UserId",
"user_agent.original",
"source.ip",
"o365.audit.ActorIpAddress",
"source.geo.country_name",
"event.outcome",
"o365.audit.ApplicationId",
"o365.audit.ObjectId",
"o365.audit.ExtendedProperties.RequestType",
"event.provider",
]
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[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 = "T1539"
name = "Steal Web Session Cookie"
reference = "https://attack.mitre.org/techniques/T1539/"
[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
Stages and Predicates
Stage 1: query
data_stream.dataset:"o365.audit" and event.category:"authentication" and event.action:"UserLoggedIn" and
(
(
o365.audit.ApplicationId:"29d9ed98-a469-4536-ade2-f981bc1d605e" and
o365.audit.ObjectId:(
"00000002-0000-0ff1-ce00-000000000000" or "00000003-0000-0000-c000-000000000000"
)
) or
(
o365.audit.ApplicationId:"4765445b-32c6-49b0-83e6-1d93765276ca" and
o365.audit.ObjectId:"4765445b-32c6-49b0-83e6-1d93765276ca"
)
) and user_agent.original:(node or axios* or undici)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"o365.audit" |
event.action | eq |
| field:"EventType" kind:eq value:"UserLoggedIn" |
event.category | eq |
| field:"event.category" kind:eq value:"authentication" |
o365.audit.ApplicationId | eq |
| field:"m365::ApplicationId" kind:eq |
o365.audit.ObjectId | eq |
| field:"m365::ObjectId" kind:eq value:"4765445b-32c6-49b0-83e6-1d93765276ca" |
o365.audit.ObjectId | in |
| field:"m365::ObjectId" kind:in |
user_agent.original | eq |
| field:"aws::userAgent" kind:eq |
user_agent.original | wildcard |
| field:"aws::userAgent" kind:wildcard value:"axios*" |
Potential AMSI Bypass via RPC Runtime Hooking
#Identifies PowerShell script block content associated with an Antimalware Scan Interface (AMSI) bypass that hooks the RPC runtime marshaling stub NdrClientCall3 (or NdrClientCall2) in rpcrt4.dll. Unlike bypasses that patch AmsiScanBuffer or set amsiInitFailed, this technique operates at the RPC layer used by AMSI to delegate scan requests to the antivirus provider, tampering with the request before it reaches the engine and leaving AMSI itself unmodified. The loader allocates an executable trampoline and marshals a delegate to the native stub; these primitives appear in PowerShell Script Block Logging before the hook takes effect.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Defense Impairment |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| PowerShell | Event ID 4104: Creating Scriptblock text (MessageNumber of MessageTotal). |
Rule Body
[metadata]
creation_date = "2026/06/22"
integration = ["windows"]
maturity = "production"
updated_date = "2026/06/22"
[rule]
author = ["Elastic"]
description = """
Identifies PowerShell script block content associated with an Antimalware Scan Interface (AMSI) bypass that hooks the
RPC runtime marshaling stub NdrClientCall3 (or NdrClientCall2) in rpcrt4.dll. Unlike bypasses that patch AmsiScanBuffer
or set amsiInitFailed, this technique operates at the RPC layer used by AMSI to delegate scan requests to the
antivirus provider, tampering with the request before it reaches the engine and leaving AMSI itself unmodified. The
loader allocates an executable trampoline and marshals a delegate to the native stub; these primitives appear in
PowerShell Script Block Logging before the hook takes effect.
"""
from = "now-9m"
index = ["winlogbeat-*", "logs-windows.powershell*"]
language = "kuery"
license = "Elastic License v2"
name = "Potential AMSI Bypass via RPC Runtime Hooking"
note = """## Triage and analysis
### Investigating Potential AMSI Bypass via RPC Runtime Hooking
The Antimalware Scan Interface (AMSI) delegates scan requests to the registered antivirus provider over RPC. By hooking
the RPC runtime marshaling stub `NdrClientCall3`/`NdrClientCall2` in `rpcrt4.dll`, an adversary can tamper with these
requests so that malicious content is reported as clean, without modifying `amsi.dll` or patching `AmsiScanBuffer`.
This makes the bypass harder to catch via AMSI buffer or memory-write telemetry; the most reliable host artifact is the
loader's own PowerShell script content, captured by Script Block Logging.
#### Possible investigation steps
- Review `powershell.file.script_block_text` for references to `NdrClientCall3`/`NdrClientCall2`, resolution of
functions in `rpcrt4.dll`, allocation of executable (`PAGE_EXECUTE_READWRITE`) memory, and delegate marshaling via
`GetDelegateForFunctionPointer`.
- PowerShell logs each statement as a separate event; pivot on `host.id` and the PowerShell process id to reconstruct
the full loader sequence and confirm intent.
- Identify how PowerShell was launched (interactive, encoded command, remote session) and review the parent process
tree for download or staging activity.
- Correlate with Elastic Defend endpoint telemetry on the same host around the same time. Note that this RPC-layer hook
may not surface as a memory modification of `rpcrt4.dll`, which is expected for this technique.
- Hunt for the same script content, user, or host pattern across the environment.
### False positive analysis
- Security research, detection engineering, and red-team development that legitimately references the RPC runtime
marshaling functions or allocates executable memory from PowerShell can match. Validate the user, host, parent
process, and surrounding script blocks against authorized testing before closing as benign, and add exceptions for
known testing identities or hosts.
### Response and remediation
- Isolate the host if the activity is confirmed malicious and review for follow-on payload execution that the bypass
was intended to conceal.
- Terminate the offending PowerShell session and preserve the Script Block Logging events for analysis.
- Restrict PowerShell usage outside of IT and engineering business units using GPOs, AppLocker, or WDAC.
- Reset credentials for accounts active on the host during the session if follow-on activity is observed.
### Limitations
This rule detects the technique only when it is delivered as logged PowerShell script-block text. In-memory delivery, a
PowerShell v2 downgrade, or implementing the hook outside PowerShell (compiled binary) can evade Script Block Logging
and therefore this rule. For customers running Elastic Defend, prefer the companion Endpoint Rule which detects the
VirtualProtect call targeting rpcrt4.dll!NdrClientCall* directly via API telemetry and is not dependent on Script
Block Logging."""
references = [
"https://github.com/andreisss/Ghosting-AMSI",
]
risk_score = 73
rule_id = "4027f24e-b02f-4605-872f-7bafd8fe1b33"
setup = """## Setup
PowerShell Script Block Logging must be enabled to generate the events used by this rule (event ID 4104). The
`Microsoft-Windows-PowerShell/Operational` channel must be collected by the Windows integration or Winlogbeat.
Setup instructions: https://ela.st/powershell-logging-setup"""
severity = "high"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Tactic: Execution",
"Data Source: PowerShell Logs",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
event.code: "4104" and host.os.type: "windows" and
powershell.file.script_block_text : (
"NdrClientCall" or
"NdrClientCall2" or
"NdrClientCall3"
) and
powershell.file.script_block_text : (
"GetProcAddress" or
"GetDelegateForFunctionPointer" or
"VirtualProtect"
)
'''
[rule.investigation_fields]
field_names = [
"@timestamp",
"host.id",
"host.name",
"user.id",
"user.name",
"user.domain",
"process.pid",
"powershell.file.script_block_text",
"powershell.file.script_block_id",
"powershell.sequence",
"powershell.total",
"file.path",
]
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1562"
name = "Impair Defenses"
reference = "https://attack.mitre.org/techniques/T1562/"
[[rule.threat.technique.subtechnique]]
id = "T1562.001"
name = "Disable or Modify Tools"
reference = "https://attack.mitre.org/techniques/T1562/001/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[rule.threat.technique.subtechnique]]
id = "T1059.001"
name = "PowerShell"
reference = "https://attack.mitre.org/techniques/T1059/001/"
[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
Stages and Predicates
Stage 1: query
event.code: "4104" and host.os.type: "windows" and
powershell.file.script_block_text : (
"NdrClientCall" or
"NdrClientCall2" or
"NdrClientCall3"
) and
powershell.file.script_block_text : (
"GetProcAddress" or
"GetDelegateForFunctionPointer" or
"VirtualProtect"
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
powershell.file.script_block_text | in |
| field:"ScriptBlockText" kind:in |
Potential ClickFix Attack via Base64 Decoded Payload
#Detects a ClickFix-style attack where a base64 encoded payload is decoded and piped to a shell interpreter for execution, resulting in a curl download. This technique is commonly used in social engineering attacks where victims are tricked into copying and pasting malicious commands from fake error dialogs or verification prompts.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Execution |
Telemetry Coverage
Rule Body
[rule]
description = """
Detects a ClickFix-style attack where a base64 encoded payload is decoded and piped to a shell interpreter for
execution, resulting in a curl download. This technique is commonly used in social engineering attacks where victims are
tricked into copying and pasting malicious commands from fake error dialogs or verification prompts.
"""
id = "9dfe40e2-3f4c-47d6-af48-f3459b53d49e"
license = "Elastic License v2"
name = "Potential ClickFix Attack via Base64 Decoded Payload"
os_list = ["macos"]
reference = ["https://blog.sekoia.io/clickfix-tactic-the-phantom-meet/"]
version = "1.0.5"
query = '''
sequence by process.Ext.effective_parent.entity_id with maxspan=10s
[process where event.type == "start" and event.action == "exec" and process.name == "base64" and process.args in ("-d", "-D", "--decode") and
process.Ext.effective_parent.name like~ ("Terminal", "iTerm2", "iTerm", "ghostty",
"alacritty", "wezterm-gui", "Hyper", "kitty",
"WarpTerminal", "stable", "rio", "tabby") and
not process.parent.command_line like ("*/.claude/shell-snapshots/snapshot-bash*", "*__CURSOR_SANDBOX_ENV_RESTORE*")]
[process where event.type == "start" and event.action == "exec" and process.name in ("bash", "sh", "zsh", "Terminal") and process.args_count <= 1]
[process where event.type == "start" and event.action == "exec" and process.name in ("curl", "nscurl") and process.parent.name in ("bash", "sh", "zsh", "Terminal") and
process.parent.command_line in ("bash", "sh", "zsh", "Terminal", "/sbin/launchd") and
not process.command_line like "/usr/bin/curl --version"]
'''
min_endpoint_version = "8.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 2
[[actions]]
action = "kill_process"
field = "process.parent.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[[threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"
[threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1204"
name = "User Execution"
reference = "https://attack.mitre.org/techniques/T1204/"
[[threat.technique.subtechnique]]
id = "T1204.001"
name = "Malicious Link"
reference = "https://attack.mitre.org/techniques/T1204/001/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[internal]
min_endpoint_version = "8.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 10s, correlated by process.Ext.effective_parent.entity_id.
Stage 1: process
[process where event.type == "start" and event.action == "exec" and process.name == "base64" and process.args in ("-d", "-D", "--decode") and
process.Ext.effective_parent.name like~ ("Terminal", "iTerm2", "iTerm", "ghostty",
"alacritty", "wezterm-gui", "Hyper", "kitty",
"WarpTerminal", "stable", "rio", "tabby") and
not process.parent.command_line like ("*/.claude/shell-snapshots/snapshot-bash*", "*__CURSOR_SANDBOX_ENV_RESTORE*")]
Stage 2: process
[process where event.type == "start" and event.action == "exec" and process.name in ("bash", "sh", "zsh", "Terminal") and process.args_count <= 1]
Stage 3: process
[process where event.type == "start" and event.action == "exec" and process.name in ("curl", "nscurl") and process.parent.name in ("bash", "sh", "zsh", "Terminal") and
process.parent.command_line in ("bash", "sh", "zsh", "Terminal", "/sbin/launchd") and
not process.command_line like "/usr/bin/curl --version"]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.Ext.effective_parent.name | wildcard |
| field:"process.Ext.effective_parent.name" kind:wildcard |
process.args | in |
| field:"process.args" kind:in |
process.args_count | le |
| field:"process.args_count" kind:le value:"1" |
process.name | eq |
| field:"process_basename" kind:eq value:"base64" |
process.name | in |
| field:"process_basename" kind:in |
process.parent.command_line | in |
| field:"ParentCommandLine" kind:in |
process.parent.name | in |
| field:"parent_process_basename" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.parent.command_line | match | /.claude/shell-snapshots/snapshot-bash, __CURSOR_SANDBOX_ENV_RESTORE | excludes:process.parent.command_line field:"process.parent.command_line" value:"/.claude/shell-snapshots/snapshot-bash" field:"process.parent.command_line" value:"__CURSOR_SANDBOX_ENV_RESTORE" |
process.command_line | eq | /usr/bin/curl --version | excludes:process.command_line field:"process.command_line" value:"/usr/bin/curl --version" |
Potential Coin Miner Execution
#This rule detects the execution of a coin miner through potential mining commandline arguments. Adversaries may leverage the resources of compromised systems to mine cryptocurrency, to generate revenue. This activity may impact system performance and availability.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Impact |
Rule Body
[rule]
description = """
This rule detects the execution of a coin miner through potential mining commandline arguments. Adversaries may leverage
the resources of compromised systems to mine cryptocurrency, to generate revenue. This activity may impact system
performance and availability.
"""
id = "0259c937-877f-4140-a67b-dc51298f3f86"
license = "Elastic License v2"
name = "Potential Coin Miner Execution"
os_list = ["linux"]
reference = ["https://xmrig.com/docs/algorithms"]
version = "1.0.7"
query = '''
process where event.type == "start" and event.action == "exec" and (
process.name like (
"telnet.netkit", "ping", "telnet", "xmrig", "dash", "bash", "sh", "zsh", "ash", "fish", "ksh", "tcsh",
"csh", "nohup", "pgrep", "python*", "perl*", "ruby*", "php*", "lua*", "sed", "pkill", "docker", "dig",
"nslookup", "inetutils-telnet", "nc", "ncat", "netcat", "netcat.openbsd", "netcat.traditional",
"nc.openbsd", "nc.traditional", "curl", "wget", "sudo", "grep", ".*"
) or
process.executable like (
"/tmp/*", "/var/tmp/*", "/dev/shm/*", "/boot/*", "./*", "/sys/*", "/lost+found/*", "/media/*", "/proc/*",
"/var/backups/*", "/var/log/*", "/var/mail/*", "/var/spool/*"
)
) and
(
(
(
(
process.args in ("-a", "--algo") and process.args in (
"gr", "rx/graft", "cn/upx2", "argon2/chukwav2", "cn/ccx", "kawpow", "rx/keva", "cn-pico/tlo", "rx/sfx", "rx/arq",
"rx/0", "argon2/chukwa", "argon2/ninja", "rx/wow", "cn/fast", "cn/rwz", "cn/zls", "cn/double", "cn/r", "cn-pico",
"cn/half", "cn/2", "cn/xao", "cn/rto", "cn-heavy/tube", "cn-heavy/xhv", "cn-heavy/0", "cn/1", "cn-lite/1",
"cn-lite/0", "cn/0"
)
) or
process.args in ("--nicehash", "--hash", "--seed") or
(
process.args == "--coin" and process.args in ("monero", "arqma", "dero")
)
) and process.args in ("-o", "--url")
) or
process.command_line like ("*stratum+tcp://*", "*stratum2+tcp://*")
) and not (
process.parent.executable like "/var/cache/sensu/sensu-agent/*" or
process.name in ("grep", "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 = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1496"
name = "Resource Hijacking"
reference = "https://attack.mitre.org/techniques/T1496/"
[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.type == "start" and event.action == "exec" and (
process.name like (
"telnet.netkit", "ping", "telnet", "xmrig", "dash", "bash", "sh", "zsh", "ash", "fish", "ksh", "tcsh",
"csh", "nohup", "pgrep", "python*", "perl*", "ruby*", "php*", "lua*", "sed", "pkill", "docker", "dig",
"nslookup", "inetutils-telnet", "nc", "ncat", "netcat", "netcat.openbsd", "netcat.traditional",
"nc.openbsd", "nc.traditional", "curl", "wget", "sudo", "grep", ".*"
) or
process.executable like (
"/tmp/*", "/var/tmp/*", "/dev/shm/*", "/boot/*", "./*", "/sys/*", "/lost+found/*", "/media/*", "/proc/*",
"/var/backups/*", "/var/log/*", "/var/mail/*", "/var/spool/*"
)
) and
(
(
(
(
process.args in ("-a", "--algo") and process.args in (
"gr", "rx/graft", "cn/upx2", "argon2/chukwav2", "cn/ccx", "kawpow", "rx/keva", "cn-pico/tlo", "rx/sfx", "rx/arq",
"rx/0", "argon2/chukwa", "argon2/ninja", "rx/wow", "cn/fast", "cn/rwz", "cn/zls", "cn/double", "cn/r", "cn-pico",
"cn/half", "cn/2", "cn/xao", "cn/rto", "cn-heavy/tube", "cn-heavy/xhv", "cn-heavy/0", "cn/1", "cn-lite/1",
"cn-lite/0", "cn/0"
)
) or
process.args in ("--nicehash", "--hash", "--seed") or
(
process.args == "--coin" and process.args in ("monero", "arqma", "dero")
)
) and process.args in ("-o", "--url")
) or
process.command_line like ("*stratum+tcp://*", "*stratum2+tcp://*")
) and not (
process.parent.executable like "/var/cache/sensu/sensu-agent/*" or
process.name in ("grep", "xargs")
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq value:"--coin" |
process.args | in |
| field:"process.args" kind:in |
process.command_line | wildcard |
| field:"CommandLine" kind:wildcard |
process.executable | wildcard |
| field:"Image" kind:wildcard |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.name | in | grep, xargs | excludes:process.name field:"process.name" value:"grep" field:"process.name" value:"xargs" |
process.parent.executable | starts_with | /var/cache/sensu/sensu-agent/ | excludes:process.parent.executable field:"process.parent.executable" value:"/var/cache/sensu/sensu-agent/" |
Potential Invoke-Mimikatz PowerShell Script
#Identifies PowerShell script block content containing Invoke-Mimikatz or Mimikatz commands used to dump credentials, extract password stores, export certificates, or use alternate authentication material. These patterns can indicate in-memory credential access and require reconstructed script context and follow-on telemetry to assess impact.
MITRE ATT&CK Coverage
Rule Body
[metadata]
creation_date = "2020/12/07"
integration = ["windows"]
maturity = "production"
updated_date = "2026/04/24"
[rule]
author = ["Elastic"]
description = """
Identifies PowerShell script block content containing Invoke-Mimikatz or Mimikatz commands used to dump credentials,
extract password stores, export certificates, or use alternate authentication material. These patterns can indicate
in-memory credential access and require reconstructed script context and follow-on telemetry to assess impact.
"""
from = "now-9m"
index = ["logs-windows.powershell*", "winlogbeat-*"]
language = "kuery"
license = "Elastic License v2"
name = "Potential Invoke-Mimikatz PowerShell Script"
references = [
"https://attack.mitre.org/software/S0002/",
"https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1",
"https://www.elastic.co/security-labs/detect-credential-access",
]
risk_score = 99
rule_id = "ac96ceb8-4399-4191-af1d-4feeac1f1f46"
severity = "critical"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Credential Access",
"Resources: Investigation Guide",
"Data Source: PowerShell Logs",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
event.category:process and host.os.type:windows and
powershell.file.script_block_text:(
(DumpCreds and DumpCerts) or
"sekurlsa::logonpasswords" or
"sekurlsa::ekeys" or
"sekurlsa::tickets" or
"sekurlsa::pth" or
"sekurlsa::minidump" or
"lsadump::sam" or
"lsadump::secrets" or
"lsadump::cache" or
"lsadump::dcsync" or
"vault::cred" or
"dpapi::cred" or
("crypto::certificates" and
"CERT_SYSTEM_STORE_LOCAL_MACHINE")
)
'''
note = """## Triage and analysis
### Investigating Potential Invoke-Mimikatz PowerShell Script
#### Possible investigation steps
- What Mimikatz behavior does the reconstructed script block show?
- Why: Invoke-Mimikatz can run in memory and split or rename command logic; reconstruction separates live credential access from inert matched text.
- Focus: read reconstructed `powershell.file.script_block_text`, `file.path`, `host.id`, `user.id`, and `@timestamp`. $investigate_0
- Hint: reconstruct first with `powershell.file.script_block_id + powershell.sequence + powershell.total`: collect fragments sharing `powershell.file.script_block_id` on the same `host.id`, order by `powershell.sequence`, and treat sequence gaps as unresolved because they can hide targets, outputs, or cleanup.
- Hint: runtime string construction, encoding, or command fragmentation can avoid literal command matches in this rule; rely on companion PowerShell obfuscation, AMSI bypass, and loader/injection detections when this exact-content rule does not fire.
- Implication: escalate when the rebuilt code performs LSASS, SAM, LSA secrets, cached-credential, DCSync, DPAPI/vault, certificate/private-key, ticket, hash, or renamed/custom Mimikatz activity; lower concern only when reconstruction shows inert sample or training content and no supported recovery shows live targets, output paths, or follow-on use.
- Does the full script declare remote targets or export destinations that change scope?
- Focus: reconstructed `powershell.file.script_block_text`, `file.path`, `host.id`, and `user.id` for remote "ComputerName" values, domain targets, export paths, certificate-store, DPAPI/vault, ticket/hash references, or cleanup commands.
- Implication: broaden scope when remote targets, private-key export paths, or cleanup logic appear, because the affected hosts or exported material may differ from the alert host; keep scope local when the reconstructed script contains only local test content with no target or output path.
- Can endpoint process recovery explain how PowerShell was launched?
- Focus: If endpoint process telemetry is available for this host, recover the matching process via `host.id + process.pid` before using `process.*` or `process.parent.*` for interpretation; then read `process.command_line`, `process.parent.command_line`, and `process.entity_id`. $investigate_1
- Hint: start near `@timestamp` and expand backward if PowerShell started earlier; use `process.parent.executable` for parent identity and keep `process.Ext.authentication_id` only for the authentication bridge. If no process event is available, keep later pivots scoped to `host.id`, `user.id`, and alert time.
- Implication: escalate when PowerShell is inline, encoded, remotely invoked, or launched by Office, browser, script-host, scheduled-task, or remote-management ancestry outside the recovered user-host context; lower concern when the launch chain, command line, and session anchor match the same recognized assessment or lab workflow.
- Does the source path show fileless execution or staged module use?
- Focus: `file.path`, `file.directory`, `file.name`, and the reconstructed `powershell.file.script_block_text`.
- Implication: escalate when no source file is present for active Mimikatz commands, or when the source path points to temp, profile, share, archive, or renamed script locations; lower concern when the path and script content are both confined to a controlled assessment repository or lab image.
- Did the activity create credential dumps, archives, exported certificates, tickets, hashes, or private-key material?
- Focus: file activity on `host.id` after `@timestamp`, bounded to the PowerShell `process.pid`, with `file.path`, `file.name`, and `file.directory` for dump, archive, ".pfx", ".pvk", ".p12", ".key", ticket, hash, DPAPI, vault, or cleanup artifacts. $investigate_2
- Implication: escalate when files appear in writable, external, or collection paths, especially certificate exports or archives matching the reconstructed command. Missing file telemetry is unresolved, not benign.
- Do authentication records show post-alert credential use?
- Focus: Windows Security events after `@timestamp`, separating `event.code` 4624/4648/4625 and reading `winlog.event_data.TargetUserName`, `source.ip`, and `winlog.event_data.TargetServerName`. $investigate_3
- Hint: If endpoint process telemetry is available for this host, recover the matching process via `host.id + process.pid` before using `process.*` or `process.parent.*` for interpretation; bridge recovered `process.Ext.authentication_id` to `winlog.event_data.TargetLogonId`, and search `winlog.event_data.SubjectLogonId` separately for 4648 explicit-credential events.
- Implication: escalate when new privileged logons, explicit-credential use, remote source IPs, or unusual authentication-package patterns follow the script. Missing authentication telemetry is unresolved, not benign.
- If local evidence remains suspicious or incomplete, do related alerts widen account or host scope?
- Focus: related alerts for `user.id` showing credential access, execution, defense evasion, or lateral movement. $investigate_4
- Hint: compare `host.id` alerts for precursor access, other credential tools, or follow-on compromise. $investigate_5
- Implication: broaden when either view shows connected credential-access or lateral-movement activity outside the same recognized assessment; keep the case local when surrounding alerts are absent or confined to the same bounded test.
- What disposition is supported by the evidence set?
- Focus: credential-dump intent, password-store or DPAPI scope, certificate/private-key export, ticket/hash use, remote targets, launch context, source path, artifacts, authentication, and related alerts.
- Implication: escalate when the evidence shows live dumping, password-store extraction, certificate export, alternate-authentication use, remote targeting, or follow-on credential use; close only when reconstruction shows inert content or telemetry plus external exercise confirmation bind the exact activity with no contradictory artifacts or authentication; preserve and escalate if evidence is mixed, partial, or telemetry is missing.
### False positive analysis
- Authorized red-team, credential-assessment, malware-analysis, training, or lab validation can legitimately trigger this rule. Confirm by verifying that reconstructed Mimikatz behavior, `user.id`, `host.id`, source `file.path`, recovered launch chain when available, authentication results, and exercise evidence all align to the same bounded test. If exercise evidence is unavailable, close only when telemetry itself proves inert content with no target, output, artifact, or follow-on authentication evidence.
- Build exceptions from the minimum confirmed pattern: stable `user.id`, `host.id`, source `file.path`, assessment repository or lab image, and recovered launcher context only when endpoint process recovery supports it. Avoid exceptions on `powershell.file.script_block_text`, Mimikatz strings, `user.name`, or `host.id` alone; do not create an exception for a single unconfirmed event.
### Response and remediation
- If confirmed benign, document the reconstructed script, source path, host-user scope, recovered launcher context if available, authentication evidence, and exercise evidence that confirmed the bounded test before reversing temporary containment. Create an exception only when that stable evidence set is confirmed, not from one unconfirmed event.
- If suspicious but unconfirmed, preserve the reconstructed script-block events, source script path, recovered process record if available, dump, password-store, ticket/hash, or certificate-export artifacts, and relevant Windows Security records before containment. Then apply reversible controls tied to the evidence, such as temporary session restriction, heightened monitoring, or limiting access for the affected `user.id` on `host.id`.
- If confirmed malicious, record evidence before destructive action, then isolate the endpoint or restrict the account based on the artifact and authentication findings. Terminate PowerShell only after evidence capture, then block or quarantine confirmed malicious scripts, artifact hashes, domains, or destinations only when those indicators were recovered during scoping.
- If credential dumping is confirmed, treat the involved `user.id` and any additional `winlog.event_data.TargetUserName` accounts as exposed only when reconstruction, artifacts, or authentication records support that exposure. Prioritize resets for privileged, service, and lateral-movement-relevant accounts, and review related hosts and users for the same authentication or alert pattern before artifact removal.
- If certificate, DPAPI, vault, ticket, or hash material is confirmed, preserve the affected `file.path` locations and references in `powershell.file.script_block_text`, then coordinate revocation, re-issuance, reset, or downstream trust updates for the confirmed material.
- After containment and credential, certificate, or alternate-authentication actions, remove staged scripts, dumps, archives, or exported key material only after scoping related hosts and users for the same source path, account, and authentication evidence.
"""
setup = """## Setup
PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104).
Setup instructions: https://ela.st/powershell-logging-setup
"""
[rule.investigation_fields]
field_names = [
"@timestamp",
"user.name",
"user.id",
"user.domain",
"powershell.file.script_block_text",
"powershell.file.script_block_id",
"powershell.sequence",
"powershell.total",
"file.path",
"file.directory",
"file.name",
"process.pid",
"host.name",
"host.id",
"powershell.file.script_block_length"
]
[[transform.investigate]]
label = "Script block fragments for the same script"
description = ""
providers = [
[
{ excluded = false, field = "powershell.file.script_block_id", queryType = "phrase", value = "{{powershell.file.script_block_id}}", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
]
]
relativeFrom = "now-1h"
relativeTo = "now"
[[transform.investigate]]
label = "Process events for the PowerShell instance"
description = ""
providers = [
[
{ excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" }
]
]
relativeFrom = "now-1h"
relativeTo = "now"
[[transform.investigate]]
label = "File events for the PowerShell process"
description = ""
providers = [
[
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" },
{ excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" }
]
]
relativeFrom = "now-1h"
relativeTo = "now"
[[transform.investigate]]
label = "Windows Security authentication events on the host"
description = ""
providers = [
[
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }
],
[
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "event.code", queryType = "phrase", value = "4648", valueType = "string" }
],
[
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "event.code", queryType = "phrase", value = "4625", valueType = "string" }
]
]
relativeFrom = "now-24h"
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 = "T1003"
name = "OS Credential Dumping"
reference = "https://attack.mitre.org/techniques/T1003/"
[[rule.threat.technique.subtechnique]]
id = "T1003.001"
name = "LSASS Memory"
reference = "https://attack.mitre.org/techniques/T1003/001/"
[[rule.threat.technique.subtechnique]]
id = "T1003.002"
name = "Security Account Manager"
reference = "https://attack.mitre.org/techniques/T1003/002/"
[[rule.threat.technique.subtechnique]]
id = "T1003.004"
name = "LSA Secrets"
reference = "https://attack.mitre.org/techniques/T1003/004/"
[[rule.threat.technique.subtechnique]]
id = "T1003.005"
name = "Cached Domain Credentials"
reference = "https://attack.mitre.org/techniques/T1003/005/"
[[rule.threat.technique.subtechnique]]
id = "T1003.006"
name = "DCSync"
reference = "https://attack.mitre.org/techniques/T1003/006/"
[[rule.threat.technique]]
id = "T1555"
name = "Credentials from Password Stores"
reference = "https://attack.mitre.org/techniques/T1555/"
[[rule.threat.technique.subtechnique]]
id = "T1555.004"
name = "Windows Credential Manager"
reference = "https://attack.mitre.org/techniques/T1555/004/"
[[rule.threat.technique]]
id = "T1649"
name = "Steal or Forge Authentication Certificates"
reference = "https://attack.mitre.org/techniques/T1649/"
[[rule.threat.technique]]
id = "T1558"
name = "Steal or Forge Kerberos Tickets"
reference = "https://attack.mitre.org/techniques/T1558/"
[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.002"
name = "Pass the Hash"
reference = "https://attack.mitre.org/techniques/T1550/002/"
[[rule.threat.technique.subtechnique]]
id = "T1550.003"
name = "Pass the Ticket"
reference = "https://attack.mitre.org/techniques/T1550/003/"
[rule.threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1550"
name = "Use Alternate Authentication Material"
reference = "https://attack.mitre.org/techniques/T1550/"
[[rule.threat.technique.subtechnique]]
id = "T1550.002"
name = "Pass the Hash"
reference = "https://attack.mitre.org/techniques/T1550/002/"
[[rule.threat.technique.subtechnique]]
id = "T1550.003"
name = "Pass the Ticket"
reference = "https://attack.mitre.org/techniques/T1550/003/"
[rule.threat.tactic]
id = "TA0008"
name = "Lateral Movement"
reference = "https://attack.mitre.org/tactics/TA0008/"
Stages and Predicates
Stage 1: query
event.category:process and host.os.type:windows and
powershell.file.script_block_text:(
(DumpCreds and DumpCerts) or
"sekurlsa::logonpasswords" or
"sekurlsa::ekeys" or
"sekurlsa::tickets" or
"sekurlsa::pth" or
"sekurlsa::minidump" or
"lsadump::sam" or
"lsadump::secrets" or
"lsadump::cache" or
"lsadump::dcsync" or
"vault::cred" or
"dpapi::cred" or
("crypto::certificates" and
"CERT_SYSTEM_STORE_LOCAL_MACHINE")
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.category | eq |
| field:"event.category" kind:eq value:"process" |
powershell.file.script_block_text | eq |
| field:"ScriptBlockText" kind:eq |
Potential Linux Tunneling or Port Forwarding via SSH
#This rule monitors for the use of SSH to potentially tunnel network traffic. Attackers can leverage SSH to establish hidden communication channels and gain unauthorized access to internal resources, facilitating data exfiltration, lateral movement, and remote control.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Rule Body
[rule]
description = """
This rule monitors for the use of SSH to potentially tunnel network traffic. Attackers can leverage SSH to establish
hidden communication channels and gain unauthorized access to internal resources, facilitating data exfiltration,
lateral movement, and remote control.
"""
id = "260c06cf-5ad8-4809-bca3-94828796e241"
license = "Elastic License v2"
name = "Potential Linux Tunneling or Port Forwarding via SSH"
os_list = ["linux"]
reference = ["https://book.hacktricks.xyz/generic-methodologies-and-resources/tunneling-and-port-forwarding"]
version = "1.0.8"
query = '''
process where event.type == "start" and event.action == "exec" and
process.parent.executable like ("/tmp/*", "/var/tmp/*", "/dev/shm/*", "/run/user/*", "/var/run/user/*", "/home/*/*", "/root/*", "/boot/*", "./*") and
(
(
process.name == "sshuttle" and
process.args in ("-r", "--remote", "-l", "--listen")
) or
(
(
process.name == "ssh" or
(
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "mksh", "busybox") and
process.args like "ssh*"
)
) and
(
(
process.args == "-J" or
(
(
process.args in ("-R", "-L", "-D", "-w") or
process.args regex """\-[A-NP-Za-np-z][A-Za-z]*[RLDwW][A-Za-z]*"""
) and
process.args_count >= 4
)
) or
(
process.args like "-o*" and
process.command_line like~ (
"*ProxyCommand*", "*LocalForward*", "*RemoteForward*", "*DynamicForward*", "*Tunnel*", "*GatewayPorts*",
"*ExitOnForwardFailure*", "*ProxyJump*"
)
)
)
)
) and
not (
process.parent.executable like (
"/home/*/.local/bin/ansible-playbook", "/tmp/newroot/*", "/home/*/.local/share/JetBrains/Toolbox/bin/jetbrains-toolbox",
"/home/*/sp/bin/forwards", "/home/*globusconnectpersonal*/bin/relaytool", "/home/*/bin/minikube/minikube-linux-amd64",
"/home/*/google-cloud-sdk/platform/bundledpythonunix/bin/python3", "/home/*/.local/share/uv/python/cpython-*-linux-x86_64-gnu/bin/python3.*",
"/home/*/.ssh/evolutixtunnelaws.sh", "/home/*/core3/dh/plz-out/bin/security/woodhouse/authenticator/authenticator",
"/home/*/.local/vscode-insiders/usr/share/code-insiders/code-insiders", "/tmp/*/globusconnectpersonal-*/gt_amd64/bin/relaytool",
"/home/*/.local/share/antigravity-ide/antigravity-ide", "/home/*/bin/minikube/minikube", "/home/*/.local/bin/codex",
"/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl"
) or
process.parent.command_line like (
"/home/*/repositories/synthetic-datasets/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(*) --multiprocessing-fork",
"SkyPilot:executor:*"
) or
(process.parent.args == "./deployment.sh" and process.working_directory like "/tmp/builds/*/metis/minerva/minerva-api") or
(process.parent.executable like "/home/*/.pyenv/versions/*/bin/python*" and process.working_directory like "/home/*/Projects/backport/ansible-*") or
(
process.parent.executable like ("/home/*/software/crux/bin/reverse_tunnel.sh", "/home/*/software/crux/bin/ssh") and
process.executable like ("/home/*/software/crux/bin/ssh", "/usr/bin/ssh")
) or
(
process.parent.command_line like "/home/*/bin/python /home/*/bin/ansible-playbook *" and
process.command_line like "ssh -C -o ControlMaster=auto -o ControlPersist=60s *"
) or
process.parent.executable like (
"/home/*/.local/share/JetBrains/Daemon/*/jetbrainsd",
"*/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
"/home/*/.codex/packages/standalone/releases/*/bin/codex"
)
)
'''
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.parent.executable like ("/tmp/*", "/var/tmp/*", "/dev/shm/*", "/run/user/*", "/var/run/user/*", "/home/*/*", "/root/*", "/boot/*", "./*") and
(
(
process.name == "sshuttle" and
process.args in ("-r", "--remote", "-l", "--listen")
) or
(
(
process.name == "ssh" or
(
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "mksh", "busybox") and
process.args like "ssh*"
)
) and
(
(
process.args == "-J" or
(
(
process.args in ("-R", "-L", "-D", "-w") or
process.args regex """\-[A-NP-Za-np-z][A-Za-z]*[RLDwW][A-Za-z]*"""
) and
process.args_count >= 4
)
) or
(
process.args like "-o*" and
process.command_line like~ (
"*ProxyCommand*", "*LocalForward*", "*RemoteForward*", "*DynamicForward*", "*Tunnel*", "*GatewayPorts*",
"*ExitOnForwardFailure*", "*ProxyJump*"
)
)
)
)
) and
not (
process.parent.executable like (
"/home/*/.local/bin/ansible-playbook", "/tmp/newroot/*", "/home/*/.local/share/JetBrains/Toolbox/bin/jetbrains-toolbox",
"/home/*/sp/bin/forwards", "/home/*globusconnectpersonal*/bin/relaytool", "/home/*/bin/minikube/minikube-linux-amd64",
"/home/*/google-cloud-sdk/platform/bundledpythonunix/bin/python3", "/home/*/.local/share/uv/python/cpython-*-linux-x86_64-gnu/bin/python3.*",
"/home/*/.ssh/evolutixtunnelaws.sh", "/home/*/core3/dh/plz-out/bin/security/woodhouse/authenticator/authenticator",
"/home/*/.local/vscode-insiders/usr/share/code-insiders/code-insiders", "/tmp/*/globusconnectpersonal-*/gt_amd64/bin/relaytool",
"/home/*/.local/share/antigravity-ide/antigravity-ide", "/home/*/bin/minikube/minikube", "/home/*/.local/bin/codex",
"/home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl"
) or
process.parent.command_line like (
"/home/*/repositories/synthetic-datasets/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(*) --multiprocessing-fork",
"SkyPilot:executor:*"
) or
(process.parent.args == "./deployment.sh" and process.working_directory like "/tmp/builds/*/metis/minerva/minerva-api") or
(process.parent.executable like "/home/*/.pyenv/versions/*/bin/python*" and process.working_directory like "/home/*/Projects/backport/ansible-*") or
(
process.parent.executable like ("/home/*/software/crux/bin/reverse_tunnel.sh", "/home/*/software/crux/bin/ssh") and
process.executable like ("/home/*/software/crux/bin/ssh", "/usr/bin/ssh")
) or
(
process.parent.command_line like "/home/*/bin/python /home/*/bin/ansible-playbook *" and
process.command_line like "ssh -C -o ControlMaster=auto -o ControlPersist=60s *"
) or
process.parent.executable like (
"/home/*/.local/share/JetBrains/Daemon/*/jetbrainsd",
"*/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
"/home/*/.codex/packages/standalone/releases/*/bin/codex"
)
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq value:"-J" |
process.args | in |
| field:"process.args" kind:in |
process.args | regex_match |
| field:"process.args" kind:regex_match value:"\-[A-NP-Za-np-z][A-Za-z]*[RLDwW][A-Za-z]*" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.args_count | ge |
| field:"process.args_count" kind:ge value:"4" |
process.command_line | wildcard |
| field:"CommandLine" kind:wildcard |
process.name | eq |
| field:"process_basename" kind:eq |
process.name | in |
| field:"process_basename" kind:in |
process.parent.executable | wildcard |
| field:"ParentImage" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.command_line | starts_with | ssh -C -o ControlMaster=auto -o ControlPersist=60s | excludes:process.command_line field:"process.command_line" value:"ssh -C -o ControlMaster=auto -o ControlPersist=60s " |
process.parent.command_line | wildcard | /home/*/bin/python /home/*/bin/ansible-playbook * | excludes:process.parent.command_line field:"process.parent.command_line" value:"/home/*/bin/python /home/*/bin/ansible-playbook *" |
process.executable | wildcard | /home/*/software/crux/bin/ssh, /usr/bin/ssh | excludes:process.executable field:"process.executable" value:"/home/*/software/crux/bin/ssh" field:"process.executable" value:"/usr/bin/ssh" |
process.parent.executable | wildcard | /home/*/software/crux/bin/reverse_tunnel.sh, /home/*/software/crux/bin/ssh | excludes:process.parent.executable field:"process.parent.executable" value:"/home/*/software/crux/bin/reverse_tunnel.sh" field:"process.parent.executable" value:"/home/*/software/crux/bin/ssh" |
process.parent.args | eq | ./deployment.sh | excludes:process.parent.args field:"process.parent.args" value:"./deployment.sh" |
process.working_directory | wildcard | /tmp/builds/*/metis/minerva/minerva-api | excludes:process.working_directory field:"process.working_directory" value:"/tmp/builds/*/metis/minerva/minerva-api" |
process.parent.executable | wildcard | /home/*/.pyenv/versions/*/bin/python* | excludes:process.parent.executable field:"process.parent.executable" value:"/home/*/.pyenv/versions/*/bin/python*" |
process.working_directory | wildcard | /home/*/Projects/backport/ansible-* | excludes:process.working_directory field:"process.working_directory" value:"/home/*/Projects/backport/ansible-*" |
process.parent.command_line | wildcard | /home/*/repositories/synthetic-datasets/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(*) --multiprocessing-fork, SkyPilot:executor:* | excludes:process.parent.command_line field:"process.parent.command_line" value:"/home/*/repositories/synthetic-datasets/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(*) --multiprocessing-fork" field:"process.parent.command_line" value:"SkyPilot:executor:*" |
process.parent.executable | wildcard | /home/*/.local/bin/ansible-playbook, /tmp/newroot/*, /home/*/.local/share/JetBrains/Toolbox/bin/jetbrains-toolbox, /home/*/sp/bin/forwards, /home/*globusconnectpersonal*/bin/relaytool, /home/*/bin/minikube/minikube-linux-amd64, /home/*/google-cloud-sdk/platform/bundledpythonunix/bin/python3, /home/*/.local/share/uv/python/cpython-*-linux-x86_64-gnu/bin/python3.*, /home/*/.ssh/evolutixtunnelaws.sh, /home/*/core3/dh/plz-out/bin/security/woodhouse/authenticator/authenticator, /home/*/.local/vscode-insiders/usr/share/code-insiders/code-insiders, /tmp/*/globusconnectpersonal-*/gt_amd64/bin/relaytool, /home/*/.local/share/antigravity-ide/antigravity-ide, /home/*/bin/minikube/minikube, /home/*/.local/bin/codex, /home/linuxbrew/.linuxbrew/Caskroom/codex/*/codex-x86_64-unknown-linux-musl | excludes:process.parent.executable |
process.parent.executable | wildcard | /home/*/.local/share/JetBrains/Daemon/*/jetbrainsd, */node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex, /home/*/.codex/packages/standalone/releases/*/bin/codex | excludes:process.parent.executable field:"process.parent.executable" value:"/home/*/.local/share/JetBrains/Daemon/*/jetbrainsd" field:"process.parent.executable" value:"*/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex" field:"process.parent.executable" value:"/home/*/.codex/packages/standalone/releases/*/bin/codex" |
Potential Operation via Direct Syscall
#Identifies any event with a call stack not starting with Windows NT syscall DLLs such as ntdll and win32u. This may indicate the use of direct system calls to evade endpoint security solutions hooking Windows APIs.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[rule]
description = """
Identifies any event with a call stack not starting with Windows NT syscall DLLs such as ntdll and win32u. This may
indicate the use of direct system calls to evade endpoint security solutions hooking Windows APIs.
"""
id = "30106950-2383-49cd-b462-ed55be29b10b"
license = "Elastic License v2"
name = "Potential Operation via Direct Syscall"
os_list = ["windows"]
reference = [
"https://www.elastic.co/security-labs/revisiting-blister-new-developments-of-the-blister-loader",
"https://www.elastic.co/security-labs/upping-the-ante-detecting-in-memory-threats-with-kernel-call-stacks",
"https://www.ired.team/offensive-security/defense-evasion/using-syscalls-directly-from-visual-studio-to-bypass-avs-edrs",
]
version = "1.0.32"
query = '''
any where process.pid != 4 and process.executable != null and process.name : "?*" and
(
/* call_stack_summary looks like process.name|etc */
(event.category in ("file", "registry", "library") and
startswith~(process.thread.Ext.call_stack_summary, process.name)) or
/* call_stack_summary looks like process.parent.name|etc. */
(event.category == "process" and event.action == "start" and
startswith~(process.parent.thread.Ext.call_stack_summary, process.parent.name) and process.parent.executable : "?:\\*") or
/* call_stack_summary looks like ntdll.dll|process.parent.name|etc */
(event.category == "process" and event.action == "start" and
endswith~(substring(process.parent.thread.Ext.call_stack_summary, 0, 10 + length(process.parent.name)), process.parent.name) and
not process.parent.executable : "?:\\Windows\\System32\\services.exe" and process.parent.executable : "?:\\*")
) and
not ((process.executable : "?:\\Windows\\system32\\smss.exe" or process.parent.executable : "?:\\Windows\\system32\\smss.exe") and
(process.parent.thread.Ext.call_stack_summary : "ntdll.dll|smss.exe|*" or process.thread.Ext.call_stack_summary like "ntdll.dll|smss.exe|*")) and
not (event.category == "library" and
process.code_signature.status like ("trusted", "errorExpired", "errorCode_endpoint*", "errorTimeStamp") and
process.code_signature.subject_name : ("Oracle Corporation", "NVIDIA Corporation")) and
not (process.code_signature.subject_name : "Rocscience Inc." and process.code_signature.status == "trusted") and
not (event.category == "process" and
process.executable : "?:\\Windows\\System32\\vmsp.exe" and
process.code_signature.subject_name like "Microsoft*" and process.code_signature.status == "trusted" and
process.parent.thread.Ext.call_stack_summary : "ntdll.dll|vmwp.exe|ntdll.dll*") and
not (event.category == "library" and dll.code_signature.status == "trusted" and not dll.code_signature.subject_name like "Microsoft*") and
not (process.executable : "?:\\Windows\\System32\\WUDFCompanionHost.exe" and process.parent.executable : "?:\\Windows\\System32\\services.exe") and
not process.executable :
("?:\\Program Files\\Oracle\\VirtualBox\\VirtualBoxVM.exe",
"?:\\Program Files (x86)\\Oracle\\VirtualBox\\VirtualBoxVM.exe",
"?:\\Program Files\\Oracle\\VirtualBox\\VBoxNetDHCP.exe",
"C:\\Program Files\\Oracle\\VirtualBox\\VBoxNetNAT.exe",
"?:\\Program Files (x86)\\Oracle\\VirtualBox\\VBoxNetDHCP.exe",
"?:\\Program Files\\Oracle\\VirtualBox\\VBoxHeadless.exe",
"?:\\Program Files\\TxGameAssistant\\ui\\aow_exe.exe",
"?:\\Program Files\\Rockstar Games\\Launcher\\Launcher.exe",
"C:\\Program Files (x86)\\Steam\\steamapps\\common\\*.exe",
"C:\\Program Files\\EA\\AC\\EAAntiCheat.GameService.dll",
"F:\\SteamLibrary\\steamapps\\common\\BeamNG.drive\\Bin64\\BeamNG.drive.x64.exe") and
not (event.category == "process" and process.executable : "C:\\Windows\\System32\\csrss.exe" and
process.parent.executable : "C:\\Program Files\\GraphOn\\GO-Global\\Programs\\aps.exe") and
not (process.executable : "C:\\Windows\\System32\\WUDFCompanionHost.exe" and
process.parent.executable : "C:\\Windows\\System32\\services.exe") and
not process.parent.executable :
("C:\\Program Files\\Rocscience\\Slide2\\slide.exe",
"?:\\Program Files\\Anatomage\\Invivo\\InVivoDental.exe",
"?:\\Program Files\\Anatomage\\Invivo\\Invivo.exe",
"?:\\Program Files\\Anatomage\\InvivoDental\\InVivoDental.exe",
"C:\\Program Files\\Rocscience\\Settle3\\Settle3.exe",
"C:\\PC SOFT\\WINDEV Suite 2026\\Programs\\wx64.exe",
"C:\\Program Files (x86)\\PC SOFT\\WINDEV Suite 2026\\Programs\\wx64.exe") and
not process.thread.Ext.call_stack_summary like "ntdll.dll|wow64.dll|wow64cpu.dll*" and
not process.parent.thread.Ext.call_stack_summary : "ntdll.dll|wow64.dll|wow64cpu.dll|*" and
not (process.name : "WerFault.exe" and
process.parent.thread.Ext.call_stack_summary : "ntdll.dll|kernelbase.dll|faultrep.dll|wersvc.dll|ntdll.dll|kernel32.dll|ntdll.dll") and
not process.hash.sha256 : "920d49c27f0b42dab747bdf48edfc6b668f3ae4d192a2a4c9b5a6cec14bec77f" and
not (event.category == "process" and _arraysearch(process.parent.thread.Ext.call_stack, $entry, $entry.symbol_info: "*kernel32.dll!CreateProcessW*")) and
not (event.category == "library" and dll.path : "C:\\Windows\\System32\\umppc*.dll") and
not (event.category == "library" and dll.code_signature.subject_name == "Microsoft Windows Hardware Compatibility Publisher" and
dll.code_signature.trusted == true) and
not (event.category == "library" and process.code_signature.subject_name == "BeamNG GmbH" and process.code_signature.trusted == true)
'''
min_endpoint_version = "8.7.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 = "T1055"
name = "Process Injection"
reference = "https://attack.mitre.org/techniques/T1055/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "8.7.0"
Stages and Predicates
Stage 1: any
any where process.pid != 4 and process.executable != null and process.name : "?*" and
(
(event.category in ("file", "registry", "library") and
startswith~(process.thread.Ext.call_stack_summary, process.name)) or
(event.category == "process" and event.action == "start" and
startswith~(process.parent.thread.Ext.call_stack_summary, process.parent.name) and process.parent.executable : "?:\\*") or
(event.category == "process" and event.action == "start" and
endswith~(substring(process.parent.thread.Ext.call_stack_summary, 0, 10 + length(process.parent.name)), process.parent.name) and
not process.parent.executable : "?:\\Windows\\System32\\services.exe" and process.parent.executable : "?:\\*")
) and
not ((process.executable : "?:\\Windows\\system32\\smss.exe" or process.parent.executable : "?:\\Windows\\system32\\smss.exe") and
(process.parent.thread.Ext.call_stack_summary : "ntdll.dll|smss.exe|*" or process.thread.Ext.call_stack_summary like "ntdll.dll|smss.exe|*")) and
not (event.category == "library" and
process.code_signature.status like ("trusted", "errorExpired", "errorCode_endpoint*", "errorTimeStamp") and
process.code_signature.subject_name : ("Oracle Corporation", "NVIDIA Corporation")) and
not (process.code_signature.subject_name : "Rocscience Inc." and process.code_signature.status == "trusted") and
not (event.category == "process" and
process.executable : "?:\\Windows\\System32\\vmsp.exe" and
process.code_signature.subject_name like "Microsoft*" and process.code_signature.status == "trusted" and
process.parent.thread.Ext.call_stack_summary : "ntdll.dll|vmwp.exe|ntdll.dll*") and
not (event.category == "library" and dll.code_signature.status == "trusted" and not dll.code_signature.subject_name like "Microsoft*") and
not (process.executable : "?:\\Windows\\System32\\WUDFCompanionHost.exe" and process.parent.executable : "?:\\Windows\\System32\\services.exe") and
not process.executable :
("?:\\Program Files\\Oracle\\VirtualBox\\VirtualBoxVM.exe",
"?:\\Program Files (x86)\\Oracle\\VirtualBox\\VirtualBoxVM.exe",
"?:\\Program Files\\Oracle\\VirtualBox\\VBoxNetDHCP.exe",
"C:\\Program Files\\Oracle\\VirtualBox\\VBoxNetNAT.exe",
"?:\\Program Files (x86)\\Oracle\\VirtualBox\\VBoxNetDHCP.exe",
"?:\\Program Files\\Oracle\\VirtualBox\\VBoxHeadless.exe",
"?:\\Program Files\\TxGameAssistant\\ui\\aow_exe.exe",
"?:\\Program Files\\Rockstar Games\\Launcher\\Launcher.exe",
"C:\\Program Files (x86)\\Steam\\steamapps\\common\\*.exe",
"C:\\Program Files\\EA\\AC\\EAAntiCheat.GameService.dll",
"F:\\SteamLibrary\\steamapps\\common\\BeamNG.drive\\Bin64\\BeamNG.drive.x64.exe") and
not (event.category == "process" and process.executable : "C:\\Windows\\System32\\csrss.exe" and
process.parent.executable : "C:\\Program Files\\GraphOn\\GO-Global\\Programs\\aps.exe") and
not (process.executable : "C:\\Windows\\System32\\WUDFCompanionHost.exe" and
process.parent.executable : "C:\\Windows\\System32\\services.exe") and
not process.parent.executable :
("C:\\Program Files\\Rocscience\\Slide2\\slide.exe",
"?:\\Program Files\\Anatomage\\Invivo\\InVivoDental.exe",
"?:\\Program Files\\Anatomage\\Invivo\\Invivo.exe",
"?:\\Program Files\\Anatomage\\InvivoDental\\InVivoDental.exe",
"C:\\Program Files\\Rocscience\\Settle3\\Settle3.exe",
"C:\\PC SOFT\\WINDEV Suite 2026\\Programs\\wx64.exe",
"C:\\Program Files (x86)\\PC SOFT\\WINDEV Suite 2026\\Programs\\wx64.exe") and
not process.thread.Ext.call_stack_summary like "ntdll.dll|wow64.dll|wow64cpu.dll*" and
not process.parent.thread.Ext.call_stack_summary : "ntdll.dll|wow64.dll|wow64cpu.dll|*" and
not (process.name : "WerFault.exe" and
process.parent.thread.Ext.call_stack_summary : "ntdll.dll|kernelbase.dll|faultrep.dll|wersvc.dll|ntdll.dll|kernel32.dll|ntdll.dll") and
not process.hash.sha256 : "920d49c27f0b42dab747bdf48edfc6b668f3ae4d192a2a4c9b5a6cec14bec77f" and
not (event.category == "process" and _arraysearch(process.parent.thread.Ext.call_stack, $entry, $entry.symbol_info: "*kernel32.dll!CreateProcessW*")) and
not (event.category == "library" and dll.path : "C:\\Windows\\System32\\umppc*.dll") and
not (event.category == "library" and dll.code_signature.subject_name == "Microsoft Windows Hardware Compatibility Publisher" and
dll.code_signature.trusted == true) and
not (event.category == "library" and process.code_signature.subject_name == "BeamNG GmbH" and process.code_signature.trusted == true)
Indicators
These rows show field, operator, and value matches.
Exclusions
The rule actively suppresses these predicates.
Potential SSH Password Grabbing via strace
#Detects potential SSH password grabbing via the use of strace on sshd processes. Attackers may use strace to capture sensitive information, such as passwords, by tracing system calls made by the sshd process. This rule looks for a sequence of events where an sshd process ends followed closely by the start of a strace process. This may be indicative of an attacker attempting to capture SSH credentials.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Credential Access |
Rule Body
[metadata]
creation_date = "2025/11/10"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/03/24"
[rule]
author = ["Elastic"]
description = """
Detects potential SSH password grabbing via the use of strace on sshd processes. Attackers may use strace to capture
sensitive information, such as passwords, by tracing system calls made by the sshd process. This rule looks for a sequence
of events where an sshd process ends followed closely by the start of a strace process. This may be indicative of an attacker
attempting to capture SSH credentials.
"""
from = "now-9m"
index = ["logs-endpoint.events.process-*"]
language = "eql"
license = "Elastic License v2"
name = "Potential SSH Password Grabbing via strace"
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 SSH Password Grabbing via strace
This detection flags a suspicious sequence where an sshd process stops and a strace process starts seconds later, indicating attempted snooping of SSH authentication. Capturing syscall activity around login exposes passwords and session secrets, enabling credential theft and lateral movement. Attackers kill sshd, then relaunch or attach with strace, logging read/write and open calls from PAM or keyboard-interactive flows to a file such as /tmp/sshd.trace.
### Possible investigation steps
- Pull the strace command-line, full path, parent chain, invoking user, and working directory to confirm whether it attached to sshd and whether output was directed to a file.
- Correlate systemd/journald and audit logs around the same seconds for sshd stop/start, kill signals, coredumps, or admin actions to distinguish debugging from credential capture.
- Identify and preserve any strace output or redirected logs (common in /tmp or home directories) and scan for PAM interactions or TTY reads containing password prompts.
- Check ptrace feasibility by verifying UID relationships, CAP_SYS_PTRACE, SELinux/AppArmor policies, and ptrace_scope to assess whether sshd could be traced.
- Pivot on the same user and host for adjacent activity such as restarting sshd, running ltrace/gdb/perf, modifying PAM or sshd_config, and creating trace files to gauge intent.
### False positive analysis
- An administrator intentionally stops sshd and immediately launches strace to troubleshoot a configuration change or startup problem, tracing a controlled test run rather than attempting to capture credentials.
- A normal sshd session process ends while strace is started to debug an unrelated application, producing a near-simultaneous end/start sequence even though strace is not attached to sshd or capturing authentication input.
### Response and remediation
- Immediately kill active strace processes targeting sshd (e.g., strace -p PID or strace -f /usr/sbin/sshd with -o /tmp/sshd.trace), isolate the host from the network, and restart the sshd service to restore a clean state.
- Preserve forensic copies, then remove artifacts such as trace outputs like /tmp/sshd.trace or ~/sshd.strace.log, purge unauthorized strace wrappers or cron entries, and revert changes in /etc/ssh/sshd_config and /etc/pam.d/*.
- Force credential hygiene by expiring passwords for users who logged in during the suspected window, rotating SSH host keys in /etc/ssh/ (ssh_host_*), revoking recently added ~/.ssh/authorized_keys entries, and terminating lingering sshd child sessions and SSH agents in /tmp or /run.
- Escalate to incident response if strace was executed as root or via sudo against /usr/sbin/sshd, if CAP_SYS_PTRACE or ptrace_scope=0 was present, if trace files contain password strings or PAM conversation data, or if similar behavior appears on more than one host.
- Harden by setting /proc/sys/kernel/yama/ptrace_scope to 1 or 2, enforcing SELinux/AppArmor policies that block ptrace to sshd, disabling PasswordAuthentication or requiring MFA in /etc/ssh/sshd_config, and adding auditd rules to alert on ptrace attaches to /usr/sbin/sshd.
"""
references = [
"https://github.com/braindead-sec/ssh-grabber",
"https://dfir.ch/posts/strace/",
]
risk_score = 47
rule_id = "9eaa3fb1-3f70-48ed-bb0e-d7ae4d3c8f28"
severity = "medium"
tags = [
"Domain: Endpoint",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Persistence",
"Tactic: Credential Access",
"Data Source: Elastic Defend",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
sequence by host.id with maxspan=3s
[process where host.os.type == "linux" and event.type == "end" and process.name == "sshd"]
[process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.name == "strace"]
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1056"
name = "Input Capture"
reference = "https://attack.mitre.org/techniques/T1056/"
[[rule.threat.technique]]
id = "T1556"
name = "Modify Authentication Process"
reference = "https://attack.mitre.org/techniques/T1556/"
[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 = "T1554"
name = "Compromise Host Software Binary"
reference = "https://attack.mitre.org/techniques/T1554/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
Stages and Predicates
Ordered sequence: each step below must occur in order within 3s, correlated by host.id.
Stage 1: process
[process where host.os.type == "linux" and event.type == "end" and process.name == "sshd"]
Stage 2: process
[process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.name == "strace"]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq |
process.name | eq |
| field:"process_basename" kind:eq |
RPC (Remote Procedure Call) from the Internet
#This rule detects network events that may indicate the use of RPC traffic from the Internet. RPC is commonly used by system administrators to remotely control a system for maintenance or to use shared resources. It should almost never be directly exposed to the Internet, as it is frequently targeted and exploited by threat actors as an initial access or backdoor vector.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
[metadata]
creation_date = "2020/02/18"
integration = ["network_traffic", "panw", "fortinet_fortigate", "pfsense", "zeek", "corelight"]
maturity = "production"
updated_date = "2026/08/26"
[rule]
author = ["Elastic"]
description = """
This rule detects network events that may indicate the use of RPC traffic from the Internet. RPC is commonly used by
system administrators to remotely control a system for maintenance or to use shared resources. It should almost never be
directly exposed to the Internet, as it is frequently targeted and exploited by threat actors as an initial access or
backdoor vector.
"""
from = "now-9m"
index = ["logs-network_traffic.*", "logs-panw.panos*", "logs-fortinet_fortigate.log-*", "logs-pfsense.log-*", "logs-zeek.*", "logs-corelight.*"]
language = "kuery"
license = "Elastic License v2"
name = "RPC (Remote Procedure Call) from the Internet"
references = ["https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml"]
risk_score = 73
rule_id = "143cb236-0956-4f42-a706-814bcaa0cf5a"
severity = "high"
tags = ["Tactic: Initial Access",
"Domain: Endpoint",
"Use Case: Threat Detection",
"Data Source: Corelight",
"Data Source: Fortinet",
"Data Source: Network Traffic",
"Data Source: PAN-OS",
"Data Source: pfSense",
"Data Source: Zeek",
"Resources: Investigation Guide"
]
timestamp_override = "event.ingested"
type = "query"
query = '''
(data_stream.dataset:(fortinet_fortigate.log or network_traffic.flow) or event.category:(network or network_traffic)) and
network.transport:tcp and (destination.port:135 or data_stream.dataset:zeek.dce_rpc) and
not (event.type: denied or event.action: flow_dropped or event.outcome: failure) and
not source.ip:(
10.0.0.0/8 or
127.0.0.0/8 or
169.254.0.0/16 or
172.16.0.0/12 or
192.0.0.0/24 or
192.0.0.0/29 or
192.0.0.8/32 or
192.0.0.9/32 or
192.0.0.10/32 or
192.0.0.170/32 or
192.0.0.171/32 or
192.0.2.0/24 or
192.31.196.0/24 or
192.52.193.0/24 or
192.168.0.0/16 or
192.88.99.0/24 or
224.0.0.0/4 or
100.64.0.0/10 or
192.175.48.0/24 or
198.18.0.0/15 or
198.51.100.0/24 or
203.0.113.0/24 or
240.0.0.0/4 or
"::1" or
"FE80::/10" or
"FF00::/8"
) and
destination.ip:(
10.0.0.0/8 or
172.16.0.0/12 or
192.168.0.0/16
)
'''
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 RPC (Remote Procedure Call) from the Internet
RPC enables remote management and resource sharing, crucial for system administration. However, when exposed to the Internet, it becomes a target for attackers seeking initial access or backdoor entry. The detection rule identifies suspicious RPC traffic by monitoring TCP port 135 and filtering out internal IP addresses, flagging potential threats from external sources.
### Possible investigation steps
- Review the source IP address of the alert to determine if it is from a known malicious actor or if it has been flagged in previous incidents.
- Check the destination IP address to confirm it belongs to a critical internal system that should not be exposed to the Internet.
- Analyze network traffic logs to identify any unusual patterns or volumes of traffic associated with the source IP, focusing on TCP port 135.
- Investigate any related alerts or logs from the same source IP or destination IP to identify potential patterns or repeated attempts.
- Assess the potential impact on the affected system by determining if any unauthorized access or changes have occurred.
- Consult threat intelligence sources to gather additional context on the source IP or any related indicators of compromise.
### False positive analysis
- Internal testing or development environments may generate RPC traffic that appears to originate from external sources. To manage this, add the IP addresses of these environments to the exception list in the detection rule.
- Legitimate remote management activities by trusted third-party vendors could trigger the rule. Verify the IP addresses of these vendors and include them in the exception list if they are known and authorized.
- Misconfigured network devices or proxies might route internal RPC traffic through external IP addresses. Review network configurations to ensure proper routing and add any necessary exceptions for known devices.
- Cloud-based services or applications that use RPC for legitimate purposes might be flagged. Identify these services and adjust the rule to exclude their IP ranges if they are verified as non-threatening.
### Response and remediation
- Immediately isolate the affected system from the network to prevent further unauthorized access or lateral movement by the attacker.
- Conduct a thorough examination of the system logs and network traffic to identify any unauthorized access or data exfiltration attempts.
- Apply the latest security patches and updates to the affected system to address any vulnerabilities that may have been exploited.
- Change all administrative and user credentials on the affected system and any other systems that may have been accessed using the same credentials.
- Implement network segmentation to limit the exposure of critical systems and services, ensuring that RPC services are not accessible from the Internet.
- Monitor the network for any signs of re-infection or further suspicious activity, focusing on traffic patterns similar to those identified in the initial alert.
- Escalate the incident to the security operations center (SOC) or relevant cybersecurity team for further investigation and to determine if additional systems are compromised."""
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1133"
name = "External Remote Services"
reference = "https://attack.mitre.org/techniques/T1133/"
[[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
(data_stream.dataset:(fortinet_fortigate.log or network_traffic.flow) or event.category:(network or network_traffic)) and
network.transport:tcp and (destination.port:135 or data_stream.dataset:zeek.dce_rpc) and
not (event.type: denied or event.action: flow_dropped or event.outcome: failure) and
not source.ip:(
10.0.0.0/8 or
127.0.0.0/8 or
169.254.0.0/16 or
172.16.0.0/12 or
192.0.0.0/24 or
192.0.0.0/29 or
192.0.0.8/32 or
192.0.0.9/32 or
192.0.0.10/32 or
192.0.0.170/32 or
192.0.0.171/32 or
192.0.2.0/24 or
192.31.196.0/24 or
192.52.193.0/24 or
192.168.0.0/16 or
192.88.99.0/24 or
224.0.0.0/4 or
100.64.0.0/10 or
192.175.48.0/24 or
198.18.0.0/15 or
198.51.100.0/24 or
203.0.113.0/24 or
240.0.0.0/4 or
"::1" or
"FE80::/10" or
"FF00::/8"
) and
destination.ip:(
10.0.0.0/8 or
172.16.0.0/12 or
192.168.0.0/16
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"zeek.dce_rpc" |
data_stream.dataset | in |
| field:"data_stream.dataset" kind:in |
destination.ip | in |
| field:"dest_ip" kind:in |
destination.port | eq |
| field:"DestinationPort" kind:eq value:"135" |
event.category | in |
| field:"event.category" kind:in |
network.transport | eq |
| field:"Protocol" kind:eq value:"tcp" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
event.action | eq | flow_dropped | excludes:event.action field:"event.action" value:"flow_dropped" |
event.outcome | eq | failure | excludes:event.outcome field:"event.outcome" value:"failure" |
event.type | eq | denied | excludes:event.type field:"event.type" value:"denied" |
source.ip | in | 10.0.0.0/8, 100.64.0.0/10, 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.10/32, 192.0.0.170/32, 192.0.0.171/32, 192.0.0.8/32, 192.0.0.9/32, 192.0.2.0/24, 192.168.0.0/16, 192.175.48.0/24, 192.31.196.0/24, 192.52.193.0/24, 192.88.99.0/24, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4, ::1, FE80::/10, FF00::/8 | excludes:source.ip |
Shortcut File Written or Modified on Startup Folder
#Identifies shortcut files written to or modified in the startup folder. Adversaries may use this technique to maintain persistence.
MITRE ATT&CK Coverage
Rule Body
[metadata]
bypass_bbr_timing = true
creation_date = "2023/08/29"
integration = ["endpoint"]
maturity = "production"
updated_date = "2024/05/21"
[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Identifies shortcut files written to or modified in the startup folder. Adversaries may use this technique to maintain
persistence.
"""
from = "now-9m"
index = ["logs-endpoint.events.file-*"]
language = "eql"
license = "Elastic License v2"
name = "Shortcut File Written or Modified on Startup Folder"
risk_score = 21
rule_id = "ee53d67a-5f0c-423c-a53c-8084ae562b5c"
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Persistence",
"Data Source: Elastic Defend",
"Rule Type: BBR",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
file where host.os.type == "windows" and event.type != "deletion" and file.extension == "lnk" and
file.path : (
"C:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*"
) and
not (
(process.name : "ONENOTE.EXE" and process.code_signature.status: "trusted" and file.name : "*OneNote.lnk") or
(process.name : "OktaVerifySetup.exe" and process.code_signature.status: "trusted" and file.name : "Okta Verify.lnk") or
(process.name : "OneLaunch.exe" and process.code_signature.status: "trusted" and file.name : "OneLaunch*.lnk") or
(process.name : "APPServerClient.exe" and process.code_signature.status: "trusted" and file.name : "Parallels Client.lnk")
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1547"
name = "Boot or Logon Autostart Execution"
reference = "https://attack.mitre.org/techniques/T1547/"
[[rule.threat.technique.subtechnique]]
id = "T1547.001"
name = "Registry Run Keys / Startup Folder"
reference = "https://attack.mitre.org/techniques/T1547/001/"
[[rule.threat.technique.subtechnique]]
id = "T1547.009"
name = "Shortcut Modification"
reference = "https://attack.mitre.org/techniques/T1547/009/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
Stages and Predicates
Stage 1: file
file where host.os.type == "windows" and event.type != "deletion" and file.extension == "lnk" and
file.path : (
"C:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*",
"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\*"
) and
not (
(process.name : "ONENOTE.EXE" and process.code_signature.status: "trusted" and file.name : "*OneNote.lnk") or
(process.name : "OktaVerifySetup.exe" and process.code_signature.status: "trusted" and file.name : "Okta Verify.lnk") or
(process.name : "OneLaunch.exe" and process.code_signature.status: "trusted" and file.name : "OneLaunch*.lnk") or
(process.name : "APPServerClient.exe" and process.code_signature.status: "trusted" and file.name : "Parallels Client.lnk")
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | ne |
| field:"event.type" kind:ne value:"deletion" |
file.extension | eq |
| field:"file.extension" kind:eq value:"lnk" |
file.path | wildcard |
| field:"TargetFilename" kind:wildcard |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
file.name | ends_with | OneNote.lnk | excludes:file.name field:"file.name" value:"OneNote.lnk" |
process.code_signature.status | eq | trusted | excludes:process.code_signature.status field:"process.code_signature.status" value:"trusted" |
process.name | eq | ONENOTE.EXE | excludes:process.name field:"process.name" value:"ONENOTE.EXE" |
file.name | eq | Okta Verify.lnk | excludes:file.name field:"file.name" value:"Okta Verify.lnk" |
process.name | eq | OktaVerifySetup.exe | excludes:process.name field:"process.name" value:"OktaVerifySetup.exe" |
file.name | eq | Parallels Client.lnk | excludes:file.name field:"file.name" value:"Parallels Client.lnk" |
process.name | eq | APPServerClient.exe | excludes:process.name field:"process.name" value:"APPServerClient.exe" |
file.name | wildcard | OneLaunch*.lnk | excludes:file.name field:"file.name" value:"OneLaunch*.lnk" |
process.name | eq | OneLaunch.exe | excludes:process.name field:"process.name" value:"OneLaunch.exe" |
Spike in Logon Events
#A machine learning job found an unusually large spike in successful authentication events. This can be due to password spraying, user enumeration or brute force activity.
Known False Positives
- Build servers and CI systems can sometimes trigger this alert. Security test cycles that include brute force or password spraying activities may trigger this alert.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Credential Access |
Rule Body
[metadata]
creation_date = "2021/06/10"
integration = ["auditd_manager", "endpoint", "system"]
maturity = "production"
min_stack_version = "9.4.0"
min_stack_comments = "Use EA (Entity Analytics) fields"
updated_date = "2026/07/27"
[rule]
anomaly_threshold = 75
author = ["Elastic"]
description = """
A machine learning job found an unusually large spike in successful authentication events. This can be due to password
spraying, user enumeration or brute force activity.
"""
false_positives = [
"""
Build servers and CI systems can sometimes trigger this alert. Security test cycles that include brute force or
password spraying activities may trigger this alert.
""",
]
from = "now-30m"
interval = "15m"
license = "Elastic License v2"
machine_learning_job_id = "auth_high_count_logon_events_ea"
name = "Spike in Logon Events"
setup = """## Setup
This rule requires the installation of associated Machine Learning jobs, as well as data coming in from one of the following integrations:
- Elastic Defend
- Auditd Manager
- System
### Anomaly Detection Setup
Once the rule is enabled, the associated Machine Learning job will start automatically. You can view the Machine Learning job linked under the "Definition" panel of the detection rule. If the job does not start due to an error, the issue must be resolved for the job to commence successfully. For more details on setting up anomaly detection jobs, refer to the [helper guide](https://www.elastic.co/guide/en/kibana/current/xpack-ml-anomalies.html).
### Elastic Defend Integration Setup
Elastic Defend is integrated into the Elastic Agent using Fleet. Upon configuration, the integration allows the Elastic Agent to monitor events on your host and send data to the Elastic Security app.
#### Prerequisite Requirements:
- Fleet is required for Elastic Defend.
- To configure Fleet Server refer to the [documentation](https://www.elastic.co/guide/en/fleet/current/fleet-server.html).
#### The following steps should be executed in order to add the Elastic Defend integration to your system:
- Go to the Kibana home page and click "Add integrations".
- In the query bar, search for "Elastic Defend" and select the integration to see more details about it.
- Click "Add Elastic Defend".
- Configure the integration name and optionally add a description.
- Select the type of environment you want to protect, either "Traditional Endpoints" or "Cloud Workloads".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/current/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
### Auditd Manager Integration Setup
The Auditd Manager Integration receives audit events from the Linux Audit Framework which is a part of the Linux kernel.
Auditd Manager provides a user-friendly interface and automation capabilities for configuring and monitoring system auditing through the auditd daemon. With `auditd_manager`, administrators can easily define audit rules, track system events, and generate comprehensive audit reports, improving overall security and compliance in the system.
#### The following steps should be executed in order to add the Elastic Agent System integration "auditd_manager" to your system:
- Go to the Kibana home page and click “Add integrations”.
- In the query bar, search for “Auditd Manager” and select the integration to see more details about it.
- Click “Add Auditd Manager”.
- Configure the integration name and optionally add a description.
- Review optional and advanced settings accordingly.
- Add the newly installed “auditd manager” to an existing or a new agent policy, and deploy the agent on a Linux system from which auditd log files are desirable.
- Click “Save and Continue”.
- For more details on the integration refer to the [helper guide](https://docs.elastic.co/integrations/auditd_manager).
#### Rule Specific Setup Note
Auditd Manager subscribes to the kernel and receives events as they occur without any additional configuration.
However, if more advanced configuration is required to detect specific behavior, audit rules can be added to the integration in either the "audit rules" configuration box or the "auditd rule files" box by specifying a file to read the audit rules from.
- For this detection rule no additional audit rules are required.
### System Integration Setup
The System integration allows you to collect system logs and metrics from your servers with Elastic Agent.
#### The following steps should be executed in order to add the Elastic Agent System integration "system" to your system:
- Go to the Kibana home page and click “Add integrations”.
- In the query bar, search for “System” and select the integration to see more details about it.
- Click “Add System”.
- Configure the integration name and optionally add a description.
- Review optional and advanced settings accordingly.
- Add the newly installed “system” to an existing or a new agent policy, and deploy the agent on your system from which system log files are desirable.
- Click “Save and Continue”.
- For more details on the integration refer to the [helper guide](https://docs.elastic.co/integrations/system).
"""
references = ["https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html"]
risk_score = 21
rule_id = "d7d5c059-c19a-4a96-8ae3-41496ef3bcf9"
severity = "low"
tags = [
"Data Source: Elastic Defend",
"Data Source: Auditd Manager",
"Data Source: Windows Security Event Logs",
"Use Case: Identity and Access Audit",
"Use Case: Threat Detection",
"Rule Type: ML",
"Rule Type: Machine Learning",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
type = "machine_learning"
note = """## Triage and analysis
> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
### Investigating Spike in Logon Events
The 'Spike in Logon Events' detection leverages machine learning to identify anomalies in authentication patterns, signaling potential threats like password spraying or brute force attacks. Adversaries exploit these methods to gain unauthorized access by overwhelming systems with login attempts. This rule detects unusual surges in successful logins, indicating possible credential access tactics, and aids in preemptive threat mitigation.
### Possible investigation steps
- Review the timestamp and source of the spike in logon events to determine the time frame and systems affected.
- Analyze the user accounts involved in the spike to identify any patterns or anomalies, such as accounts with multiple logins from different locations or IP addresses.
- Check for any recent changes in user permissions or roles that could explain the increase in logon events.
- Investigate the IP addresses associated with the logon events to identify any known malicious sources or unusual geographic locations.
- Correlate the logon events with other security alerts or logs, such as failed login attempts, to identify potential password spraying or brute force activities.
- Assess whether there are any concurrent alerts or indicators of compromise that could suggest a broader attack campaign.
### False positive analysis
- High-volume legitimate logins from automated systems or scripts can trigger false positives. Identify and whitelist these systems to prevent unnecessary alerts.
- Scheduled batch processes or system maintenance activities may cause spikes in logon events. Exclude these known activities by setting up exceptions based on time and source.
- Users with roles that require frequent logins, such as IT administrators or customer support agents, might be flagged. Create user-based exceptions for these roles to reduce false positives.
- Integration with third-party services that authenticate frequently can lead to detection triggers. Review and exclude these services from the rule to avoid misclassification.
- Consider adjusting the sensitivity of the machine learning model if certain patterns are consistently flagged as anomalies but are verified as legitimate.
### Response and remediation
- Immediately isolate the affected user accounts to prevent further unauthorized access. This can be done by disabling the accounts or resetting passwords.
- Conduct a thorough review of recent authentication logs to identify any other accounts that may have been compromised or targeted.
- Implement multi-factor authentication (MFA) for all user accounts to add an additional layer of security against unauthorized access.
- Notify the security operations team to monitor for any further suspicious logon activities and to ensure that the threat is contained.
- Escalate the incident to the incident response team if there is evidence of a broader attack or if sensitive data may have been accessed.
- Review and update access controls and permissions to ensure that users have the minimum necessary access to perform their roles.
- Enhance monitoring and alerting mechanisms to detect similar spikes in logon events in the future, ensuring rapid response to potential threats."""
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1110"
name = "Brute Force"
reference = "https://attack.mitre.org/techniques/T1110/"
[[rule.threat.technique.subtechnique]]
id = "T1110.003"
name = "Password Spraying"
reference = "https://attack.mitre.org/techniques/T1110/003/"
[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 = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
Suspicious Child Process of Adobe Acrobat Reader Update Service
#Detects attempts to exploit privilege escalation vulnerabilities related to the Adobe Acrobat Reader PrivilegedHelperTool responsible for installing updates. For more information, refer to CVE-2020-9615, CVE-2020-9614 and CVE-2020-9613 and verify that the impacted system is patched.
Known False Positives
- Trusted system or Adobe Acrobat Related processes.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Rule Body
[metadata]
creation_date = "2021/01/19"
integration = ["endpoint"]
maturity = "production"
updated_date = "2025/03/18"
[rule]
author = ["Elastic"]
description = """
Detects attempts to exploit privilege escalation vulnerabilities related to the Adobe Acrobat Reader
PrivilegedHelperTool responsible for installing updates. For more information, refer to CVE-2020-9615, CVE-2020-9614 and
CVE-2020-9613 and verify that the impacted system is patched.
"""
false_positives = ["Trusted system or Adobe Acrobat Related processes."]
from = "now-9m"
index = ["logs-endpoint.events.*"]
language = "eql"
license = "Elastic License v2"
name = "Suspicious Child Process of Adobe Acrobat Reader Update Service"
references = [
"https://rekken.github.io/2020/05/14/Security-Flaws-in-Adobe-Acrobat-Reader-Allow-Malicious-Program-to-Gain-Root-on-macOS-Silently/",
]
risk_score = 73
rule_id = "f85ce03f-d8a8-4c83-acdc-5c8cd0592be7"
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 macOS 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, for MacOS it is recommended to select "Traditional Endpoints".
- Select a configuration preset. Each preset comes with different default settings for Elastic Agent, you can further customize these later by configuring the Elastic Defend integration policy. [Helper guide](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html).
- We suggest selecting "Complete EDR (Endpoint Detection and Response)" as a configuration setting, that provides "All events; all preventions"
- Enter a name for the agent policy in "New agent policy name". If other agent policies already exist, you can click the "Existing hosts" tab and select an existing policy instead.
For more details on Elastic Agent configuration settings, refer to the [helper guide](https://www.elastic.co/guide/en/fleet/current/agent-policy.html).
- Click "Save and Continue".
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
"""
severity = "high"
tags = [
"Domain: Endpoint",
"OS: macOS",
"Use Case: Threat Detection",
"Tactic: Privilege Escalation",
"Use Case: Vulnerability",
"Data Source: Elastic Defend",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "macos" and event.type in ("start", "process_started") and
process.parent.name like "com.adobe.ARMDC.SMJobBlessHelper" and
user.name == "root" and
not process.executable like ("/Library/PrivilegedHelperTools/com.adobe.ARMDC.SMJobBlessHelper",
"/usr/bin/codesign",
"/private/var/folders/zz/*/T/download/ARMDCHammer",
"/usr/sbin/pkgutil",
"/usr/bin/shasum",
"/usr/bin/perl*",
"/usr/sbin/spctl",
"/usr/sbin/installer",
"/usr/bin/csrutil")
'''
note = """## Triage and analysis
> **Disclaimer**:
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
### Investigating Suspicious Child Process of Adobe Acrobat Reader Update Service
Adobe Acrobat Reader's update service on macOS uses a privileged helper tool to manage updates, running with elevated permissions. Adversaries may exploit vulnerabilities in this service to escalate privileges by spawning unauthorized child processes. The detection rule identifies such anomalies by monitoring for unexpected child processes initiated by the update service, especially those not matching known legitimate executables, thus flagging potential exploitation attempts.
### Possible investigation steps
- Review the alert details to confirm the parent process is com.adobe.ARMDC.SMJobBlessHelper and the user is root, as these are key indicators of potential exploitation.
- Identify the child process executable that triggered the alert and determine if it is known or expected in the context of Adobe Acrobat Reader updates.
- Check the system for any recent updates or patches related to Adobe Acrobat Reader to ensure they are up to date, particularly concerning CVE-2020-9615, CVE-2020-9614, and CVE-2020-9613.
- Investigate the process tree to understand the sequence of events leading to the suspicious child process, looking for any unusual or unauthorized activities.
- Examine system logs and other security tools for additional indicators of compromise or related suspicious activities around the time of the alert.
- Assess the system for any signs of privilege escalation or unauthorized access, focusing on changes made by the suspicious process.
### False positive analysis
- Legitimate software updates or installations may trigger the rule if they spawn child processes not listed in the known legitimate executables. Users can mitigate this by monitoring update schedules and temporarily excluding these processes during known update windows.
- Custom scripts or administrative tools executed by system administrators with root privileges might be flagged. To handle this, users can create exceptions for these specific scripts or tools if they are verified as safe and necessary for operations.
- Security or system management tools that perform integrity checks or system modifications could be misidentified as suspicious. Users should review these tools and, if deemed safe, add them to the exclusion list to prevent false alerts.
- Development or testing environments where new or experimental software is frequently run may generate false positives. In such cases, users can establish a separate monitoring profile with adjusted rules to accommodate the unique activities of these environments.
### Response and remediation
- Immediately isolate the affected macOS system from the network to prevent further unauthorized access or lateral movement by the adversary.
- Terminate any suspicious child processes identified by the detection rule that do not match known legitimate executables, ensuring that no unauthorized processes are running.
- Conduct a thorough review of system logs and process execution history to identify any additional indicators of compromise or unauthorized changes made by the suspicious process.
- Apply the latest security patches and updates to Adobe Acrobat Reader and the macOS system to address vulnerabilities CVE-2020-9615, CVE-2020-9614, and CVE-2020-9613, ensuring the system is not susceptible to known exploits.
- Restore any affected files or system configurations from a known good backup to ensure system integrity and remove any potential backdoors or malicious modifications.
- Enhance monitoring and logging on the affected system to detect any future unauthorized process executions or privilege escalation attempts, ensuring quick detection and response.
- Report the incident to the appropriate internal security team or external authorities if required, providing detailed information about the threat and actions taken for further investigation and compliance."""
[[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.tactic]
id = "TA0004"
name = "Privilege Escalation"
reference = "https://attack.mitre.org/tactics/TA0004/"
Stages and Predicates
Stage 1: process
process where host.os.type == "macos" and event.type in ("start", "process_started") and
process.parent.name like "com.adobe.ARMDC.SMJobBlessHelper" and
user.name == "root" and
not process.executable like ("/Library/PrivilegedHelperTools/com.adobe.ARMDC.SMJobBlessHelper",
"/usr/bin/codesign",
"/private/var/folders/zz/*/T/download/ARMDCHammer",
"/usr/sbin/pkgutil",
"/usr/bin/shasum",
"/usr/bin/perl*",
"/usr/sbin/spctl",
"/usr/sbin/installer",
"/usr/bin/csrutil")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | in |
| field:"event.type" kind:in |
process.parent.name | wildcard |
| field:"parent_process_basename" kind:wildcard value:"com.adobe.ARMDC.SMJobBlessHelper" |
user.name | eq |
| field:"user" kind:eq value:"root" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
process.executable | wildcard | /Library/PrivilegedHelperTools/com.adobe.ARMDC.SMJobBlessHelper, /usr/bin/codesign, /private/var/folders/zz/*/T/download/ARMDCHammer, /usr/sbin/pkgutil, /usr/bin/shasum, /usr/bin/perl*, /usr/sbin/spctl, /usr/sbin/installer, /usr/bin/csrutil | excludes:process.executable |
Suspicious Control Panel DLL Loaded by Explorer
#Identifies DLL load of an unsigned or untrusted Control Panel Item by the Explorer process. Adversaries may load a malicious DLL when Control Panel is executed via setting the CPLs subkey to the payload path.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[rule]
description = """
Identifies DLL load of an unsigned or untrusted Control Panel Item by the Explorer process. Adversaries may load a
malicious DLL when Control Panel is executed via setting the CPLs subkey to the payload path.
"""
id = "1dbf6ac3-540a-4214-8173-9aa93232da38"
license = "Elastic License v2"
name = "Suspicious Control Panel DLL Loaded by Explorer"
os_list = ["windows"]
reference = [
"https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/hh127454(v=vs.85)",
"https://www.elastic.co/security-labs/Hunting-for-Suspicious-Windows-Libraries-for-Execution-and-Evasion",
]
version = "1.0.28"
query = '''
sequence with maxspan = 5s
[library where process.name : "explorer.exe" and
(dll.code_signature.trusted == false or dll.code_signature.exists == false) and
(dll.Ext.relative_file_creation_time <= 500 or dll.Ext.relative_file_name_modify_time <= 500) and
not dll.path :
("?:\\Program Files\\*",
"?:\\Program Files (x86)\\*",
"?:\\Windows\\System32\\*",
"?:\\Windows\\SysWOW64\\*",
"?:\\Windows\\assembly\\*",
"?:\\Windows\\WinSxS\\*",
"?:\\Windows\\Microsoft.NET\\assembly\\*",
"?:\\ProgramData\\RICOH_DRV\\*",
"?:\\ProgramData\\EPSON\\*",
"?:\\ProgramData\\Seagull\\Drivers\\*") and
not dll.hash.sha256 : "35fb376fac5bbd83843958df8c3bf941681db116f1f500396ce813efd13d76b0" and
not (dll.pe.imphash : "d41d8cd98f00b204e9800998ecf8427e" and
dll.path : ("?:\\ProgramData\\Seagull\\Drivers\\Temp\\*.tmp",
"?:\\Users\\*\\AppData\\Local\\Temp\\ptx*.tmp",
"?:\\Users\\*\\Temp\\ptx*.tmp"))
] by process.entity_id
[process where event.action == "start" and process.parent.name : "explorer.exe" and
/* CLSID_ControlPanelProcessExplorerHost */
process.parent.args : "/factory,{5BD95610-9434-43C2-886C-57852CC8A120}" and
/* false positives */
not (process.name : "rundll32.exe" and
process.args :
("printui.dll,PrintUIEntryDPIAware",
"?:\\WINDOWS\\system32\\spool\\DRIVERS\\*PrintJobStatus",
"fdprint,InvokeTask")) and
not (process.name : "mmc.exe" and process.args : "?:\\windows\\system32\\devmgmt.msc") and
not process.executable : ("?:\\windows\\system32\\DevicePairingWizard.exe", "?:\\Windows\\System32\\spool\\drivers\\x64\\3\\E_YARNYWE.EXE")
] by process.parent.entity_id
'''
min_endpoint_version = "8.4.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 1
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[[threat.technique.subtechnique]]
id = "T1218.002"
name = "Control Panel"
reference = "https://attack.mitre.org/techniques/T1218/002/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "8.4.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 5s, correlated by process.entity_id, process.parent.entity_id.
Stage 1: library
[library where process.name : "explorer.exe" and
(dll.code_signature.trusted == false or dll.code_signature.exists == false) and
(dll.Ext.relative_file_creation_time <= 500 or dll.Ext.relative_file_name_modify_time <= 500) and
not dll.path :
("?:\\Program Files\\*",
"?:\\Program Files (x86)\\*",
"?:\\Windows\\System32\\*",
"?:\\Windows\\SysWOW64\\*",
"?:\\Windows\\assembly\\*",
"?:\\Windows\\WinSxS\\*",
"?:\\Windows\\Microsoft.NET\\assembly\\*",
"?:\\ProgramData\\RICOH_DRV\\*",
"?:\\ProgramData\\EPSON\\*",
"?:\\ProgramData\\Seagull\\Drivers\\*") and
not dll.hash.sha256 : "35fb376fac5bbd83843958df8c3bf941681db116f1f500396ce813efd13d76b0" and
not (dll.pe.imphash : "d41d8cd98f00b204e9800998ecf8427e" and
dll.path : ("?:\\ProgramData\\Seagull\\Drivers\\Temp\\*.tmp",
"?:\\Users\\*\\AppData\\Local\\Temp\\ptx*.tmp",
"?:\\Users\\*\\Temp\\ptx*.tmp"))
] by process.entity_id
Stage 2: process
[process where event.action == "start" and process.parent.name : "explorer.exe" and
process.parent.args : "/factory,{5BD95610-9434-43C2-886C-57852CC8A120}" and
not (process.name : "rundll32.exe" and
process.args :
("printui.dll,PrintUIEntryDPIAware",
"?:\\WINDOWS\\system32\\spool\\DRIVERS\\*PrintJobStatus",
"fdprint,InvokeTask")) and
not (process.name : "mmc.exe" and process.args : "?:\\windows\\system32\\devmgmt.msc") and
not process.executable : ("?:\\windows\\system32\\DevicePairingWizard.exe", "?:\\Windows\\System32\\spool\\drivers\\x64\\3\\E_YARNYWE.EXE")
] by process.parent.entity_id
Indicators
These rows show field, operator, and value matches.
Exclusions
The rule actively suppresses these predicates.
Suspicious Elevated Command Execution
#Detects potential malicious elevated command executions on macOS by monitoring processes spawned by authtrampoline, which handles macOS privilege escalation. It flags processes with untrusted or missing code signatures, commonly abused process names like osascript, curl, and dscl, as well as shell executions with suspicious arguments. The aim is to swiftly identify and respond to abnormal elevated activities on a macOS system.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Telemetry Coverage
Rule Body
[rule]
description = """
Detects potential malicious elevated command executions on macOS by monitoring processes spawned by authtrampoline,
which handles macOS privilege escalation. It flags processes with untrusted or missing code signatures, commonly abused
process names like osascript, curl, and dscl, as well as shell executions with suspicious arguments. The aim is to
swiftly identify and respond to abnormal elevated activities on a macOS system.
"""
id = "2f7b4008-99c6-46e9-9d93-97a4b801ac91"
license = "Elastic License v2"
name = "Suspicious Elevated Command Execution"
os_list = ["macos"]
version = "1.0.8"
query = '''
process where event.type == "start" and event.action == "exec" and
process.parent.name == "authtrampoline" and
(
((process.code_signature.trusted == false or process.code_signature.exists == false) and not process.executable like~ ("/opt/homebrew/*", "/usr/local/Cellar/*")) or
(process.name like~ ("osascript", "curl", "nscurl", "dscl", ".*")) or
(process.name in ("sh", "bash", "zsh") and process.args == "-c" and
process.args like~ ("dscl*", "curl*", "nscurl*", "osascript*", "/tmp/*", "/private/tmp/*", "/var/tmp/*"))
)
'''
min_endpoint_version = "8.5.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[internal]
min_endpoint_version = "8.5.0"
Stages and Predicates
Stage 1: process
process where event.type == "start" and event.action == "exec" and
process.parent.name == "authtrampoline" and
(
((process.code_signature.trusted == false or process.code_signature.exists == false) and not process.executable like~ ("/opt/homebrew/*", "/usr/local/Cellar/*")) or
(process.name like~ ("osascript", "curl", "nscurl", "dscl", ".*")) or
(process.name in ("sh", "bash", "zsh") and process.args == "-c" and
process.args like~ ("dscl*", "curl*", "nscurl*", "osascript*", "/tmp/*", "/private/tmp/*", "/var/tmp/*"))
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"exec" |
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | eq |
| field:"process.args" kind:eq value:"-c" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.code_signature.exists | eq |
| field:"process.code_signature.exists" kind:eq value:"false" |
process.code_signature.trusted | eq |
| field:"process.code_signature.trusted" kind:eq value:"false" |
process.name | in |
| field:"process_basename" kind:in |
process.name | wildcard |
| field:"process_basename" kind:wildcard |
process.parent.name | eq |
| field:"parent_process_basename" kind:eq value:"authtrampoline" |
Suspicious Microsoft Diagnostics Wizard Execution
#Identifies potential abuse of the Microsoft Diagnostics Troubleshooting Wizard (MSDT) to proxy malicious command or binary execution via malicious process arguments.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
[metadata]
creation_date = "2022/05/31"
integration = ["endpoint", "windows", "m365_defender", "crowdstrike", "sentinel_one_cloud_funnel"]
maturity = "production"
updated_date = "2026/04/30"
[rule]
author = ["Elastic"]
description = """
Identifies potential abuse of the Microsoft Diagnostics Troubleshooting Wizard (MSDT) to proxy malicious command or
binary execution via malicious process arguments.
"""
from = "now-9m"
index = [
"logs-endpoint.events.process-*",
"winlogbeat-*",
"logs-windows.sysmon_operational-*",
"endgame-*",
"logs-m365_defender.event-*",
"logs-crowdstrike.fdr*",
"logs-sentinel_one_cloud_funnel.*",
]
language = "eql"
license = "Elastic License v2"
name = "Suspicious Microsoft Diagnostics Wizard Execution"
references = [
"https://twitter.com/nao_sec/status/1530196847679401984",
"https://lolbas-project.github.io/lolbas/Binaries/Msdt/",
]
risk_score = 73
rule_id = "2c3c29a4-f170-42f8-a3d8-2ceebc18eb6a"
severity = "high"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Defense Evasion",
"Data Source: Elastic Endgame",
"Data Source: Elastic Defend",
"Data Source: Microsoft Defender XDR",
"Data Source: Sysmon",
"Data Source: Crowdstrike",
"Data Source: SentinelOne",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
process where host.os.type == "windows" and event.type == "start" and
(?process.pe.original_file_name == "msdt.exe" or process.name : "msdt.exe") and
(
process.args : ("IT_RebrowseForFile=*", "*FromBase64*", "*/../../../*", "IT_BrowseForFile=*") or
(
process.args : ("-af", "/af") and process.args : "/skip" and
process.parent.name : ("explorer.exe", "cmd.exe", "powershell.exe", "cscript.exe", "wscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe") and
process.args : ("?:\\WINDOWS\\diagnostics\\index\\PCWDiagnostic.xml", "PCWDiagnostic.xml", "?:\\Users\\Public\\*", "?:\\Windows\\Temp\\*")
) or
(process.pe.original_file_name == "msdt.exe" and not process.name : "msdt.exe" and process.name != null) or
(
?process.pe.original_file_name == "msdt.exe" and
not process.executable : (
"?:\\Windows\\system32\\msdt.exe",
"?:\\Windows\\SysWOW64\\msdt.exe",
/* Crowdstrike specific exclusion as it uses NT Object paths */
"\\Device\\HarddiskVolume*\\Windows\\system32\\msdt.exe",
"\\Device\\HarddiskVolume*\\Windows\\SysWOW64\\msdt.exe"
)
)
)
'''
note = """## Triage and analysis
### Investigating Suspicious Microsoft Diagnostics Wizard Execution
#### Possible investigation steps
- Does the alert show MSDT proxy-execution behavior or a bounded diagnostic launch?
- Why: MSDT abuse depends on PCWDiagnostic answer files, rebrowse or browse-file parameters, traversal, or encoded input, not on "msdt.exe" alone.
- Focus: `process.command_line` and `process.args`, classifying answer-file use, rebrowse or browse-file parameters, encoded input, traversal, and package location.
- Implication: escalate when arguments point to attacker-controlled content, encoded or traversal input, or user-writable answer files; lower concern only when they resolve to a recognized local diagnostic pack with no external, encoded, traversal, or user-writable references.
- Do binary identity and launcher lineage fit a legitimate diagnostic launch?
- Focus: `process.executable`, `process.pe.original_file_name`, `process.code_signature.trusted`, `process.parent.executable`, and `process.parent.command_line`.
- Implication: escalate when MSDT is renamed, relocated, unsigned or untrusted, or launched by Office, a browser, script host, "mshta.exe", "rundll32.exe", "regsvr32.exe", or a shell using profile or temp content; lower concern when a trusted Windows MSDT path and signed helpdesk, OEM, or management parent launch the same diagnostic pack.
- Did MSDT or a diagnostic-host child launch another binary or script?
- Focus: child process events where `process.parent.entity_id` matches alert `process.entity_id`; record child `process.entity_id`, `process.executable`, `process.command_line`, and `process.code_signature.trusted`. $investigate_0
- Hint: if the first child is a signed diagnostic host, inspect that child's descendants before treating the chain as contained.
- Implication: escalate when MSDT or its diagnostic-host child launches shells, script interpreters, "mshta.exe", "regsvr32.exe", "rundll32.exe", unsigned payloads, or content from user-writable paths; lower concern when the child chain stays inside expected Microsoft or OEM diagnostic components.
- Do file events show package staging or later execution?
- Focus: if file telemetry exists, pivot with `host.id` plus alert `process.entity_id`, parent `process.parent.entity_id`, direct-child parent linkage, and exact referenced paths when present; otherwise use `host.id`, `process.pid`, and alert-time window for referenced path, provenance, write timing, and later execution. Missing file telemetry is unresolved, not benign. $investigate_1
- Implication: escalate when the package appears in Public, Temp, profile, share, or newly written staging paths, carries web or archive provenance, or later executes; lower concern only when artifact evidence stays bound to the same recognized diagnostic package.
- If remote delivery is suggested, do optional network events show retrieval or external control?
- Focus: when network telemetry exists, query with `host.id` plus alert `process.entity_id` or alert-backed `process.parent.entity_id`, separating DNS from connections. Review child-process network activity from recovered child results. Missing network telemetry is unresolved, not benign. $investigate_2
- Implication: escalate when the parent, MSDT, or child chain retrieves remote HTML/package content or contacts unrelated infrastructure; lower concern only when available network evidence stays local or vendor-aligned with the same diagnostic package.
- If local evidence is suspicious or unresolved, does related alert history broaden scope?
- Focus: compare related alerts for `user.id` and `host.id` over 48 hours for recurring MSDT command patterns, parent launchers, package paths, child payloads, or remote indicators. $investigate_3 $investigate_4
- Implication: broaden scope when the same proxy-execution pattern appears across unrelated hosts or users; keep response local only when current process, file, child, and network evidence bind one recognized diagnostic workflow.
- What disposition is supported?
- Weigh command-line intent, image identity, parent lineage, package evidence, child or descendant processes, and file or network corroboration; escalate proxy execution or payload delivery, close only when evidence binds one recognized diagnostic workflow, and preserve artifacts when evidence is mixed or incomplete.
### False positive analysis
- Helpdesk, OEM troubleshooting, software deployment, or validation can trigger this rule when a signed support or management parent starts Microsoft-signed MSDT from a standard Windows path, uses the same controlled local diagnostic pack, and produces the same child-process set. Close only when parent path and command line, MSDT path and signature, command line, package path, child behavior, `user.id`, and `host.id` align in the current case; records can corroborate but not replace telemetry.
- Do not create exceptions on `process.name`, `process.pe.original_file_name`, or Microsoft signature alone.
### Response and remediation
- If confirmed benign:
- Reverse temporary containment and document the process, parent, package, and child-process evidence. Build exceptions only from the confirmed parent path plus command-line/package pattern plus `host.id` or `user.id`, not from "msdt.exe" alone.
- If suspicious but unconfirmed:
- Preserve the alert, MSDT `process.entity_id`, `process.pid`, `process.command_line`, `process.args`, parent evidence, package path, child identifiers, suspicious package copies, and remote indicators.
- Apply reversible containment for the affected `host.id` and `user.id`, such as temporary network restrictions, heightened monitoring, or child-process blocking. Isolate only for spawned payload behavior or high host criticality.
- If confirmed malicious:
- Isolate the host or escalate after preserving the MSDT and child identifiers, package paths, payload paths, command lines, and remote indicators.
- Terminate MSDT, diagnostic-host, and payload processes only after recording identifiers; block malicious child binaries, package paths, domains, and IP indicators.
- Remove malicious ".xml", ".msi", ".diagcab", remote package, or payload artifacts, then remediate the parent document, browser, script, or management path.
- Post-incident hardening:
- Restrict MSDT where business use no longer requires it, verify Follina-era mitigations, and retain process, file, and network telemetry for MSDT, parents, and children.
"""
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)
"""
[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.args",
"process.pe.original_file_name",
"process.code_signature.trusted",
"process.parent.entity_id",
"process.parent.executable",
"process.parent.command_line",
]
[transform]
[[transform.investigate]]
label = "Child process events for the same MSDT instance"
description = ""
providers = [
[
{ excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
]
]
relativeFrom = "now-1h"
relativeTo = "now"
[[transform.investigate]]
label = "File events for parent and child processes"
description = ""
providers = [
[
{ excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
],
[
{ excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.parent.entity_id}}", valueType = "string" }
],
[
{ excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
]
]
relativeFrom = "now-1h"
relativeTo = "now"
[[transform.investigate]]
label = "Network and DNS events for MSDT or its parent"
description = ""
providers = [
[
{ excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
],
[
{ excluded = false, field = "event.category", queryType = "phrase", value = "dns", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.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.parent.entity_id}}", valueType = "string" }
],
[
{ excluded = false, field = "event.category", queryType = "phrase", value = "dns", valueType = "string" },
{ excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
{ excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.parent.entity_id}}", 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 = "T1036"
name = "Masquerading"
reference = "https://attack.mitre.org/techniques/T1036/"
[[rule.threat.technique.subtechnique]]
id = "T1036.003"
name = "Rename Legitimate Utilities"
reference = "https://attack.mitre.org/techniques/T1036/003/"
[[rule.threat.technique]]
id = "T1218"
name = "System Binary Proxy Execution"
reference = "https://attack.mitre.org/techniques/T1218/"
[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.pe.original_file_name == "msdt.exe" or process.name : "msdt.exe") and
(
process.args : ("IT_RebrowseForFile=*", "*FromBase64*", "*/../../../*", "IT_BrowseForFile=*") or
(
process.args : ("-af", "/af") and process.args : "/skip" and
process.parent.name : ("explorer.exe", "cmd.exe", "powershell.exe", "cscript.exe", "wscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe") and
process.args : ("?:\\WINDOWS\\diagnostics\\index\\PCWDiagnostic.xml", "PCWDiagnostic.xml", "?:\\Users\\Public\\*", "?:\\Windows\\Temp\\*")
) or
(process.pe.original_file_name == "msdt.exe" and not process.name : "msdt.exe" and process.name != null) or
(
?process.pe.original_file_name == "msdt.exe" and
not process.executable : (
"?:\\Windows\\system32\\msdt.exe",
"?:\\Windows\\SysWOW64\\msdt.exe",
"\\Device\\HarddiskVolume*\\Windows\\system32\\msdt.exe",
"\\Device\\HarddiskVolume*\\Windows\\SysWOW64\\msdt.exe"
)
)
)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.type | eq |
| field:"event.type" kind:eq value:"start" |
process.args | wildcard |
| field:"process.args" kind:wildcard |
process.name | is_not_null | field:"process_basename" kind:is_not_null | |
process.name | wildcard |
| field:"process_basename" kind:wildcard value:"msdt.exe" |
process.parent.name | wildcard |
| field:"parent_process_basename" kind:wildcard |
process.pe.original_file_name | eq |
| field:"OriginalFileName" kind:eq value:"msdt.exe" |
Suspicious PowerShell Console History Deletion
#Identifies when a process attempts to delete PowerShell Console History. An adversary may clear the command history of a compromised account to conceal the actions undertaken during an intrusion.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Rule Body
[rule]
description = """
Identifies when a process attempts to delete PowerShell Console History. An adversary may clear the command history of a
compromised account to conceal the actions undertaken during an intrusion.
"""
id = "feb6d562-7c15-412a-8be1-48d93f382028"
license = "Elastic License v2"
name = "Suspicious PowerShell Console History Deletion"
os_list = ["windows"]
reference = ["https://attack.mitre.org/techniques/T1070/004/"]
version = "1.0.10"
query = '''
sequence by process.entity_id with maxspan=5m
[process where event.action == "start" and
(
process.name in~ ("powershell.exe", "rundll32.exe", "regsvr32.exe", "cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe",
"winword.exe", "excel.exe") or
process.executable : ("?:\\Users\\*", "?:\\Windows\\Temp\\*", "?:\\ProgramData\\*", "?:\\Windows\\Microsoft.NEt\\*") or
(process.code_signature.trusted == false or process.code_signature.exists == false)
) and
not user.id in ("S-1-5-18", "S-1-5-19")
]
[file where event.action == "deletion" and file.name : "ConsoleHost_history.txt"]
'''
min_endpoint_version = "7.16.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1070"
name = "Indicator Removal"
reference = "https://attack.mitre.org/techniques/T1070/"
[[threat.technique.subtechnique]]
id = "T1070.003"
name = "Clear Command History"
reference = "https://attack.mitre.org/techniques/T1070/003/"
[[threat.technique.subtechnique]]
id = "T1070.004"
name = "File Deletion"
reference = "https://attack.mitre.org/techniques/T1070/004/"
[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"
[internal]
min_endpoint_version = "7.16.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 5m, correlated by process.entity_id.
Stage 1: process
[process where event.action == "start" and
(
process.name in~ ("powershell.exe", "rundll32.exe", "regsvr32.exe", "cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe",
"winword.exe", "excel.exe") or
process.executable : ("?:\\Users\\*", "?:\\Windows\\Temp\\*", "?:\\ProgramData\\*", "?:\\Windows\\Microsoft.NEt\\*") or
(process.code_signature.trusted == false or process.code_signature.exists == false)
) and
not user.id in ("S-1-5-18", "S-1-5-19")
]
Stage 2: file
[file where event.action == "deletion" and file.name : "ConsoleHost_history.txt"]
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq |
file.name | wildcard |
| field:"file.name" kind:wildcard value:"ConsoleHost_history.txt" |
process.code_signature.exists | eq |
| field:"process.code_signature.exists" kind:eq value:"false" |
process.code_signature.trusted | eq |
| field:"process.code_signature.trusted" kind:eq value:"false" |
process.executable | wildcard |
| field:"Image" kind:wildcard |
process.name | in |
| field:"process_basename" kind:in |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
user.id | in | S-1-5-18, S-1-5-19 | excludes:user.id field:"user.id" value:"S-1-5-18" field:"user.id" value:"S-1-5-19" |