Translated ['', 'src/pentesting-ci-cd/github-security/abusing-github-act

This commit is contained in:
Translator
2026-07-06 15:30:49 +00:00
parent 7e48633230
commit 5ba2f9072e
@@ -4,18 +4,18 @@
## Razumevanje rizika
GitHub Actions renderuje izraze ${{ ... }} pre nego što se korak izvrši. Renderovana vrednost se ubacuje u program koraka (za run korake, shell skripta). Ako interpolirate nepouzdan ulaz direktno unutar run:, napadač kontroliše deo shell programa i može izvršavati proizvoljne komande.
GitHub Actions renderuje expression-e ${{ ... }} pre nego što se step izvrši. Renderovana vrednost se ubacuje u program stepa (za run steps, shell script). Ako direktno interpoliraš nepouzdani input unutar run:, napadač kontroliše deo shell programa i može da izvrši arbitrary commands.
Dokumentacija: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions i contexts/functions: https://docs.github.com/en/actions/learn-github-actions/contexts
Docs: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions and contexts/functions: https://docs.github.com/en/actions/learn-github-actions/contexts
Ključne tačke:
- Renderovanje se dešava pre izvršenja. Skripta koja se pokreće u run koraku se generiše sa svim razrešenim izrazima, a zatim je izvršava shell.
- Mnogi contexts sadrže polja pod kontrolom korisnika u zavisnosti od događaja koji pokreće (issues, PRs, comments, discussions, forks, stars, itd.). Pogledajte referencu o nepouzdanom ulazu: https://securitylab.github.com/resources/github-actions-untrusted-input/
- Quoting u shell-u unutar run: nije pouzdana odbrana, jer se injekcija dešava u fazi renderovanja šablona. Napadači mogu probiti navodnike ili ubaciti operatore putem pažljivo sastavljenog unosa.
- Renderovanje se dešava pre execution. run script se generiše sa svim resolved expression-ima, a zatim ga izvršava shell.
- Mnogi contexts sadrže polja pod kontrolom korisnika, u zavisnosti od triggering event-a (issues, PRs, comments, discussions, forks, stars, itd.). Pogledaj reference za untrusted input: https://securitylab.github.com/resources/github-actions-untrusted-input/
- Shell quoting unutar run: nije pouzdana odbrana, jer se injection dešava u template rendering stage-u. Napadači mogu da izađu iz navodnika ili da ubace operators preko crafted input-a.
## Ranljiv obrazac → RCE na runner-u
## Vulnerable pattern → RCE on runner
Ranljiv workflow (pokreće se kada neko otvori novi issue):
Vulnerable workflow (triggered when someone opens a new issue):
```yaml
name: New Issue Created
on:
@@ -36,20 +36,56 @@ with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: new
```
Ako napadač otvori issue sa naslovom $(id), renderovani step postaje:
Ako napadač otvori issue sa naslovom $(id), renderovani korak postaje:
```sh
echo "New issue $(id) created"
```
Zamena komande izvršava id na runneru. Primer izlaza:
Command substitution izvršava id na runner-u. Primer izlaza:
```
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
```
Zašto citiranje ne štiti:
- Izrazi se prvo evaluiraju, zatim se izvršava dobijena skripta. Ako nepouzdana vrednost sadrži $(...), `;`, `"`/`'` ili prelome reda (newlines), može promeniti strukturu programa uprkos vašem citiranju.
Zašto quoting ne pomaže:
- Expressions se prvo renderuju, a zatim se izvršava dobijeni script. Ako nepoverljiva vrednost sadrži $(...), `;`, `"`/`'`, ili nove redove, može da izmeni strukturu programa uprkos tvom quoting-u.
## Siguran obrazac (shell variables via env)
## Zbunjenost stanja komentara: spoofed bot comments → shell injection
Ispravna mitigacija: kopirajte nepouzdani ulaz u environment variable, zatim koristite native shell expansion ($VAR) u run skripti. Nemojte ponovo umetati sa ${{ ... }} unutar komande.
Opasna varijanta se pojavljuje kada workflow **pretražuje komentare i kasnije tretira vraćeni komentar kao trusted automation state**. Na primer, `peter-evans/find-comment` može da pretražuje po `body-includes` i da izloži odgovarajući `comment-body` kao step output. Ako workflow ne ograniči i `comment-author`, svaki korisnik koji može da komentariše može da spoofuje marker tekst koji se očekuje od bota.
```yaml
- uses: peter-evans/find-comment@v4
id: fc
with:
issue-number: ${{ github.event.issue.number }}
body-includes: "Opened a new issue in org/repo:"
```
Ako se taj izlaz kasnije ugradi u shell syntax, workflow postaje exploitable čak iako je originalni source bio „samo comment“:
```yaml
- run: |
if [ '${{ steps.fc.outputs.comment-body }}' = '' ]; then
echo "new issue needed"
fi
```
Napadač može da postavi komentar koji:
- poklapa se sa traženim marker stringom, i
- sadrži shell-breaking sadržaj kao što je `' ]; <cmd>; if [ 'x`
Nakon što GitHub renderuje `${{ ... }}`, Bash dobija attacker-controlled sintaksu, a ne podatke. Ovo stvara **two-stage exploit**:
1. **Provenance confusion**: workflow greškom uzima komentare napadača kao bot state.
2. **Script injection**: vraćeni `comment-body` se nalepi u `run:` i izvrši.
### TOCTOU race against bot comments
Ako se legitimni bot komentar kreira tek nakon nekog ranijeg koraka, napadač može da ga preduhitri tako što će prvo postaviti spoofed komentar. Ako search action vrati komentar napadača pre nego što real bot komentar postoji (ili pre nego što bude izabran), javni commenter sa niskim privilegijama može da pretvori `issue_comment`/issue workflow u privileged runner execution.
### Safer patterns for comment-driven automation
- Kada koristiš `find-comment`, zahtevaj **i sadržaj i provenance** (`comment-author`, repository/App identity, ili neku drugu jaku vezu).
- Ne koristi komentare kao state ako label, artifact, issue field, ili external datastore može bezbednije da čuva isti state.
- Nikada ne lepi `comment-body`, issue titles, labels, ili bilo koji workflow output izveden iz njih direktno u `run:`.
- Ako moraš da trošiš comment text, prosledi ga kroz `env:` ili fajl i tretiraj ga samo kao podatke.
## Safe pattern (shell variables via env)
Ispravna mitigation: kopiraj untrusted input u environment variable, a zatim koristi native shell expansion ($VAR) u run scriptu. Nemoj ponovo ugrađivati sa ${{ ... }} unutar komande.
```yaml
# safe
jobs:
@@ -63,31 +99,39 @@ run: |
echo "New issue $TITLE created"
```
Napomene:
- Izbegavajte upotrebu ${{ env.TITLE }} inside run:. To ponovo uvodi template rendering nazad u komandu i stvara isti rizik od injekcije.
- Preferirajte prosleđivanje nepouzdanih inputa putem env: mapping i referencirajte ih sa $VAR in run:.
- Izbegavaj korišćenje ${{ env.TITLE }} unutar run:. To ponovo uvodi template rendering nazad u komandu i donosi isti injection rizik.
- Radije prosleđuj nepouzdane inpute preko env: mapping i referenciraj ih sa $VAR u run:.
## Reader-triggerable surfaces (treat as untrusted)
Nalozi sa samo read permission na public repositories i dalje mogu pokrenuti mnoge event-e. Svako polje u kontekstima izvedenim iz ovih event-a mora se smatrati kontrolisanim od strane napadača, osim ako se ne dokaže suprotno. Primeri:
Nalozi sa samo read permission na public repositories i dalje mogu da pokrenu mnoge events. Svako polje u contexts izvedeno iz ovih events mora se smatrati attacker-controlled osim ako nije dokazano suprotno. Primeri:
- issues, issue_comment
- discussion, discussion_comment (orgs can restrict discussions)
- pull_request, pull_request_review, pull_request_review_comment
- pull_request_target (dangerous if misused, runs in base repo context)
- fork (anyone can fork public repos)
- watch (starring a repo)
- Indirectly via workflow_run/workflow_call chains
- Indirektno preko workflow_run/workflow_call chains
Koja specifična polja su attacker-controlled zavisi od event-a. Pogledajte GitHub Security Labs untrusted input guide: https://securitylab.github.com/resources/github-actions-untrusted-input/
Koja su tačno polja attacker-controlled zavisi od event-a. Pogledaj GitHub Security Labs untrusted input guide: https://securitylab.github.com/resources/github-actions-untrusted-input/
## Local validation without touching the target repo
Možeš bezbedno da reprodukuješ mnoge GitHub Actions script injections pomoću [`act`](https://github.com/nektos/act): generiši sintetički event JSON, pokreni ranjivi workflow lokalno, i zameni output eksternog action-a kontrolisanom vrednošću (na primer mockovanim `comment-body`). Ovo je korisno za debug payload structure, proveru da li injektovani tekst i dalje ostavlja valid Bash syntax, i potvrdu bezopasnog canary exfiltration pre bilo kog live testa.
## Practical tips
- Minimizirajte korišćenje expressions inside run:. Prefer env: mapping + $VAR.
- Ako morate transformisati input, uradite to u shell-u koristeći sigurne alate (printf %q, jq -r, itd.), pri čemu i dalje počinjete od shell promenljive.
- Budite posebno oprezni pri interpolaciji branch names, PR titles, usernames, labels, discussion titles i PR head refs u skripte, komandne flagove ili putanje fajlova.
- Za reusable workflows i composite actions primenite isti obrazac: mapirajte u env pa onda referencirajte $VAR.
- Minimizuj upotrebu expressions unutar run:. Radije env: mapping + $VAR.
- Ako moraš da transformišeš input, uradi to u shell-u koristeći bezbedne alate (printf %q, jq -r, itd.), i dalje polazeći od shell variable.
- Posebno pazi kada interpoliraš branch names, PR titles, usernames, labels, discussion titles, i PR head refs u scripts, command-line flags, ili file paths.
- Za reusable workflows i composite actions, primeni isti pattern: map to env pa referenciraj $VAR.
## References
- [Find Comment, Get Shell: Command Injection in dbts GitHub Actions](https://landh.tech/blog/20260701-find-comment-get-shell)
- [peter-evans/find-comment](https://github.com/peter-evans/find-comment)
- [GHSL-2023-109: GitHub Actions command injection in a TDesign Vue Next workflow](https://securitylab.github.com/advisories/GHSL-2023-109_TDesign_Vue_Next/)
- [nektos/act](https://github.com/nektos/act)
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
- [GitHub workflow syntax](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions)
- [Contexts and expression syntax](https://docs.github.com/en/actions/learn-github-actions/contexts)