Query Details
// Hunt : Hunt - VM Script Extension and Run Command Execution History (30 Days)
// Tactics : Execution, Persistence
// MITRE : T1059, T1059.009
// Purpose : Enumerate all Custom Script Extension deployments and Run Command executions across all VMs for the last 30 days. Use to identify unusual actors, one-off script injections, or scripts deployed outside known IaC patterns. Cross-reference with Rule-15 alerts to investigate full scope.
//==========================================================================================
let ScriptExtTypes = dynamic([
"CustomScriptExtension", "CustomScriptForLinux",
"RunCommandHandler", "RunCommand",
"Microsoft.Compute.CustomScriptExtension",
"Microsoft.Azure.Extensions.CustomScript"
]);
AzureActivity
| where TimeGenerated > ago(30d)
| where OperationNameValue =~ "MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE"
or OperationNameValue =~ "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION"
| where ActivityStatusValue =~ "Success"
| where Properties has_any (ScriptExtTypes)
or OperationNameValue has "RUNCOMMAND"
| extend PropsParsed = todynamic(Properties)
| extend ExtensionType = coalesce(
tostring(PropsParsed["type"]),
tostring(PropsParsed.type),
iff(OperationNameValue has "RUNCOMMAND", "RunCommand", "Unknown"))
| extend VMName = tostring(split(ResourceId, "/")[8])
| project
TimeGenerated,
Caller,
CallerIpAddress,
VMName,
ExtensionType,
ResourceId,
ResourceGroup,
SubscriptionId
| summarize
ExecCount = count(),
DistinctVMs = dcount(VMName),
VMNames = make_set(VMName, 20),
ExtensionTypes = make_set(ExtensionType, 5),
SourceIPs = make_set(CallerIpAddress, 5),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by Caller, ResourceGroup, SubscriptionId
| order by ExecCount desc
This KQL query is designed to track and analyze the deployment of custom scripts and run command executions on virtual machines (VMs) over the past 30 days. Here's a simple breakdown of what the query does:
Purpose: The query aims to identify all instances where custom scripts or run commands have been executed on VMs. This helps in spotting unusual activities, such as unauthorized script injections or scripts that don't align with known Infrastructure as Code (IaC) patterns.
Data Source: It pulls data from the AzureActivity log, focusing on activities related to VM extensions and run commands.
Filtering Criteria:
Data Extraction:
Projection: The query selects specific fields to focus on, including the time of the activity, the caller's identity and IP address, the VM name, extension type, and various identifiers like resource group and subscription ID.
Aggregation:
ExecCount).Ordering: The results are sorted by the number of executions in descending order, highlighting the most active callers or scripts.
Overall, this query helps security analysts monitor and investigate script execution activities on VMs, potentially uncovering security threats or policy violations.

David Alonso
Released: March 12, 2026
Tables
Keywords
Operators