Modern Frontend CVEs

対象CVE: GHSA-v42f-v8xc-j435

[技術解説] BudibaseのSSRF脆弱性:undici利用におけるDNSリバインディングの落とし穴

BudibaseのRESTデータソースで発見された深刻度HighのSSRF脆弱性について解説します。Node.jsのHTTPクライアントである`node-fetch`と`undici`の挙動の違いが、どのようにDNSリバインディング攻撃を可能にしてしまったのかを深掘りし、フロントエンドエンジニアが学ぶべき教訓を考察します。

はじめに:Node.jsアプリケーションに潜むSSRFの脅威

皆さん、こんにちは。今回は、一見フロントエンドとは直接関係なさそうに見えるものの、現代のJavaScriptエコシステム全体に深く関わるNode.jsアプリケーションの深刻な脆弱性「GHSA-v42f-v8xc-j435」について解説します。この脆弱性は、Low権限のユーザーでも利用可能なDNSリバインディングを利用したServer-Side Request Forgery(SSRF)で、Budibaseというオープンソースのローコード開発プラットフォームで発見されました。しかし、その根本原因は、異なるHTTPクライアントライブラリ(`node-fetch`と`undici`)の挙動の違いにあり、Node.jsで開発を行う全てのエンジニアにとって重要な教訓を含んでいます。

SSRFとDNSリバインディングの基本

まず、今回の脆弱性を理解するために必要な2つの基本的な概念を解説します。

SSRFは、攻撃者がサーバーに対して、意図しないリクエストを内部ネットワーク内の他のサービスや、サーバー自身に向けて送信させる脆弱性です。これにより、通常は外部からアクセスできない内部リソース(データベース、管理画面、クラウドのメタデータサービスなど)にアクセスし、機密情報の窃取や不正な操作が可能になることがあります。

DNSリバインディングは、DNSレコードのTTL(Time-To-Live)を短く設定し、DNS解決のタイミングによって異なるIPアドレスを返すことで、セキュリティ機構を騙す攻撃手法です。具体的には、

1. サーバーがURLのバリデーションを行う際(防御側が「安全な」IPアドレスとして認識しているパブリックIPアドレスを返す)。

2. 実際にHTTPリクエストを送信する際(攻撃対象となる内部IPアドレスやループバックアドレスを返す)。

という時間差(TOCTOU: Time-Of-Check To Time-Of-Use)を利用して、外部からのアクセスは制限されている内部リソースへのアクセスを可能にします。

脆弱性の詳細:なぜ保護が迂回されたのか?

Budibaseには、SSRF/DNSリバインディングを防ぐための強力なセキュリティガード`fetchWithBlacklist`が存在しました。このガードは、以下のような仕組みで機能するように設計されていました。

つまり、一度検証された安全なIPアドレスに対してのみリクエストが送られるはずでした。実際、デフォルトの`node-fetch`を使用するパスでは、このピン留めが正常に機能していました。

問題は、BudibaseのRESTデータソース統合が、HTTPクライアントとして**`undici`**ライブラリの`fetch`を使用していた点にあります。`undici`は高性能なHTTP/1.1およびHTTP/2クライアントとして注目されていますが、**Node.jsの標準的な`agent`オプションをサイレントに無視する**という特性があります。

RESTデータソースは`undici`の`fetch`を呼び出す際に、独自の`dispatcher`オプションを設定していました。この`dispatcher`は、接続時に改めてDNS解決を行うため、`fetchWithBlacklist`が生成した「ピン留めされたIPアドレス」は完全に無視されてしまいました。

結果として、以下のシナリオが可能になりました。

このように、異なるHTTPクライアントライブラリの挙動の違いが、既存のセキュリティ対策を迂回する結果を招いてしまったのです。

脆弱性の影響と深刻度

この脆弱性の深刻度はHigh(CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H)と評価されています。具体的な影響は以下の通りです。

フロントエンドエンジニアが学ぶべき教訓

この脆弱性はバックエンドに起因するものですが、Node.jsでツール開発やSSG、SSRなどを行っているフロントエンドエンジニアにとっても、非常に重要な教訓を投げかけます。

表面的なAPIが似ていても、内部で利用しているHTTPクライアントライブラリ(`node-fetch`や`undici`など)が異なると、低レベルなネットワーク挙動に違いが生じることがあります。特に、DNS解決、接続の管理、プロキシの扱いなどはセキュリティに直結するため、安易にライブラリを切り替えたり、新しいライブラリを導入する際は、その内部挙動まで深く理解することが不可欠です。

開発中のアプリケーションが直接利用するライブラリだけでなく、そのライブラリがさらに依存している間接的なライブラリ(推移的依存)にも注意を払う必要があります。今回のケースでは、Budibaseが`undici`を採用したことで、既存のセキュリティ機構が予期せず無効化されてしまいました。依存関係ツリーを定期的に確認し、脆弱性が報告されていないかをチェックする習慣をつけましょう。

フロントエンドからバックエンドのAPIを叩く際、どのようなパラメータを渡すか、そのパラメータがバックエンドでどのように処理されるかについて、より深いセキュリティ意識を持つことが重要です。URLやドメイン名をユーザー入力から受け取るようなケースでは、バックエンド側で厳格な検証が必須であることを理解し、開発者間で協力してセキュリティを確保する必要があります。

利用しているフレームワーク、ライブラリ、プラットフォームのセキュリティ情報を常にチェックし、脆弱性が報告された際には、迅速にアップデートを適用することが重要です。これにより、既知の脆弱性を悪用した攻撃からアプリケーションを保護できます。

まとめ

今回のBudibaseのSSRF脆弱性は、一見些細に見えるHTTPクライアントライブラリの選択が、アプリケーション全体のセキュリティに壊滅的な影響を与えうることを示しています。Node.jsエコシステムは進化が速く、新しいライブラリや技術が次々と登場しますが、その利便性の裏には、細かな挙動の違いや未知の落とし穴が潜んでいる可能性があることを忘れてはなりません。

私たちフロントエンドエンジニアも、もはや「ブラウザの中だけ」のセキュリティを考えていれば良い時代ではありません。Node.jsを使った開発が増える中で、バックエンド寄りのセキュリティ知識も積極的に学び、より堅牢で安全なアプリケーション開発に貢献していきましょう。

← ブログ一覧に戻る