Webキャッシュポイズニング攻撃を防ぐ方法
Najia Gul
2023年9月11日
0 分で読めますWebキャッシュポイズニングは、予期せぬ被害をもたらすサイバー攻撃です。Webサーバー、プロキシ、コンテンツデリバリーネットワーク(CDN)が利用するキャッシュ機構の脆弱性を悪用し、データの完全性を損ないます。攻撃者はキャッシュポイズニングを利用して、悪意のあるペイロードを配信したり、機密情報を改ざんしたり、ユーザーを偽サイトに誘導したりできます。
この記事では、Webキャッシュポイズニング攻撃の概要とその仕組みを詳しく解説します。また、Webアプリケーションを保護するために効果的な緩和策についてもご紹介します。
Webキャッシュの仕組みと重要性
Webキャッシュは、Webサイトのパフォーマンス向上に欠かせない仕組みです。HTMLファイル、画像、スクリプト、スタイルシートなどのWebコンテンツを、キャッシュと呼ばれる一時的な保存領域に格納します。これにより、ユーザーから次回以降にリクエストがあった際、コンテンツにすばやく簡単にアクセスできます。
Webキャッシュを保存する場所に応じて、キャッシュ機構にはいくつかの種類があります。主なものは次のとおりです。
ブラウザーキャッシュ:ブラウザーキャッシュでは、Webブラウザーが静的リソースのコピーをユーザーのデバイスに保存します。ユーザーがWebサイトに再度アクセスすると、ブラウザーは以前ダウンロードしたファイルがキャッシュにあるか確認します。ファイルがまだ有効であれば、サーバーに新たなリクエストを送る代わりに、キャッシュから取得します。
サーバーキャッシュ:ブラウザーキャッシュがクライアント側で行われるのに対し、サーバーキャッシュでは、後で再利用できるようコンテンツをサーバー自体に保存します。ユーザーがオリジンサーバーにリクエストを送ると、キャッシュは生成されたレスポンスのコピーを保存します。その後、同じコンテンツへのリクエストがあれば、オリジンサーバーの代わりにキャッシュからコピーを配信します。
コンテンツデリバリーネットワーク(CDN)キャッシュ:CDNは、静的なWebコンテンツをキャッシュして配信する、地理的に分散したサーバーネットワークです。ユーザーがそのコンテンツに再度アクセスする場合、ユーザーの場所に最も近いエッジサーバーがリクエストを処理します。これにより、すべてのリクエストをオリジンサーバーが処理する必要がなくなります。
キャッシュを利用すると、Webコンテンツの取得に必要な時間とリソースが減り、ページの読み込みが速くなってユーザー体験が向上します。また、サーバーの負荷が軽減され、より多くのリクエストを処理できるようになります。
しかし、適切に実装・管理されていない場合、キャッシュにはいくつかの潜在的なリスクもあります。キャッシュされたコンテンツが速やかに更新されないと、古くなったり誤った内容になったりして、不整合や、攻撃者に悪用されるセキュリティ上の脆弱性につながる可能性があります。
機密情報をキャッシュすると、プライバシー上のリスクも生じます。たとえば、キャッシュにユーザーの個人情報やアカウント認証情報が含まれている場合、不正アクセスによってデータ漏えいやプライバシー侵害が起きるおそれがあります。
Webキャッシュポイズニング攻撃の仕組み
Webキャッシュポイズニングは、キャッシュインフラをだまして、改ざんされたコンテンツや許可されていないコンテンツをユーザーに配信させる攻撃です。通常、次の4つの手順で行われます。
脆弱な標的を特定する:攻撃者は、設定ミスや不適切な入力検証など、キャッシュ機構に潜在的な問題があるWebサイトを探します。
HTTPリクエストを操作する:攻撃者は、脆弱性を悪用するよう細工したHTTPリクエストを標的のWebサイトに送信します。
キャッシュ機構を悪用する:攻撃者はさまざまな手法を使い、独自の悪意あるコンテンツを注入したり、キャッシュ内の既存コンテンツを改ざんしたりします。
改ざんされたコンテンツを配信する:攻撃が完了すると、その後キャッシュに届いたリクエストには、正規のコンテンツではなく、汚染されたコンテンツが返されます。
Webキャッシュポイズニング攻撃が成功すると、機密情報や秘密情報が漏えいするおそれがあります。攻撃者はキャッシュされたコンテンツを改ざんし、標的のWebサイトを改ざんしたり、偽情報を拡散したり、悪意のあるリンクを配布したりできます。
さらに深刻なのは、攻撃者が被害を拡大するため、Webキャッシュポイズニングを他のサイバー攻撃と組み合わせることが多い点です。たとえば2018年、攻撃者はBritish AirwaysのWebサイトのキャッシュポイズニングに成功しました。悪意のあるペイロードを注入してユーザーを偽サイトにリダイレクトし、その結果、英国のユーザー4万人以上のメールアドレスとクレジットカード情報を盗み出しました。
よくあるWebキャッシュポイズニング攻撃の手法
キャッシュポイズニング攻撃から保護するには、Webサイトに潜む脆弱性を特定し、対処する必要があります。ここでは、よくある攻撃手法と、攻撃者がそれらをどう悪用するかを紹介します。
HTTPヘッダーの操作:攻撃者はHTTPヘッダーを改変し、悪意のあるコンテンツを正規のURLやキャッシュキーに関連付けることがあります。たとえば、
Cache-ControlHTTPヘッダーを操作して、キャッシュシステムに攻撃者のコンテンツを保存させることができます。これにより、正規のコンテンツが変更された後でも、同じリソースをリクエストしたユーザーに悪意のあるペイロードを配信できるようになります。クエリ文字列の操作:攻撃者は、Webアプリケーションによるクエリ文字列の処理方法を悪用できます。URLに付加されたクエリパラメーターを操作し、同じリソースに対して複数のキャッシュバリエーションを作成します。その中に悪意のあるペイロードを含める可能性もあります。
Cookieの操作:攻撃者はCookieの値や属性を改変して、キャッシュを汚染することもできます。正規ユーザーのセッションとしてキャッシュシステムに攻撃者のコンテンツを保存させるために、この手法を使います。
ただし、これらはあくまで一例です。攻撃者は目的を達成するため、常に新たな手法や脆弱性を探しています。よくある攻撃手法だけを監視しても、Webデータを保護するには不十分です。
HTTPヘッダーの操作によるキャッシュポイズニング攻撃
ここでは、攻撃者がHTTPヘッダーを使ってWebサイトの脆弱性を悪用する、Webキャッシュポイズニングの例を見てみましょう。よく標的となるヘッダーの1つがX-Forwarded-Host(XFH)です。この事実上の標準ヘッダーは、HTTP/HTTPSリクエストでクライアントがアプリケーションやAPIに要求した元のホストを識別するために使われます。ヘッダーの値は通常、クライアントのリクエスト先である元のホストを示すホスト名です。
このヘッダーはリバースプロキシやロードバランサーを使う環境で役立つよう設計されていますが、適切に検証しないと攻撃者に悪用されるおそれがあります。また、同様の攻撃には他の多くのヘッダーも利用される可能性がある点に注意が必要です。
それでは、キャッシュサービスを使うJavaScriptコードに潜む脆弱性の例を見ていきましょう。この例ではRedisを使用します。
キャッシュミドルウェアは、元のURLをキーとしてRedisにレスポンスをキャッシュします。originalURLはホスト名以降のすべてを指します(たとえば、http://example.com/user?userId=1の/user?userId=1)。このURLに対応するレスポンスがキャッシュに存在すれば、すぐに返されます。存在しない場合は、リクエストが適切なルートハンドラーに渡され、ここではユーザーごとのあいさつ文を生成してキャッシュします。
しかし、この実装はキャッシュポイズニング攻撃につながる可能性があります。URLに基づいてレスポンスをキャッシュしている点を攻撃者に悪用されるおそれがあるためです。ユーザーが制御できる入力であるX-Forwarded-Hostヘッダーが、レスポンスの生成に使われている状況を考えてみましょう。このコードでは、X-Forwarded-Hostの値を使ってユーザーへのあいさつ文を表示しています(例:「Welcome, user ${req.query.userId}, you’re accessing from ${req.headers['x-forwarded-host']}!」)。この値が適切に検証されなければ、攻撃者がヘッダーに悪意のあるスクリプトを含め、それがキャッシュされて他のユーザーに配信される可能性があります。
攻撃の流れは次のとおりです。
攻撃者は
X-Forwarded-Hostヘッダーにfoo."><script>alert(document.cookie)</script>を設定し、/user?userId=1へのGETリクエストを送信します。サーバーはヘッダーの値を含むあいさつ文を生成し、キー
/user?userId=1でキャッシュして、攻撃者に返します。その後、
/user?userId=1へのリクエストには、毎回キャッシュから悪意のあるあいさつ文が返されます。
上記のコードのセキュリティを強化する方法の1つは、キャッシュキーに使用するURLをサニタイズすることです。ここでは、validatorモジュールのescapeメソッドを使った基本的なサニタイズ関数の実装例を紹介します。
実装したsanitize関数を使うことで、脅威となる可能性のある文字をreq.originalUrlから効果的に除去できます。
さらに、Expressサーバーでミドルウェア関数を実行することで、ユーザー入力が有効かどうかを確認できます。以下の例では、ヘッダーを検証する基本的な方法を示します。
ここではvalidatorモジュールのisFQDN関数を使い、X-Forwarded-Hostヘッダーに有効なドメイン名が含まれているかを確認します。有効でない場合、ミドルウェア関数はリクエストを拒否し、400 Bad Requestステータスを返します。
この検証手順は、X-Forwarded-Host headerを介した有害なスクリプトの注入を防ぐうえで不可欠です。先ほど説明したとおり、こうした状況はキャッシュポイズニング攻撃につながる可能性があります。
Webキャッシュポイズニングを防ぐためのベストプラクティス
Webキャッシュポイズニングを防ぐ最も効果的な方法は、強固なキャッシュポリシーを確立することです。このポリシーでは、何を、どのくらいの期間、どのような条件でキャッシュするかを明確に定めます。キャッシュポリシーを策定する際は、データの種類、認証要件、キャッシュすべきでない動的コンテンツなどを考慮する必要があります。
キャッシュ機構の安全性を高めるその他の方法は次のとおりです。
キャッシュキーの正規化:キャッシュキーを正規化すると、入力形式や大文字・小文字の違いによるバリエーションを防ぎやすくなります。
ユーザー入力を検証する:厳格な入力検証とサニタイズを実施することで、キャッシュポイズニングにつながるインジェクション攻撃を防止できます。具体的には、入力のフィルタリング、許可リストによるパラメーター制限、正規表現によるチェックなどがあります。
キャッシュ制御ヘッダー:キャッシュ制御ヘッダーを使うと、キャッシュの動作を適切に管理し、リスクを軽減できます。たとえば「no-store」や「no-cache」などのヘッダーを使えば、機密データがキャッシュされるのを防げます。
サードパーティーの入力を信用しない:ヘッダー、Cookie、クエリ文字列など、サードパーティーからの入力を利用する際は注意が必要です。キャッシュ関連の処理に使う前に、すべての外部入力を十分に検証し、サニタイズしてください。ユーザーが提供するデータはすべて悪意のあるものと想定し、攻撃者が細工したコンテンツをキャッシュに注入できないよう、厳格な入力検証とフィルタリングを適用しましょう。
Webアプリケーションファイアウォール(WAF)を使う:堅牢なWAFを導入すると、キャッシュポイズニングの試みを検出してブロックできます。WAFは受信リクエストを分析し、キャッシュポイズニングを示す不審なパターンを特定します。こうしたリクエストを警告またはブロックするようWAFを設定すれば、攻撃に対する防御層を追加できます。
Webキャッシュポイズニング攻撃の監視と検出
適切な緩和策を講じていても、Webキャッシュポイズニングが発生する可能性はあります。そのため、Webトラフィックを定期的に監視し、ログを分析して潜在的な攻撃を検出することが重要です。リクエストパターンの異常、予期しないキャッシュバリエーション、キャッシュから配信される不審なコンテンツなど、通常とは異なる挙動に注意してください。
もう一つのベストプラクティスは、定期的にセキュリティテストと侵入テストを実施することです。これらの評価により、キャッシュポイズニング攻撃につながる可能性のある弱点を特定できます。セキュリティテストには、脆弱性スキャンやセキュリティ監査が含まれます。侵入テストではさらに一歩進んで、現実の攻撃シナリオをシミュレーションします。攻撃者の手法や考え方を再現し、通常のセキュリティテストでは見逃される可能性のある特定の弱点を探ります。
Webキャッシュポイズニング攻撃の検出と防止に役立つツールやリソースは数多くあります。たとえば、次のようなものを導入できます。
Snykなどの脆弱性スキャナーを使って、一般的なキャッシュポイズニングの脆弱性を自動的に特定できます。
キャッシュ診断・分析ツールを使えば、キャッシュ設定の分析、キャッシュ動作の監視、異常の検出に役立ちます。
開発者に愛され、セキュリティチームから信頼される。
Snykの開発者ファーストのツールは、ガバナンスやコンプライアンスのニーズに応える、統合された自動化セキュリティを提供します。
まとめ
Webキャッシュポイズニング攻撃は、ユーザーに気づかれないまま、キャッシュから古いコンテンツや改ざんされたコンテンツを配信させる攻撃です。データ漏えいやプライバシー侵害につながり、最終的にはWebサイトの評判を損なうおそれがあります。
こうした攻撃に対する最善の防御策は、強固なキャッシュポリシーを確立し、Webアプリケーションの最新のセキュリティ動向を把握することです。また、適切な入力検証やキャッシュキーの正規化など、セキュリティのベストプラクティスに従う必要があります。
こうしたセキュアな開発手法を実践することで、キャッシュ汚染のリスクを最小限に抑えながら、Webキャッシュのメリットを活用できます。
