Web Cache Poisoning
Web Cache Poisoning คือการทำให้ cache (CDN/reverse proxy) เก็บ response ที่มี payload ของผู้โจมตี แล้วเสิร์ฟให้ผู้ใช้คนอื่นทุกคนที่ขอ path เดียวกัน อาศัย 'unkeyed input' — ส่วนของ request ที่มีผลต่อ response แต่ไม่ถูกนำมาคำนวณเป็น cache key บทนี้ไล่ตั้งแต่หลักการ cache key, การหา unkeyed input ด้วย cache buster + Param Miner, การยกระดับเป็น XSS/redirect/DoS, fat GET และ cache-key normalization bugs
1. หลักการ — cache key และ unkeyed input
Cache ตัดสินใจว่า request สองอันเป็น 'อันเดียวกัน' จาก cache key ซึ่งโดยทั่วไป = method + host + path + query string + บาง header (เช่น Accept, Cookie ที่ config ไว้) ถ้ามีส่วนของ request ที่มีผลต่อ response แต่ไม่อยู่ใน cache key — เรียกว่า unkeyed input — ผู้โจมตีใส่ payload ลงใน unkeyed input นั้น response ที่ถูก 'poison' จะถูก cache ด้วย key เดิม แล้วเสิร์ฟให้เหยื่อทุกคนที่ขอ path เดียวกัน โดยเหยื่อไม่ต้องส่ง header ผิดอะไรเลย
2. ตรวจว่า response ถูก cache ไหม
ก่อนอื่นต้องยืนยันว่า path เป้าหมาย cacheable และหา indicator ของ cache hit/miss — ดูจาก response header
| Header / สัญญาณ | ความหมาย |
|---|---|
| X-Cache: hit / miss | เสิร์ฟจาก cache (hit) หรือ origin (miss) — พบใน Varnish, CloudFront |
| CF-Cache-Status: HIT/MISS/DYNAMIC | สถานะ cache ของ Cloudflare |
| Age: 120 | response อยู่ใน cache มาแล้วกี่วินาที (มี = ถูก cache) |
| Cache-Control: public, max-age= | อนุญาตให้ cache และนานแค่ไหน |
| X-Cache-Hits: 5 | จำนวนครั้งที่ถูก serve จาก cache |
| Vary: User-Agent | header ที่ถูกนับเป็นส่วนหนึ่งของ key (แตก cache ตามค่านี้) |
?cb=12345 เพื่อให้แต่ละรอบทดสอบมี cache key ของตัวเอง จะได้ไม่ poison ผู้ใช้จริงและไม่โดน response เก่าที่ค้างอยู่รบกวนผล3. หา unkeyed input (Param Miner)
- 1เพิ่ม cache buster (?cb=random) เพื่อแยก cache key ของ session ทดสอบออกจากผู้ใช้จริง
- 2ส่ง header ต้องสงสัย: X-Forwarded-Host, X-Forwarded-Scheme, X-Host, X-Forwarded-For, X-Original-URL
- 3ดูว่า header นั้นทำให้ response เปลี่ยนไหม (เช่น URL ใน