← All field notes
azuremanaged identityfor responders

Agentless and invisible: VM Run Command as a control-plane pivot

With Bastion and the VM Run Command extension an attacker executes on a VM with no open port and no agent of their own, then steals its managed-identity token to pivot.

Some attacks never open a port or drop a tool. They borrow the platform’s own management plane to run code, and the only trace is a control-plane log.

How the attack works

An attacker with contributor-style RBAC opens a browser-based Azure Bastion session to a sensitive VM, then invokes the VM Run Command extension to execute a script in-guest without deploying any agent of their own. The script requests an access token for the VM’s system-assigned managed identity from the instance metadata service and turns it against Azure Resource Manager. From there the attacker pivots to the storage account and Key Vault that identity is authorized for. Run Command is a control-plane operation, so the authoritative record is the Azure Activity log entry for Microsoft.Compute/virtualMachines/runCommand/action, followed by the managed-identity-backed calls. This maps to T1651, Cloud Administration Command, and T1078.004, Valid Accounts: Cloud Accounts.

Why it works

Run Command rights are over-assigned and VM managed identities carry broad role assignments, so any compromised contributor becomes an in-guest executor with a ready-made pivot. Because there is no inbound RDP or SSH and no foreign agent, host-centric controls never see it.

How to fix it

Resetting the local administrator password and rebooting does nothing to a stolen managed-identity token or to control-plane execution. The real containment is to revoke the VM managed identity’s role assignments and force its tokens to expire, then remove the runCommand RBAC from the attacking principal so it cannot execute again. Treat any Key Vault secret the identity touched as compromised and rotate it, because a viewed secret is a spent secret. Durably, restrict Run Command RBAC to a minimal admin set, scope every VM managed identity to least privilege, and alert on Run Command invocations across the fleet.

Practice it

We built this as a GraphLattice Range scenario so responders learn to chase the control-plane pivot, not the local host.