SJ blog
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のみにできる。