vergiftet-pipeline-Ausführung-II

Ein tiefes Eintauchen in CI/CD Pipelines Schwachstellen (II) : Indirekte Vergiftung Pipeline Ausführung (I-PPE)

In unserem vorherigen Beitrag, Wir haben gesehen, wie man direkte Vergiftungen erkennt und sich davor schützt Pipeline Ausführung (D-PPE). Wir haben auch gesehen, wie man diese Schwachstelle erkennt, indem man Xygeni-Scanner, sowie einige Schutzmechanismen. 

 Vergiftet Pipeline Ausführung (PSA) entsteht, wenn der Angreifer die pipeline Logik auf eine der beiden Arten:

  • Durch Ändern der CI-Konfigurationsdatei (die pipeline) -> Direkte PSA (D-PSA)
  • Durch die Änderung von Dateien, auf die von pipeline (Beispiel: Skripte, auf die innerhalb des pipeline Konfigurationsdatei) -> Indirekte PSA (I-PSA)
pp2

In diesem Beitrag werden wir uns eingehend mit Indirekter PSA befassen. Aber vorher und als Ergänzung zu meinem vorherigen Beitrag wollen wir uns zunächst ansehen, wie GitHub die Ausführung von verwaltet pipelines und welche Schutzmechanismen gibt es gegen D-PSA?

Wie schützt GitHub die Ausführung von pipelines kommt von PRs?

Wie funktioniert GitHub hinsichtlich der Ausführung geänderter pipelines?

Geändert pipelines können von Pushes kommen oder Pull Requests (PR). Als bewährte Methode wird dringend empfohlen, direkte Push-Vorgänge in geschützte Zweige zu vermeiden und stattdessen Pull Requests als Mechanismus, um eine Überprüfung durchzusetzen, bevor beigesteuerter Code akzeptiert wird. 

Pull Requests kann aus zwei verschiedenen Quellen stammen:

  • PRs kommen von Gabeln
  • PRs kommen von Geäst

PRs von Gabeln kann kommen entweder aus Öffentlichkeit or privat Repositories.

Da es sich um PSA (Vergiftete Pipeline Ausführung), unser Hauptanliegen ist nicht die „Akzeptanz“ einer PR, sondern die Ausführung einer modifizierten pipeline während des Akzeptanz-/Genehmigungsprozesses des PR. Im Kern eines PPE-Angriffs steht die unbeabsichtigte Ausführung eines „böswilligen“ modifizierten pipeline. 

In wenigen Worten: Poisoned Pipeline Ausführung (PPE) wird erzeugt, wenn Der Angreifer kann die pipeline Logik.

Es gibt zwei Varianten:

  • Direkte PSA (D-PSA): In einem D-PPE-Szenario Der Angreifer ändert die CI-Konfigurationsdatei in einem Repository, auf das sie Zugriff haben, entweder indem sie die Änderung direkt in einen ungeschützten Remote-Zweig im Repository pushen oder indem sie einen PR mit der Änderung von einem Zweig oder Fork übermitteln. Da die CI pipeline Die Ausführung wird durch die Befehle in der geänderten CI-Konfigurationsdatei definiert. Die bösartigen Befehle des Angreifers werden letztendlich im Build-Knoten ausgeführt, sobald der Build pipeline ausgelöst wird.
  • Indirekte PSA (I-PSA): In bestimmten Fällen steht einem Gegner mit Zugang zu einer SCM Repository (z. B. wenn die pipeline ist so konfiguriert, dass die CI-Konfigurationsdatei aus einem separaten, geschützten Zweig im selben Repository abgerufen wird). In einem solchen Szenario, anstatt die pipeline selbst injiziert ein Angreifer bösartigen Code in Dateien, auf die von der pipeline (Beispiel: Skripte, auf die innerhalb des pipeline Konfigurationsdatei)

In beiden Fällen, GitHub führt die geänderte pipeline ohne dass eine vorherige Überprüfung oder Genehmigung erforderlich ist.

PRs von Forks auf Öffentlichkeit repos

GitHub ermöglicht die Konfiguration des Verhaltens bei der Verarbeitung PRs aus Forks in öffentlichen Repos.

Wenn ein PR von einem Fork kommt, erzwingt GitHub immer ein gewisses Maß an „Genehmigung“, bevor der pipeline im Zusammenhang mit der PR. Diese Zustimmungsstufe reicht von einer schwachen bis zu einer strengen Zustimmung.

At Organisationsebene (Org>>Einstellungen>>Aktionen>>Allgemein) können Sie zwischen mehreren „Genehmigungs“-Optionen entscheiden:

ppe3

Am strengsten ist der letzte („Genehmigung aller externen Mitarbeiter einholen“), da GitHub immer eine Genehmigung erfordert, wenn der PR von Forks externer Mitarbeiter stammt. 

Aber selbst in diesem strengen Fall gibt es Unterschiede zwischen Mitarbeitern mit Lese- und Schreibberechtigungen.

  • Wenn die PR von einem besuch Benutzer, der Ausführung der pipeline ist gestoppt bis eine Genehmigung der Änderungen vorliegt. Wenn die Genehmigung in Ordnung ist, werden die geänderten pipeline ausgeführt wird. 
  • Wenn die PR von einem schreiben Benutzer, der Eine Genehmigung ist nicht erforderlich und die geänderten pipeline wird immer ausgeführt !! 
pp4

Zusammenfassend lässt sich sagen, dass PRs aus Forks in öffentlichen Repositorien nur geringfügig gegen PPE geschützt sind. Gegen externe (Lese-)Benutzer besteht ein gewisser Schutz, gegen interne (Schreib-)Benutzer jedoch nicht.

Wie wäre es mit PRs aus Forks von privaten Repos?

PRs von Forks auf privat repos

In diesem Szenario stellt GitHub einige nützliche Konfigurationseinstellungen bereit.

ppe9

Die obigen Einstellungen können entweder unter Org oder Repo Ebene.

Wenn die Funktion Keine Option ist aktiviert, GitHub wird um Zustimmung bitten und es wird nicht ausgeführt werden die geänderten pipeline. Dies ist die sicherste Konfiguration!!

Die unsichere Konfiguration ist, wenn "Ausführen von Workflows vom Fork pull request" wird geprüft. In diesem Fall, für Lese- und Schreibbenutzer gleich, führt Github automatisch die geänderte pipeline!! Und diese Situation kann sogar schlimmer wenn "Senden Sie Schreibtoken vom Fork an Workflows pull requests" und "Senden Sie Geheimnisse und Variablen von Fork an Workflows pull requests” sind angekreuzt. Tun Sie dies nicht, es sei denn, es ist eindeutig gerechtfertigt!!

Wenn "Genehmigung für Fork erforderlich pull request Workflows” aktiviert ist, wird die obige Situation etwas verbessert: GitHub wird um Genehmigung bitten und die geänderten pipeline für den Lesebenutzer, wird es aber trotzdem für einen Schreibbenutzer ausgeführt.

ppe6

Gabeln gesehen, was ist mit PRs aus Zweigstellen?

PRs von Geäst

Um dieses Szenario zu schützen, müssen Sie sich verlassen auf Regeln zum Schutz von Zweigstellen

Auf Repo-Ebene können Sie Branch-Schutzregeln für jeden Branch erstellen. Diese Regeln fügen einige Einschränkungen bei der Änderung geschützter Zweige.

Obwohl Sie eine Regel konfigurieren, um „Benötigen pull request vor dem Zusammenschluss" und "Genehmigungen erforderlich" die geändert pipeline wird automatisch bei PR-Erstellung ausgeführtDie „Genehmigung“ gilt nur für die Zusammenführungsaktion.

ppe7

Was ist mit indirekt vergifteten Pipeline Ausführung

Wie wir oben gesehen haben, kann D-PPE gemildert werden durch den Einsatz von Pull_Anfrage_Ziel, Aber es gilt nicht für I-PSA.

Wenn Sie pull_request_target verwenden, wird standardmäßig der Basiscode ausgecheckt. Wenn Sie jedoch einige Prüfungen des beigesteuerten Codes (PR-Code) validieren möchten, müssen Sie den PR-Code explizit auschecken. Wenn der PR-Code also ein Shell-Skript geändert hat, das vom pipeline, die „Basis“ (sicher) pipeline ruft das „modifizierte“ Shell-Skript auf → Indirekte PSA!!

Die Lösung hierfür ist etwas komplizierter (es gibt kein Allheilmittel wie pull_request_target). 

Unsere pipeline ist jetzt sicher für D-PPE, da wir pull_request_target verwenden. Aber es ist immer noch anfällig für I-PPE. 

In unserem Testbeispiel müssen wir den PR-Code grundsätzlich auschecken, um den Build zu erstellen, aber die Tests werden auf dem vom Build generierten Artefakt ausgeführt. 

Damit .. warum schaust du dir nicht beide Codebasen an? 

  • Checkout PR-Code, denn der beigesteuerte Code ist das, was wir erstellen und testen möchten
  • Checkout Base-Code zur Ausführung der Originalversion des pipeline und die Build/Test-Skripte 

Dies könnte geschehen durch Auschecken dieser Codebasen in verschiedene Ordner: Der Basiscode wird möglicherweise in den Stammordner und der PR in einen anderen Ordner ausgecheckt. In diesem Fall würden wir den Build und das Testskript aus dem Stammordner für den Code ausführen, der im neuen Ordner abgelegt wurde.

Dies ist natürlich eine einfache Lösung!! Aber zu Lernzwecken möchte ich eine recht interessante Variante vorstellen (…) 

GitHub workflow_run auslösendes Ereignis

Neben Pull_Anfrage_Zielbietet GitHub ein weiteres Trigger-Ereignis: workflow_runDieses Ereignis ermöglicht Ausführung eines pipeline konditioniert zu einem anderen pipeline's Hinrichtung

workflow_run und Pull_Anfrage_Ziel Trigger sind in einem Punkt ähnlich: beide werden im privilegierten Modus ausgeführt und, trotz der PR-Änderungen, die Basis pipeline wird durchgeführt !! 

Sehen wir uns unsere aktuelle 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
        [...]

Der Build-Abschnitt ist sicher gegenüber D-PPE, der Testabschnitt ist jedoch weiterhin anfällig gegenüber I-PPE.

Die pipeline selbst ist sicher für D-PPE aufgrund der Pull_Anfrage_Ziel Auslöser. Der Testschritt ist jedoch aufgrund des Aufrufs eines externen Shell-Skripts immer noch anfällig für I-PPE.

Vermeidung von I-PSA 

Der Zweck der oben genannten pipeline besteht darin, den beigesteuerten Code zu erstellen und zu testen und dabei die persönliche Schutzausrüstung zu verwenden. 

Damit .. Warum teilen wir nicht die pipeline in zwei ? Einer zum Erstellen und einer zum Testen..

  • Die 1st pipeline (Erstellen Sie CI) würde checke den PR-Code aus (um ihn zu erstellen), erstellen Sie den Build und generieren Sie ein Artefakt.
  • Der 2nd pipeline (Test-CI) würde Checken Sie den Basiscode aus (um Shell-Skriptänderungen zu vermeiden) und führen Sie die Originalskripts für das Artefakt aus. 
  • So synchronisieren Sie das Test-CI pipeline zur Ausführung NACH dem Build CI pipelinewerden wir die verwenden workflow_run auslösen. 
ppe8

Auf diese Weise:

  • pipeline Erstellen Sie CI is Safe zu beiden D-PSA (durch Pull_Anfrage_Ziel) und I-PSA (weil es das Shell-Skript nicht mehr ausführt).
  • pipeline Test-CI ist auch Safe zu beiden D-PSA (durch workflow_run) und I-PSA (weil es den Basiscode auscheckt, um das ursprüngliche Shell-Skript zu erhalten) 

Schauen wir uns den Code beider an pipelines gemäß diesen Modifikationen …

1. pipeline (CI erstellen):

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

2. 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
        [...]

Wow… schöne Lösung!! Aber ….. Sind wir sicher? Ich fürchte, nein 😭

Tatsächlich haben wir eine neue Schwachstelle eingeführt!! Welche? Dies wird das Thema unseres nächsten Beitrags sein 🙂 … Bleiben Sie dran!! 

PS: Tut mir leid, ich kann nicht still sein 🤐 ..Hast du gehört von Artefaktvergiftung ? 😂

Artefaktvergiftung und Code-Injektion

Ein tiefes Eintauchen in CI/CD Pipelines Schwachstellen (III)​

Schutz vor Artifact Poisoning durch Software-Bescheinigungen

Ein tiefes Eintauchen in CI/CD Pipelines Schwachstellen (IV)​

Vergiftet Pipeline Ausführung (PSA)

Ein tiefes Eintauchen in CI/CD Pipelines Schwachstellen (I)​
SCA-Tools-Software-Zusammensetzungs-Analyse-Tools
Priorisieren, beheben und sichern Sie Ihre Softwarerisiken
7-Tage kostenlose Testversion
Keine Kreditkarte erforderlich

Sichern Sie Ihre Softwareentwicklung und -bereitstellung

mit der Xygeni-Produktsuite