enverinat-pipeline-execució-II

Una immersió profunda CI/CD PipelineVulnerabilitats (II): Enverinament indirecte Pipeline Execució (I-PPE)

A la nostra publicació anterior, vam veure com detectar i protegir-nos contra la intoxicació directa Pipeline Execució (D-PPE). També vam veure com detectar aquesta vulnerabilitat utilitzant Escàner Xygeni, així com alguns mecanismes de protecció. 

 Intoxicats Pipeline Execució (PPE) es produeix quan l'atacant pot modificar el pipeline lògica de dues maneres:

  • Modificant el fitxer de configuració de CI (el pipeline) -> EPI directe (D-PPE)
  • En modificar els fitxers als quals fa referència el pipeline (per exemple: scripts als quals es fa referència des de dins del pipeline fitxer de configuració) -> EPI indirecte (EPI-I)
pp2

En aquesta publicació, aprofundirem en el PPE indirecte. Però, abans d'això, i com a complement a la meva publicació anterior, vegem primer com GitHub gestiona l'execució de pipelines i quins són els mecanismes de protecció contra els D-PPE.

Com protegeix GitHub l'execució de pipelineVe de les relacions públiques?

Com funciona GitHub pel que fa a l'execució de modificacions pipelines?

Modificat pipelines poden provenir d'empentes o Pull Requests (PR). Com a pràctica recomanada, es recomana fermament evitar qualsevol "push" directe a una branca protegida i utilitzar Pull Requests com a mecanisme per imposar una revisió abans d'acceptar qualsevol codi contribuït. 

Pull Requests poden provenir de dues fonts diferents:

  • PRs procedents de forquilles
  • PRs procedents de branques

RP de forquilles pot venir de públic or privat dipòsits.

Com que tractem amb EPI (Equip de protecció individual) Pipeline Execució), el nostre punt principal no és l'"acceptació" d'una RP sinó l'execució d'una modificada pipeline durant el procés d'acceptació/aprovació del PR. Al centre d'un atac EPI, hi ha l'execució no intencionada d'un dispositiu modificat "maliciós" pipeline. 

En poques paraules, enverinat Pipeline L'execució (PPE) es produeix quan l'atacant pot modificar el pipeline lògica.

Hi ha dos variants:

  • EPI directe (D-PPE): En un escenari D-PPE, l'atacant modifica el fitxer de configuració de CI en un repositori al qual tenen accés, ja sigui enviant el canvi directament a una branca remota no protegida del repositori o enviant una PR amb el canvi des d'una branca o una bifurcació. Des de la CI pipeline l'execució està definida per les ordres del fitxer de configuració de CI modificat, les ordres malicioses de l'atacant finalment s'executen al node de compilació un cop la compilació pipeline s'activa.
  • EPI indirecte (I-PPE): En certs casos, la possibilitat de D-PPE no està disponible per a un adversari amb accés a un SCM repositori (per exemple, si el pipeline està configurat per extreure el fitxer de configuració de CI d'una branca protegida separada al mateix repositori). En un escenari així, en lloc d'enverinar el pipeline en si mateix, un atacant injecta codi maliciós als fitxers als quals fa referència pipeline (per exemple: scripts als quals es fa referència des de dins del pipeline fitxer de configuració)

En ambdós casos, GitHub executarà el fitxer modificat pipeline sense necessitat de revisió ni aprovació prèvia.

RPs de forquilles enceses públic descans

GitHub permet configurar el comportament durant el processament PRs provinents de forks en repositoris públics.

Quan una PR prové d'una bifurcació, GitHub sempre força algun nivell d'"aprovació" abans d'executar-la. pipeline associat amb el PRAquest nivell d'aprovació alterna entre una aprovació feble i una aprovació estricta.

At Nivell d'organització (Org >>Configuració >>Accions >>General), podeu triar entre diverses opcions d'"aprovació":

ppe3

El més estricte és l'últim (“Requerir l'aprovació de tots els col·laboradors externs") perquè GitHub sempre requerirà aprovació quan la PR provingui de forks de col·laboradors externs. 

Però fins i tot en aquest cas estricte, hi ha diferències entre col·laboradors amb permisos de lectura i escriptura.

  • Quan la RP prové d'un llegir usuari, l' execució del pipeline està ATURAT fins que hi hagi una aprovació dels canvis. Si l'aprovació és correcta, aleshores els canvis modificats pipeline s'executa. 
  • Quan la RP prové d'un escriure usuari, l' no cal aprovació i la modificació pipeline sempre s'executa!! 
pp4

En conclusió, les PR que provenen de forks en repositoris públics estan lleugerament protegides contra el PPE. Hi ha alguna protecció contra usuaris externs (de lectura), però res relacionat amb usuaris interns (d'escriptura).

I què passa amb PRs provinents de forks de repositoris privats?

RPs de forquilles enceses privat descans

En aquest escenari, GitHub proporciona alguns paràmetres de configuració útils.

ppe9

Els paràmetres anteriors es poden configurar a òrgan o en repo nivell.

Quan? no hi ha cap opció marcada, GitHub ho farà demanar aprovació i no executarà la modificació pipelineAquesta és la configuració més segura!!

L' configuració més insegura és quan "Executar fluxos de treball des de la bifurcació pull request"està marcatEn aquest cas, igual per a usuaris de lectura i escriptura, Github executarà automàticament la modificació. pipeline!! I aquesta situació pot ser fins i tot pitjor si "Enviar tokens d'escriptura a fluxos de treball des de la bifurcació pull requests"I"Enviar secrets i variables a fluxos de treball des de la fork pull requests"estan marcats. No ho feu si no està clarament justificat!!

Si "Cal aprovació per a la forquilla pull request fluxos de treball"està marcat, la situació anterior millora una mica: GitHub demanarà aprovació i no executarà la modificació pipeline per a l'usuari de lectura, però encara l'executarà per a un usuari d'escriptura.

ppe6

Forquilles vistes, què passa? PRs provinents de sucursals?

RP de branques

Per protegir aquest escenari, heu de confiar en Normes de protecció de sucursals

A nivell de repositori, podeu crear regles de protecció de branques per a qualsevol branca. Aquestes regles afegeixen algunes restriccions a la modificació de branques protegides.

Tot i que configureu una regla per a "Requereix a pull request abans de la fusió"I"Requereix aprovacions", el modificat pipeline s'executarà automàticament en crear la PRL'"aprovació" només s'aplicarà a l'acció de fusió.

ppe7

Què passa amb l'enverinament indirecte? Pipeline Execució

Com hem vist anteriorment, el D-PPE es pot mitigar mitjançant l'ús de sol·licitud_d'extracció_objectiu, però no s'aplica a l'EPI intern.

Si feu servir pull_request_target, la comprovació per defecte serà el codi base. Però si voleu validar algunes comprovacions del codi contribuït (codi PR), heu de comprovar explícitament el codi PR. Per tant, si el codi PR ha modificat algun script de shell invocat pel pipeline, la «base» (segura) pipeline invocarà l'script de shell "modificat" → PPE indirecte!!

La solució a això és una mica més complicada (no hi ha una bala màgica com pull_request_target). 

El nostre pipeline ara és segur per a D-PPE perquè estem utilitzant pull_request_target. Però encara és vulnerable a I-PPE. 

En el nostre exemple de prova, bàsicament necessitem revisar el codi PR per fer la compilació, però les proves s'executen sobre l'artefacte generat per la compilació. 

Tan .. Per què no consultes les dues bases de codi? 

  • Codi PR de Checkout perquè és el codi contribuït que volem construir i provar.
  • Codi base de comprovació per executar la versió original del pipeline i els scripts de compilació/proves 

Això es podria fer per revisant aquestes bases de codi a diferents carpetes: el codi base es pot desar a la carpeta arrel i el PR a una carpeta diferent. En aquest cas, executaríem l'script de compilació i de prova des de la carpeta arrel amb el codi col·locat a la carpeta nova.

Aquesta és una solució fàcil, és clar!! Però, per a fins d'aprenentatge, m'agradaria introduir una variant força interessant (…) 

GitHub execució_flux_de_treball esdeveniment desencadenant

A més de sol·licitud_d'extracció_objectiu, GitHub proporciona un altre esdeveniment desencadenant: execució_flux_de_treballAquest esdeveniment permet execució d'una pipeline condicionat a un altre pipelinel'execució

execució_flux_de_treball i sol·licitud_d'extracció_objectiu Els disparadors són similars en un aspecte: tots dos s'executaran en mode privilegiat i, malgrat les modificacions de les relacions públiques, la base pipeline serà executat!! 

Vegem el nostre actualitat pipeline:

				
					name: PR TARGET CI


on:
  pull_request_target:
    branches: [ main ]


env:
  MY_SECRET: ${{ secrets.MY_SECRET }}
 
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ó de construcció és segura per al D-PPE, però la secció de prova encara és vulnerable al I-PPE.

L' pipeline en si mateix és segur per a D-PPE a causa de la sol·licitud_d'extracció_objectiu desencadenant. Però el pas de prova encara és vulnerable a I-PPE a causa de la invocació d'un script de shell extern.

Evitar l'EPI intrauterí 

La finalitat de l'anterior pipeline és construir i provar el codi contribuït, sent segur per a l'EPI. 

Tan .. Per què no dividir el pipeline en dos? Un per construir i un altre per provar..

  • El 1st pipeline (Crea CI) faria consulta el codi PR (per construir-lo), fes la construcció i genera un artefacte.
  • El 2n pipeline (Prova de CI) faria Revisar el codi base (per evitar la modificació de scripts de shell) i executar els scripts originals contra l'artefacte. 
  • Per sincronitzar el CI de prova pipeline per executar DESPRÉS del CI de compilació pipeline, utilitzarem el execució_flux_de_treball disparador. 
ppe8

D'aquesta manera:

  • pipeline Crea CI is segur a tots dos D-PPE (degut a sol·licitud_d'extracció_objectiu) I I-PPE (perquè ja no executa l'script de shell).
  • pipeline Prova de CI és també segur a tots dos D-PPE (degut a execució_flux_de_treball) I I-PPE (perquè revisa el codi base per obtenir l'script de shell original) 

Vegem el codi de tots dos pipelinesegons aquestes modificacions…

1st pipeline (Construcció de CI):

				
					name: Build CI


on:
  pull_request_target:
    branches: [ main ]


env:
  MY_SECRET: ${{ secrets.MY_SECRET }}
  GITHUB_PAT: ${{ secrets.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 (Prova de CI):

				
					ame: Test CI


on:
  workflow_run:
    workflows: [ 'PR TARGET CI' ]
    types: [completed]
   
env:
  MY_SECRET: ${{ secrets.MY_SECRET }}
  GITHUB_PAT: ${{ secrets.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
        [...]

				
			

Ostres... bona solució!! Però... Estem fora de perill? Em temo que no 😭

Sí, hem introduït una nova vulnerabilitat!! Quina? Aquest serà el tema de la nostra propera publicació 🙂 … Estigueu atents!! 

PS: Ho sento, no puc callar 🤐 .. Has sentit a parlar d'això Intoxicació per artefactes ? 😂

Enverinament per artefactes i injecció de codi

Una immersió profunda CI/CD PipelineVulnerabilitats (III)

Protecció contra la intoxicació per artefactes mitjançant atestacions de programari

Una immersió profunda CI/CD PipelineVulnerabilitats (IV)

Intoxicats Pipeline Execució (EPI)

Una immersió profunda CI/CD PipelineVulnerabilitats (I)
sca-tools-software-composition-analyse-tools
Prioritzar, solucionar i protegir els riscos del programari
Obtén el teu compte gratuït.
No es requereix cap targeta de crèdit.

Assegura el desenvolupament i el lliurament del teu programari

amb el paquet de productes Xygeni