JWT Attacks
JWT (JSON Web Token) เป็น token ที่เซิร์ฟเวอร์ใช้ยืนยันตัวตน ช่องโหว่เกิดจากการ verify signature ที่ผิดพลาด เช่น alg=none, algorithm confusion (RS256→HS256), weak secret บทนี้ครอบคลุมโครงสร้าง JWT และการโจมตีหลัก
1. โครงสร้าง JWT
JWT มี 3 ส่วนคั่นด้วยจุด: header.payload.signature แต่ละส่วนเป็น base64url header บอก algorithm (alg) payload เก็บ claims (เช่น user, role) signature ใช้ยืนยันว่าไม่ถูกแก้ — ความปลอดภัยทั้งหมดอยู่ที่การ verify signature อย่างถูกต้อง
2. alg=none
ถ้าเซิร์ฟเวอร์ยอมรับ alg: none หมายความว่ามันไม่ verify signature เลย — ผู้โจมตีแก้ payload (เช่น role: admin) ตั้ง alg เป็น none และลบ signature ทิ้ง token ก็ยังผ่าน
# header: {"alg":"none","typ":"JWT"} payload: {"user":"admin"}
# base64url ทั้งสองส่วน ตามด้วยจุดและ signature ว่าง
echo -n '{"alg":"none","typ":"JWT"}' | base64 | tr '+/' '-_' | tr -d '='
echo -n '{"user":"admin","role":"admin"}' | base64 | tr '+/' '-_' | tr -d '='
# ผลลัพธ์: <header>.<payload>. (ลงท้ายด้วยจุด ไม่มี signature)
# หรือใช้ jwt_tool
jwt_tool TOKEN -X a3. Algorithm confusion (RS256 → HS256)
RS256 ใช้ private key เซ็น/public key verify ส่วน HS256 ใช้ secret เดียวกันทั้งเซ็นและ verify ถ้าเซิร์ฟเวอร์เขียนโค้ดไม่รัดกุม ผู้โจมตีเปลี่ยน alg เป็น HS256 แล้วใช้ public key (ที่เปิดเผยอยู่แล้ว) เป็น secret ในการเซ็น — เซิร์ฟเวอร์จะ verify ด้วย public key เดียวกันแล้วผ่าน
# ต้องมี public key ของเซิร์ฟเวอร์ (มักหาได้จาก /jwks.json, cert, หรือ derive)
jwt_tool TOKEN -X k -pk public.pem
# -X k = key confusion attack4. จุดอ่อนอื่น
- Weak secret (HS256): brute-force secret ด้วย wordlist —
jwt_tool TOKEN -C -d rockyou.txtหรือ hashcat mode 16500 - kid injection: header
kidชี้ไฟล์ key — ลอง path traversal หรือ SQLi ใน kid เพื่อควบคุม key - jku/x5u: header ชี้ URL ของ key set — ชี้ไป key ของเราเอง (ถ้าไม่ validate domain)
- ไม่เช็ค expiry: token หมดอายุยังใช้ได้
- claim ไม่ถูก validate: แก้ role/user ใน payload หลัง bypass signature
5. Quick Reference
- JWT = header.payload.signature (base64url)
- alg=none → ลบ signature, แก้ payload ได้
- RS256→HS256 confusion: เซ็นด้วย public key เป็น secret
- weak secret: jwt_tool -C -d wordlist / hashcat -m 16500
- kid/jku/x5u: ควบคุม key ที่ใช้ verify
- เครื่องมือหลัก: jwt_tool, jwt.io (decode)
- ป้องกัน: บังคับ alg, ไม่รับ none, validate kid/jku, secret แข็งแรง
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเจอ token ที่ขึ้นต้นด้วย eyJ ในคุกกี้หรือ Authorization header มีแค่ Kali เปล่าๆ ทำตามนี้ทีละขั้นเพื่อดูว่าปลอมได้ไหม
- 1ก็อป token ไปวางที่ jwt.io ดู header/payload (decode ได้เลยไม่ต้องมี secret)
- 2เช็คว่า header
algเป็นอะไร: none, HS256, RS256 - 3ติดตั้ง jwt_tool (git clone https://github.com/ticarpi/jwt_tool) แล้วลอง
jwt_tool TOKEN -X aเพื่อสร้าง token alg=none ส่งกลับไปแทน token เดิม - 4ถ้า alg=HS256 ลอง crack weak secret ด้วย
jwt_tool TOKEN -C -d /usr/share/wordlists/rockyou.txtหรือhashcat -m 16500 -a 0 token.txt rockyou.txt - 5ถ้า alg=RS256 หา public key จาก
/jwks.jsonหรือ/.well-known/jwks.jsonแล้วลองjwt_tool TOKEN -X k -pk public.pem(algorithm confusion) - 6เช็ค header ว่ามี
kidไหม ลอง path traversal/SQLi ใน kid ด้วยjwt_tool TOKEN -X i - 7เช็คว่ามี
jku/x5uheader ชี้ URL ที่เราคุมเองได้ไหม - 8เมื่อได้ signature ที่ปลอมได้แล้ว แก้ payload (เช่น role:admin) แล้วส่ง token กลับไปยัง endpoint จริงเพื่อยืนยันผล
- 9เช็ค claim หมดอายุ (exp) ด้วยว่า token เก่ายังใช้ได้ไหม
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| decode/inspect JWT | - | - | jwt.io |
| โจมตี/แก้/เซ็น JWT อัตโนมัติ | - | git clone https://github.com/ticarpi/jwt_tool | - |
| crack weak HMAC secret | hashcat (-m 16500), john | - | crackstation.net |
| wordlist สำหรับ crack secret | /usr/share/wordlists/rockyou.txt | - | - |
| ดักจับ/แก้ token ใน request | Burp Suite Community | - | - |
| แปลง/encode base64url ด้วยมือ | - | - | CyberChef |
หัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้