Modern Frontend CVEs

対象CVE: GHSA-2mf3-mr2r-r4vf

[技術解説] @rhinostone/swigに潜む危険なファイル読み取り脆弱性 (GHSA-2mf3-mr2r-r4vf)

Node.jsのテンプレートエンジン`@rhinostone/swig`において、ディレクトリトラバーサル攻撃を許す脆弱性が発見されました。これにより、攻撃者はアプリケーションサーバ上の任意のファイルを読み取ることができ、機密情報の漏洩につながる可能性があります。

はじめに

Node.jsのエコシステムにおいて、Webアプリケーション開発に欠かせないのがテンプレートエンジンです。今回ご紹介する脆弱性は、人気のあるテンプレートエンジン`swig`のフォークであり、メンテナンスされている`@rhinostone/swig`に影響を与えるものです。

この脆弱性は、テンプレートのパス解決における不適切な処理により、ディレクトリトラバーサル攻撃を許してしまうというものです。結果として、攻撃者はアプリケーションが稼働するサーバ上の任意のファイルを読み取ることが可能になり、機密情報の漏洩という深刻なリスクを引き起こします。

脆弱性の概要 (GHSA-2mf3-mr2r-r4vf)

この脆弱性 (GHSA-2mf3-mr2r-r4vf) は、深刻度「High」と評価されており、元々の上流プロジェクト`swig`で追跡されていたCVE-2023-25345 / GHSA-2rq5-699j-x7p6を継承したものです。

`@rhinostone/swig`のテンプレートタグ、特に`{% include %}`、`{% extends %}`、`{% import %}`が問題となります。これらのタグは、テンプレートのパスをファイルシステムローダーを通じて解決しますが、その際に設定されたテンプレートルート(`basepath`)に結果が制限されません。これにより、`../`のようなディレクトリを遡るパスが使用されると、テンプレートルートを抜け出し、ホストファイルシステム上の任意のファイルを読み込み、その内容がレンダリング結果として出力されてしまいます。

具体的な攻撃シナリオと影響

この脆弱性の危険な点は、攻撃者がテンプレートのソースコード自体を制御する必要がないという点です。攻撃に必要なのは、レンダリング時に渡されるテンプレートの「データ」(`locals`オブジェクト)を制御できることだけです。もしアプリケーションが、信頼されたテンプレートでありながら、`include`や`extends`のパスが変数によって動的に決定される場合、この脆弱性の影響を受けます。

例えば、以下のようなアプリケーションコードとテンプレートがあったとします。 ```javascript // アプリケーションコード — 設定済みのファイルシステムローダーとbasepath swig.renderFile('page.html', { partial: req.query.partial }); ``` ```html {# page.html — 信頼されたテンプレート #} {% include partial %} ``` この場合、攻撃者がURLクエリパラメータを`?partial=../../../../etc/passwd`のように設定すると、ファイルシステムローダーはこのパスを解決し、`/etc/passwd`ファイルの内容を読み取ってレンダリング結果として出力してしまいます。もしテンプレートソース自体に`{% include "../../../etc/passwd" %}`のように直接記述されていたとしても、同様に影響を受けます。

この脆弱性による最大のインパクトは、**任意のローカルファイルの内容が漏洩する(機密性の侵害)**ことです。攻撃者はテンプレートのパスに影響を与えることができれば、アプリケーションの設定ファイル、認証情報、ソースコード、OSの重要な設定ファイル(例:`/etc/passwd`)などを読み取ることができます。ただし、データの改ざん(完全性)やサービスの停止(可用性)への直接的な影響はありません。

影響を受けるバージョンと修正済みバージョン

`@rhinostone/swig`および共有ライブラリである`@rhinostone/swig-core`、そしてそれらに依存する`@rhinostone/swig-twig`、`@rhinostone/swig-jinja2`、`@rhinostone/swig-django`の**`2.7.0`までのすべての公開バージョン**が影響を受けます。

この脆弱性は**`2.7.1`で修正されました**。ファイルシステムローダーは、設定された`basepath`ルート外に解決される`include` / `extends` / `import`パスを拒否するようになりました。ただし、`2.7.1`では、相対パスの`basepath`を使用した場合に、本来ルート内にあるべきテンプレートパスも誤って拒否してしまうという回帰バグが導入されました。

この回帰バグは**`2.7.2`でさらに修正されています**。`2.7.2`では、`basepath`がチェック前に絶対パスに解決されるようになり、ルート内のテンプレートが正しく解決されるようになりました。

したがって、**`@rhinostone/swig`を利用している場合は、`2.7.2`以降のバージョンへ速やかにアップグレードすることを強く推奨します。**

対策とワークアラウンド

最も確実な対策は、前述の通り**`@rhinostone/swig`を`2.7.2`以降のバージョンへアップグレードすること**です。これにより、ファイルシステムローダーがデフォルトでディレクトリトラバーサル攻撃を防止するようになります。

もし直ちにアップグレードができない場合は、以下のワークアラウンドを適用してください。 <ul><li>ファイルシステムローダーに、明示的な`basepath`を設定する。</li><li>信頼できないユーザーからの入力を、`{% include %}` / `{% extends %}` / `{% import %}` タグのパスに決して渡さない。</li></ul>

なお、非常に稀なケースとして意図的にルート外のファイルを読み込む必要がある場合のために、新しいローダーオプション`allowOutsideRoot`が導入されていますが、セキュリティリスクを伴うため、特別な理由がない限りは使用を避けるべきです。

まとめ

`@rhinostone/swig`のディレクトリトラバーサル脆弱性は、Node.jsアプリケーションの機密情報を危険にさらす可能性があります。多くのフロントエンドエンジニアの皆さんも、Node.jsでのバックエンド構築やビルドツールチェインで間接的に影響を受ける可能性があります。ご自身のプロジェクトで使用しているライブラリとそのバージョンを確認し、速やかに`2.7.2`以降へのアップグレードを検討してください。

開発における依存ライブラリのセキュリティチェックは、常に重要です。定期的な脆弱性スキャンや、依存関係のアップデートを怠らないようにしましょう。

参考情報

<ul><li>GHSA-2rq5-699j-x7p6: <a href="https://github.com/advisories/GHSA-2rq5-699j-x7p6" target="_blank" rel="noopener noreferrer">https://github.com/advisories/GHSA-2rq5-699j-x7p6</a></li><li>CVE-2023-25345 (NVD): <a href="https://nvd.nist.gov/vuln/detail/CVE-2023-25345" target="_blank" rel="noopener noreferrer">https://nvd.nist.gov/vuln/detail/CVE-2023-25345</a></li><li>Upstream issue (swig-templates): <a href="https://github.com/node-swig/swig-templates/issues/88" target="_blank" rel="noopener noreferrer">https://github.com/node-swig/swig-templates/issues/88</a></li><li>Fix commit: <a href="https://github.com/gina-io/swig/commit/381bdc305e0b10e45368d56324328b9b4f7017fc" target="_blank" rel="noopener noreferrer">https://github.com/gina-io/swig/commit/381bdc305e0b10e45368d56324328b9b4f7017fc</a></li></ul>

← ブログ一覧に戻る