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

This commit is contained in:
Translator
2025-06-25 00:23:23 +00:00
parent 0c3ba9f77a
commit 2699fb42a3
2 changed files with 72 additions and 31 deletions

BIN
src/images/CH_logo_ads.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -2,6 +2,16 @@
{{#include ../../../banners/hacktricks-training.md}}
## Herramientas
Las siguientes herramientas son útiles para encontrar flujos de trabajo de Github Action e incluso encontrar algunos vulnerables:
- [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) - Consulta también su lista de verificación en [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits)
## Información Básica
En esta página encontrarás:
@@ -9,10 +19,10 @@ En esta página encontrarás:
- Un **resumen de todos los impactos** de un atacante que logra acceder a una Github Action
- Diferentes formas de **obtener acceso a una acción**:
- Tener **permisos** para crear la acción
- Abusar de los **triggers** relacionados con **pull requests**
- Abusar de los **disparadores** relacionados con **pull request**
- Abusar de **otras técnicas de acceso externo**
- **Pivotar** desde un repositorio ya comprometido
- Finalmente, una sección sobre **técnicas de post-explotación para abusar de una acción desde adentro** (causando los impactos mencionados)
- Finalmente, una sección sobre **técnicas de post-explotación para abusar de una acción desde adentro** (causar los impactos mencionados)
## Resumen de Impactos
@@ -20,9 +30,9 @@ Para una introducción sobre [**Github Actions consulta la información básica*
Si puedes **ejecutar código arbitrario en GitHub Actions** dentro de un **repositorio**, podrías ser capaz de:
- **Robar secretos** montados en la pipeline y **abusar de los privilegios de la pipeline** para obtener acceso no autorizado a plataformas externas, como AWS y GCP.
- **Robar secretos** montados en la tubería y **abusar de los privilegios de la tubería** para obtener acceso no autorizado a plataformas externas, como AWS y GCP.
- **Comprometer despliegues** y otros **artefactos**.
- Si la pipeline despliega o almacena activos, podrías alterar el producto final, habilitando un ataque a la cadena de suministro.
- Si la tubería despliega o almacena activos, podrías alterar el producto final, habilitando un ataque a la cadena de suministro.
- **Ejecutar código en trabajadores personalizados** para abusar del poder computacional y pivotar a otros sistemas.
- **Sobrescribir el código del repositorio**, dependiendo de los permisos asociados con el `GITHUB_TOKEN`.
@@ -35,7 +45,7 @@ Este "**secreto**" (proveniente de `${{ secrets.GITHUB_TOKEN }}` y `${{ github.t
Este token es el mismo que una **Aplicación de Github utilizará**, por lo que puede acceder a los mismos 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 debería liberar un [**flujo**](https://github.com/github/roadmap/issues/74) que **permita el acceso entre repositorios** dentro de GitHub, para que un repositorio pueda acceder a otros repositorios internos utilizando el `GITHUB_TOKEN`.
> Github debería lanzar un [**flujo**](https://github.com/github/roadmap/issues/74) que **permita el acceso entre repositorios** dentro de GitHub, para que un repositorio pueda acceder a otros repositorios internos utilizando el `GITHUB_TOKEN`.
Puedes ver los posibles **permisos** de este token en: [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)
@@ -81,7 +91,7 @@ https://api.github.com/repos/<org_name>/<repo_name>/pulls \
{{#endtabs }}
> [!CAUTION]
> Tenga en cuenta que en varias ocasiones podrá encontrar **tokens de usuario de github dentro de los entornos de Github Actions o en los secretos**. Estos tokens pueden otorgarle más privilegios sobre el repositorio y la organización.
> Ten en cuenta que en varias ocasiones podrás encontrar **tokens de usuario de github dentro de los entornos de Github Actions o en los secretos**. Estos tokens pueden darte más privilegios sobre el repositorio y la organización.
<details>
@@ -179,13 +189,13 @@ El desencadenador de flujo de trabajo **`pull_request`** ejecutará el flujo de
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
> [!NOTE]
> Como la **limitación predeterminada** es para **contribuyentes de primera vez**, podrías contribuir **corrigiendo un error/tipografía válido** y luego enviar **otras PRs para abusar de tus nuevos privilegios de `pull_request`**.
> Como la **limitación predeterminada** es para **contribuyentes primerizos**, podrías contribuir **corrigiendo un error/tipografía válido** y luego enviar **otras PRs para abusar de tus nuevos privilegios de `pull_request`**.
>
> **Probé esto y no funciona**: ~~Otra opción sería crear una cuenta con el nombre de alguien que contribuyó al proyecto y eliminó su cuenta.~~
Además, por defecto **previene permisos de escritura** y **acceso a secretos** al repositorio objetivo como se menciona en la [**documentación**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
> Con la excepción de `GITHUB_TOKEN`, **los secretos no se pasan al runner** cuando un flujo de trabajo es desencadenado desde un repositorio **forked**. El **`GITHUB_TOKEN` tiene permisos de solo lectura** en solicitudes de extracción **de repositorios forked**.
> Con la excepción de `GITHUB_TOKEN`, **los secretos no se pasan al runner** cuando se desencadena un flujo de trabajo desde un repositorio **forked**. El **`GITHUB_TOKEN` tiene permisos de solo lectura** en solicitudes de extracción **de repositorios forked**.
Un atacante podría modificar la definición de la Github Action para ejecutar cosas arbitrarias y agregar acciones arbitrarias. Sin embargo, no podrá robar secretos ni sobrescribir el repositorio debido a las limitaciones mencionadas.
@@ -201,7 +211,7 @@ El desencadenador de flujo de trabajo **`pull_request_target`** tiene **permiso
Ten en cuenta que el desencadenador de flujo de trabajo **`pull_request_target`** **se ejecuta en el contexto base** y no en el proporcionado por la PR (para **no ejecutar código no confiable**). Para más información sobre `pull_request_target`, [**consulta la documentación**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
Además, para más información sobre este uso específico y peligroso, consulta este [**post del blog de github**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
Puede parecer que debido a que el **flujo de trabajo ejecutado** es el definido en la **base** y **no en la PR**, es **seguro** usar **`pull_request_target`**, pero hay **algunos casos en los que no lo es**.
Puede parecer que, dado que el **flujo de trabajo ejecutado** es el definido en la **base** y **no en la PR**, es **seguro** usar **`pull_request_target`**, pero hay **algunos casos en los que no lo es**.
Y este tendrá **acceso a secretos**.
@@ -219,14 +229,14 @@ types:
```
Además, según la documentación: El flujo de trabajo iniciado por el evento `workflow_run` puede **acceder a secretos y escribir tokens, incluso si el flujo de trabajo anterior no lo fue**.
Este tipo de flujo de trabajo podría ser atacado si **depende** de un **flujo de trabajo** que puede ser **activado** por un usuario externo a través de **`pull_request`** o **`pull_request_target`**. Un par de ejemplos vulnerables se pueden [**encontrar en este blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** El primero consiste en que el flujo de trabajo activado por **`workflow_run`** descarga el código del atacante: `${{ github.event.pull_request.head.sha }}`\
Este tipo de flujo de trabajo podría ser atacado si **depende** de un **flujo de trabajo** que puede ser **activado** por un usuario externo a través de **`pull_request`** o **`pull_request_target`**. Un par de ejemplos vulnerables pueden ser [**encontrados en este blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** El primero consiste en que el flujo de trabajo activado por **`workflow_run`** descarga el código del atacante: `${{ github.event.pull_request.head.sha }}`\
El segundo consiste en **pasar** un **artifact** del código **no confiable** al flujo de trabajo **`workflow_run`** y usar el contenido de este artifact de una manera que lo haga **vulnerable a RCE**.
### `workflow_call`
TODO
TODO: Verificar si al ejecutarse desde un pull_request el código utilizado/descargado es el de la fuente o el del PR bifurcado.
TODO: Verificar si al ejecutarse desde un pull_request el código utilizado/descargado es el del origen o del PR bifurcado.
## Abusando de la Ejecución Bifurcada
@@ -269,10 +279,10 @@ message: |
¡Gracias!
</code></pre>
El código potencialmente **no confiable se está ejecutando durante `npm install` o `npm build`** ya que los scripts de construcción y los **paquetes referenciados son controlados por el autor del PR**.
El código **no confiable potencialmente se está ejecutando durante `npm install` o `npm build`** ya que los scripts de construcción y los **paquetes referenciados son controlados por el autor del PR**.
> [!WARNING]
> Un dork de github para buscar acciones vulnerables es: `event.pull_request pull_request_target extension:yml`, sin embargo, hay diferentes formas de configurar los trabajos para que se ejecuten de manera segura incluso si la acción está configurada de manera insegura (como usar condicionales sobre quién es el actor que genera el PR).
> Un dork de github para buscar acciones vulnerables es: `event.pull_request pull_request_target extension:yml` sin embargo, hay diferentes formas de configurar los trabajos para que se ejecuten de manera segura incluso si la acción está configurada de manera insegura (como usar condicionales sobre quién es el actor que genera el PR).
### Inyecciones de Script en Contexto <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
@@ -286,19 +296,59 @@ gh-actions-context-script-injections.md
Según la documentación: Puede hacer que una **variable de entorno esté disponible para cualquier paso posterior** en un trabajo de flujo de trabajo definiendo o actualizando la variable de entorno y escribiendo esto en el archivo de entorno **`GITHUB_ENV`**.
Si un atacante pudiera **inyectar cualquier valor** dentro de esta **variable env**, podría inyectar variables de entorno que podrían ejecutar código en pasos posteriores como **LD_PRELOAD** o **NODE_OPTIONS**.
Si un atacante pudiera **inyectar cualquier valor** dentro de esta variable **env**, podría inyectar variables de entorno que podrían ejecutar código en pasos posteriores como **LD_PRELOAD** o **NODE_OPTIONS**.
Por ejemplo ([**esto**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) y [**esto**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), imagina un flujo de trabajo que confía en un artifact subido para almacenar su contenido dentro de la variable de entorno **`GITHUB_ENV`**. Un atacante podría subir algo como esto para comprometerlo:
Por ejemplo ([**esto**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) y [**esto**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), imagine un flujo de trabajo que confía en un artifact subido para almacenar su contenido dentro de la variable de entorno **`GITHUB_ENV`**. Un atacante podría subir algo como esto para comprometerlo:
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
### Dependabot y otros bots de confianza
Como se indica en [**esta publicación de blog**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), varias organizaciones tienen una Acción de Github que fusiona cualquier PRR de `dependabot[bot]` como en:
```yaml
on: pull_request_target
jobs:
auto-merge:
runs-on: ubuntu-latest
if: ${ { github.actor == 'dependabot[bot]' }}
steps:
- run: gh pr merge $ -d -m
```
Lo cual es un problema porque el campo `github.actor` contiene al usuario que causó el último evento que activó el flujo de trabajo. Y hay varias formas de hacer que el usuario `dependabot[bot]` modifique un PR. Por ejemplo:
- Hacer un fork del repositorio de la víctima
- Agregar la carga útil maliciosa a tu copia
- Habilitar Dependabot en tu fork añadiendo una dependencia desactualizada. Dependabot creará una rama corrigiendo la dependencia con código malicioso.
- Abrir un Pull Request al repositorio de la víctima desde esa rama (el PR será creado por el usuario, así que aún no pasará nada)
- Luego, el atacante regresa al PR inicial que Dependabot abrió en su fork y ejecuta `@dependabot recreate`
- Luego, Dependabot realiza algunas acciones en esa rama, que modificaron el PR sobre el repositorio de la víctima, lo que hace que `dependabot[bot]` sea el actor del último evento que activó el flujo de trabajo (y por lo tanto, el flujo de trabajo se ejecuta).
Pasando a otro tema, ¿qué pasaría si en lugar de fusionar, la Acción de Github tuviera una inyección de comandos como en:
```yaml
on: pull_request_target
jobs:
just-printing-stuff:
runs-on: ubuntu-latest
if: ${ { github.actor == 'dependabot[bot]' }}
steps:
- run: echo ${ { github.event.pull_request.head.ref }}
```
Bueno, la publicación del blog original propone dos opciones para abusar de este comportamiento, siendo la segunda:
- Hacer un fork del repositorio de la víctima y habilitar Dependabot con alguna dependencia desactualizada.
- Crear una nueva rama con el código de inyección de shell malicioso.
- Cambiar la rama predeterminada del repositorio a esa.
- Crear un PR desde esta rama al repositorio de la víctima.
- Ejecutar `@dependabot merge` en el PR que Dependabot abrió en su fork.
- Dependabot fusionará sus cambios en la rama predeterminada de tu repositorio bifurcado, actualizando el PR en el repositorio de la víctima, haciendo que ahora `dependabot[bot]` sea el actor del último evento que activó el flujo de trabajo y utilizando un nombre de rama malicioso.
### Acciones de Github de Terceros Vulnerables
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
Como se mencionó en [**esta publicación de blog**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), esta Acción de Github permite acceder a artifacts de diferentes flujos de trabajo e incluso repositorios.
Como se menciona en [**esta publicación del blog**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), esta Acción de Github permite acceder a artefactos de diferentes flujos de trabajo e incluso repositorios.
El problema es que si el parámetro **`path`** no está configurado, el artifact se extrae en el directorio actual y puede sobrescribir archivos que podrían ser utilizados o incluso ejecutados más tarde en el flujo de trabajo. Por lo tanto, si el Artifact es vulnerable, un atacante podría abusar de esto para comprometer otros flujos de trabajo que confían en el Artifact.
El problema es que si el parámetro **`path`** no está configurado, el artefacto se extrae en el directorio actual y puede sobrescribir archivos que podrían ser utilizados o incluso ejecutados en el flujo de trabajo. Por lo tanto, si el artefacto es vulnerable, un atacante podría abusar de esto para comprometer otros flujos de trabajo que confían en el artefacto.
Ejemplo de flujo de trabajo vulnerable:
```yaml
@@ -347,16 +397,16 @@ path: ./script.py
Si una cuenta cambia su nombre, otro usuario podría registrar una cuenta con ese nombre después de un tiempo. Si un repositorio tenía **menos de 100 estrellas antes del cambio de nombre**, Github permitirá que el nuevo usuario registrado con el mismo nombre cree un **repositorio con el mismo nombre** que el eliminado.
> [!CAUTION]
> Así que si una acción está utilizando un repositorio de una cuenta no existente, aún es posible que un atacante pueda crear esa cuenta y comprometer la acción.
> Así que si una acción está utilizando un repositorio de una cuenta no existente, todavía es posible que un atacante pueda crear esa cuenta y comprometer la acción.
Si otros repositorios estaban utilizando **dependencias de los repositorios de este usuario**, un atacante podrá secuestrarlos. Aquí tienes una explicación más completa: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
Si otros repositorios estaban utilizando **dependencias de estos repositorios de usuario**, un atacante podrá secuestrarlos. Aquí tienes una explicación más completa: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
---
## Pivotar Repositorio
> [!NOTE]
> En esta sección hablaremos sobre técnicas que permitirían **pivotar de un repositorio a otro** suponiendo que tenemos algún tipo de acceso al primero (ver la sección anterior).
> En esta sección hablaremos sobre técnicas que permitirían **pivotar de un repositorio a otro** suponiendo que tenemos algún tipo de acceso en el primero (ver la sección anterior).
### Envenenamiento de Caché
@@ -536,18 +586,9 @@ Incluso si **Github** intenta **detectar valores secretos** en los registros de
(Técnica de [**aquí**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Primero que nada, cualquier PR levantada es claramente visible al público en Github y a la cuenta de GitHub objetivo. En GitHub, por defecto, **no podemos eliminar un PR de internet**, pero hay un giro. Para las cuentas de Github que están **suspendidas** por Github, todos sus **PRs son eliminados automáticamente** y removidos de internet. Así que, para ocultar tu actividad, necesitas o bien hacer que tu **cuenta de GitHub sea suspendida o que tu cuenta sea marcada**. Esto **ocultará todas tus actividades** en GitHub de internet (básicamente eliminará todos tus PR de explotación).
Una organización en GitHub es muy proactiva en reportar cuentas a GitHub. Todo lo que necesitas hacer es compartir "algunas cosas" en un Issue y se asegurarán de que tu cuenta sea suspendida en 12 horas :p y ahí lo tienes, has hecho tu explotación invisible en github.
Una organización en GitHub es muy proactiva en reportar cuentas a GitHub. Todo lo que necesitas hacer es compartir algunas cosas en un Issue y se asegurarán de que tu cuenta sea suspendida en 12 horas :p y ahí lo tienes, has hecho tu explotación invisible en github.
> [!WARNING]
> La única forma en que una organización puede darse cuenta de que ha sido objetivo es revisar los registros de GitHub desde SIEM, ya que desde la interfaz de GitHub el PR sería eliminado.
## Herramientas
Las siguientes herramientas son útiles para encontrar flujos de trabajo de Github Action e incluso encontrar algunos vulnerables:
- [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)
> La única forma en que una organización puede darse cuenta de que ha sido objetivo es revisar los registros de GitHub desde SIEM, ya que desde la interfaz de usuario de GitHub el PR sería eliminado.
{{#include ../../../banners/hacktricks-training.md}}