Azure Run Command Correlated with Process Execution
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.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/05/20"
3integration = ["azure", "endpoint"]
4maturity = "production"
5updated_date = "2026/09/18"
6
7[rule]
8author = ["Elastic"]
9description = """
10Correlates successful Azure Virtual Machine Run Command operations with endpoint process execution on the same host
11within minutes. Adversaries abuse Run Command to run scripts remotely as SYSTEM or root while activity logs only record the
12control-plane action; Elastic Defend process telemetry reveals the on-guest payload.
13"""
14false_positives = [
15 """
16 Legitimate automation that deploys configuration via Azure Run Command and launches PowerShell with unrestricted
17 policy and numbered script files (for example `script1.ps1`) may match. Baseline known deployment pipelines, VM
18 names, and principal IDs before tuning.
19 """,
20]
21from = "now-9m"
22language = "esql"
23license = "Elastic License v2"
24name = "Azure Run Command Correlated with Process Execution"
25note = """## Triage and analysis
26
27### Investigating Azure Run Command Correlated with Process Execution
28
29This ES|QL rule correlates Azure Activity Log `MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION` events with
30endpoint process starts, joined on host name within a two-minute bucket and a 0–120 second delay between Run Command and process start.
31
32Pivot into raw `logs-azure.activitylogs-*` and `logs-endpoint.events.process-*` events for full command lines and
33resource identifiers.
34
35### Possible investigation steps
36
37- Review `user.email` and `azure.activitylogs.identity.authorization.evidence.principal_id` for who invoked Run Command.
38- Inspect `Esql.process_command_line_values` for script paths and arguments beyond the matched pattern.
39- Confirm `Esql.host_name` maps to the intended VM and whether Run Command timing aligns with change windows.
40- Hunt for additional Run Command or PowerShell activity from the same principal or subscription.
41
42### Response and remediation
43
44- If unauthorized, isolate the VM, revoke credentials used for Run Command, and review role assignments on the VM and
45 subscription.
46- Collect endpoint artifacts and Azure activity logs for incident reporting.
47"""
48references = [
49 "https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#virtual-machine-contributor",
50 "https://posts.specterops.io/attacking-azure-azure-ad-and-introducing-powerzure-ca70b330511a",
51 "https://adsecurity.org/?p=4277",
52]
53risk_score = 47
54rule_id = "ebbc1959-3309-4abf-b6cb-2bee3dbc9a7b"
55severity = "medium"
56tags = [
57 "Domain: Cloud",
58 "Domain: Endpoint",
59 "OS: Windows",
60 "OS: Linux",
61 "Use Case: Threat Detection",
62 "Tactic: Execution",
63 "Data Source: Azure",
64 "Data Source: Microsoft Azure",
65 "Data Source: Azure Activity Logs",
66 "Data Source: Elastic Defend",
67 "Resources: Investigation Guide",
68 "Noise: Unknown",
69 "Performance: Normal",
70 "Threat: Cloud VM Execution",
71 "Rule Type: ES|QL",
72 "Platform: Windows",
73 "Platform: Linux",
74 "Platform: Azure",
75]
76timestamp_override = "event.ingested"
77type = "esql"
78
79query = '''
80FROM logs-azure.activitylogs-*, logs-endpoint.events.process-* METADATA _id, _version, _index
81| WHERE
82 (
83 event.category == "process" AND KQL("event.action:start")
84 AND process.parent.name == "powershell.exe"
85 AND process.parent.command_line LIKE "powershell -ExecutionPolicy Unrestricted -File script?.ps1"
86 AND process.name != "conhost.exe"
87 ) OR
88 (
89 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")
90 ) OR
91 (
92 event.module == "azure"
93 AND event.action == "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION"
94 AND NOT KQL("event.outcome:failure")
95 )
96
97// Azure hostname comes as upper-case while Endpoint event comes as lowercase
98| EVAL Esql.host_name = COALESCE(
99 TO_LOWER(host.name),
100 TO_LOWER(azure.resource.name)
101 )
102| EVAL ts_runcommand = CASE(event.module == "azure", @timestamp, null)
103| EVAL ts_endpoint = CASE(event.category == "process", @timestamp, null)
104| EVAL is_runcommand = CASE(event.module == "azure", 1, null)
105| EVAL is_endpoint = CASE(event.category == "process", 1, null)
106| EVAL Esql.time_bucket = DATE_TRUNC(2 minutes, @timestamp)
107| STATS
108 runcommand_count = COUNT(is_runcommand),
109 endpoint_count = COUNT(is_endpoint),
110 user.email = VALUES(user.email),
111 azure.activitylogs.identity.authorization.evidence.principal_id = VALUES(azure.activitylogs.identity.authorization.evidence.principal_id),
112 azure.activitylogs.tenant_id = VALUES(azure.activitylogs.tenant_id),
113 azure.subscription_id = VALUES(azure.subscription_id),
114 source.ip = VALUES(source.ip),
115 source.geo.country_name = VALUES(source.geo.country_name),
116 source.as.number = VALUES(source.as.number),
117 Esql.process_command_line_values = VALUES(process.command_line),
118 first_runcommand = MIN(ts_runcommand),
119 first_ps_exec = MIN(ts_endpoint),
120 outcome = VALUES(event.outcome)
121 BY Esql.host_name, Esql.time_bucket
122| WHERE runcommand_count >= 1 AND endpoint_count >= 1
123| EVAL delta_ms = TO_LONG(first_ps_exec) - TO_LONG(first_runcommand)
124| EVAL delta_sec = delta_ms / 1000
125| WHERE delta_sec >= 0 AND delta_sec <= 120
126| KEEP
127 user.email,
128 azure.activitylogs.identity.authorization.evidence.principal_id,
129 source.ip,
130 source.as.number,
131 source.geo.country_name,
132 azure.activitylogs.tenant_id,
133 azure.subscription_id,
134 Esql.*
135'''
136
137
138[[rule.threat]]
139framework = "MITRE ATT&CK"
140
141[[rule.threat.technique]]
142id = "T1059"
143name = "Command and Scripting Interpreter"
144reference = "https://attack.mitre.org/techniques/T1059/"
145
146[[rule.threat.technique.subtechnique]]
147id = "T1059.001"
148name = "PowerShell"
149reference = "https://attack.mitre.org/techniques/T1059/001/"
150
151[[rule.threat.technique]]
152id = "T1651"
153name = "Cloud Administration Command"
154reference = "https://attack.mitre.org/techniques/T1651/"
155
156[rule.threat.tactic]
157id = "TA0002"
158name = "Execution"
159reference = "https://attack.mitre.org/tactics/TA0002/"
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.emailandazure.activitylogs.identity.authorization.evidence.principal_idfor who invoked Run Command. - Inspect
Esql.process_command_line_valuesfor script paths and arguments beyond the matched pattern. - Confirm
Esql.host_namemaps 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
Related rules
- Azure Run Command Script Child Process
- AWS SSM `SendCommand` with Run Shell Command Parameters
- Long Base64 Encoded Command via Scripting Interpreter
- AWS EC2 LOLBin Execution via SSM SendCommand
- AWS SSM Session Manager Child Process Execution