Cloud & Cross-Workload Lateral Movement Investigation
In a cloud-native Microsoft environment, lateral movement does not rely on legacy on-prem RPC/SMB exploitation. Instead, adversaries pivot between cloud identities, Microsoft Graph API permissions, Azure Virtual Machines, and M365 workloads.
🧭 Cloud Lateral Movement Vectors Overview
Section titled “🧭 Cloud Lateral Movement Vectors Overview”| Vector | Mechanism | Attacker Goal | Key Telemetry Source |
|---|---|---|---|
| Azure VM RunCommand | Azure Resource Manager API (RunCommand/action) | Execute remote commands as SYSTEM / root on Azure VMs | AzureActivity |
| IMDS Token Theft | SSRF or shell access to 169.254.169.254 | Steal Azure Managed Identity token to access Key Vault or SQL | AzureDiagnostics, Sentinel |
| Intune Script Injection | Abusing Intune Admin role via Graph API | Deploy malicious script to all Intune-managed endpoints | AuditLogs, IntuneManagementExtension |
| Mailbox Delegation Pivot | Exploiting FullAccess / SendAs permissions | Pivot from victim mailbox into Executive / Finance mailboxes | OfficeActivity, Exchange Audit |
| Cloud Cross-Tenant Pivot | Abusing Cross-Tenant Access Policies / B2B Trust | Pivot into partner or subsidiary Entra ID tenants | SigninLogs (CrossTenantAccessType) |
⚡ 1. Detecting Azure VM RunCommand Execution Abuse
Section titled “⚡ 1. Detecting Azure VM RunCommand Execution Abuse”Adversaries possessing Contributor or Virtual Machine Administrator rights execute arbitrary PowerShell / Bash scripts on target Azure VMs without needing network line-of-sight (SSH or RDP):
KQL Query: Hunt for RunCommand Invocations in AzureActivity
Section titled “KQL Query: Hunt for RunCommand Invocations in AzureActivity”AzureActivity| where TimeGenerated > ago(7d)| where OperationNameValue =~ "Microsoft.Compute/virtualMachines/runCommand/action"| where ActivityStatusValue =~ "Success" or ActivityStatusValue =~ "Start"| extend TargetVM = tostring(parse_json(Properties).resource)| extend CallerIP = CallerIpAddress| project TimeGenerated, Caller, CallerIP, TargetVM, ActivityStatusValue, ResourceGroup, SubscriptionId| sort by TimeGenerated desc🔑 2. Detecting Managed Identity & IMDS Token Theft
Section titled “🔑 2. Detecting Managed Identity & IMDS Token Theft”Adversaries with local execution on an Azure Virtual Machine or App Service query the Azure Instance Metadata Service (IMDS) at 169.254.169.254 to obtain tokens for the resource’s Managed Identity:
# Attacker command executed on compromised Azure Linux/Windows VM:curl -H "Metadata:true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"KQL Query: Detecting Managed Identity Sign-ins from External / Unexpected IPs
Section titled “KQL Query: Detecting Managed Identity Sign-ins from External / Unexpected IPs”Managed Identities are designed to authenticate only from the host they are assigned to. A Managed Identity sign-in from an external or unexpected IP indicates token exfiltration:
AADServicePrincipalSignInLogs| where TimeGenerated > ago(7d)| where ServicePrincipalType =~ "ManagedIdentity"| project TimeGenerated, ServicePrincipalName, ServicePrincipalId, IPAddress, Location, ResourceDisplayName| summarize Signins = count(), DistinctIPs = dcount(IPAddress), IPList = make_set(IPAddress) by ServicePrincipalName, ServicePrincipalId| where DistinctIPs > 1| sort by DistinctIPs desc💻 3. Detecting Rogue Intune Script Deployment (Endpoint Pivot)
Section titled “💻 3. Detecting Rogue Intune Script Deployment (Endpoint Pivot)”If an administrative account is compromised, the attacker can deploy a malicious PowerShell or shell script through Intune to execute on all managed Windows and macOS endpoints:
KQL Query: Hunt for New or Modified Intune Device Management Scripts
Section titled “KQL Query: Hunt for New or Modified Intune Device Management Scripts”AuditLogs| where TimeGenerated > ago(7d)| where LoggedByService =~ "Device Management"| where OperationName has_any ("Create DeviceManagementScript", "Update DeviceManagementScript", "Create CustomAppConfig")| extend Actor = tostring(InitiatedBy.user.userPrincipalName)| extend ScriptName = tostring(TargetResources[0].displayName)| project TimeGenerated, OperationName, Actor, ScriptName, Result, TargetResources| sort by TimeGenerated desc📬 4. Exchange Online Mailbox Delegation Pivoting
Section titled “📬 4. Exchange Online Mailbox Delegation Pivoting”Adversaries pivot laterally across business units by assigning themselves permissions to high-value mailboxes (Finance, C-Suite, Legal):
KQL Query: Detecting Mailbox Permission Grants
Section titled “KQL Query: Detecting Mailbox Permission Grants”OfficeActivity| where TimeGenerated > ago(7d)| where RecordType =~ "ExchangeAdmin"| where Operation in~ ("Add-MailboxPermission", "Add-RecipientPermission")| extend TargetMailbox = tostring(parse_json(Parameters)[0].Value)| extend GrantedUser = tostring(parse_json(Parameters)[1].Value)| extend AccessRights = tostring(parse_json(Parameters)[2].Value)| project TimeGenerated, UserId, Operation, TargetMailbox, GrantedUser, AccessRights| sort by TimeGenerated desc🛡️ 5. Cross-Tenant Access & External Collaboration Pivots
Section titled “🛡️ 5. Cross-Tenant Access & External Collaboration Pivots”Detect when an account in your tenant is used to authenticate into external Entra ID organizations:
SigninLogs| where TimeGenerated > ago(7d)| where isnotempty(ResourceTenantId)| where ResourceTenantId != HomeTenantId // Cross-tenant authentication| project TimeGenerated, UserPrincipalName, IPAddress, ResourceDisplayName, ResourceTenantId, AppDisplayName| sort by TimeGenerated desc