SSRF とは何か
SSRF(Server-Side Request Forgery)は、攻撃者が用意した URL をサーバー側に取得させ、本来アクセスできないはずの内部リソースへ接続させる攻撃です。OWASP Top 10 2021 では A10:2021 - Server-Side Request Forgery として単独項目に格上げされました(2017年版にはなく、調査で多数報告された結果の格上げ)。
鍵となるのは 「サーバーはクライアントよりも強い権限とネットワーク到達範囲を持つ」という点です。クラウド環境では特に致命的で、AWS/GCP/Azure のメタデータサービスを経由して認証情報(一時クレデンシャル)を奪われると、そのクラウドアカウント全体が侵害されます。
典型的な脆弱なコード
URL を受け取って画像をプロキシ取得する、よくあるサムネイル生成 API:
# 脆弱な例(Python/Flask)
@app.route("/thumbnail")
def thumbnail():
url = request.args.get("url")
response = requests.get(url) # ← URL検証なし
return process_image(response.content)攻撃者は次の URL を送り込めます:
# AWS のインスタンスメタデータサービスを直接取得
GET /thumbnail?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
# 内部 Redis を叩く
GET /thumbnail?url=http://localhost:6379/
# 内部管理画面
GET /thumbnail?url=http://10.0.0.5/admin
# file:// で /etc/passwd を読む
GET /thumbnail?url=file:///etc/passwdクラウド IMDS を狙う攻撃(最大の脅威)
AWS/GCP/Azure には インスタンスメタデータサービス(IMDS)があり、EC2 等から特定 IP に HTTP リクエストを送るとそのインスタンスに紐づく IAM 一時クレデンシャルを取得できます。
| クラウド | メタデータエンドポイント |
|---|---|
| AWS | http://169.254.169.254/latest/meta-data/ |
| GCP | http://metadata.google.internal/ |
| Azure | http://169.254.169.254/metadata/ |
SSRF でこの内部 IP に到達できれば、EC2 にアタッチされた IAM Role の一時アクセスキー・シークレット・セッショントークンが そのまま JSON で返ってきます。攻撃者はそれを盗んで AWS API を直接叩き、S3 全件ダウンロード・DB スナップショット作成・新規 IAM ユーザー作成といった操作が可能になります。
Capital One 事件(1億件流出)
2019年に発生した Capital One(米大手銀行)の1億件流出は、SSRF が引き金となった代表的な事例です。
- WAF に SSRF 脆弱性が存在
- 攻撃者が SSRF を悪用し、EC2 メタデータから WAF にアタッチされていた IAM Role の一時クレデンシャルを取得
- そのクレデンシャルで S3 バケットをリスト・取得
- 米国のクレジットカード申込者 約1億600万件、カナダの約600万件のデータが流出
- Capital One には1億9000万ドルの和解金
この事件以降、クラウド業界での SSRF と IMDS 保護の重要性は決定的になりました。
防御1: IMDSv2 への移行(AWS)
AWS は事件を受けて IMDSv2を導入しました。IMDSv2 では、メタデータ取得前にトークン取得 PUT リクエストを必須化し、SSRF による単純な GET 攻撃を防ぎます:
# IMDSv2: まず PUT でトークン取得(TTL指定が必須)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# その後 GET にトークンをヘッダで付与
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/多くの SSRF は GET リクエストしか送れない(URL 取得型)ため、PUT を強制することで実害を大きく減らせます。さらに X-Forwarded-For ヘッダがあると IMDSv2 はリクエストを拒否し、リバースプロキシ越しの SSRF にも耐性を持たせています。
2024年以降、AWS は新規 EC2 のデフォルトを IMDSv2 のみに変更しました。既存環境は IMDSv1 を明示的に無効化することが推奨されます。
防御2: 許可リスト方式の URL 検証
ユーザー入力 URL を取得する場合、「禁止リスト」ではなく「許可リスト」で実装します。禁止リストは DNS Rebinding、IPv6 表記、10進整数表記、URL ショートナー、リダイレクトなどで容易に回避されるためです。
# 悪い例(禁止リスト方式 - 回避されやすい)
if "169.254" in url or "localhost" in url:
raise ValidationError()
# 良い例(許可リスト方式)
ALLOWED_HOSTS = {"images.example.com", "cdn.example.com"}
parsed = urlparse(url)
if parsed.hostname not in ALLOWED_HOSTS:
raise ValidationError()
if parsed.scheme not in {"http", "https"}:
raise ValidationError()防御3: 名前解決後の IP チェック
DNS Rebinding 攻撃を防ぐため、「名前解決した IP がプライベート IP 範囲かをチェック」し、外部接続前にも同じチェックを再度行います。プライベート IP には次が含まれます:
10.0.0.0/8(プライベートクラスA)172.16.0.0/12(プライベートクラスB)192.168.0.0/16(プライベートクラスC)169.254.0.0/16(リンクローカル、IMDS含む)127.0.0.0/8(ループバック)::1/128,fc00::/7,fe80::/10(IPv6 各種)
IP 範囲チェックには CIDR Calculator で許可・禁止範囲を整理しておくと検証コードに転用しやすくなります。
防御4: ネットワーク層での隔離
アプリケーション層の防御に加え、ネットワーク層でも内部リソースへの egress を制限します:
- EC2 から IMDS への到達は IAM Role が必要な特定プロセスだけに制限(ホストファイアウォール)
- VPC 内のサービスからインターネット egress を NAT Gateway 経由に集約し、egress ルールで内部 IP を遮断
- コンテナ環境では Pod の
NetworkPolicyで他 Pod・メタデータサービスへの到達を制御 - WAF レベルで
169.254.169.254等の宛先を拒否
SSRF が見つかる典型箇所
- 画像プロキシ・サムネイル生成(URL から画像取得)
- Webhook 送信機能(ユーザー指定 URL に POST)
- OAuth Discovery(issuer URL の
.well-known取得) - PDF 生成(HTML 内の
<img>をサーバー側で取得) - RSS リーダー、URL プレビュー(OGP 取得)
- SSRF 経由でクラウド API、内部管理画面、Redis/Memcached を叩く
まとめ
SSRF は「サーバーに URL を取得させる」というシンプルな手口ながら、クラウド環境では 1リクエストでアカウント全体侵害に直結する破壊力を持ちます。Capital One 事件はその実例で、教訓として AWS は IMDSv2 を導入しました。
実装時の鉄則は (1) IMDSv2 強制、(2) URL 許可リスト方式、(3) 名前解決後 IP チェック、(4) ネットワーク層 egress 制限の4段重ね。1層に穴があっても他層で止まる多層防御を構築してください。
IP 範囲の確認には CIDR Calculator、関連リスクは OWASP Top 10 入門、ネットワーク基礎は NAT とポートフォワーディングも合わせてご覧ください。