EC2 のメタデータ 169.254.169.254 の正体 - リンクローカルアドレスと IMDSv2 の設計

EC2 インスタンスメタデータサービスのエンドポイント 169.254.169.254 がリンクローカルアドレスである理由、SSRF 攻撃で悪用された歴史、IMDSv2 のトークンベース認証が生まれた経緯を解説します。

169.254.169.254 はどこにあるのか

EC2 インスタンスの内部から http://169.254.169.254/latest/meta-data/ にアクセスすると、インスタンス ID、AMI ID、IAM ロールの一時認証情報、ネットワーク設定など、インスタンスに関するメタデータが返されます。この 169.254.169.254 というアドレスは、インターネット上のサーバーではなく、Nitro System のハイパーバイザーが提供するローカルサービスです。169.254.0.0/16 は RFC 3927 で定義されたリンクローカルアドレスで、ルーターを越えて転送されない特殊なアドレス範囲です。つまり、このアドレスへのリクエストはインスタンスの外に出ることなく、ハイパーバイザーが直接応答します。この設計により、メタデータサービスはネットワーク障害の影響を受けず、VPC のルーティング設定にも依存しません。インスタンスが起動した瞬間から、ネットワーク設定が完了する前でも、メタデータサービスにアクセスできます。cloud-init がインスタンスの初期設定を行う際に、最初にメタデータサービスからユーザーデータやネットワーク設定を取得するのは、この信頼性の高さがあるからです。

Capital One 事件 - SSRF でメタデータが漏洩した日

2019 年 7 月、Capital One (米国の大手銀行) で約 1 億人の個人情報が漏洩する事件が発生しました。攻撃者は、Capital One の Web アプリケーションに存在した SSRF (Server-Side Request Forgery) 脆弱性を悪用し、EC2 インスタンスのメタデータサービスから IAM ロールの一時認証情報を取得しました。SSRF は、サーバーサイドのアプリケーションに任意の URL へのリクエストを実行させる攻撃です。攻撃者は Web アプリケーションに http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name というリクエストを送信させ、IAM ロールのアクセスキー、シークレットキー、セッショントークンを取得しました。この認証情報を使って S3 バケットにアクセスし、大量の個人情報をダウンロードしました。この事件は、IMDSv1 (Instance Metadata Service Version 1) の設計上の弱点を浮き彫りにしました。IMDSv1 は単純な HTTP GET リクエストでメタデータを返すため、SSRF 攻撃で容易にアクセスできてしまいます。

IMDSv2 - トークンベース認証による防御

Capital One 事件を受けて、AWS は 2019 年 11 月に IMDSv2 (Instance Metadata Service Version 2) をリリースしました。IMDSv2 は、メタデータへのアクセスにセッショントークンを要求するトークンベースの認証方式です。IMDSv2 でメタデータを取得するには、まず PUT リクエストでセッショントークンを取得し、そのトークンを HTTP ヘッダーに含めて GET リクエストを送信する必要があります。この 2 ステップの認証が SSRF 攻撃を防ぐ理由は、ほとんどの SSRF 脆弱性が GET リクエストしか実行できないためです。PUT リクエストを実行できる SSRF 脆弱性は稀であり、さらにレスポンスヘッダーからトークンを抽出して次のリクエストに含めるという複雑な操作が必要です。加えて、IMDSv2 のトークン取得リクエストには X-aws-ec2-metadata-token-ttl-seconds ヘッダーが必須で、IP フォワーディングされたリクエスト (TTL が 1 に設定されるため、ネットワークホップを越えられない) もブロックされます。2024 年以降、AWS は新規インスタンスのデフォルトを IMDSv2 のみに変更しており、IMDSv1 を無効化することを強く推奨しています。

メタデータで取得できる情報の全体像

メタデータサービスから取得できる情報は多岐にわたります。インスタンスの基本情報 (instance-id、instance-type、ami-id、hostname)、ネットワーク情報 (local-ipv4、public-ipv4、mac、network/interfaces)、IAM ロールの一時認証情報 (iam/security-credentials/role-name)、ユーザーデータ (user-data)、ブロックデバイスマッピング (block-device-mapping) などです。特に重要なのは IAM ロールの一時認証情報です。EC2 インスタンスに IAM ロールをアタッチすると、メタデータサービスから一時的なアクセスキー、シークレットキー、セッショントークンが取得できます。AWS SDK はこの仕組みを内部で自動的に使用しており、開発者がアクセスキーをコードにハードコードする必要がありません。一時認証情報は自動的にローテーションされ、有効期限は通常 6 時間です。メタデータサービスにはインスタンスのユーザーデータも含まれます。ユーザーデータはインスタンス起動時に指定するスクリプトやデータで、cloud-init が初期設定に使用します。ユーザーデータにパスワードやシークレットを含めるのは危険です。メタデータサービス経由で誰でも読み取れるためです。

メタデータサービスのセキュリティ強化策

IMDSv2 の有効化に加えて、メタデータサービスのセキュリティを強化する方法がいくつかあります。第 1 に、HttpPutResponseHopLimit を 1 に設定することです。これにより、コンテナ内からのメタデータアクセスがブロックされます。ECS や Docker コンテナ内のアプリケーションがメタデータサービスにアクセスする必要がない場合、ホップ制限を 1 にすることで、コンテナからの SSRF 攻撃を防げます。第 2 に、メタデータサービス自体を無効化することです。HttpEndpoint を disabled に設定すれば、メタデータサービスへのアクセスが完全にブロックされます。IAM ロールの認証情報が不要なインスタンス (固定の認証情報を使用する場合) では、メタデータサービスを無効化するのが最も安全です。第 3 に、IAM ロールの権限を最小限にすることです。メタデータサービスから認証情報が漏洩しても、そのロールの権限が最小限であれば被害を限定できます。Capital One 事件では、漏洩したロールが S3 バケットへの広範なアクセス権限を持っていたことが被害を拡大させました。EC2 のセキュリティ設計を体系的に学ぶには、専門書籍 (Amazon)が参考になります。