คลัง
web

Web Cache Deception

Web Cache Deception คือการหลอกให้ cache เก็บหน้าที่มีข้อมูลส่วนตัวของเหยื่อ (เช่นหน้า account) ไว้ที่ URL สาธารณะ แล้วผู้โจมตีเปิด URL นั้นเพื่ออ่านข้อมูล ต่างจาก cache poisoning ตรงที่ deception หลอกเรื่อง 'อะไรถูก cache' บทนี้อธิบายกลไก cache, เงื่อนไขที่ทำให้เกิด, เทคนิค path confusion และการทดสอบ (เนื้อหาเพื่อฝึกใน lab/CTF/ระบบที่ได้รับอนุญาต)

IntermediateAdvanced#cache-deception#web-cache#caching#information-disclosure#web#ctf

1. แนวคิด — deception ต่างจาก poisoning

CDN/cache มักเก็บ static file (.css/.js/.jpg) ไว้แชร์ทุกคนเพื่อความเร็ว Cache Deception อาศัยช่องว่างระหว่าง 'cache ตัดสินใจ cache จากนามสกุล' กับ 'server ตอบเนื้อหาตาม path จริง' — ผู้โจมตีส่งลิงก์อย่าง /account/profile.css ให้เหยื่อ ถ้า server ไม่สน .css แล้วคืนหน้า profile (ข้อมูลเหยื่อ) แต่ cache เห็น .css เลย cache ไว้ → ผู้โจมตีเปิด URL เดียวกันอ่านข้อมูลเหยื่อจาก cache

เนื้อหานี้เพื่อการศึกษาและฝึกในสภาพแวดล้อมที่ได้รับอนุญาต (CTF, lab, การทดสอบที่มีสัญญา) เท่านั้น
Cache DeceptionCache Poisoning
เป้าอ่านข้อมูลส่วนตัวของเหยื่อยัด response อันตรายให้เหยื่อ
หลอกเรื่องอะไรถูก cache (path/ext)ค่าใน cache key (header)
ผลข้อมูลรั่วXSS/redirect หมู่

2. เงื่อนไขที่ทำให้เกิด

  • cache ตัดสินจากนามสกุล/path (cache .css .js .jpg เสมอ) โดยไม่ดู Cache-Control จาก origin
  • server ทำ path ยืดหยุ่นเกินไป/account/profile.css คืนหน้า /account/profile (ละเลยส่วนเกิน)
  • หน้ามีข้อมูลส่วนตัว (account, API key, token, session info)
  • cache key ไม่รวมส่วนที่แยกผู้ใช้ — เก็บ response รวมไม่แยก cookie

3. เทคนิค path confusion

รูปแบบ path ที่ลองหลอก cache
# ต่อ .css/.js ปลอม (server ละเลย, cache เห็น static)
/account                -> /account/foo.css
/account                -> /account/foo.js

# path parameter / delimiter ที่ server กับ cache parse ต่างกัน
/account;foo.css
/account%2ffoo.css
/account%00.css
/account#.css
/account?.css

# encoded path traversal กลับเข้า endpoint เดิม
/static/..%2faccount%2ffoo.css

# ดูว่าถูก cache ไหม: response header
#   X-Cache: hit / miss
#   CF-Cache-Status: HIT
#   Age: <วินาที>  (มี = ถูก cache)
ลองหลาย delimiter (; %2f %00 # ?) เพราะ cache กับ origin parse path ต่างกัน; ดู X-Cache/CF-Cache-Status/Age ยืนยันว่าโดน cache

4. Workflow ทดสอบ

ทดสอบ Web Cache Deception
หาหน้าที่มีข้อมูลส่วนตัว (login แล้ว)
/account, /profile, /api/me
ต่อนามสกุล static ปลอม
/account/foo.css
server คืนอะไร?
คืนหน้า account (ข้อมูลเหยื่อ)มีโอกาส deception
404/redirectลอง delimiter อื่น (; %2f %00)
ดู response header
X-Cache/CF-Cache-Status/Age
HIT / มี Ageถูก cache → deception ได้
เปิด URL เดียวกันจาก session อื่น/ไม่ login
ถ้าเห็นข้อมูลเหยื่อ = ยืนยันช่องโหว่
ข้อมูลส่วนตัวรั่วผ่าน cache สาธารณะ

5. Quick Reference

  • deception = หลอก cache ให้เก็บหน้า private ที่ URL สาธารณะ
  • ลอง: /account/foo.css, delimiter ; %2f %00 # ?
  • ยืนยัน cache: header X-Cache: HIT / Age
  • ทดสอบจริง: เปิด URL จาก context อื่น เห็นข้อมูลเหยื่อ = ช่องโหว่
  • ป้องกัน: cache ตาม Cache-Control จาก origin, cache key แยกผู้ใช้

🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ

สมมติเจอหน้าที่ต้อง login แล้วมีข้อมูลส่วนตัว (เช่น /account) และเว็บอยู่หลัง CDN มีแค่ Kali เปล่าๆ ไล่หา cache deception ทีละขั้น

  1. 1login เข้าเว็บ แล้วเปิด /account (หรือหน้าที่มีข้อมูลส่วนตัว) จับ request ด้วย Burp
  2. 2ต่อนามสกุลปลอมท้าย path แล้วลองด้วย curl: curl -s https://target/account/foo.css -b 'session=YOUR_SESSION'
  3. 3ดูว่า response ที่ได้ยังเป็นหน้า account (มีข้อมูลเหยื่อ) หรือเป็น 404/redirect
  4. 4ถ้าคืนหน้า account จริง เช็ค header ว่าถูก cache ไหม: curl -sI (ดู X-Cache, CF-Cache-Status, Age)
  5. 5ถ้าไม่ cache ลอง delimiter อื่นต่อท้าย path เช่น /account;foo.css, /account%2ffoo.css, /account%00.css
  6. 6เมื่อยืนยันว่า path+delimiter ที่ใช้ถูก cache แล้ว ให้เปิด URL เดียวกันจาก browser profile อื่น (private window ไม่ login)
  7. 7ถ้าเห็นข้อมูลของเหยื่อ (จาก session ที่ login ไว้ก่อนหน้า) ในหน้าที่ไม่ได้ login = ยืนยันช่องโหว่จริง
  8. 8บันทึก path + delimiter ที่ใช้ได้ผล เป็นหลักฐาน (screenshot + response header ที่มี X-Cache: HIT)
Decision flow — จับมือทำ Cache Deception
หาหน้าที่มีข้อมูลส่วนตัว (login แล้ว)
/account, /profile, /api/me
ต่อนามสกุล static ปลอมท้าย path
/account/foo.css
server คืนอะไร?
✅ คืนหน้า account (ข้อมูลเหยื่อ)→ เช็คว่าถูก cache ไหม
❌ 404/redirect→ ลอง delimiter อื่น (; %2f %00 # ?)
response header มี X-Cache/CF-Cache-Status/Age ไหม?
✅ HIT / มี Age→ ถูก cache แล้ว ทดสอบข้ามผู้ใช้
❌ ไม่มีเลย (MISS ตลอด)→ ลอง delimiter อื่น หรือข้ามไป cache poisoning
เปิด URL เดียวกันจาก private window / session อื่น
เห็นข้อมูลของเหยื่อไหม?
✅ เห็นข้อมูลเหยื่อ→ ยืนยันช่องโหว่ ข้อมูลรั่วผ่าน cache
❌ ไม่เห็นอะไร (cache แยกตาม cookie)→ ตันสนิท
ยืนยันสำเร็จ → ข้อมูลส่วนตัวรั่วผ่าน cache สาธารณะ
ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
ต่อนามสกุลปลอมทดสอบ pathcurl--
เช็คว่า cache ไหมcurl -sI--
fuzz delimiter หลายแบบอัตโนมัติffuf--
เปิดจาก session/context อื่นเพื่อยืนยันFirefox Private Window--
proxy ดูทุก request/responseBurp Suite Community--
🚑 ถ้าตันสนิท ลองท่าถัดไป: Web Cache Poisoning — ถ้าต่อนามสกุลแล้วไม่ cache เลยแต่เจอ unkeyed header ที่เปลี่ยน response ได้ ให้เปลี่ยนไปโจมตี cache key แทน; IDOR — ถ้า server ไม่ยืดหยุ่นเรื่อง path เลยสักแบบ ให้ข้ามไปหาการอ้าง object ตรงๆ (id ของผู้ใช้อื่น) แทน; Directory Enumeration — ถ้ายังไม่แน่ใจว่าโครงสร้าง path เป็นอย่างไร ให้ enumerate ก่อนว่ามี path ไหนที่ยืดหยุ่นบ้าง

โน้ตของฉัน

ยังไม่มีโน้ตสำหรับหัวข้อนี้