Abusing Github Actions
Información Básica
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 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 dentro (causar los impactos mencionados)
Resumen de Impactos
Para una introducción sobre Github Actions revisa la información básica.
En caso de que puedas ejecutar acciones arbitrarias de Github/inyectar código en un repositorio, podrías ser capaz de:
Robar los secretos de ese repo/organización.
Si solo puedes inyectar, puedes robar lo que ya esté presente en el workflow.
Abusar de los privilegios del repo para acceder a otras plataformas como AWS y GCP.
Ejecutar código en trabajadores personalizados (si se usan trabajadores personalizados) e intentar pivotar desde allí.
Sobrescribir el código del repositorio.
Esto depende de los privilegios del
GITHUB_TOKEN
(si los hay).Comprometer despliegues y otros artefactos.
Si el código está desplegando o almacenando algo, podrías modificar eso y obtener más acceso.
GITHUB_TOKEN
Este "secreto" (proveniente de ${{ secrets.GITHUB_TOKEN }}
y ${{ github.token }}
) se da cuando el administrador habilita esta opción:
Este token es el mismo que usará una Aplicación de Github, por lo que puede acceder a los mismos endpoints: https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps
Github debería lanzar un flujo que permita el acceso entre repositorios dentro de GitHub, para que un repo pueda acceder a otros repos internos usando 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
Ten en cuenta que el token expira después de que el trabajo se haya completado.
Estos tokens se ven así: ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7
Algunas cosas interesantes que puedes hacer con este token:
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.
Es posible verificar los permisos otorgados a un Github Token en los repositorios de otros usuarios revisando los logs de las acciones:
Ejecución Permitida
Esta sería la forma más fácil de comprometer las acciones de Github, ya que este caso supone que tienes acceso para crear un nuevo repositorio en la organización, o tienes privilegios de escritura sobre un repositorio.
Si estás en este escenario, puedes simplemente revisar las técnicas de Post Explotación.
Ejecución desde la Creación de Repositorio
En caso de que los miembros de una organización puedan crear nuevos repositorios y puedas ejecutar acciones de github, puedes crear un nuevo repositorio y robar los secretos establecidos a nivel de organización.
Ejecución desde una Nueva Rama
Si puedes crear una nueva rama en un repositorio que ya contiene una Github Action configurada, puedes modificarla, subir el contenido y luego ejecutar esa acción desde la nueva rama. De esta manera puedes exfiltrar secretos a nivel de repositorio y organización (pero necesitas saber cómo se llaman).
Puedes hacer que la acción modificada sea ejecutable manualmente, cuando se crea un PR o cuando se sube algún código (dependiendo de qué tan ruidoso quieras ser):
Ejecución Bifurcada
Hay diferentes desencadenantes que podrían permitir a un atacante ejecutar una Github Action de otro repositorio. Si esas acciones desencadenables están mal configuradas, un atacante podría comprometerlas.
pull_request
pull_request
El desencadenante del flujo de trabajo pull_request
ejecutará el flujo de trabajo cada vez que se reciba una solicitud de extracción con algunas excepciones: por defecto, si es la primera vez que estás colaborando, algún mantenedor necesitará aprobar la ejecución del flujo de trabajo:
Como la limitación por defecto es para colaboradores de primera vez, podrías contribuir arreglando un error/typo 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:
Con la excepción de
GITHUB_TOKEN
, los secretos no se pasan al runner cuando un flujo de trabajo se desencadena desde un repositorio bifurcado. ElGITHUB_TOKEN
tiene permisos de solo lectura en solicitudes de extracción desde repositorios bifurcados.
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.
Sí, si el atacante cambia en la PR la github action que se desencadenará, su Github Action será la utilizada y no la del repositorio original!
Como el atacante también controla el código que se ejecuta, incluso si no hay secretos o permisos de escritura en el GITHUB_TOKEN
, un atacante podría, por ejemplo, subir artefactos maliciosos.
pull_request_target
pull_request_target
El desencadenante del flujo de trabajo pull_request_target
tiene permiso de escritura en el repositorio objetivo y acceso a secretos (y no pide permiso).
Ten en cuenta que el desencadenante del flujo de trabajo pull_request_target
se ejecuta en el contexto base y no en el dado por la PR (para no ejecutar código no confiable). Para más información sobre pull_request_target
consulta la documentación.
Además, para más información sobre este uso específico y peligroso, consulta este blog de github.
Podría parecer que porque 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.
workflow_run
workflow_run
El desencadenante workflow_run permite ejecutar un flujo de trabajo desde otro diferente cuando está completed
, requested
o in_progress
.
En este ejemplo, un flujo de trabajo está configurado para ejecutarse después de que el flujo de trabajo separado "Run Tests" se complete:
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 podía.
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. 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 artefacto del código no confiable al flujo de trabajo workflow_run
y usar el contenido de este artefacto de una manera que lo hace vulnerable a RCE.
workflow_call
workflow_call
TODO
TODO: Verificar si cuando se ejecuta desde un pull_request el código usado/descargado es el del origen o del PR bifurcado
Abusando de la Ejecución Bifurcada
Hemos mencionado todas las formas en que un atacante externo podría lograr que un flujo de trabajo de github se ejecute, ahora veamos cómo estas ejecuciones, si están mal configuradas, podrían ser abusadas:
Ejecución de checkout no confiable
En el caso de pull_request
, el flujo de trabajo se ejecutará en el contexto del PR (por lo que ejecutará el código malicioso del PR), pero alguien necesita autorizarlo primero y se ejecutará con algunas limitaciones.
En caso de un flujo de trabajo que use pull_request_target
o workflow_run
que dependa de un flujo de trabajo que puede ser activado desde pull_request_target
o pull_request
se ejecutará el código del repositorio original, por lo que el atacante no puede controlar el código ejecutado.
Sin embargo, si la acción tiene un checkout explícito del PR que obtendrá el código del PR (y no de la base), usará el código controlado por el atacante. Por ejemplo (ver línea 12 donde se descarga el código del PR):
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 están controlados por el autor del PR.
Un github dork 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 el Contexto
Tenga en cuenta que hay ciertos contextos de github cuyos valores son controlados por el usuario que crea el PR. Si la acción de github está usando esos datos para ejecutar algo, podría llevar a ejecución arbitraria de código:
Gh Actions - Context Script InjectionsInyección de Script en GITHUB_ENV
De la documentación: Puedes hacer que una variable de entorno esté disponible para cualquier paso subsecuente en un trabajo de flujo de trabajo definiendo o actualizando la variable de entorno y escribiéndola en el archivo de entorno GITHUB_ENV
.
Si un atacante pudiera inyectar cualquier valor dentro de esta variable de entorno, podría inyectar variables de entorno que podrían ejecutar código en pasos siguientes como LD_PRELOAD o NODE_OPTIONS.
Por ejemplo (este y este), imagina un flujo de trabajo que confía en un artefacto subido para almacenar su contenido dentro de la variable de entorno GITHUB_ENV
. Un atacante podría subir algo como esto para comprometerlo:
Acciones de Github de Terceros Vulnerables
Como se menciona en esta publicación de blog, 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 artefacto 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 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:
Esto podría ser atacado con este flujo de trabajo:
Otro Acceso Externo
Secuestro de Repositorio de Namespace Eliminado
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á al nuevo usuario registrado con el mismo nombre crear un repositorio con el mismo nombre que el eliminado.
Entonces, si una acción está usando un repositorio de una cuenta inexistente, aún es posible que un atacante pueda crear esa cuenta y comprometer la acción.
Si otros repositorios estaban usando 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/
Repo Pivoting
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 (revisa la sección anterior).
Envenenamiento de Caché
Se mantiene una caché entre ejecuciones de workflow en la misma rama. Lo que significa que si un atacante compromete un paquete que luego se almacena en la caché y es descargado y ejecutado por un workflow más privilegiado, también podrá comprometer ese workflow.
GH Actions - Cache PoisoningEnvenenamiento de Artefactos
Los workflows podrían usar artefactos de otros workflows e incluso repositorios, si un atacante logra comprometer la Github Action que sube un artefacto que luego es usado por otro workflow, podría comprometer los otros workflows:
Gh Actions - Artifact PoisoningPost Explotación desde una Acción
Accediendo a AWS y GCP vía OIDC
Revisa las siguientes páginas:
AWS - Federation AbuseGCP - Federation AbuseAccediendo a secretos
Si estás inyectando contenido en un script, es interesante saber cómo puedes acceder a secretos:
Si el secreto o token está configurado como una variable de entorno, se puede acceder directamente a través del entorno usando
printenv
.
Si el secreto se usa directamente en una expresión, el script de shell generado se almacena en disco y es accesible.
cat /home/runner/work/_temp/*
Para una acción personalizada, el riesgo puede variar dependiendo de cómo un programa esté usando el secreto que obtuvo del argumento:
Abusando de runners autohospedados
La forma de encontrar qué Github Actions se están ejecutando en infraestructura no-Github es buscar runs-on: self-hosted
en la configuración yaml de Github Action.
Los runners autohospedados podrían tener acceso a información extra sensible, a otros sistemas de red (¿endpoints vulnerables en la red? ¿servicio de metadatos?) o, incluso si está aislado y destruido, más de una acción podría ejecutarse al mismo tiempo y la maliciosa podría robar los secretos de la otra.
En los runners autohospedados también es posible obtener los secretos del proceso _Runner.Listener_ que contendrá todos los secretos de los flujos de trabajo en cualquier paso al volcar su memoria:
Consulta esta publicación para más información.
Registro de Imágenes Docker de Github
Es posible crear acciones de Github que construyan y almacenen una imagen Docker dentro de Github. Un ejemplo se puede encontrar en el siguiente desplegable:
Last updated