diff --git a/rules/cross-platform/execution_azure_run_command_script_child_process.toml b/rules/cross-platform/execution_azure_run_command_script_child_process.toml new file mode 100644 index 00000000000..5adaeeb0b3c --- /dev/null +++ b/rules/cross-platform/execution_azure_run_command_script_child_process.toml @@ -0,0 +1,112 @@ +[metadata] +creation_date = "2026/05/20" +integration = ["endpoint", "windows"] +maturity = "production" +updated_date = "2026/05/20" + +[rule] +author = ["Elastic"] +description = """ +Identifies process start events whose parent matches Azure Virtual Machine Run Command execution patterns on Windows +or Linux. On Windows, Run Command often launches PowerShell with `-ExecutionPolicy Unrestricted` and a `script?.ps1` +file; on Linux, the Azure Linux Agent (waagent) runs downloaded script.sh under "/var/lib/waagent/run-command/". +Child process telemetry exposes the on-guest payload that cloud activity logs do not fully describe. +""" +false_positives = [ + """ + Legitimate configuration management, extension deployment, or automation that uses Azure Run Command with the same + PowerShell or shell script paths may match. Baseline approved VM names, script naming, and deployment windows + before tuning. + """, +] +from = "now-9m" +index = [ + "logs-endpoint.events.process*", + "logs-windows.sysmon_operational-*" +] +language = "eql" +license = "Elastic License v2" +name = "Azure Run Command Script Child Process" +note = """## Triage and analysis + +### Investigating Azure Run Command Script Child Process + +Azure VM Run Command executes scripts on guests without interactive RDP or SSH. On Windows, a parent PowerShell +process with `-ExecutionPolicy Unrestricted -File script?.ps1` often precedes child utilities; on Linux, `waagent` +invokes `/var/lib/waagent/run-command/download/*/script.sh` via `bash`, `sh`, or `dash`. + +Correlate with `logs-azure.activitylogs-*` for `MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION` when available. + +### Possible investigation steps + +- Review `process.command_line`, `process.name`, and `process.parent.command_line` or `process.parent.args`. +- Confirm whether the host is an Azure VM and whether Run Command was expected for that asset. +- Pivot on `host.name` or `host.id` for other suspicious process or network activity in the same window. + +### False positive analysis + +- Extension handlers, guest configuration, and patch orchestration may use the same parent patterns. +- Exclude known automation hosts or script paths after validating with platform teams. + +### Response and remediation + +- If unauthorized, review Azure RBAC on the VM and subscription, revoke compromised credentials, and isolate the guest. +- Collect endpoint artifacts and Azure activity logs for incident reporting. +""" +references = ["https://docs.microsoft.com/en-us/azure/virtual-machines/run-command"] +risk_score = 47 +rule_id = "cb9554e8-9f31-41a8-b4f5-d82144e6dc33" +severity = "medium" +tags = [ + "Domain: Cloud", + "Domain: Endpoint", + "OS: Linux", + "OS: Windows", + "Use Case: Threat Detection", + "Tactic: Execution", + "Data Source: Elastic Defend", + "Data Source: Sysmon", + "Data Source: Azure", + "Resources: Investigation Guide", +] +timestamp_override = "event.ingested" +type = "eql" + +query = ''' +process where event.type in ("start", "process_started") and + ( + (process.parent.name == "powershell.exe" and + process.parent.command_line like "powershell -ExecutionPolicy Unrestricted -File script?.ps1") or + (process.parent.name in ("dash", "bash", "sh", "zsh") and + process.parent.args like "/var/lib/waagent/run-command/download/*/script.sh") + ) +''' + + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1059" +name = "Command and Scripting Interpreter" +reference = "https://attack.mitre.org/techniques/T1059/" + +[[rule.threat.technique.subtechnique]] +id = "T1059.001" +name = "PowerShell" +reference = "https://attack.mitre.org/techniques/T1059/001/" + +[[rule.threat.technique.subtechnique]] +id = "T1059.004" +name = "Unix Shell" +reference = "https://attack.mitre.org/techniques/T1059/004/" + +[[rule.threat.technique]] +id = "T1651" +name = "Cloud Administration Command" +reference = "https://attack.mitre.org/techniques/T1651/" + +[rule.threat.tactic] +id = "TA0002" +name = "Execution" +reference = "https://attack.mitre.org/tactics/TA0002/" diff --git a/rules/cross-platform/execution_azure_vm_run_command_powershell_unrestricted_script.toml b/rules/cross-platform/execution_azure_vm_run_command_powershell_unrestricted_script.toml new file mode 100644 index 00000000000..51f1ff2c38c --- /dev/null +++ b/rules/cross-platform/execution_azure_vm_run_command_powershell_unrestricted_script.toml @@ -0,0 +1,152 @@ +[metadata] +creation_date = "2026/05/20" +integration = ["azure", "endpoint"] +maturity = "production" +updated_date = "2026/05/20" + +[rule] +author = ["Elastic"] +description = """ +Correlates successful Azure Virtual Machine Run Command operations with endpoint process execution on the same host +within minutes. Adversaries abuse Run Command to run scripts remotely as SYSTEM or root while activity logs only record the +control-plane action; Elastic Defend process telemetry reveals the on-guest payload. +""" +false_positives = [ + """ + Legitimate automation that deploys configuration via Azure Run Command and launches PowerShell with unrestricted + policy and numbered script files (for example `script1.ps1`) may match. Baseline known deployment pipelines, VM + names, and principal IDs before tuning. + """, +] +from = "now-9m" +language = "esql" +license = "Elastic License v2" +name = "Azure Run Command Correlated with Process Execution" +note = """## Triage and analysis + +### Investigating Azure Run Command Correlated with Process Execution + +This ES|QL rule correlates Azure Activity Log `MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION` events with +endpoint process starts, joined on host name within a two-minute bucket and a 0–120 second delay between Run Command and process start. + +Pivot into raw `logs-azure.activitylogs-*` and `logs-endpoint.events.process-*` events for full command lines and +resource identifiers. + +### Possible investigation steps + +- Review `user.email` and `azure.activitylogs.identity.authorization.evidence.principal_id` for who invoked Run Command. +- Inspect `Esql.process_command_line_values` for script paths and arguments beyond the matched pattern. +- Confirm `Esql.host_name` maps to the intended VM and whether Run Command timing aligns with change windows. +- Hunt for additional Run Command or PowerShell activity from the same principal or subscription. + +### Response and remediation + +- If unauthorized, isolate the VM, revoke credentials used for Run Command, and review role assignments on the VM and + subscription. +- Collect endpoint artifacts and Azure activity logs for incident reporting. +""" +references = [ + "https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#virtual-machine-contributor", + "https://posts.specterops.io/attacking-azure-azure-ad-and-introducing-powerzure-ca70b330511a", + "https://adsecurity.org/?p=4277", +] +risk_score = 47 +rule_id = "ebbc1959-3309-4abf-b6cb-2bee3dbc9a7b" +severity = "medium" +tags = [ + "Domain: Cloud", + "Domain: Endpoint", + "OS: Windows", + "OS: Linux", + "Use Case: Threat Detection", + "Tactic: Execution", + "Data Source: Azure", + "Data Source: Microsoft Azure", + "Data Source: Azure Activity Logs", + "Data Source: Elastic Defend", + "Resources: Investigation Guide", +] +timestamp_override = "event.ingested" +type = "esql" + +query = ''' +FROM logs-azure.activitylogs-*, logs-endpoint.events.process-* METADATA _id, _version, _index +| WHERE + ( + event.category == "process" AND KQL("event.action:start") + AND process.parent.name == "powershell.exe" + AND process.parent.command_line LIKE "powershell -ExecutionPolicy Unrestricted -File script?.ps1" + AND process.name != "conhost.exe" + ) OR + ( + KQL("event.category:process and event.action:exec and process.parent.name:(dash or bash or sh) and process.parent.args:/var/lib/waagent/run-command/download/*/script.sh") + ) OR + ( + event.module == "azure" + AND event.action == "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION" + AND NOT KQL("event.outcome:failure") + ) + +// Azure hostname comes as upper-case while Endpoint event comes as lowercase +| EVAL Esql.host_name = COALESCE( + TO_LOWER(host.name), + TO_LOWER(azure.resource.name) + ) +| EVAL ts_runcommand = CASE(event.module == "azure", @timestamp, null) +| EVAL ts_endpoint = CASE(event.category == "process", @timestamp, null) +| EVAL is_runcommand = CASE(event.module == "azure", 1, null) +| EVAL is_endpoint = CASE(event.category == "process", 1, null) +| EVAL Esql.time_bucket = DATE_TRUNC(2 minutes, @timestamp) +| STATS + runcommand_count = COUNT(is_runcommand), + endpoint_count = COUNT(is_endpoint), + user.email = VALUES(user.email), + azure.activitylogs.identity.authorization.evidence.principal_id = VALUES(azure.activitylogs.identity.authorization.evidence.principal_id), + azure.activitylogs.tenant_id = VALUES(azure.activitylogs.tenant_id), + azure.subscription_id = VALUES(azure.subscription_id), + source.ip = VALUES(source.ip), + source.geo.country_name = VALUES(source.geo.country_name), + source.as.number = VALUES(source.as.number), + Esql.process_command_line_values = VALUES(process.command_line), + first_runcommand = MIN(ts_runcommand), + first_ps_exec = MIN(ts_endpoint), + outcome = VALUES(event.outcome) + BY Esql.host_name, Esql.time_bucket +| WHERE runcommand_count >= 1 AND endpoint_count >= 1 +| EVAL delta_ms = TO_LONG(first_ps_exec) - TO_LONG(first_runcommand) +| EVAL delta_sec = delta_ms / 1000 +| WHERE delta_sec >= 0 AND delta_sec <= 120 +| KEEP + user.email, + azure.activitylogs.identity.authorization.evidence.principal_id, + source.ip, + source.as.number, + source.geo.country_name, + azure.activitylogs.tenant_id, + azure.subscription_id, + Esql.* +''' + + +[[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.technique]] +id = "T1651" +name = "Cloud Administration Command" +reference = "https://attack.mitre.org/techniques/T1651/" + +[rule.threat.tactic] +id = "TA0002" +name = "Execution" +reference = "https://attack.mitre.org/tactics/TA0002/"