Session Testing
Session Testing คือการตรวจการจัดการ session/token เพื่อหาจุดที่ทำให้ขโมย ปลอม หรือคง session ของคนอื่นได้ ครอบคลุม cookie attributes (HttpOnly/Secure/SameSite), session fixation, predictable/weak token, การไม่ invalidate หลัง logout/เปลี่ยนรหัส, token รั่วผ่าน URL/Referer, และ JWT บทนี้ไล่ทุกจุดพร้อม request จริงและ workflow
1. Cookie attributes
attribute ของ session cookie เป็นด่านแรก — flag ที่ขาดไปแต่ละตัวเปิดช่องโจมตีคนละแบบ ตรวจ Set-Cookie ตอน login เสมอ
| attribute | ถ้าขาด → เสี่ยง | หมายเหตุ |
|---|---|---|
| HttpOnly | JS อ่าน cookie ได้ → XSS ขโมย session | session cookie ต้องมีเสมอ |
| Secure | cookie ส่งผ่าน HTTP → ดักได้ | บังคับ HTTPS-only |
| SameSite | ไม่กัน CSRF/cross-site | Strict/Lax/None (None ต้องมี Secure) |
| Domain กว้าง | cookie รั่วไปทุก subdomain | หลีกเลี่ยง .example.com ถ้าไม่จำเป็น |
| Path กว้าง | cookie ส่งไป path ที่ไม่เกี่ยว | จำกัด scope เท่าที่ใช้ |
| Expires/Max-Age ยาว | session อยู่นานเกิน | ควรมี idle + absolute timeout |
curl -sI https://target/login | grep -i set-cookie
# ตัวอย่างที่ดี:
# Set-Cookie: session=...; HttpOnly; Secure; SameSite=Lax; Path=/
# ที่ขาด flag → ตั้งสมมติฐานตามตาราง แล้วไปพิสูจน์ผลกระทบ2. Session fixation
Session fixation เกิดเมื่อ server ไม่สร้าง session id ใหม่หลัง login ผู้โจมตี 'กำหนด' session id ให้เหยื่อล่วงหน้า (ผ่านลิงก์/cookie injection) พอเหยื่อ login ด้วย id นั้น ผู้โจมตีที่รู้ id เดียวกันก็เข้าบัญชีเหยื่อได้ทันที
- 1จด session id ก่อน login (ยังไม่ยืนยันตัวตน)
- 2login ให้สำเร็จ แล้วดู session id อีกครั้ง
- 3ถ้า id เหมือนเดิม = เสี่ยง fixation (server ควร regenerate)
- 4จำลองการโจมตี: ตั้ง id ที่รู้ให้ 'เหยื่อ' (ผ่าน ?sessionid= หรือ cookie ที่ set ได้) แล้วรอ login
- 5หลังเหยื่อ login ลองใช้ id เดิม → ถ้าเข้าได้ = fixation ยืนยัน
3. Predictable / weak token
session id ที่ดีต้องสุ่มด้วย CSPRNG และยาวพอ (≥128 บิต entropy) ถ้า id เรียงลำดับ, เป็น base64 ของค่าที่เดาได้, หรือมี entropy ต่ำ ผู้โจมตีคาดเดา/enumerate session ของคนอื่นได้
- เก็บ token หลายอัน: สร้างบัญชีหลายรอบเก็บ session id มาเทียบหา pattern (เลขเรียง, timestamp, counter)
- Decode: ลอง base64/hex/URL-decode — ข้างในอาจเป็น
userid:timestampหรือ JSON - วัด entropy: ใช้ Burp Sequencer เก็บ token จำนวนมากแล้ววิเคราะห์ randomness
- Structure leak: token ที่มี username/role/email ฝังอยู่ = แก้เพื่อ escalate ได้ (คล้าย JWT ที่ไม่เซ็น)
import base64
tok = "dXNlcjoxMDA1OnJvbGU6dXNlcg==" # ตัวอย่าง cookie ที่ได้มา
print(base64.b64decode(tok))
# b'user:1005:role:user' → เดา id คนอื่น + ลองแก้ role:admin
# ถ้าไม่มี signature/HMAC → ปลอมได้ทันที4. Session lifecycle & invalidation
session ที่ 'ไม่ตาย' คือปัญหา — หลัง logout, เปลี่ยนรหัส, หรือ admin สั่ง revoke แล้ว token เก่าต้องใช้ไม่ได้ทันที ทดสอบด้วยการเก็บ token ไว้ก่อนเหตุการณ์แล้วลองใช้หลังจากนั้น
| เหตุการณ์ | token เก่าควรเป็นอย่างไร | วิธีทดสอบ |
|---|---|---|
| Logout | ใช้ไม่ได้ทันที (server-side) | logout แล้ว replay request เก่าด้วย token เดิม |
| เปลี่ยนรหัสผ่าน | session อื่นทั้งหมดต้องหลุด | login 2 ที่, เปลี่ยนรหัสที่หนึ่ง, ทดสอบอีกที่ |
| Idle timeout | หมดอายุหลังไม่ใช้งาน | ทิ้งไว้แล้วลองใช้ |
| Absolute timeout | หมดอายุตามเวลาจริง | ใช้ token ข้ามวัน |
| Concurrent login | จำกัด/แจ้งเตือนตาม policy | login หลายที่พร้อมกัน |
5. Token leakage & hijacking chain
- Token ใน URL:
?sessionid=รั่วผ่าน Referer header, browser history, proxy/access log, และ analytics - ผ่าน XSS: ถ้าไม่มี HttpOnly →
document.cookieส่งออกได้ (ดู XSS) - ผ่าน network: ไม่มี Secure → ดักบน HTTP/Wi-Fi สาธารณะ
- ผ่าน subdomain: Domain กว้าง (.example.com) → subdomain ที่ถูก compromise อ่าน cookie ได้
- Cache: response ที่มี token ถูก cache โดย CDN/proxy
6. เมื่อ session เป็น JWT
ถ้า token เป็น JWT (สาม segment คั่นด้วยจุด, ขึ้นต้น eyJ) การทดสอบเปลี่ยนไปเน้นที่ signature — ดูหัวข้อ JWT Attacks สำหรับ alg=none, weak HMAC secret (crack ด้วย hashcat), kid injection, และ algorithm confusion (RS256→HS256)
# JWT: base64url 3 ส่วน, decode ส่วนแรกได้ header JSON
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMDA1In0.abc...
header = {"alg":"HS256","typ":"JWT"}
payload = {"sub":"1005","role":"user"} ← แก้ role แล้วต้องเซ็นใหม่
# Opaque: สุ่มล้วน อ้างอิง state ฝั่ง server → ทดสอบ predictability/lifecycle แทน7. ตัวอย่าง CTF & Real-world
CTF: cookie auth=YWRtaW46ZmFsc2U= ถอด base64 ได้ admin:false เปลี่ยนเป็น admin:true แล้ว encode กลับ → ยกสิทธิ์ทันทีเพราะ token ไม่มี signature เป็นตัวอย่าง weak session token คลาสสิก
Real-world: เว็บออก session id ผ่าน URL ?jsessionid= เพื่อรองรับเบราว์เซอร์ไม่รับ cookie — id หลุดเข้า Referer เมื่อผู้ใช้คลิกลิงก์ออกไปเว็บอื่น ผู้ดูแลเว็บภายนอกเก็บ id จาก Referer log แล้ว hijack session ได้ทันที เป็นเหตุผลว่าทำไม session ต้องอยู่ใน cookie เท่านั้น
8. ข้อผิดพลาด & การป้องกัน
- ดูแค่ flag แล้วจบ: ต้องพิสูจน์ผลกระทบจริง (fixation/reuse/predictability)
- ลืมทดสอบไขว้ 2 session: เปลี่ยนรหัสที่ session หนึ่งแล้วลืมเช็คอีก session
- ตัดสิน logout จาก client: cookie หายแต่ server ยังถือ valid — ต้อง replay ทดสอบ
- ลืม subdomain/Domain scope: cookie รั่วข้าม subdomain
HttpOnly; Secure; SameSite=Lax/Strict, regenerate id หลัง login/privesc, invalidate ฝั่ง server จริงเมื่อ logout/เปลี่ยนรหัส (revoke ทุก session), มี idle+absolute timeout, ห้ามใส่ token ใน URL, และผูก session กับสัญญาณ (เช่น binding อ่อนๆ กับ User-Agent) โดยไม่ทำให้ใช้งานพัง9. Quick Reference
- เช็ค Set-Cookie: HttpOnly + Secure + SameSite + Domain/Path แคบ
- fixation: จด id ก่อน-หลัง login → ต้องเปลี่ยน
- predictable: เก็บหลาย token, decode, Burp Sequencer
- invalidation: token หลัง logout/เปลี่ยนรหัสต้องตาย (replay ทดสอบ)
- leak: URL/Referer, XSS (ไม่มี HttpOnly), network (ไม่มี Secure), subdomain
- JWT → ดู JWT Attacks (alg=none, weak secret, RS256→HS256)
- ป้องกัน: CSPRNG, regenerate, invalidate จริง, cookie flags ครบ, ไม่ใส่ token ใน URL
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติ login เว็บเป้าหมายได้แล้ว มีแค่ Kali เปล่าๆ อยากรู้ว่า session/token ที่ได้มามีช่องให้ขโมย/ปลอมไหม — ทำตามนี้ทีละขั้น
- 1login แล้วดู Set-Cookie ด้วย curl -sI (หรือ Burp) ตรวจว่ามี HttpOnly / Secure / SameSite ครบไหม
- 2จด session id/token ทันทีก่อน login และหลัง login เทียบกัน (เช็ค fixation)
- 3login/สมัครใหม่หลายรอบ เก็บ token แต่ละครั้งไว้ วางใน Burp Sequencer เพื่อวัด randomness
- 4วาง token ใน CyberChef (From Base64 / From Hex) ดูว่ามี structure ที่อ่าน/แก้ได้ไหม (เช่น user:role)
- 5logout แล้วเก็บ token เดิมไว้ ลอง replay request เก่าด้วย token นั้นดูว่ายังใช้ได้ไหม
- 6ถ้าเปลี่ยนรหัสผ่านได้ ลอง login 2 ที่พร้อมกัน เปลี่ยนรหัสที่หนึ่ง แล้วเช็คอีกที่ว่า session หลุดไหม
- 7ถ้า token ขึ้นต้น eyJ (เป็น JWT) เอาไปวางที่ jwt.io ดู header/payload
- 8ถ้าไม่มี HttpOnly ลองยืนยันด้วย PoC XSS ง่ายๆ (document.cookie) ในช่องที่รับ input ได้
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| ตรวจ cookie flags | curl | - | - |
| ดักจับ/แก้ไข token | Burp Suite Community | - | - |
| วัด entropy ของ token | Burp Sequencer | - | - |
| decode token (base64/hex) | - | - | CyberChef |
| ถอด/แก้ JWT | - | git clone https://github.com/ticarpi/jwt_tool | jwt.io |
| crack weak JWT secret | hashcat | - | crackstation.net |
หัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้