Query Details

Detect Azure Script Or Run Command By Risky User

Query

# *Detect Custom Script or Run Command deployment by risky user*

## Query Information

#### MITRE ATT&CK Technique(s)

| Technique ID | Title    | Link    |
| ---  | --- | --- |
| T1021.008 | Remote Services: Direct Cloud VM Connections | https://attack.mitre.org/techniques/T1021/008/ |
| T1651 | Cloud Administration Command | https://attack.mitre.org/techniques/T1651/ |


#### Description
This detection rule flags when a user with risk events in Entra ID Identity Protection is deploying Custom Scripts or Run Commands on Azure or Azure Arc machines. This may indicate a compromised cloud user that is now performaring lateral movement from the Azure control plane to Virtual Machines in other environments. 

#### Risk
This rule tries to mitigate the risk of compromised cloud admin accounts performing lateral movement via Azure or Azure Arc Custom Script or Run Command deployments.

#### Author <Optional>
- **Name:** Robbe Van den Daele
- **Github:** https://github.com/RobbeVandenDaele
- **Twitter:** https://x.com/RobbeVdDaele
- **LinkedIn:** https://www.linkedin.com/in/robbe-van-den-daele-677986190/
- **Website:** https://hybridbrothers.com/

#### References
- https://thecollective.eu/

## Defender XDR
```kql
AzureActivity 
| where TimeGenerated > ago(1h)
| where CategoryValue == "Administrative"
| where OperationNameValue =~ "Microsoft.Compute/virtualMachines/runCommand/action"
    or OperationNameValue =~ "MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE"
| extend VMName = tostring(todynamic(Properties).resource)
| summarize make_list(ActivityStatusValue), TimeGenerated = max(TimeGenerated) by CorrelationId, CallerIpAddress, Caller, ResourceGroup, VMName
| join kind=inner (AADUserRiskEvents | where TimeGenerated > ago(14d) ) on $left.Caller == $right.UserPrincipalName
```

Explanation

This query is designed to detect potentially risky activities involving the deployment of custom scripts or run commands on Azure or Azure Arc virtual machines by users who have been flagged for risk events in Entra ID Identity Protection. Here's a simplified breakdown of what the query does:

  1. Data Source: It starts by looking at Azure activity logs from the past hour.

  2. Filter Criteria: It focuses on administrative activities, specifically those involving the execution of run commands or the writing of extensions on virtual machines.

  3. Extract Information: For each relevant activity, it extracts details like the virtual machine name, the status of the activity, the time it occurred, the caller's IP address, the caller's identity, and the resource group.

  4. Risk Assessment: It then checks if the user who performed these activities has any associated risk events in the past 14 days, as recorded in the AADUserRiskEvents.

  5. Output: The query outputs a summary of these activities, including the status of each activity and the time it was last generated, for users with identified risk events.

The purpose of this query is to identify and mitigate the risk of compromised cloud admin accounts that might be used to perform unauthorized actions on virtual machines, potentially indicating lateral movement within the cloud environment.

Details

Robbe Van den Daele profile picture

Robbe Van den Daele

Released: October 6, 2025

Tables

AzureActivityAADUserRiskEvents

Keywords

AzureActivityAdministrativeVirtualMachinesAADUserRiskEventsCallerResourceGroup

Operators

AzureActivitywhere>ago===~orextendtostringtodynamicsummarizemake_listmaxbyjoinkind=inneron==

Actions