1. SSRF とは #what-is
サーバ側の URL fetcher を悪用して、攻撃者が選んだ URL を読みに行かせる。
典型例:うつろい EC の「商品画像 URL を貼ると自動取込」機能。
POST /api/products/{id}/import-image
{ "url": "https://supplier.example/cosmetics/cream.jpg" }
// サーバ側
$content = file_get_contents($_POST['url']);
file_put_contents('/var/www/uploads/' . $id . '.jpg', $content);
意図はサプライヤサイトからの画像取込。攻撃者が次のような URL を送ると:
http://localhost:6379/— サーバ内部の Redis に到達http://192.168.1.100/admin— 同じネットワークの管理画面http://169.254.169.254/latest/meta-data/iam/— AWS のメタデータ(IAM 認証情報を含む)file:///etc/passwd— サーバ内のファイル(プロトコル制限なしの場合)
2. なぜ危険か — 内部ネットワークへの侵入 #why-dangerous
外から到達できないサービスに、Web アプリ経由で到達される。
本番環境では「外向け Web サーバ」と「内部 DB / 内部管理画面 / Redis」がネットワーク的に分離されています。SSRF はこの境界を破ります。
- 内部 DB(認証なしで自由にクエリできる Redis、Memcached)
- 内部管理画面(社内 IP からのアクセスだから認証なしの Jenkins、Kibana 等)
- クラウド・メタデータ — AWS / GCP / Azure の IAM トークン
- 同一サーバ上のサービス(Sidecar、ローカルプロキシ)
3. クラウド・メタデータエンドポイント #cloud-metadata
169.254.169.254 から認証情報が漏洩する。AWS、GCP、Azure いずれも「インスタンス自身の情報を返すメタデータ API」を提供しており、リンクローカルアドレス 169.254.169.254 でアクセスできます。SSRF でここに到達されると、IAM トークンが漏洩 → AWS アカウント全体が乗っ取られる重大事案に。
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2-WebServer-Role
=> { "AccessKeyId": "ASIA...", "SecretAccessKey": "...", "Token": "FwoGZXIvYXdz..." }
2019 年の Capital One 事案(1億件以上の顧客情報漏洩)も、SSRF からのメタデータ窃取が起点でした。AWS では IMDSv2 を強制(セッショントークン必須)することで、単純な GET ベースの SSRF を緩和できます。
4. よくあるフィルタ回避 #bypass
「内部 IP は禁止」のチェックが甘いと回避される。
- 10進形式:
http://2130706433/=http://127.0.0.1/ - 16進・8進:
http://0x7f000001/やhttp://0177.0.0.1/ - DNS リバインディング:攻撃者がコントロールするドメインで、初回検証時は public IP を返し、実際のリクエスト時は
127.0.0.1を返す - サブドメイン:
http://localhost.attacker.com/が DNS で127.0.0.1に解決される - URL パーサの差:
http://expected.com#@evil.com/等、パーサの解釈の違いを突く
5. 正しい防御 #defense
ホワイトリスト + 名前解決後の IP チェック + ネットワーク分離。
- 許可ドメインのホワイトリスト — 任意 URL を受け付けるのではなく、信頼できる外部ドメインだけ許す
- 名前解決後の IP チェック — DNS で得た IP が プライベート/loopback/リンクローカル なら拒否
- HTTP/HTTPS のみ許可 — file:、gopher:、dict: 等のスキームを禁止
- ネットワークレベルの分離 — Web アプリのアウトバウンド先を NAT/プロキシで限定
- クラウド側の対策 — IMDSv2、メタデータエンドポイントへのアクセスをホワイトリストで制限