otruty-pipeline-wykonanie-II

Głębokie nurkowanie w CI/CD Pipelines Podatności (II): Pośrednie zatrucie Pipeline Wykonanie (I-PPE)

W naszym poprzednim poście, zobaczyliśmy, jak wykrywać i chronić się przed bezpośrednim zatruciem Pipeline Wykonanie (D-PPE). Pokazaliśmy również, jak wykryć tę lukę za pomocą Skaner Xygenioraz pewne mechanizmy ochronne. 

 Zatrute Pipeline Wykonanie (PPE) powstaje, gdy atakujący może zmodyfikować pipeline logikę na jeden z dwóch sposobów:

  • Modyfikując plik konfiguracyjny CI ( pipeline) -> Bezpośrednie środki ochrony indywidualnej (D-PPE)
  • Modyfikując pliki, do których odwołuje się pipeline (na przykład: skrypty, do których odwołuje się użytkownik w ramach pipeline plik konfiguracyjny) -> Pośrednie środki ochrony indywidualnej (I-PPE)
pp2

W tym poście zagłębimy się w pośrednie środki ochrony indywidualnej. Ale zanim to zrobimy i jako uzupełnienie mojego poprzedniego wpisu, zobaczmy najpierw, jak GitHub zarządza wykonywaniem pipelinei jakie są mechanizmy ochrony przed D-PPE.

W jaki sposób GitHub chroni wykonywanie pipelinepochodzą z PR-ów?

Jak działa GitHub w zakresie wykonywania zmodyfikowanych pipelines?

zmodyfikowany pipelinemogą pochodzić z pchnięć lub Pull Requests (PR). Zgodnie z najlepszą praktyką zdecydowanie zaleca się unikanie bezpośredniego „wypychania” do chronionej gałęzi i używanie Pull Requests jako mechanizm wymuszający przeprowadzenie przeglądu przed zaakceptowaniem jakiegokolwiek dostarczonego kodu. 

Pull Requests mogą pochodzić z dwóch różnych źródeł:

  • PR-y pochodzące z widły
  • PR-y pochodzące z gałęzie

PR-y z widły może pochodzić z publiczny or prywatny repozytoria.

Ponieważ mamy do czynienia z PPE (środkami ochrony indywidualnej) Pipeline (Wykonanie) Naszym głównym punktem nie jest „akceptacja” PR, ale wykonanie zmodyfikowanego pipeline podczas procesu akceptacji/zatwierdzania PR. U podstaw ataku PPE leży niezamierzone wykonanie „złośliwej” modyfikacji pipeline. 

W kilku słowach, Otruty Pipeline Wykonanie (PPE) jest wykonywane, gdy atakujący może modyfikować pipeline logika.

Istnieją dwa warianty:

  • Bezpośrednie środki ochrony indywidualnej (D-ŚOI): W scenariuszu D-PPE, atakujący modyfikuje plik konfiguracyjny CI w repozytorium, do którego mają dostęp, albo poprzez bezpośrednie przesłanie zmiany do niezabezpieczonej zdalnej gałęzi w repozytorium, albo poprzez przesłanie żądania zmiany ze zmianą z gałęzi lub rozwidlenia. Od czasu CI pipeline wykonanie jest definiowane przez polecenia w zmodyfikowanym pliku konfiguracji CI, złośliwe polecenia atakującego są ostatecznie uruchamiane w węźle kompilacji po zakończeniu kompilacji pipeline jest wyzwalany.
  • Pośrednie środki ochrony indywidualnej (I-ŚOI): W pewnych przypadkach przeciwnik mający dostęp do środków ochrony indywidualnej nie ma możliwości ich zastosowania. SCM repozytorium (np. jeśli pipeline jest skonfigurowany tak, aby pobierać plik konfiguracji CI z oddzielnej, chronionej gałęzi w tym samym repozytorium). W takim scenariuszu zamiast zatruwać pipeline sam atakujący wstrzykuje złośliwy kod do plików, do których odwołuje się pipeline (na przykład: skrypty, do których odwołuje się użytkownik w ramach pipeline plik konfiguracyjny)

W obu przypadkach, GitHub wykona zmodyfikowaną wersję pipeline bez konieczności wcześniejszego przeglądu lub zatwierdzenia.

PR z widelców na publiczny repo

GitHub umożliwia konfigurację zachowania podczas przetwarzania PR-y pochodzące z rozwidleń w repozytoriach publicznych.

Gdy żądanie PR pochodzi z rozwidlenia, GitHub zawsze wymusza pewien poziom „zatwierdzenia” przed wykonaniem pipeline związany z PR. Ten poziom aprobaty zmienia się ze słabego na ścisły.

At Poziom organizacji (Org>>Ustawienia>>Akcje>>Ogólne) możesz wybrać jedną z kilku opcji „zatwierdzania”:

ppe3

Najsurowsza jest ta ostatnia („Wymagaj zatwierdzenia od wszystkich zewnętrznych współpracowników”), ponieważ GitHub zawsze będzie wymagał zatwierdzenia, gdy żądanie żądania pochodzi z rozwidleń od zewnętrznych współpracowników. 

Ale nawet w tym ścisłym przypadku istnieją różnice między współpracownikami posiadającymi uprawnienia do odczytu i zapisu.

  • Kiedy PR pochodzi od czytać użytkownik, tzw wykonanie pipeline jest ZATRZYMANE do momentu zatwierdzenia zmian. Jeśli zatwierdzenie jest pozytywne, to zmiany zostaną wprowadzone. pipeline jest wykonywany. 
  • Kiedy PR pochodzi od napisać użytkownik, tzw zatwierdzenie nie jest potrzebne i zmodyfikowane pipeline jest zawsze wykonywany !! 
pp4

Podsumowując, żądania PR pochodzące z forków w publicznych repozytoriach są słabo chronione przed PPE. Istnieje pewna ochrona przed użytkownikami zewnętrznymi (odczyt), ale nie dotyczy to użytkowników wewnętrznych (zapis).

A co z PR-y pochodzące z rozwidleń z prywatnych repozytoriów?

PR z widelców na prywatny repo

W tym scenariuszu GitHub udostępnia kilka przydatnych ustawień konfiguracyjnych.

ppe9

Powyższe ustawienia można skonfigurować w narząd lub Repo poziom.

Kiedy żadna opcja nie jest zaznaczona, GitHub będzie poproś o zgodę oraz nie wykona zmodyfikowanej pipeline. To jest najbezpieczniejsza konfiguracja!!

najniebezpieczniejsza konfiguracja jest kiedy "Uruchamianie przepływów pracy z forka pull request„jest zaznaczoneW tym przypadku dotyczy to zarówno użytkowników z uprawnieniami do odczytu, jak i zapisu. Github automatycznie wykona zmodyfikowane polecenie. pipeline!! A taka sytuacja może być nawet gorzej Jeśli "Wysyłaj tokeny zapisu do przepływów pracy z forka pull requests"I"Wysyłaj sekrety i zmienne do przepływów pracy z forka pull requests” są sprawdzane. Nie rób tego, chyba że jest to wyraźnie uzasadnione!!

Jeśli "Wymagaj zatwierdzenia dla widelca pull request przepływów pracy„jest zaznaczone, powyższa sytuacja ulega pewnemu wzmocnieniu: GitHub poprosi o zatwierdzenie i nie wykona zmodyfikowanej pipeline dla użytkownika z uprawnieniami do odczytu, ale nadal będzie wykonywany dla użytkownika z uprawnieniami do zapisu.

ppe6

Widziane widelce, co z PR-y pochodzące z oddziałów?

PR-y z gałęzie

Aby zabezpieczyć się przed tym scenariuszem, musisz polegać na Zasady ochrony oddziałów. 

Na poziomie repozytorium możesz tworzyć reguły ochrony gałęzi dla dowolnej gałęzi. Reguły te dodają kilka ograniczenia modyfikacji chronionych gałęzi.

Chociaż skonfigurujesz regułę do „Wymagaj pull request przed połączeniem"I"Wymagaj zatwierdzeń" zmodyfikowany pipeline zostanie automatycznie wykonany po utworzeniu PR„Zatwierdzenie” będzie dotyczyć wyłącznie akcji scalania.

ppe7

Co z pośrednim zatruciem? Pipeline Egzekucja

Jak widzieliśmy powyżej, skutki stosowania środków ochrony indywidualnej D-PPE można złagodzić, stosując cel_żądania_pociągnięcia, Ale nie dotyczy I-PPE.

Jeśli używasz pull_request_target, domyślnym pobraniem będzie kod bazowy. Jeśli jednak chcesz zweryfikować niektóre sprawdzenia w kodzie wniesionym (kodzie PR), musisz jawnie pobrać kod PR. W związku z tym, jeśli kod PR zmodyfikował którykolwiek skrypt powłoki wywołany przez… pipeline, „baza” (bezpieczna) pipeline wywoła „zmodyfikowany” skrypt powłoki → Pośrednie środki ochrony indywidualnej!!

Rozwiązanie tego problemu jest nieco bardziej skomplikowane (nie ma magicznego rozwiązania takiego jak pull_request_target). 

Nasza pipeline jest teraz bezpieczny dla D-PPE, ponieważ używamy pull_request_target. Nadal jednak jest podatny na I-PPE. 

W naszym przykładzie testowym musimy pobrać kod PR, aby wykonać kompilację, ale testy są wykonywane na artefakcie wygenerowanym przez kompilację. 

Więc .. dlaczego nie sprawdzisz obu baz kodów? 

  • Sprawdź kod PR, ponieważ jest to kod, który chcemy zbudować i przetestować
  • Sprawdź kod bazowy, aby uruchomić oryginalną wersję pipeline i skrypty kompilacji/testów 

Można to zrobić poprzez sprawdzanie tych baz kodów w różnych folderach:Kod bazowy może zostać przeniesiony do folderu głównego, a żądanie ściągnięcia (PR) do innego folderu. W takim przypadku wykonalibyśmy kompilację i skrypt testowy z folderu głównego, korzystając z kodu umieszczonego w nowym folderze.

To oczywiście proste rozwiązanie! Ale w celach edukacyjnych chciałbym przedstawić dość ciekawą odmianę (…) 

GitHub uruchomienie przepływu pracy zdarzenie wyzwalające

Oprócz cel_żądania_pociągnięciaGitHub udostępnia kolejne zdarzenie wyzwalające: uruchomienie przepływu pracy. To wydarzenie pozwala wykonanie pipeline warunkowany przez inny pipelinewykonanie. 

uruchomienie przepływu pracy oraz cel_żądania_pociągnięcia wyzwalacze są podobne w jednym aspekcie: oba będą wykonywane w trybie uprzywilejowanym i, pomimo modyfikacji PR, baza pipeline zostanie stracony!! 

Zobaczmy nasze obecne 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
        [...]
				
			

Sekcja konstrukcyjna jest bezpieczna dla D-PPE, jednak sekcja testowa jest nadal podatna na I-PPE.

pipeline sam w sobie jest bezpieczny dla D-PPE ze względu na cel_żądania_pociągnięcia wyzwalacz. Jednak krok testowy jest nadal podatny na atak I-PPE z powodu wywołania zewnętrznego skryptu powłoki.

Unikanie środków ochrony indywidualnej (I-PPE) 

Cel powyższego pipeline polega na budowaniu i testowaniu dostarczonego kodu, tak aby był bezpieczny dla środków ochrony indywidualnej. 

Więc .. Dlaczego nie podzielić pipeline na dwa? Jeden do budowy, a drugi do testowania..

  • 1 pipeline (Kompilacja CI) zrobiłbym sprawdź kod PR (aby go zbudować), wykonaj kompilację i wygeneruj artefakt.
  • 2nd pipeline (Test CI) zrobiłbym sprawdź kod bazowy (aby uniknąć modyfikacji skryptu powłoki) i wykonaj oryginalne skrypty na artefakcie. 
  • Aby zsynchronizować test CI pipeline uruchomić PO kompilacji CI pipeline, użyjemy uruchomienie przepływu pracy wyzwalacz. 
ppe8

W ten sposób:

  • pipeline Kompilacja CI is "bezpiecznym" do obu D-ŚOI (spowodowany cel_żądania_pociągnięcia) i I-ŚOI (ponieważ nie wykonuje już skryptu powłoki).
  • pipeline Test CI Jest również "bezpiecznym" do obu D-ŚOI (spowodowany uruchomienie przepływu pracy) i I-ŚOI (ponieważ pobiera kod bazowy w celu uzyskania oryginalnego skryptu powłoki) 

Zobaczmy kod obu pipelines zgodnie z tymi modyfikacjami …

1 pipeline (Kompilacja 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
				
			

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… niezłe rozwiązanie!! Ale… Czy jesteśmy bezpieczni? Obawiam się, że nie 😭

Rzeczywiście, wprowadziliśmy nową lukę! Jaką? To będzie tematem naszego następnego wpisu 🙂 … Bądźcie czujni!! 

PS: Przepraszam, nie mogę milczeć 🤐 ..Czy słyszałeś o Zatrucie artefaktem ?

Zatruwanie artefaktami i wstrzykiwanie kodu

Głębokie nurkowanie w CI/CD Pipelines Luki (III)​

Ochrona przed zatruciem artefaktami poprzez atesty oprogramowania

Głębokie nurkowanie w CI/CD Pipelines Luki (IV)​

Zatrute Pipeline Wykonanie (PPE)

Głębokie nurkowanie w CI/CD Pipelines Luki (I)​
sca-tools-oprogramowanie-narzędzia-analizy-kompozycji
Określ priorytety, rozwiąż problemy i zabezpiecz zagrożenia związane z oprogramowaniem
Załóż darmowe konto.
Nie wymagamy karty kredytowej.

Zabezpiecz rozwój i dostarczanie oprogramowania

z pakietem produktów Xygeni