vergiftigd-pipeline-executie-II

Een diepe duik in CI/CD Pipelines Kwetsbaarheden (II): Indirect vergiftigd Pipeline Uitvoering (I-PPE)

In ons vorige bericht, we hebben gezien hoe je Direct Poisoned kunt detecteren en ertegen kunt beschermen Pipeline Uitvoering (D-PPE). We hebben ook gezien hoe je die kwetsbaarheid kunt detecteren met behulp van Xygeni-scanner, evenals enkele beschermingsmechanismen. 

 vergiftigde Pipeline Executie (PPE) wordt geproduceerd wanneer de aanvaller het pipeline logica op twee manieren:

  • Door het CI-configuratiebestand (de pipeline) -> Directe PBM (D-PBM)
  • Door bestanden te wijzigen waarnaar wordt verwezen door de pipeline (bijvoorbeeld: scripts waarnaar wordt verwezen vanuit de pipeline configuratiebestand) -> Indirecte PBM (I-PBM)
pp2

In dit bericht gaan we dieper in op indirecte PBM. Maar laten we eerst, als aanvulling op mijn vorige bericht, eerst kijken hoe GitHub de uitvoering beheert van pipelines en wat zijn de beschermingsmechanismen tegen D-PPE.

Hoe beschermt GitHub de uitvoering van pipelineKomt het van PR's?

Hoe werkt GitHub met betrekking tot het uitvoeren van gewijzigde pipelines?

Gewijzigd pipelines kunnen afkomstig zijn van Pushes of Pull Requests (PR). Als een belangrijke best practice wordt het ten zeerste aanbevolen om elke directe 'push' naar een beschermde branch te vermijden en Pull Requests als een mechanisme om een ​​zekere mate van controle af te dwingen voordat bijgedragen code wordt geaccepteerd. 

Pull Requests kan uit twee verschillende bronnen komen:

  • PR's komen vandaan vorken
  • PR's komen vandaan takken

PR's van vorken kan van beide afkomstig zijn publiek or privaat opslagplaatsen.

Omdat we te maken hebben met PPE (Poisoned Pipeline Uitvoering) is ons belangrijkste punt niet de “acceptatie” van een PR, maar de uitvoering van een gewijzigde PR pipeline tijdens het acceptatie-/goedkeuringsproces van de PR. De kern van een PBM-aanval is de onbedoelde uitvoering van een ‘kwaadwillige’ wijziging pipeline. 

In een paar woorden: Vergiftigd Pipeline Uitvoering (PPE) wordt geproduceerd wanneer de aanvaller kan het pipeline logica.

Er zijn er twee varianten:

  • Directe PBM (D-PPE): In een D-PPE-scenario, de aanvaller wijzigt het CI-configuratiebestand in een repository waartoe ze toegang hebben, door de wijziging rechtstreeks naar een onbeschermde externe branch op de repo te pushen, of door een PR in te dienen met de wijziging van een branch of een fork. Sinds de CI pipeline uitvoering wordt gedefinieerd door de opdrachten in het gewijzigde CI-configuratiebestand; de kwaadaardige opdrachten van de aanvaller worden uiteindelijk uitgevoerd in het build-knooppunt zodra de build is voltooid pipeline wordt geactiveerd.
  • Indirecte PBM (I-PPE): In bepaalde gevallen is de mogelijkheid van D-PPE niet beschikbaar voor een tegenstander met toegang tot een SCM repository (bijvoorbeeld als de pipeline is geconfigureerd om het CI-configuratiebestand uit een afzonderlijke, beveiligde vertakking in dezelfde repository op te halen). In een dergelijk scenario, in plaats van de pipeline zelf injecteert een aanvaller kwaadaardige code in bestanden waarnaar wordt verwezen door de pipeline (bijvoorbeeld: scripts waarnaar wordt verwezen vanuit de pipeline configuratiebestand)

In beide gevallen, GitHub zal het gewijzigde pipeline zonder dat een eerdere beoordeling of goedkeuring nodig is.

PR's vanaf vorken publiek rust

Met GitHub kunt u het gedrag tijdens de verwerking configureren PR's afkomstig van forks in openbare repository's.

Wanneer een PR afkomstig is van een fork, dwingt GitHub altijd een bepaald niveau van ‘goedkeuring’ af voordat de actie wordt uitgevoerd. pipeline verbonden aan de PR. Dit goedkeuringsniveau wisselt van een zwakke naar een strikte goedkeuring.

At Org-niveau (Org>>Instellingen>>Acties>>Algemeen), kunt u kiezen uit verschillende “goedkeurings”-opties:

ppe3

De strengste is de laatste (“Vereist goedkeuring van alle externe medewerkers”) Omdat GitHub altijd goedkeuring vereist als de PR afkomstig is van vorken van externe medewerkers. 

Maar zelfs in dit strikte geval zijn die er wel verschillen tussen bijdragers met lees- en schrijfrechten.

  • Wanneer de PR afkomstig is van a dit artikel lezen gebruiker, de uitvoering van de pipeline is gestopt totdat er goedkeuring is voor de wijzigingen. Als de goedkeuring in orde is, wordt het aangepast pipeline is geëxecuteerd. 
  • Wanneer de PR afkomstig is van a schrijven gebruiker, de goedkeuring is niet nodig en de gewijzigd pipeline wordt altijd uitgevoerd !! 
pp4

Concluderend: PR's afkomstig van forks op openbare repository's zijn lichtelijk beschermd tegen PPE. Er is enige bescherming tegen externe (lees)gebruikers, maar niets gerelateerd aan interne (schrijf)gebruikers.

Hoe zit het met PR's afkomstig van forks van privérepo's?

PR's vanaf vorken privaat rust

In dit scenario biedt GitHub enkele nuttige configuratie-instellingen.

ppe9

Bovenstaande instellingen kunnen worden geconfigureerd op Org of repo niveau.

. er is geen optie aangevinkt, GitHub zal dat doen om goedkeuring vragen en het zal de gewijzigde versie niet uitvoeren pipeline. Dit is de veiligste configuratie!!

Het onveiligste configuratie is wanneer "Workflows uitvoeren vanaf een fork pull request" is nagekeken. In dit geval, hetzelfde voor zowel lees- als schrijfgebruikers, zal Github automatisch de gewijzigde versie uitvoeren pipeline!! En deze situatie kan zelfs zijn erger als "Schrijftokens naar workflows verzenden vanaf een fork pull requests"En"Stuur geheimen en variabelen naar workflows vanuit een fork pull requests' zijn aangevinkt. Doe dit niet tenzij dit duidelijk gerechtvaardigd is!!

Als "Goedkeuring voor vork nodig pull request workflows” is aangevinkt, is de bovenstaande situatie enigszins verbeterd: GitHub zal om goedkeuring vragen en de gewijzigde versie niet uitvoeren pipeline voor de leesgebruiker, maar het wordt nog steeds uitgevoerd voor een schrijfgebruiker.

ppe6

Vorken gezien, hoe zit het? PR's afkomstig van vestigingen?

PR's van takken

Om dit scenario te beschermen, moet u erop vertrouwen Regels voor branchebescherming

Op repo-niveau kunt u voor elk filiaal filiaalbeschermingsregels maken. Deze regels voegen wat toe beperkingen voor de wijziging van beschermde takken.

Hoewel u een regel configureert om “Vereisen een pull request voor het samenvoegen"En"Goedkeuringen vereisen" de gewijzigde pipeline wordt automatisch uitgevoerd bij het maken van PR.De “goedkeuring” is alleen van toepassing op de samenvoegactie.

ppe7

Hoe zit het met indirect vergiftigd? Pipeline Uitvoering

Zoals we hierboven hebben gezien, kunnen D-PBM’s worden verzacht door het gebruik ervan pull_request_target, Maar geldt niet voor I-PPE.

Als u pull_request_target gebruikt, is de standaardafrekening de basiscode. Maar als u bepaalde controles op de bijgedragen code (PR-code) wilt valideren, moet u de PR-code expliciet afrekenen. Daarom, als de PR-code een shellscript heeft gewijzigd dat is aangeroepen door de pipeline, de “basis” (veilig) pipeline zal het “gewijzigde” shellscript aanroepen → Indirecte PPE!!

De oplossing hiervoor is iets ingewikkelder (er bestaat geen wondermiddel zoals pull_request_target). 

Het pipeline is nu veilig voor D-PPE omdat we pull_request_target gebruiken. Maar het is nog steeds kwetsbaar voor I-PPE. 

In ons testvoorbeeld moeten we in principe de PR-code uitchecken om de build te maken, maar de tests worden uitgevoerd op het artefact dat door de build wordt gegenereerd. 

Dus .. waarom bekijk je niet beide codebases? 

  • Bekijk de PR-code, want dit is de bijgedragen code die we willen bouwen en testen
  • Afrekenen Basiscode om de originele versie van het uit te voeren pipeline en de build-/testscripts 

Dit kan gedaan worden door het uitchecken van die codebases naar verschillende mappen: de basiscode kan worden uitgecheckt naar de hoofdmap en de PR naar een andere map. In dit geval zouden we de build en het testscript vanuit de hoofdmap uitvoeren op basis van de code die in de nieuwe map is geplaatst.

Dit is natuurlijk een makkelijke oplossing!! Maar voor leerdoeleinden zou ik een behoorlijk interessante variant willen introduceren (…) 

GitHub workflow_run gebeurtenis triggeren

Behalve pull_request_target, biedt GitHub nog een triggergebeurtenis: workflow_run. Dit evenement maakt het mogelijk uitvoering van een pipeline geconditioneerd voor een ander pipeline's executie

workflow_run en pull_request_target triggers zijn in één aspect vergelijkbaar: beide worden uitgevoerd in de bevoorrechte modus en, ondanks de PR-wijzigingen, de basis pipeline zal worden uitgevoerd !! 

Laten we onze stroom eens bekijken 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
        [...]

Het bouwgedeelte is veilig voor D-PPE, maar het testgedeelte is nog steeds kwetsbaar voor I-PPE.

Het pipeline zelf is veilig voor D-PPE vanwege de pull_request_target trekker. Maar de teststap is nog steeds kwetsbaar voor I-PPE vanwege het aanroepen van een extern shellscript.

I-PPE vermijden 

Het doel van het bovenstaande pipeline is het bouwen en testen van de bijgedragen code, zodat deze veilig is voor PPE. 

Dus .. Waarom splitsen we de pipeline in twee ? Eén om te bouwen en één om te testen..

  • de 1st pipeline (Bouw CI) zou bekijk de PR-code (om deze te bouwen), maak de build en genereer een artefact.
  • De 2nd pipeline (Test-CI) zou check de basiscode af (om wijziging van het shell-script te voorkomen) en voer de originele scripts uit op het artefact. 
  • Om het TestCI te synchroniseren pipeline om NA het Build CI uit te voeren pipeline, we zullen de gebruiken workflow_run aansteken, veroorzaken. 
ppe8

Op deze manier:

  • pipeline Bouw CI is veilig aan beide D-PPE (door pull_request_target) en I-PPE (omdat het niet langer het shellscript uitvoert).
  • pipeline Test-CI Ook veilig aan beide D-PPE (door workflow_run) en I-PPE (omdat het de basiscode uitcheckt om het originele shell-script te krijgen) 

Laten we de code van beide bekijken pipelines volgens deze wijzigingen …

1e pipeline (Bouw 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

2e pipeline (Test-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
        [...]

Wauw... mooie oplossing!! Maar….. Zijn we veilig? Ik ben bang van niet 😭

We hebben inderdaad een nieuwe kwetsbaarheid geïntroduceerd!! Welke? Dit zal het onderwerp zijn van ons volgende bericht 🙂 … Blijf op de hoogte!! 

PS: Sorry, ik kan niet zwijgen 🤐 ..Heb je er al van gehoord Artefactvergiftiging ?

Artefactvergiftiging en code-injectie

Een diepe duik in CI/CD Pipelines Kwetsbaarheden (III)

Bescherming tegen artefactvergiftiging via softwareattesten

Een diepe duik in CI/CD Pipelines Kwetsbaarheden (IV)

vergiftigde Pipeline Uitvoering (PPE)

Een diepe duik in CI/CD Pipelines Kwetsbaarheden (I)
sca-tools-software-compositie-analyse-tools
Prioriteer, herstel en beveilig uw softwarerisico's
Gratis proefperiode van 7-dag
Geen kredietkaart nodig

Beveilig uw softwareontwikkeling en -levering

met Xygeni-productsuite