envenenado-pipeline-ejecución-II

Una foto más profunda CI/CD PipelineVulnerabilidades (II): Envenenado indirecto Pipeline Ejecución (I-PPE)

En nuestra publicación anterior, Vimos cómo detectar y proteger contra el envenenamiento directo. Pipeline Ejecución (D-PPE). También vimos cómo detectar esa vulnerabilidad usando Escáner Xygeni, así como algunos mecanismos de protección. 

 Envenenado Pipeline Ejecución (PPE) se produce cuando el atacante puede modificar el pipeline lógica de cualquiera de dos maneras:

  • Modificando el archivo de configuración de CI (el pipeline) -> EPI directo (D-PPE)
  • Modificando archivos a los que hace referencia el pipeline (por ejemplo: scripts a los que se hace referencia desde dentro del pipeline archivo de configuración) -> EPI indirectos (I-PPE)
pp2

En esta publicación, profundizaremos en Más infoto EPI indirectos. Pero, antes de eso, y como complemento a mi post anterior, veamos primero cómo gestiona GitHub la ejecución de pipelines y cuáles son los mecanismos de protección contra D-PPE.

¿Cómo protege GitHub la ejecución de pipeline¿Viene de relaciones públicas?

¿Cómo funciona GitHub con respecto a la ejecución de modificaciones? pipelines?

Modificado pipelines puede provenir de Empujones o Pull Requests (PR). Como práctica recomendada, se recomienda encarecidamente evitar cualquier "envío" directo a una rama protegida y utilizar Pull Requests como mecanismo para imponer cierta revisión antes de aceptar cualquier código aportado. 

Pull Requests Puede provenir de dos fuentes diferentes:

  • RP provenientes de tenedores
  • RP provenientes de sucursales

relaciones públicas de tenedores puede venir de público or de inversores privados repositorios.

Como estamos tratando con EPI (envenenados Pipeline Ejecución), nuestro punto principal no es la “aceptación” de un RP sino la ejecución de un RP modificado. pipeline durante el proceso de aceptación/aprobación del RP. En el centro de un ataque PPE, hay una ejecución involuntaria de un software modificado "malicioso". pipeline. 

En pocas palabras, envenenado. Pipeline La ejecución (PPE) se produce cuando El atacante puede modificar el pipeline lógica.

Hay dos variantes:

  • EPI directo (D-PPE): En un escenario D-PPE, el atacante modifica el archivo de configuración de CI en un repositorio al que tienen acceso, ya sea enviando el cambio directamente a una rama remota desprotegida en el repositorio o enviando un PR con el cambio desde una rama o una bifurcación. Desde el CI pipeline La ejecución está definida por los comandos en el archivo de configuración de CI modificado, los comandos maliciosos del atacante finalmente se ejecutan en el nodo de compilación una vez que la compilación pipeline se activa
  • EPI indirectos (I-PPE): En ciertos casos, la posibilidad de EPP D no está disponible para un adversario con acceso a un SCM repositorio (por ejemplo, si el pipeline está configurado para extraer el archivo de configuración de CI de una rama protegida separada en el mismo repositorio). En tal escenario, en lugar de envenenar la pipeline En sí mismo, un atacante inyecta código malicioso en archivos a los que hace referencia el pipeline (por ejemplo: scripts a los que se hace referencia desde dentro del pipeline archivo de configuración)

En ambos casos, GitHub ejecutará el modificado pipeline sin necesidad de revisión o aprobación previa.

PR desde las bifurcaciones en adelante público repos

GitHub permite configurar el comportamiento al procesar RP provenientes de bifurcaciones en repositorios públicos.

Cuando un PR proviene de una bifurcación, GitHub siempre fuerza cierto nivel de "aprobación" antes de ejecutar el pipeline asociado con el PR. Este nivel de aprobación pasa de una aprobación débil a una estricta.

At Nivel de organización (Org>>Configuración>>Acciones>>General), puedes decidir entre varias opciones de “aprobación”:

ppe3

El más estricto es el último (“Requerir la aprobación de todos los colaboradores externos.”) porque GitHub siempre requerirá aprobación cuando las relaciones públicas provengan de bifurcaciones de colaboradores externos. 

Pero incluso en este caso estricto, hay diferencias entre colaboradores con permisos de lectura y escritura.

  • Cuando el PR proviene de un read usuario, el ejecución de la pipeline está parado hasta que haya una aprobación de los cambios. Si la aprobación es correcta, entonces la modificación pipeline es ejecutado. 
  • Cuando el PR proviene de un escribir usuario, el No se necesita aprobación y la modificación pipeline siempre se ejecuta!! 
pp4

Como conclusión, los RP provenientes de bifurcaciones en repositorios públicos están ligeramente protegidos contra el PPE. Existe cierta protección contra usuarios externos (lectura), pero nada relacionado con usuarios internos (escritura).

Qué pasa RP provenientes de bifurcaciones de repositorios privados?

PR desde las bifurcaciones en adelante de inversores privados repos

En este escenario, GitHub proporciona algunas opciones de configuración útiles.

ppe9

Los ajustes anteriores se pueden configurar en Org o en Repo .

Al no hay ninguna opción marcada, GitHub pedir aprobación y no ejecutará el modificado pipeline. ¡Esta es la configuración más segura!

El configuración insegura es cuando "Ejecutar flujos de trabajo desde fork pull request" está chequeado. En este caso, lo mismo para los usuarios de lectura y escritura, Github ejecutará automáticamente el modificado pipeline!! Y esta situación puede ser incluso peor si "Enviar tokens de escritura a flujos de trabajo desde fork pull requests" y "Enviar secretos y variables a flujos de trabajo desde fork pull requests”están marcados. ¡¡No hagas esto a menos que esté claramente justificado!!

Si "Requiere aprobación para la horquilla pull request flujos de trabajo”está marcado, la situación anterior mejora un poco: GitHub solicitará aprobación y no ejecutará la modificación pipeline para el usuario de lectura, pero aún así lo ejecutará para un usuario de escritura.

ppe6

Horquillas vistas, ¿qué pasa? RP provenientes de sucursales?

relaciones públicas de sucursales

Para proteger este escenario usted debe confiar en Reglas de protección de sucursales

A nivel de repositorio, puede crear reglas de protección de sucursales para cualquier sucursal. Estas reglas añaden algunas restricciones a la modificación de ramas protegidas.

Aunque configures una regla para “Requerir un pull request Antes de fusionarse" y "Requerir aprobaciones", el modificado pipeline se ejecutará automáticamente al crear el PR.La “aprobación” sólo se aplicará a la acción de fusión.

ppe7

¿Qué pasa con el envenenamiento indirecto? Pipeline Ejecución

Como vimos anteriormente, el D-PPE se puede mitigar mediante el uso pull_request_target, Pero no se aplica al I-PPE.

Si usa pull_request_target, el pago predeterminado será el código base. Pero si desea validar algunas comprobaciones del código aportado (código PR), debe verificar explícitamente el código PR. Por lo tanto, si el código PR ha modificado cualquier script de shell invocado por el pipeline, la “base” (segura) pipeline invocará el script de shell “modificado” → ¡PPE indirecto!

La solución a esto es un poco más complicada (no existe una solución mágica como pull_request_target). 

Nuestro pipeline Ahora es seguro para D-PPE porque estamos usando pull_request_target. Pero sigue siendo vulnerable al I-PPE. 

En nuestro ejemplo de prueba, básicamente necesitamos verificar el código PR para realizar la compilación, pero las pruebas se ejecutan en el artefacto generado por la compilación. 

Entonces .. ¿Por qué no revisas ambas bases de código? 

  • Consulte el código PR porque es el código aportado lo que queremos construir y probar.
  • Código base de pago para ejecutar la versión original del pipeline y los scripts de compilación/pruebas 

Esto podría hacerse mediante revisando esas bases de código en diferentes carpetas: el código base puede estar desprotegido en la carpeta raíz y el PR en una carpeta diferente. En este caso, ejecutaríamos la compilación y el script de prueba desde la carpeta raíz con el código colocado en la nueva carpeta.

¡Esta es una solución fácil, por supuesto! Pero, para fines de aprendizaje me gustaría introducir una variante bastante interesante (…) 

GitHub flujo de trabajo_ejecutar acontecimiento desencadenante

Además de pull_request_target, GitHub proporciona otro evento desencadenante: flujo de trabajo_ejecutar. Este evento permite ejecución de un pipeline condicionado a otro pipelinela ejecución

flujo de trabajo_ejecutar y pull_request_target Los disparadores son similares en un aspecto: ambos se ejecutarán en modo privilegiado y, a pesar de las modificaciones de PR, la base pipeline será ejecutado !! 

Veamos nuestra actualidad. pipeline:

name: PR TARGET CI


on:
  pull_request_target:
    branches: [ main ]


env:
  MY_Secreto: ${{ Secretos.MY_Secreto }}
 
jobs:
  prt_build_test_and_merge:
    runs-on: ubuntu-latest


    steps:
      # checkout PR code
      - name: Checkout repository
        uses: actions/checkout@v4
        with:


          # This is to get the PR code instead of the repo code
          ref: ${{ github.event.pull_request.head.sha }}


      # Simulation of a compilation
      - name: Building ...
        run: |
          mkdir ./bin
          touch ./bin/mybin.exe
          ls -lR
     
      # Simulation of running tests
      - name: Running tests ...
        id : run_tests
        run: |
          echo Running tests..
          chmod +x runtests.sh
          ./runtests.sh 
          echo Tests executed.
         
      #
      # Let’s omit the check conditions at this moment …
      #
      - name: pr_check_conditions_to_merge
        [...]

La sección de construcción es segura para el D-PPE, pero la sección de prueba sigue siendo vulnerable al I-PPE.

El pipeline en sí es seguro para el D-PPE debido a la pull_request_target desencadenar. Pero el paso de prueba sigue siendo vulnerable a I-PPE debido a que se invoca un script de shell externo.

Evitar el I-PPE 

El propósito de lo anterior pipeline es construir y probar el código aportado, siendo seguro para el PPE. 

Entonces .. ¿Por qué no dividir el pipeline En dos ? Uno para construir y otro para probar...

  • el 1st pipeline (Construir CI) haría consulte el código PR (para construirlo), realiza la compilación y genera un artefacto.
  • El xnumxnd pipeline (Prueba de CI) haría consulte el código base (para evitar la modificación del script de shell) y ejecutar los scripts originales contra el artefacto. 
  • Para sincronizar el CI de prueba pipeline para ejecutar DESPUÉS de la compilación CI pipeline, usaremos el flujo de trabajo_ejecutar desencadenar. 
ppe8

De este modo:

  • pipeline Construir CI is seguras a ambos D-PPE (debido a pull_request_target) y I-PPE (porque ya no ejecuta el script de shell).
  • pipeline Prueba de CI También es seguras a ambos D-PPE (debido a flujo de trabajo_ejecutar) y I-PPE (porque verifica el código base para obtener el script de shell original) 

Veamos el código de ambos. pipelines según estas modificaciones…

1 pipeline (Construir CI):

name: Build CI


on:
  pull_request_target:
    branches: [ main ]


env:
  MY_Secreto: ${{ Secretos.MY_Secreto }}
  GITHUB_PAT: ${{ Secretos.GH_PAT }}
 
jobs:
               
  prt_build_and_upload:
    runs-on: ubuntu-latest
    steps:
      - name: Checking out PR code
        uses: actions/checkout@v4
        if: ${{ github.event_name == 'pull_request_target' }}
        with:
          # This is to get the PR code instead of the repo code
          ref: ${{ github.event.pull_request.head.sha }}


      - name: Building ...
        run: |
          mkdir ./bin
          touch ./bin/mybin.exe
	    # Save some PR info for later use by the 2nd pipeline
          echo "${{github.event.pull_request.title}}" > ./bin/PR_TITLE.txt
          echo "${{github.event.number}}" > ./bin/PR_ID.txt
 
	# Upload the binary as a pipeline artifact
      - name: Archive building artifacts
        uses: actions/upload-artifact@v3
        with:
          name: archive-bin
          path: |
            bin

2nd pipeline (Prueba CI):

ame: Test CI


on:
  workflow_run:
    workflows: [ 'PR TARGET CI' ]
    types: [completed]
   
env:
  MY_Secreto: ${{ Secretos.MY_Secreto }}
  GITHUB_PAT: ${{ Secretos.GH_PAT }}




jobs:
  deploy:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
 


      # By default, checks out base code (not PR code)
      - name: Checkout repository
        uses: actions/checkout@v4


	# Download the artifact
      - name: 'Download artifact'
        uses: actions/github-script@v6
        with:
          script: |
            let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
               owner: context.repo.owner,
               repo: context.repo.repo,
               run_id: context.payload.workflow_run.id,
            });
            let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
              return artifact.name == "archive-bin"
            })[0];
            let download = await github.rest.actions.downloadArtifact({
               owner: context.repo.owner,
               repo: context.repo.repo,
               artifact_id: matchArtifact.id,
               archive_format: 'zip',
            });
            let fs = require('fs');
            fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/myartifact.zip`, Buffer.from(download.data));


	# Unzip the artifact
      - name: 'Unzip artifact'
        run: |
          unzip -o myartifact.zip


      # Runs tests
      - name: Running tests ...
        id : run_tests
        run: |
          echo Running tests..
          chmod +x runtests.sh
          ./runtests.sh
          echo Tests executed.


#
      # Let’s omit the check conditions at this moment …
      #
      - name: pr_check_conditions_to_merge
        [...]

¡¡Vaya… buena solución!! Pero….. ¿Estamos a salvo? Me temo que no 😭

¡¡De hecho, hemos introducido una nueva vulnerabilidad!! ¿Cuál? Este será el tema de nuestro próximo post 🙂… ¡¡Estad atentos!! 

PS: Lo siento, no puedo quedarme callado 🤐. ¿Has oído hablar de Envenenamiento por artefactos ? 😂

Envenenamiento por artefactos e inyección de código

Una foto más profunda CI/CD PipelineVulnerabilidades (III)​

Protección contra el envenenamiento por artefactos mediante certificaciones de software

Una foto más profunda CI/CD PipelineVulnerabilidades (IV)​

Envenenado Pipeline Ejecución (PPE)

Una foto más profunda CI/CD PipelineVulnerabilidades (I)​
sca-tools-software-herramientas-de-analisis-de-composicion
Priorice, solucione y proteja sus riesgos de software
Además, te ofrecemos una prueba gratuita de 7 días de nuestra Business Edition para que puedas explorar las funciones avanzadas de la plataforma SecurityScorecard.
No se requiere tarjeta de crédito

Asegure el desarrollo y entrega de software

con la suite de productos Xygeni