[緊急解説] Node.jsのSSRF脆弱性「GHSA-j4rj-2jr5-m439」について - フロントエンド開発者も要注意!
はじめに:なぜフロントエンドエンジニアもこの脆弱性に関心を持つべきなのか
皆さんはじめまして。今回は、Node.jsのエコシステムにおいて見過ごせない、非常に危険なサーバーサイドリクエストフォージェリ(SSRF)の脆弱性「GHSA-j4rj-2jr5-m439 / CVE-2026-43929」について解説します。フロントエンドエンジニアの方々は「SSRFはバックエンドの話では?」と思われるかもしれません。しかし、BFF(Backend For Frontend)やNode.jsベースのサーバーサイドレンダリング(SSR)、あるいは画像最適化などの各種ユーティリティでNode.jsを使用している場合、この脆弱性が直接あなたのアプリケーションに影響を及ぼす可能性があります。
`ssrfcheck`というライブラリは、Node.jsアプリケーションがユーザーから提供されたURLを外部にリクエストする際に、私的IPアドレスなどへのアクセスを防ぎ、SSRF攻撃を予防するためのものです。しかし、このライブラリに致命的な欠陥が発見されました。この脆弱性が悪用されると、クラウド環境の機密情報窃取や内部ネットワークへの不正アクセスなど、甚大な被害につながる恐れがあります。自身の開発環境やデプロイされているサービスにこのライブラリが使われていないか、今一度確認し、適切な対策を講じることが急務です。
脆弱性の概要:`ssrfcheck`ライブラリの盲点
この脆弱性は、Node.jsの`ssrfcheck`ライブラリのv1.3.0(およびそれ以前の全バージョン)に存在します。深刻度は「High」と評価されており、認証や特別な権限なしに攻撃が可能です。具体的には、`isSSRFSafeURL()`関数が特定の形式のURLを誤って「安全である」と判断してしまうことで、SSRF防御を迂回されてしまいます。
脆弱性の仕組み:IPv4-mapped IPv6アドレスと正規表現のミスマッチ
この脆弱性の核心は、Node.jsのWHATWG URLパーサーと`ssrfcheck`ライブラリ内部のIPアドレス検証ロジックとの間のミスマッチにあります。
攻撃者は、私的IPアドレス(例: `127.0.0.1`や`192.168.1.1`)を「IPv4-mapped IPv6アドレス」という特殊な形式でエンコードしたURLを使用します。例えば、`http://[::ffff:127.0.0.1]/` のような形式です。
Node.js v10以降に組み込まれているWHATWG URLパーサーは、このようなURLを解析する際に、内部的にドット(.)で区切られたIPv4部分を16進数表記に正規化します。つまり、`127.0.0.1` は `7f00:1` のように変換され、結果的にURLは `http://[::ffff:7f00:1]/` のような形になります。
問題はここからです。`ssrfcheck`ライブラリは、内部で私的IPアドレスを検出するために正規表現を使用しています。この正規表現は、従来のドット表記のIPv4アドレス形式を前提に設計されているため、WHATWG URLパーサーによって正規化された「16進数表記のIPv4アドレス」にはマッチしません。
結果として、`isSSRFSafeURL()`関数は、本来ブロックすべき私的IPアドレスを含むURLを「安全である(true)」と誤って判断し、アプリケーションが意図しない内部リソースへのリクエストを許可してしまうのです。
具体的なリスクと影響を受けるシステム
この脆弱性の影響を受けるのは、以下の条件をすべて満たすNode.jsアプリケーションです。
1. `ssrfcheck`ライブラリのv1.3.0またはそれ以前のバージョンを使用している。
2. Node.js v10以上で稼働している。
3. ユーザーから提供されるURLを検証し、その後そのURLへHTTPリクエストを行う機能がある。
具体的なリスクシナリオは以下の通りです。
AWS、GCP、Azureなどのクラウド環境では、`http://169.254.169.254/latest/meta-data/` のような特定のIPアドレスを通じてインスタンスのメタデータサービスにアクセスし、一時的な認証情報やその他の機密情報を取得することが可能です。攻撃者は、このIPアドレスをIPv4-mapped IPv6アドレス形式(例: `http://[::ffff:169.254.169.254]/latest/meta-data/`)で指定し、クラウド環境の機密情報を盗み出すことができます。
攻撃者は、インターネットに公開されていない内部ネットワーク上のサービス(例: `http://[::ffff:192.168.1.1]/admin`)へアクセスし、脆弱なサービスを悪用したり、機密情報を収集したりすることが可能になります。
サーバー自身の`127.0.0.1`にバインドされたサービス(例: データベース、管理コンソールなど)へのアクセスも可能になります。これにより、データベースの内容の不正取得やサーバーの設定変更などが行われる可能性があります。
推奨される対応策
この深刻な脆弱性に対し、以下の対応策を速やかに検討・実施してください。
`ssrfcheck`ライブラリの作者は、この問題を解決するために、手動で作成された正規表現の代わりにNode.jsに組み込まれている`net.BlockList`APIを使用する修正案を提案しています。`net.BlockList`はIPアドレスを数値として処理するため、URLパーサーによる文字列表記の正規化に影響されず、より堅牢なチェックが可能です。
`ssrfcheck`ライブラリの修正版がリリースされたら、**速やかにアップデートを適用してください**。あるいは、より堅牢なSSRF対策を提供する代替ライブラリへの移行も検討してください。依存関係スキャンツールなどで`ssrfcheck`がプロジェクトに含まれていないか確認しましょう。
もし、すぐにライブラリのアップデートが難しい場合、ユーザー入力のURLを外部サービスへリクエストする前に、URLの`hostname`部分を別途詳細に検証する追加のロジックを実装することを検討してください。具体的には、IPv4-mapped IPv6アドレスが、内部IPアドレス範囲(RFC1918 Private Address Spaceやループバックアドレス、リンクローカルアドレスなど)にマッピングされていないかを独自にチェックする必要があります。ただし、これは複雑で、実装ミスによる新たな脆弱性を生むリスクが高いため、あくまで一時的な回避策としてください。
まとめ
今回の`ssrfcheck`の脆弱性は、一見すると安全に見えるライブラリにも潜む、予期せぬリスクを浮き彫りにしました。Node.jsを使用しているフロントエンドエンジニアの皆さんにとって、自身のアプリケーションが間接的であれNode.jsのバックエンドやユーティリティに依存している場合、このような脆弱性は決して他人事ではありません。
ライブラリの依存関係を定期的にチェックし、セキュリティ情報を常にキャッチアップする習慣を身につけることが、安全なアプリケーション開発の鍵となります。この脆弱性はCWE-918 (Server-Side Request Forgery) と CWE-184 (Incomplete List of Disallowed Inputs) に該当します。速やかな対応で、皆さんのサービスをSSRF攻撃から守りましょう。