現場のエンジニア諸君、お疲れ様。
今日はクラウドインフラの心臓部、「メタデータサービス」の話をしよう。
君たちが何気なく使っているAmazon EC2のIAMロール。aws configureもせず、なぜかAPIを叩けてしまうあの魔法のような仕組みの裏側には、実は「IMDS(Instance Metadata Service)」という強力な入り口が存在する。そしてこの入り口こそが、多くの企業を破滅に導いてきた「SSRF(Server Side Request Forgery)」という悪夢の標的なんだ。
今日は、教科書に載っているような生ぬるい解説ではなく、攻撃者がどう足元をすくい、我々がそれをどう完全に封じ込めるのか、実戦的な話をしよう。
—
1. なぜIMDSv1は「開かれたパンドラの箱」なのか
IMDSv1は、特定のIPアドレス(169.254.169.254)にHTTP GETリクエストを投げるだけで、そのインスタンスに紐付いたIAMロールの認証情報を平文で返してくれる。
攻撃者は、君たちが書いたWebアプリにたった一行のSSRF脆弱性があるだけで、このURLを叩く。
# 攻撃者がSSRF経由で実行するコマンド例
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<ロール名>
これで手に入れたAccessKeyIdとSecretAccessKey、Tokenがあれば、攻撃者はそのサーバーになりすましてAWSリソースを自由に操れる。S3バケットの全流出、RDSのデータ削除、あるいはバックドアの設置。現場で遭遇するクラウド侵害の多くは、この「メタデータの抜き取り」から始まるんだ。
2. IMDSv2による「セッションベース」の防御
この悪夢を終わらせるのが IMDSv2 だ。
IMDSv2では、メタデータを取得する前に「PUTリクエストによるセッションの確立」を要求する。SSRF脆弱性は通常GETリクエストを誘発させるものが多いため、この「PUTの壁」を挟むだけで、ほとんどの自動化された攻撃は失敗に終わる。
実践:IMDSv2を強制する設定(Terraform)
インフラレベルでv1を無効化し、v2を強制するのは基本中の基本だ。Terraformで構築しているなら、以下の設定を忘れていないか確認してほしい。
resource "aws_instance" "secure_server" {
# ... 省略 ...
metadata_options {
# IMDSv2の利用を強制する
http_tokens = "required"
# PUTリクエストのホップ数を制限(SSRF対策の強化)
http_put_response_hop_limit = 1
# v1を無効化
http_endpoint = "enabled"
}
}
3. アプリ層でのSSRF対策(Node.js/Pythonコード例)
インフラで防ぐのは大前提だが、アプリ側で「そもそも外部へのリクエストを制御する」ことも重要だ。例えば、ユーザー入力のURLをフェッチする機能を作る際、169.254.169.254をブラックリストに入れるのは素人のやることだ。
Python(Requests)での安全なリクエスト例:
import requests
from urllib.parse import urlparse
def fetch_safe_url(url):
parsed = urlparse(url)
# 許可されたドメイン以外へのアクセスを遮断する(ホワイトリスト方式)
allowed_hosts = ['api.trusted-service.com', 'images.example.com']
if parsed.netloc not in allowed_hosts:
raise ValueError("不正なホストです")
# メタデータIPへのアクセスを物理的に防ぐ
if parsed.hostname == '169.254.169.254':
raise ValueError("メタデータサービスへのアクセスは許可されていません")
return requests.get(url, timeout=2)
4. 現場のプロが教える「最後の砦」
どれだけコードを磨いても、未知の脆弱性はゼロにはならない。だからこそ、IAMロールの最小権限設定(Least Privilege)を徹底してくれ。
「とりあえず管理者権限(AdministratorAccess)を付けておこう」という甘えが、SSRFを「致命的な侵害」に変える。
- S3の特定のパスにしか書き込めないロール
- 特定のDynamoDBテーブルしか読めないロール
攻撃者がメタデータを盗み出したとしても、そのロールに何も権限がなければ、被害は「ゼロ」に抑えられる。これが多層防御の本質だ。
今日からできるアクションプラン
1. AWS CLIで確認せよ: aws ec2 describe-instances で HttpTokens が required になっているか全インスタンスをチェックする。
2. Lambdaを確認せよ: Lambdaはデフォルトで安全だが、VPC内に配置している場合はセキュリティグループでメタデータIPへのアウトバウンドを遮断しているか確認する。
3. IAMポリシーの棚卸し: 「このロール、何に使ってるんだっけ?」と問い直す。使われていない権限は即座に削除せよ。
セキュリティは「魔法のツール」を導入することではない。「穴を塞ぎ、権限を絞り、疑うこと」の繰り返しだ。泥臭い作業こそが、最強の防御になる。
さあ、今すぐコンソールを開いて、君たちのインスタンスが「裸」になっていないか確認してきてくれ。健闘を祈る。
コメント