security
A
信頼度ランク
| S | 公式ソース確認済み |
| A | 成功実績多数・失敗例少数 |
| B | 賛否両論 |
| C | 動作未確認・セキュリティリスク高 |
| Z | 個人所感 |
EC2 IMDSv2 — v1との違い・SSRF攻撃対策・強制設定方法
EC2インスタンスメタデータサービスのIMDSv1とIMDSv2の違い、セッション指向のトークン方式によるSSRF攻撃対策、IMDSv2の強制設定方法、アクセス制限の設定を解説。
一言結論
IMDSv2はPUTトークン取得を必須化することでSSRF攻撃によるIAMクレデンシャル漏洩を防ぐため、すべてのEC2インスタンスでhttp-tokens=requiredに設定し、SCPでIMDSv1を組織全体で禁止することが最善策だ。
インスタンスメタデータサービス(IMDS)とは
EC2インスタンスはリンクローカルアドレス 169.254.169.254 からインスタンスの情報を取得できる。
# インスタンスのIAMクレデンシャルを取得(悪用リスクあり)
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# → ロール名が返る
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/MyRole
# → AccessKeyId, SecretAccessKey, Token, Expiration が返る
このエンドポイントへのアクセスは同一ネットワーク内からのみ可能だが、SSRF(Server-Side Request Forgery)脆弱性があるWebアプリケーションを経由して攻撃者がクレデンシャルを盗める可能性がある。
IMDSv1の問題点
IMDSv1では認証なしで直接メタデータにアクセスできる。
攻撃シナリオ:
1. 攻撃者がSSRF脆弱性のあるWebアプリに細工したリクエストを送信
2. WebアプリがSSRF経由で 169.254.169.254 にリクエスト
3. IAMクレデンシャルが攻撃者に漏洩
4. 攻撃者がAWSリソースを不正操作
IMDSv2の仕組み
IMDSv2はセッション指向のトークン方式を使う。まずトークンを取得し、以降はそのトークンを付けてメタデータにアクセスする。
# ステップ1: セッショントークンを取得
TOKEN=$(curl -s -X PUT \
"http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# ステップ2: トークンを付けてメタデータを取得
curl -s \
"http://169.254.169.254/latest/meta-data/iam/security-credentials/MyRole" \
-H "X-aws-ec2-metadata-token: $TOKEN"
PUTリクエストでトークンを取得する仕組みにより:
- SSRF攻撃では通常GETリクエストのみが転送され、PUTは転送されない
- ブラウザからのCSRFでもPUTは送信されない
- WAFのSSRF防御と組み合わせてさらに強固にできる
IMDSv2の強制設定
インスタンスレベルとアカウントレベルで設定できる。
# 既存インスタンスでIMDSv2を強制
aws ec2 modify-instance-metadata-options \
--instance-id i-xxx \
--http-tokens required \
--http-put-response-hop-limit 1 \
--http-endpoint enabled
# 新規インスタンス起動時にIMDSv2を強制
aws ec2 run-instances \
--image-id ami-xxx \
--instance-type t3.micro \
--metadata-options '{
"HttpTokens": "required",
"HttpPutResponseHopLimit": 1,
"HttpEndpoint": "enabled"
}'
HttpPutResponseHopLimit: 1 はコンテナからのアクセスをブロックする設定だ(TTL=1でコンテナの外に出られない)。コンテナ内からのIMDSアクセスが必要な場合は2以上に設定する。
アカウントレベルでのデフォルト設定
# アカウントのデフォルトでIMDSv2を強制(新規インスタンスに適用)
aws ec2 modify-instance-metadata-defaults \
--http-tokens required \
--http-put-response-hop-limit 2 \
--instance-metadata-tags enabled
IMDSの無効化
メタデータへのアクセスが不要な場合は完全に無効化できる。
aws ec2 modify-instance-metadata-options \
--instance-id i-xxx \
--http-endpoint disabled
SCP/IAMでIMDSv1を禁止
// SCP: IMDSv1(http-tokens=optional)を禁止
{
"Statement": [{
"Effect": "Deny",
"Action": [
"ec2:RunInstances",
"ec2:ModifyInstanceMetadataOptions"
],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringEquals": {
"ec2:MetadataHttpTokens": "optional"
}
}
}]
}
IMDSv1の使用を検出
# CloudTrail + EventBridgeでIMDSv1使用を検出
# CloudWatch Logsのメトリクスフィルターで検出
# AWS Security Hubでも検出可能(EC2.8チェック)
aws securityhub describe-standards-controls \
--standards-subscription-arn arn:aws:securityhub:ap-northeast-1:123456789012:subscription/aws-foundational-security-best-practices/v/1.0.0 \
--query 'Controls[?ControlId==`EC2.8`]'
インスタンスメタデータで取得できる情報
# 主要なメタデータ
curl .../latest/meta-data/instance-id # インスタンスID
curl .../latest/meta-data/instance-type # インスタンスタイプ
curl .../latest/meta-data/public-ipv4 # パブリックIP
curl .../latest/meta-data/placement/region # リージョン
curl .../latest/meta-data/iam/security-credentials/ # IAMクレデンシャル
curl .../latest/user-data # ユーザーデータ(起動スクリプト)
試験頻出ポイント
- IMDSv2はPUT→GETの2ステップトークン方式でSSRF対策
http-tokens: requiredでIMDSv2を強制(v1は使えなくなる)hop-limit: 1でコンテナからのアクセスを防止- IMDSv1からv2への移行はダウンタイムなしで変更可能
- VPCフローログにはIMDSアクセス(169.254.169.254)は記録されない
まとめ
IMDSv2は既存インスタンスでも変更可能で、すべてのEC2インスタンスで有効化することが推奨される。SCPでIMDSv1を禁止することで組織全体で強制的にv2のみにできる。