flawopen.com/SSRF/Node.js fetch()とSSRF
Node.jsのfetch()はSSRFを防ぎますか?
いいえ。サーバー側のfetch()はサーバーから通信します。呼び出し元が宛先を選べると、自分では届かないシステムへサーバーを向かわせる可能性があります。住所を確認せずに信頼できる配達員へ配送を頼むようなものです。リスクはネットワーク、権限、URL方針、リダイレクトに左右されます。
providerIdなどの利用者選択を、アプリが設定した接続先へ固定対応させます。任意URLを受け取りません。根本原因:利用者が選んだ宛先をサーバーが信頼
Node.jsのfetch()は汎用HTTPクライアントで、SSRFポリシーを決めません。ブラウザーのCORSもサーバーの接続先を制限しません。URLの解析だけでは不十分です。許可した名前が禁止IPに解決されることや、応答が別ホストへ転送することがあります。利用者指定のアバター、Webhook、文書、プレビュー取得が入口になり得ます。
リクエストが信頼境界を越える流れ
利用者がURLに影響する
画像プレビューなどのため、完全なURLまたは構築に使えるデータをエンドポイントが受け取ります。
サーバーが通信する
HTTPクライアントはサーバーのネットワーク経路、DNS、proxy、プロセス権限を使います。
転送応答で宛先が変わる
Fetchは既定でリダイレクトに追従します。最初に許可した接続先がLocationで禁止ホストを示すことがあります。
応答から到達可能な情報が漏れる
ネットワークとポリシー次第で内部サービスやクラウドメタデータへ届きます。すべてのfetchで起きるわけではありません。
Node.jsの危険な例と安全性を高めた例
// 呼び出し元指定の任意URLを取得しない。
const response = await fetch(userProvidedUrl);
// 呼び出し元が選ぶのはキーであり、宛先ではない。
const destinations = new Map([
["status", new URL("https://status.example/")],
["docs", new URL("https://docs.example/")],
]);
const target = destinations.get(providerId);
if (!target) throw new Error("Unknown provider");
const response = await fetch(target, {
redirect: "error",
signal: AbortSignal.timeout(3000),
});
if (!response.ok) throw new Error("Upstream request failed");
利用者がURLを入力する必要がある場合
可能ならprovider IDを受け取り、固定宛先マップから要求を作ります。任意の公開URLが必要なら、必要なschemeとportだけ許可し、user-info、loopback、private、link-local、および禁止IPv4/IPv6を拒否します。全DNS応答を検証し、再検証されないDNS lookupなしに確認済みIPへ接続します。自動リダイレクトを無効化するか各遷移を検証します。169.254.169.254と有効なIPv6メタデータ宛先を含む送信制御も適用。時間、応答サイズ、並列数を制限し、内部資格情報を転送しません。
SSRF防止チェックリスト
- ✓任意URLを避け、検証済みprovider keyをアプリ管理の固定宛先へ対応させます。
- ✓
https:と必要なportだけ許可し、URL資格情報、想定外host、IP直書き、禁止rangeを拒否します。 - ✓
redirect: "error"で転送を止めます。必要なら各接続前に宛先を検証します。 - ✓A/AAAA応答をすべて検証し、host名検証を保ったまま接続を確認済みIPへ固定します。retryやproxyにも適用。
- ✓送信firewall/proxyでloopback、private、link-local、metadataをIPv6も含め遮断。アプリ検査だけに依存しません。
- ✓時間、応答byte数、並列数を制限し、Cookie、認可header、クラウド資格情報を転送しません。
- ✓AWSでは追加防御としてIMDSv2を必須化しmetadataアクセスを制限します。URL・送信制御の代わりにはなりません。
よくある質問
いいえ。リダイレクト、IPv4/IPv6表記、DNS rebinding、proxy、解決から接続までの競合で単純検査を回避されます。固定許可リストを優先し、任意宛先なら全IPを検証して接続先を固定し、ネットワーク出口でも制御します。
いいえ。IMDSv2のtoken手順は一部リスクを減らしますが、設定次第で他の内部サービスやmetadataへ届く可能性があります。宛先と送信の制御は継続してください。
一次資料
- OWASP — SSRF防止チートシート
- Node.js — グローバルfetch API
- WHATWG Fetch標準 — リダイレクトモード
- AWS — EC2インスタンスメタデータの設定
- CWE-918 — Server-Side Request Forgery