[解説] Novuの深刻なXSS脆弱性(GHSA-26wg-9xf2-q495)とフロントエンドにおける対策
はじめに:Novuの深刻なXSS脆弱性とは
こんにちは、日本のフロントエンドエンジニアの皆さん。今回は、オープンソースの通知インフラNovuで報告された、深刻度「High」のCross-Site Scripting (XSS) 脆弱性(GHSA-26wg-9xf2-q495)について深く掘り下げていきます。この脆弱性は、悪意のあるHTMLコードがメールプレビューなどを通じて実行され、ユーザーのセッションハイジャックや情報漏洩につながる可能性があり、単なるSelf-XSS以上の危険性を孕んでいます。自身の開発プロジェクトで似たような入力値のサニタイズ処理を行っている場合、他人事ではありません。本記事でそのメカニズムと対策を理解し、よりセキュアなアプリケーション開発に役立てましょう。
脆弱性の詳細:なぜXSSがすり抜けたのか?
この脆弱性の核心は、Novuが内部的に使用している`sanitize-html`ライブラリの設定ミスにあります。通常、HTMLコンテンツを扱う際には、悪意のあるスクリプトが埋め込まれないようにサニタイズ処理を施しますが、Novuの実装には以下の不備がありました。
`sanitize-html`の初期設定では、`allowedAttributes: false`と指定されていたため、デフォルトですべてのHTML属性が許可されてしまっていました。この後、`DANGEROUS_ATTRIBUTES`というブラックリストを用いて危険な属性を除外しようと試みていますが、このリストが不完全だったのです。
具体的には、HTML5で追加された`oncontentvisibilityautostatechange=`のような新しいイベントハンドラ属性が`DANGEROUS_ATTRIBUTES`リストに含まれていなかったため、サニタイズ処理をすり抜けてしまいます。これにより、攻撃者はメールの内容などに悪意のあるJavaScriptコードを埋め込み、Novuのダッシュボード上でそのコードを実行させることが可能となります。例えば、`<img src=x onerror=alert(document.cookie)>`のような古典的なXSSだけでなく、より高度なイベントハンドラを利用したペイロードも実行される可能性があります。
攻撃シナリオ:Self-XSSにとどまらない深刻な影響
この脆弱性は、一見すると自分自身に影響するSelf-XSS(自分で悪意のあるコードを入力して、自分のブラウザで実行される)のように思えるかもしれませんが、以下に示すように、より深刻なリスクがあります。
Novuのダッシュボードが複数ユーザーによってアクセスされる環境(例:チームメンバーが共有で利用)の場合、攻撃者がXSSペイロードを仕込んだメールテンプレートや編集画面のURLを共有することで、他のユーザーに直接XSSをトリガーさせることが可能です。被害者がそのURLを開くと、攻撃者のJavaScriptコードが実行され、被害者のセッション情報が盗まれたり、任意の操作が行われたりするリスクがあります。
さらに巧妙な手口として、攻撃者はGoogleやGitHubなどのOAuth認証フローを悪用することができます。攻撃者は、認証コールバックを完了させない状態の「不完全なOAuthリダイレクトURL」を作成し、これを被害者に送りつけます。
被害者がこのURLをクリックすると、OAuthプロバイダーによる認証は行われますが、その後のリダイレクト処理によって、**意図せず攻撃者のNovuアカウントにログインさせられてしまいます。** 攻撃者は、この自分のアカウントにあらかじめXSSペイロードを仕込んでいるため、ログインした被害者のブラウザでそのXSSが発動します。結果として、被害者のブラウザ上のNovuセッションが乗っ取られ、Cookie情報が盗まれたり、個人情報が漏洩したりする可能性があります。これは非常に悪質で、ユーザーの予期しない形で攻撃が成立するため、注意が必要です。
フロントエンドエンジニアが取るべき対策
このようなXSS脆弱性は、フロントエンド開発において常に警戒すべき脅威です。以下の対策を徹底しましょう。
`DANGEROUS_ATTRIBUTES`のようなブラックリスト方式を使用している場合は、そのリストを最新かつ包括的なものに更新し、既知のすべての危険なHTML属性およびイベントハンドラが確実にフィルタリングされるようにしてください。HTML5以降に追加された属性や、ブラウザごとの解釈の違いにも注意を払う必要があります。
セキュリティのベストプラクティスとして、危険な属性をブラックリストで除外するのではなく、「許可する安全なタグと属性のみをホワイトリストで明示的に指定する」方式へサニタイズロジックを変更することを強く推奨します。これにより、将来的に新たな脆弱な属性が発見された場合でも、デフォルトでブロックされるため、安全性が格段に向上します。
ユーザーからの入力値(特にHTMLコンテンツ)は、クライアントサイドでのサニタイズだけでなく、サーバーサイドでも厳格な検証を行い、不正な形式や危険なコンテンツが含まれていないことを確認してください。クライアントサイドの対策はバイパスされる可能性があるため、サーバーサイドでの「最後の砦」としての検証が不可欠です。
Novuのようなオープンソースプロジェクトや、自身が利用しているライブラリについて、公式のアナウンスやセキュリティ情報を常に監視し、この脆弱性に対する修正パッチがリリースされた場合は、速やかに適用してください。最新のバージョンを利用することは、セキュリティ対策の基本中の基本です。
まとめ
今回のNovuのXSS脆弱性は、サニタイズ処理の設計ミスや、新しいWeb標準への追従の遅れが原因で発生しました。フロントエンドエンジニアとしては、単にライブラリを使うだけでなく、その内部的な挙動や設定、そして最新のWeb技術動向を理解し、常にセキュリティを意識した開発を行うことが求められます。特に、ユーザーが提供するコンテンツを表示する機能を持つアプリケーションでは、XSS対策は最優先事項の一つです。本記事が、皆さんの安全なWebアプリケーション開発の一助となれば幸いです。