株式会社セキュアイノベーション
Menu

セキュリティ技術BLOG

    公開:2022.07.11 12:00 | 更新: 2022.11.08 01:24

    X-XSS-Protectionの引退に備えCSP導入を検討しよう

    目次

    X-XSS-Protectionヘッダとは

    ブラウザが万が一反射型クロスサイトスクリプティング(以下XSS)攻撃にさらされてしまった場合に、ページの読み込みを停止するように指示するレスポンスヘッダのことです。XSSタイプとしては、反射型以外にも格納型、DOMベース型も存在しているため、当該ヘッダを導入したからといって、すべてのタイプのXSS攻撃を防止するものではないことに注意してください。

    X-XSS-Protectionヘッダの引退理由

    今回なぜこのヘッダが引退(使用されることがなくなる)することになるかと言いますと、MDN webdocsによると、このヘッダをサポートしているブラウザが、IE8以上、Safari、Edge 12から16まで、Chrome 4から77までとなっており、最新のブラウザについてはサポートされていないからです。マイクロソフトのアナウンスによるとIE11においては2022年6月16日にサポート終了しています。またChrome 77のリリース日を確認すると、2019年9月10日となっており、すでに古いブラウザとなっております。なんらかの状況で古いブラウザを使用せざる得ない環境においても、サポート切れのブラウザを使用続けるのは非常に危険であり、後述しますCSPヘッダの導入を検討をしていくべきです。

    X-XSS-Protectionの抱える問題

    XSS対策としては、基本的にはユーザからの入力値をサニタイズ(無害化)することでスクリプト実行を防止するのが基本的な対策となりますが、万が一サニタイズ漏れがあった場合の保険的対策としては有効であり、これまでレガシーブラウザをサポートするために使用されてきました。

    しかし最新のブラウザについては、このヘッダをサポートしておらずXSS攻撃を許してしまうという問題を抱えております。実際にいくつかの最新ブラウザと当該ヘッダを使用して、XSS攻撃からブラウザが保護されるのか検証してみました。

    各ブラウザでX-XSS-Protection効果を検証

    検証に使用するブラウザ

    • IE11
    • Firefox 100.0
    • Chrome 101.0.4951.64
    • Edge 101.0.1210.39

    検証に使用したXSSの脆弱性を持つウェブアプリケーション

    XSSに対して脆弱性なウェブアプリケーションの例

    今回検証に使用するウェブアプリケーションは、ユーザがメッセージを投稿すると、そのメッセージがそのまま画面出力されます。

    検証においては、以下のURLにアクセスすることで反射型XSS攻撃が成立するかどうかを判断します。

    検証に使用する反射型XSSを引き起こすための疑似攻撃コードを含んだURL

    http://xss-csp.test.local/xss_protection_test.php?msg=<script>alert(1);</script>

    パラメータ「msg」にアラートを表示するためのスクリプト<script>alert(1);</script>を埋め込んでいます。

    IPアドレス「xss-csp.test.local」は、検証用に使用したローカル上のウェブサーバです。

    レスポンスヘッダにセットするヘッダ

    X-XSS-Protection: 1; mode=block

    X-XSS-Protection: 1;は、ブラウザに対してXSSフィルタを有効にすることを指示します。
    mode=blockでは、XSSフィルタが反射型XSSを検知した場合に、ページの読み込みをしないように指示しています。

    それでは、各ブラウザでX-XSS-Protectionヘッダがサーバレスポンスに含まれていた場合の挙動を見ていきましょう。IE11は、XSSフィルタが既定の状態で常に有効になっています。検証時はX-XSS-Protectionヘッダを受信時にXSSフィルタを有効にしたいので、インターネットオプションからXSSフィルタは無効にしておきます。

    XSS filterは無効に設定した状態で検証

    IE11

    反射型XSSを検知し、ページの内容が読み込まれず「#」という文字が表示されました。結果、XSS攻撃は無効化されました。

    IE11がXSSをブロックした様子

    Firefox 100.0

    疑似攻撃コードを含んだURLにアクセスすると、アラートがポップアップされました。確かにX-XSS-Protectionヘッダでは、XSS攻撃からブラウザを保護することができませんでした。

    Chrome 101.0.4951.64

    疑似攻撃コードを含んだURLにアクセスすると、アラートがポップアップされました。

    Edge 101.0.1210.39

    疑似攻撃コードを含んだURLにアクセスすると、アラートがポップアップされました。

    以上の結果から確かにX-XSS-Protectionヘッダでは、最新のブラウザをXSSから保護がされないことが分かりました。そのため最新のブラウザで対応するには、CSP(Content Security Policy)ヘッダの導入を検討する必要があります。

    CSP(Content Security Policy)ヘッダでのXSS対策例

    CSPヘッダでは、インラインスクリプト(HTML内にJSスクリプトをコーディングすること)を禁止する指示を出すことにより、反射型のみならず格納型、DOM型のXSS対策をすることが可能です。注意すべきことは、レガシーブラウザは当該ヘッダをサポートしていないため、XSS攻撃を許してしまいます。

    XSS対策をするための一番基本的なCSPヘッダの設定は以下の通りです。この例では、自サイト内のJSファイルのみからスクリプトを読み込み・実行を許可するポリシーです。もしブラウザが、このポリシーに違反していると判断するとスクリプト実行がブロックされます。今回は、こちらの設定例を使用してヘッダ検証を行います。

    Content-Security-Policy: script-src 'self'

    しかしjQuery等の外部ホストからJSファイルを読み込みたい場合もあるかと思います。その場合には、以下のように読込先のドメイン名を設定できます。

    Content-Security-Policy: script-src 'self' code.jquery.com

    最新ブラウザを使ったCSPヘッダ動作の検証

    さきほどと同様に反射型XSSを引き起こす疑似攻撃コードを含むURLにアクセスしてアラートが表示されるかを検証していきます。

    IE11

    スクリプト実行によりアラートのポップアップが確認できたことから、XSS攻撃に成功しました。IE11はCSPをサポートしているものの、「Content-Security-Policy」ヘッダではなく、「X-Content-Security-Policy」ヘッダとsandboxディレクティブを付加する必要があります。しかしsandboxディレクティブのみでは柔軟なポリシー設定ができないので、他の最新ブラウザ同様にサポートしていくのは難しいと考えられます。特別な理由のない限り、今後はIE11のサポート廃止を検討するべきです。

    Firefox 100.0

    ウェブディベロッパーツールのConsoleタブを確認すると、Content Security PolicyによりJS実行がブロックされたことが確認できました。

    Chrome 101.0.4951.64

    ChromeにおいてもCSPヘッダによりインラインスクリプト実行がブロックされたことが確認できました。

    Edge 101.0.1210.39

    こちらもウェブディベロッパーツールを起動し、コンソールタブから確認すると、CSPによりインラインスクリプト実行が拒否されたことが分かります。
     
    これらの結果をまとめると、以下となります。

    BrowserX-XSS-ProtectionCSP
    IE11△(極めて限定的にサポート)
    Edge 101.0.1210.39×
    Firefox 100.0×
    Chrome 101.0.4951.64×

    インラインスクリプトをCSPで許可する運用

    上記で挙げた対策としてインラインスクリプトをJSファイルにまとめてインクルードする方法は、運用上簡単にはいかないというケースがあります。例えばインラインスクリプトを使用せざる得ない状況では、CSP nonce値の導入を検討してもいいでしょう。それでは、nonceの導入例を見てみましょう。

    nonce値は、'nonce-ランダム値をBase64エンコードした値'と設定します。アクセス毎にnonce値をランダムに変更することで、攻撃者にnonce値を予測されないようにしなければいけません。またMDN webdocsによるとnonce値をBase64でエンコードする前のランダムバイト列は、少なくとも128ビット以上とするのが望ましいです。

    Content-Security-Policy: script-src 'self' 'nonce-CdcFfSZJ2P2KTAHHaIy6FLw1hgQ=';

    注意しなければならないのは、nonce-secureiv123のような固定値を使用するべきではないことです。もし固定値を使ってしまえば、以下のように攻撃者もnonceの固定値入りのスクリプトを挿入して、XSS攻撃を成功させることができるからです。

    http://xss-csp.test.local/xss_protection_test.php?msg=<script nonce="secureiv123">alert(1);</script>

    次にインラインスクリプトへのnonce値の設定です。さきほどCSPヘッダのnonce値で設定した値をnonce=”…”という形で指定します。これによりnonceが正しく設定されていないインラインスクリプトは、実行がブロックされ、nonceが設定されているスクリプトのみの実行が許可されます。攻撃者は、XSS攻撃を成功させるために、毎回正しいnonce値を予想しなければいけないためXSS攻撃を難しくすることが可能です。さらにstored型、DOM型のXSS攻撃であっても、インラインスクリプトからJS実行させるタイプであればブロックできるので有効な対策となります。

    <script type="text/javascript" nonce="CdcFfSZJ2P2KTAHHaIy6FLw1hgQ=">
     alert("nonce !");
    </script>

    結論

    既にX-XSS-Protectionヘッダを付加している場合には、ウェブアプリケーションにおいて古いブラウザをサポートする必要があるかどうかを検討しましょう。また最新のブラウザを保護するためにCSPの導入も検討しましょう。

    最後に基本的なXSS対策はユーザの入力値をサニタイズすることです。X-XSS-ProtectionやCSPは補助的な対策となりますので、入力値のサニタイズと合わせて対策していきましょう。

    弊社では、今回紹介したセキュリティに関わるレスポンスヘッダの不備検査以外にも様々なヘッダ不備に関わる脆弱性診断を行っております。もし、ウェブアプリケーションセキュリティ診断サービスにご興味がございましたらお問い合わせページからお気軽にご連絡して頂けると幸いです。

    セキュアイノベーション サービス一覧

    ネットワーク・サーバー

    Webサイトを守る