XSリークとは?その仕組みと防止方法
2023年7月17日
0 分で読めますクロスサイトリーク(XSリーク)は、ハッカーがユーザーの他のWebサイトやWebアプリでの閲覧セッションから機密情報を取得できる、Webセキュリティ脆弱性の一種です。最新のWebアプリケーションは、さまざまな機能やAPIを通じてデータを共有しています。攻撃者はこの仕組みを悪用し、ユーザーデータにアクセスできます。
最終的にXSリークは機密情報の漏えいにつながり、悪意のある攻撃者はその情報を、機密システムやデータベースへの不正アクセスなど、さまざまな違法行為に利用する可能性があります。
この記事では、XSリークとは何か、どのように発生するのかを詳しく解説します。さらに、実践的な例を交えながら、その防止方法を紹介します。
XSリークが発生する仕組み
最新のWebアプリケーションは非常に複雑で、信頼レベルの異なる複数のドメインで構成されています。そのため、ブラウザー内でシームレスな操作を実現するには、Webサイト間で情報を共有できる必要があります。開発者はこの通信の安全性を確保してきましたが、Webサイトやブラウザーの機能には、もともと一定の脆弱性が存在します。
XSリークは、攻撃者がこうした脆弱性を悪用して、ユーザーの非公開データに不正にアクセスすることで発生します。攻撃者は、Cookie、JavaScript API、CSSスタイルシート、HTML要素などのWeb機能を操作し、サイドチャネルやアプリケーション固有の脆弱性を利用して、ユーザーが訪問した他のWebサイトから機密情報を引き出します。さらに、こうした攻撃はユーザーに気づかれることも、同意を得ることもなく、ひそかに実行されます。
XSリークにはどのような種類があるか
攻撃者が利用できるXSリークには、いくつかの種類があります。代表的なものを見ていきましょう。
タイミング攻撃
タイミング攻撃では、悪意のある攻撃者がさまざまな処理にかかる時間を測定し、システムの機密情報を収集しようとします。攻撃者は、API呼び出しやAJAXリクエストを実行したり、クロスオリジンリソース共有(CORS)が必要なリソースリクエストを発生させたりする、細工したスクリプトを標的サイトに送信します。そして、各処理にかかる時間を調べ、Webサイトの動作やデータ処理の方法を推測します。
たとえば攻撃者は、ユーザー名とパスワードの組み合わせなど、さまざまな入力をクロスオリジンリクエストで送信した際の、サーバー側の検証処理にかかる時間を観察します。次に、時間の目立った差から、ログインが成功したかどうかや、ユーザーが管理者か一般ユーザーかを判断できます。攻撃者はこの情報をもとに、次の行動を決めます。
フレーム数のカウント
フレーム数を数える攻撃では、攻撃者は標的サイト内の異なるURLを指すiFrameを複数階層に埋め込みます。次に、サイトのCORS機能を利用して、ユーザーが標的のURLにアクセスしたときにブラウザーが読み込むフレーム数を確認します。
攻撃者が、アカウント設定や注文履歴など、Webサイトの保護されたページを指すiFrameを複数階層に作成したとします。ユーザーが攻撃者のiFrameを埋め込んだページにアクセスすると、攻撃者は正常に読み込まれたフレームと、読み込まれなかったフレームを数えます。その情報から、認証要件や会員ランクなどのアカウント制限を推測し、特定のユーザーが標的サイトの特定領域へのアクセス権を持つか、過去に利用したことがあるかを明らかにできます。
キャッシュの調査
キャッシュの調査では、ユーザーの端末にWebコンテンツをローカル保存するブラウザーキャッシュを悪用します。攻撃を実行するため、攻撃者は標的サイトから画像やスクリプトなどの特定のリソースを要求する悪意のあるWebサイトを作成します。要求するリソースには、一般的でないファイルサイズや読み込み時間など、特徴的な性質があります。
ユーザーが悪意のあるWebサイトにアクセスした際、攻撃者はリソースが読み込まれる速度を測定します。リソースは標的サーバーから直接読み込まれる場合も、ユーザーのブラウザーにキャッシュされたものから読み込まれる場合もあります。そして、その情報を使って、リソースがユーザーのブラウザーキャッシュにすでに保存されていたかどうかを推測します。
フレーム数のカウントと同様に、キャッシュ調査で得られた情報は、フィッシングキャンペーンのカスタマイズ、複数のオンラインサービスやプラットフォームで使われる別々のアカウント間の関係の特定、さらにはより高度な攻撃の連携に利用される可能性があります。
XSリークを引き起こす仕組み
XSリーク攻撃は、ブラウザー本来の機能を操作し、間接的な観察手法を用いて機密データに不正アクセスします。攻撃を成功させる主な仕組みは次のとおりです。
ブラウザー機能の悪用 — 攻撃者は、プリフェッチ、プリレンダリングなどのブラウザー機能や、Fetch、WebSocketsなどのさまざまなAPIを利用します。これらの機能を操作したり、キャッシュ調査などの手法と組み合わせたりすることで、同一オリジンポリシー(SOP)に直接違反することなく、ユーザーの機密情報を引き出せます。
サイドチャネル — 攻撃者が機密情報を収集するための間接的な経路です。Webアプリケーション内でSOPにより課されるセキュリティ制限のため、データに直接アクセスするのではなく、ユーザーのブラウザー上での描画時間やリソース読み込みのパターンなどの変化を観察します。
クロスオリジン通信 — 攻撃者は、postMessage APIやWebワーカーなどのクロスオリジン通信方式を標的にすることもあります。そして、1つのページ内のiFrameに埋め込まれた異なるオリジン間でやり取りされるメッセージを傍受したり、改ざんしたりします。
XSリークで悪用される脆弱性
上記の仕組みを利用すると、攻撃者は、現代のWebサイトの大半が採用するCORSやSOPなどのセキュリティポリシーに直接違反することなく、機密情報にアクセスできます。
こうした対策を講じても、XSリークの発生を完全に防ぐことはできません。攻撃者はサイドチャネルを使ってSOPの防御を回避し、CORSの設定ミスを悪用し、さらに別の脆弱性を組み合わせて、より組織的な攻撃を仕掛けることができます。
CORSとSOPは、異なるオリジンのリソース間のやり取りを制御します。SOPは、Webページが別のドメインから読み込まれたデータやコンテンツにアクセスすることを制限し、スクリプトがそのオリジンのコンテキスト内で実行されるようにします。CORSはこのポリシーを拡張し、サーバーがHTTPヘッダーを通じてリソースへのアクセスを明示的に許可した場合に、特定のクロスオリジンリクエストを可能にします。この2つの仕組みにより、理論上はWebサイト間の安全な通信が実現し、クロスサイトリクエストフォージェリ(CSRF)攻撃や不正なデータアクセスなど、悪意のあるドメイン間のやり取りを防止できます。
しかし、XSリークはサイドチャネルや間接的なデータ露出を悪用するため、攻撃者は別のオリジンから機密情報を推測してSOPを回避できます。同様に、WebアプリケーションでCORSの設定や実装に不備があると、情報漏えいにつながる可能性があります。
悪意のある攻撃者がXSリークの手法を実行するもう1つの方法は、脆弱性の悪用を組み合わせることです。クロスサイトスクリプティング(XSS)は、XSリークと組み合わせて効果を発揮する攻撃です。攻撃者はXSSの脆弱性を悪用した後、サイドチャネル情報を露呈させるさまざまなブラウザー機能やAPIを通じて、XSリークを引き起こそうとすることがあります。
攻撃者はこの2つの攻撃手法を組み合わせ、SOPに直接違反することなく、侵害したドメインから機密データを取得し、さらに別のオリジンに関する情報を集めることができます。
XSリークによる影響
XSリーク攻撃は、機密情報の漏えいなど、深刻な結果を招く可能性があります。攻撃者が個人情報や金融情報などの機密データにアクセスすると、ユーザーの同意なく、その個人情報を改ざん、窃取、悪用するおそれがあります。
さらに、XSリーク攻撃の結果として、セッションハイジャックが起きる可能性もあります。セッションハイジャックとは、攻撃者がユーザーのアクティブなセッションを乗っ取り、ユーザーになりすまして不正な変更を加えることです。こうした事態は、個々のユーザーのプライバシーとセキュリティを脅かすだけでなく、オンラインプラットフォームやサービスへの信頼を損ないます。
XSリークは、より広範な攻撃手法や脆弱性の一部と見なされることが多い点に注意が必要です。メディアで大きく報道される重大な情報漏えいでも、主要な攻撃手法としてXSリークが使われたとは限りません。しかし、悪意のある攻撃者はXSリークを利用して、より組織的な攻撃を実行することがあります。
XSリーク攻撃のリスクを軽減するためのベストプラクティス
XSリークを防ぐ万能な方法はありませんが、関連するリスクを大幅に軽減する手段はあります。以下では、XSリークのリスクを抑えるベストプラクティスを、実装方法の実例とともに紹介します。
コンテンツセキュリティポリシーを使用する
強固なコンテンツセキュリティポリシー(CSP)を導入し、ブラウザーがサイトに読み込めるコンテンツの配信元を制限しましょう。これにより、攻撃者がXSSなどのインジェクション脆弱性を悪用して引き起こす情報漏えいのリスクを軽減できます。
以下の例のように、Content-Security-PolicyというHTTPレスポンスヘッダーを使ってCSPを実装できます。
この例では、ほかのディレクティブで明示的に指定しない限り、外部リソースの読み込みは許可されません(default-src)。スクリプト(script-src)、画像(img-src)、スタイルシート(style-src)、フォント(font-src)は、自社ドメイン(self)またはGoogle API(googleapis.com)からのみ読み込めます。
適切に定義されたCSPは、スクリプト、画像、スタイルシートなどのコンテンツについて、許可する配信元を指定することで、不正なクロスオリジンリクエストやインラインコードの実行を防ぎます。
CookieにSameSite属性を設定する
CookieのSameSite属性は、外部からのリクエストにCookieを含めるかどうかをブラウザーに伝えます。たとえば、JavaScriptでは次のようになります。
username Cookieの値はJohnDoeです。また、パス/を指定すると、Cookieはドメイン内のすべてのページで利用できます。Secureキーワードにより、CookieはHTTPS接続でのみ送信されます。最後に、SameSite属性を次のいずれかに設定します。
None— セキュアなHTTPSチャネルで送信する場合、Cookieが付与されます。Lax— Chromiumベースのブラウザーでのデフォルトの動作です。トップレベルのナビゲーションに対するGETリクエストではCookieが送信されます。Strict— Cookieは自社ドメインの外部には送信されません。
CookieのSameSite属性をStrictに設定すると、クロスサイトリクエスト時にCookieが送信されなくなり、CSRFや、タイミング測定を伴うものなど一部のXSリーク攻撃を軽減できます。
URLでの機密データの使用を最小限に抑える
URLでの機密データの使用を最小限に抑えることは、サイバーセキュリティにおける重要なベストプラクティスです。ユーザー認証情報や個人を特定できる情報(PII)などの機密データは、URLに含めないでください。ブラウザーの履歴、サーバーログ、リファラーヘッダー、サニタイズされていない共有リンクなどを通じて、攻撃者が簡単にアクセスできるためです。
機密データのURLでの使用を最小限に抑える方法には、次のようなものがあります。
URLに機密データを含めるのではなく、HTTPSを使用した
POSTリクエストを利用するユーザーの認証情報やPIIを直接渡すのではなく、セッショントークンを使用する
レート制限を実装する
もう1つのベストプラクティスは、特に列挙攻撃やブルートフォース攻撃を受けやすい機密性の高いエンドポイントにレート制限を適用することです。一定時間内に攻撃者が送信できるリクエスト数を制限し、XSリーク攻撃の有効性を低下させます。多くのプログラミング言語やWebフレームワークには、レート制限を実装するためのライブラリやミドルウェアソリューションが用意されています。
たとえばNode.jsとExpressを使用する場合は、express-rate-limitミドルウェアをnpm install express-rate-limitコマンドでインストールする必要があります。その後、次のようにサーバー側のレート制限を設定できます。
この対策は、ほかの対策と組み合わせることで最も効果を発揮します。サーバーに大量のリクエストを送信して情報を収集するXSリーク攻撃に対するセキュリティを強化できます。
適切なCORS設定を使用する
アプリケーションに適切なCORS設定を適用し、許可されていないドメインからのクロスオリジンリクエストや、保護されたリソースへのアクセスを防ぎましょう。Access-Control-Allow-OriginなどのCORSヘッダーを適切に設定し、信頼できるオリジンからのみクロスオリジンリクエストを送信できるようにします。また、許可するオリジンのリストで不要なワイルドカード(*)を使用しないようにしてください。
サーバーがAccess-Control-Allow-Originヘッダーで任意のオリジン(*)を許可している場合や、ユーザー入力(リファラーなど)を適切に検証せずにオリジンを動的に生成している場合、攻撃者は悪意のあるWebサイトからクロスオリジンリクエストを送信して、この設定を悪用する可能性があります。
Snyk Codeなどのインテグレーションを活用する
Snyk Codeは開発ワークフローに組み込むことで、セキュリティ脆弱性の特定と修正を支援します。依存関係をスキャンして脆弱性を通知し、修正を提案・適用するとともに、プロジェクトのセキュリティ問題を継続的に監視します。たとえば、Node.jsとExpress.jsでアプリケーションを作成する場合、次の簡単な手順でセキュリティヘッダーの不足による脆弱性への対策を支援できます。
依存関係をスキャン — Snykをプロジェクトに統合したら、プロジェクトの依存関係をスキャンして、パッケージに既知の脆弱性がないか確認できます。
問題を特定 — セキュリティヘッダーが不足している場合、Snyk Codeが脆弱性を検出して通知します。たとえば、XSS攻撃の防止に役立つCSPヘッダーがアプリケーションに設定されていないことを特定できます。
修正を提案 — Snykは特定された脆弱性への修正を提案します。セキュリティヘッダーが不足している場合は、Express.jsアプリケーションにhelmet middlewareを追加するよう提案することがあります。Helmetは、さまざまなセキュリティヘッダーをアプリケーションにデフォルトで設定する、広く使われているパッケージです。
Snykはプロジェクトを継続的に監視し、新たな脆弱性や既知の脆弱性の更新も検出できます。新たな問題が発生すると通知が届くため、プロジェクトのセキュリティを常に把握できます。
XSリークを防ぐ
XSリークを利用すると、攻撃者は別のWebサイトでのユーザーの閲覧セッションから機密情報を取得できます。攻撃者はブラウザーの機能、サイドチャネル、クロスオリジン通信を悪用します。一般的なXSリークの手法には、タイミング攻撃、フレーム数のカウント、キャッシュプロービングなどがあります。
XSリークを確実に防ぐ方法はありませんが、この記事で紹介したベストプラクティスを実践することで、リスクを大幅に軽減し、ユーザーの機密情報を不正なアクセスや漏えいから保護できます。
Capture the Flagを始めよう
オンデマンドのバーチャル入門ワークショップを見て、Capture the Flagの課題の解き方を学びましょう。



