From 8e36767db4b9c08a6504f9184c6f7db23e57b83d Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Wed, 20 May 2026 18:57:39 +0100 Subject: [PATCH 1/5] [New] Azure Run Command Correlated with Process Execution Correlates successful Azure Virtual Machine Run Command operations with endpoint PowerShell execution on the same host within two minutes. Adversaries abuse Run Command to run scripts remotely as SYSTEM while activity logs only record the control-plane action; Elastic Defend process telemetry reveals the on-guest payload. --- ...ommand_powershell_unrestricted_script.toml | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 rules/cross-platform/execution_azure_vm_run_command_powershell_unrestricted_script.toml 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..01ccdbf53f6 --- /dev/null +++ b/rules/cross-platform/execution_azure_vm_run_command_powershell_unrestricted_script.toml @@ -0,0 +1,153 @@ +[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 PowerShell execution on the same host +within two minutes. Adversaries abuse Run Command to run scripts remotely as SYSTEM 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 where PowerShell runs `-ExecutionPolicy Unrestricted -File script?.ps1` (or a child of that +parent), 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", + "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.type:start") + AND process.name == "powershell.exe" + AND process.command_line LIKE "powershell -ExecutionPolicy Unrestricted -File script?.ps1" + ) OR + ( + 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 + ( + 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/" From 59e0c1b53018481818b557a0789539d5f009bf86 Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Wed, 20 May 2026 20:10:23 +0100 Subject: [PATCH 2/5] Update execution_azure_vm_run_command_powershell_unrestricted_script.toml --- ..._vm_run_command_powershell_unrestricted_script.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 index 01ccdbf53f6..c6d1950c341 100644 --- 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 @@ -58,6 +58,7 @@ tags = [ "Domain: Cloud", "Domain: Endpoint", "OS: Windows", + "OS: Linux", "Use Case: Threat Detection", "Tactic: Execution", "Data Source: Azure", @@ -71,17 +72,16 @@ type = "esql" query = ''' FROM logs-azure.activitylogs-*, logs-endpoint.events.process-* METADATA _id, _version, _index -| WHERE ( - event.category == "process" AND KQL("event.type:start") - AND process.name == "powershell.exe" - AND process.command_line LIKE "powershell -ExecutionPolicy Unrestricted -File script?.ps1" - ) OR +| 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") + ) ( event.module == "azure" AND event.action == "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION" From 4b5f9e3ea56b6865d2d379901cbab5ed62be70f1 Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Wed, 20 May 2026 20:14:00 +0100 Subject: [PATCH 3/5] Update execution_azure_vm_run_command_powershell_unrestricted_script.toml --- ...n_azure_vm_run_command_powershell_unrestricted_script.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index c6d1950c341..570f623b767 100644 --- 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 @@ -81,12 +81,12 @@ FROM logs-azure.activitylogs-*, logs-endpoint.events.process-* METADATA _id, _ve ) 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( From 3853cf7c61990c58f54f65db52f71e8da75c5771 Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Thu, 21 May 2026 17:20:09 +0100 Subject: [PATCH 4/5] ++ --- ...zure_run_command_script_child_process.toml | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 rules/cross-platform/execution_azure_run_command_script_child_process.toml 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/" From 98fa451f525871ad497e9036f39722093ccd2656 Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Fri, 22 May 2026 12:07:28 +0100 Subject: [PATCH 5/5] Update execution_azure_vm_run_command_powershell_unrestricted_script.toml --- ...zure_vm_run_command_powershell_unrestricted_script.toml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 index 570f623b767..51f1ff2c38c 100644 --- 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 @@ -7,8 +7,8 @@ updated_date = "2026/05/20" [rule] author = ["Elastic"] description = """ -Correlates successful Azure Virtual Machine Run Command operations with endpoint PowerShell execution on the same host -within two minutes. Adversaries abuse Run Command to run scripts remotely as SYSTEM while activity logs only record the +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 = [ @@ -27,8 +27,7 @@ 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 where PowerShell runs `-ExecutionPolicy Unrestricted -File script?.ps1` (or a child of that -parent), joined on host name within a two-minute bucket and a 0–120 second delay between Run Command and process start. +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.