Broken Access Control
Broken Access Control คือหมวดที่ผู้ใช้เข้าถึงฟังก์ชัน/ข้อมูลเกินสิทธิ์ อันดับ 1 ของ OWASP Top 10 (2021) ครอบคลุม horizontal (ข้อมูลคนอื่นระดับเดียวกัน = IDOR), vertical (ยกระดับเป็น admin), และ function-level (forced browsing) บทนี้เน้นการทำ role matrix, forced browsing, การ manipulate role/header, และการทดสอบด้วย Autorize/AuthMatrix อย่างเป็นระบบ
1. ประเภทของ Broken Access Control
| ประเภท | ความหมาย | ตัวอย่าง |
|---|---|---|
| Horizontal | เข้าข้อมูลคนอื่นระดับเดียวกัน | ดู order ของ user อื่น (IDOR) |
| Vertical | ยกระดับเป็น role สูงกว่า | user ทั่วไปเข้า /admin ได้ |
| Function-level | เรียกฟังก์ชันที่ไม่ควรเห็น | POST /api/admin/delete-user |
| Context-dependent | ทำ action ผิดลำดับ/ผิดสถานะ | ข้ามขั้นตอน checkout |
| Multi-step bypass | ผ่านด่านแรกแล้วข้ามด่านหลัง | เข้า wizard step 3 ตรงๆ |
IDOR เป็น subset ของ horizontal access control (ดูหัวข้อ IDOR แยก) บทนี้เน้น vertical และ function-level ซึ่งเป็นการเข้าถึง 'ฟังก์ชัน' ที่สงวนไว้ให้ role สูงกว่า
2. สร้าง Role/Access Matrix
ก่อนยิงมั่ว ให้ทำ matrix ของ role × ฟังก์ชัน ให้ครบก่อน — จะได้รู้ว่าอะไร 'ควรเข้าไม่ได้' แล้วไปพิสูจน์ว่าจริงไหม ใช้ทุกบัญชีที่มี (guest, user, manager, admin) map ว่าใครเห็น endpoint อะไร
| endpoint | guest | user | admin | ต้องทดสอบ |
|---|---|---|---|---|
| GET /dashboard | ✗ | ✓ | ✓ | guest เข้าได้ไหม |
| GET /admin/users | ✗ | ✗ | ✓ | user เข้าได้ไหม (vertical) |
| POST /admin/users/{id}/ban | ✗ | ✗ | ✓ | user เรียกได้ไหม |
| GET /orders/{id} | ✗ | เจ้าของ | ✓ | user เข้า order คนอื่น (horizontal) |
| PATCH /users/{id} | ✗ | ตัวเอง | ✓ | แก้ role/คนอื่นได้ไหม |
- 1รวบรวมทุก endpoint จาก proxy history, JS bundle, sitemap, API docs/Swagger
- 2map ว่าแต่ละ role เห็น/เรียกอะไรได้ตามปกติ (baseline)
- 3ทำเครื่องหมายช่องที่ 'ควรเข้าไม่ได้' — นี่คือรายการที่ต้องพิสูจน์
- 4ยิงแต่ละช่องด้วย role ที่ต่ำกว่า แล้วดูว่า server บังคับสิทธิ์จริงไหม
- 5บันทึกทุกผลลง matrix — ช่องไหน 200 ทั้งที่ควร 403 = ช่องโหว่
3. Forced Browsing & Function-level bypass
แนวคิด: frontend ซ่อนปุ่ม/เมนู admin ไว้ แต่ backend อาจไม่เช็คสิทธิ์ที่ endpoint จริง — เดา/หา URL ของ admin แล้วเรียกตรงด้วย session สิทธิ์ต่ำ
# เดา endpoint admin ตรงๆ ด้วย session user ธรรมดา
GET /admin
GET /admin/dashboard
GET /administrator
GET /api/v1/admin/users
GET /api/internal/config
# path case / trailing tricks (บาง proxy route ไม่เหมือน backend)
GET /Admin GET /ADMIN GET /admin/ GET /./admin
GET /admin%2f GET /admin..;/ GET /api/;/admin/users
# static/backup ที่หลุด
GET /admin.php.bak GET /.git/config GET /swagger.jsonffuf -u 'https://target/FUZZ' \
-H 'Cookie: session=LOW_PRIV_SESSION' \
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-mc 200,301,302,403 -o forced.json
# 403 ที่ endpoint admin = มีอยู่จริง → หาทาง bypass ต่อ4. Manipulate role / header / token
ถ้า endpoint ตัดสินสิทธิ์จากค่าที่ ผู้ใช้ควบคุมได้ (cookie, body field, custom header) ก็แก้ค่านั้นเพื่อยกระดับได้เลย
# 1) role ใน cookie / body / JSON
Cookie: role=user → Cookie: role=admin
{"role":"user"} → {"role":"admin","isAdmin":true}
# 2) custom header ที่ backend เชื่อ (มักตั้งจาก gateway ภายใน)
X-Forwarded-For: 127.0.0.1
X-Original-URL: /admin/users
X-Rewrite-URL: /admin/users
X-Custom-IP-Authorization: 127.0.0.1
# 3) method override หลอก route ที่กันเฉพาะบาง method
X-HTTP-Method-Override: PUT
X-HTTP-Method: DELETE
# 4) JWT: แก้ claim role (ถ้า sig อ่อน / alg=none — ดู JWT Attacks)
{"sub":"user","role":"admin"}# proxy บล็อก /admin แต่ backend เชื่อ X-Original-URL
GET / HTTP/1.1
X-Original-URL: /admin/deleteUser?username=carlos
# หรือ path บล็อกที่ proxy แต่ normalize ต่างกันที่ backend
GET /admin/deleteUser HTTP/1.1 → 403
GET /ADMIN/deleteUser HTTP/1.1 → 200 (backend case-insensitive)5. Decision flow
6. เครื่องมือ
- Autorize (Burp): browse ด้วย admin, ให้ replay ทุก request ด้วย session ต่ำ ไฮไลต์ Bypassed!/Enforced! อัตโนมัติ
- AuthMatrix (Burp): สร้างตาราง role × request รันครั้งเดียวเทียบทุก role — เหมาะเว็บที่มีหลาย role
- ffuf / dirsearch: forced browsing หา endpoint ที่ซ่อน
- param-miner: ค้น header ลับ เช่น X-Original-URL, X-User-Role
- JWT Editor / jwt_tool: แก้ claim role เพื่อทดสอบ vertical (ดู JWT Attacks)
1. เพิ่มทุก role พร้อม session token (guest, user, admin)
2. เพิ่ม request สำคัญทั้งหมด (โดยเฉพาะ admin/write endpoints)
3. ติ๊ก checkbox: role ไหน 'ควร' เข้าถึง request ไหน (baseline สิทธิ์)
4. Run → ช่องที่ผล != baseline = broken access control
(เช่น user ได้ 200 ที่ช่องที่ควรเป็นของ admin)7. ตัวอย่าง CTF & Real-world
CTF: เมนู admin ถูกซ่อนใน UI แต่ JS bundle มี string /admin-panel-yb556 เรียกตรงด้วย session user ธรรมดา → เข้า panel ได้เลยเพราะ backend ตรวจแค่ 'ล็อกอินแล้ว' ไม่เช็ค role — solve ด้วยการ delete user carlos ผ่าน panel
Real-world: API gateway บล็อก /internal/* จากภายนอก แต่ microservice หลัง gateway เชื่อ header X-Original-URL ที่ผู้ใช้ส่งได้ — ยิง GET /public พร้อม X-Original-URL: /internal/admin ทะลุถึงฟังก์ชันภายใน เป็น pattern คลาสสิกของ front-end/back-end path มismatch
8. ข้อผิดพลาด & การป้องกัน
- ทดสอบแค่ GET: endpoint write (POST/PUT/DELETE) มักเช็คสิทธิ์ต่างจาก read
- เชื่อ UI: ปุ่มหาย ≠ backend กัน — ยิง API ตรงเสมอ
- ลืม role กลาง: โฟกัส user↔admin แต่ลืม manager/support ที่มีสิทธิ์คร่อม
- ไม่ทดสอบ multi-step: ด่านแรกเช็คสิทธิ์แต่ step หลังไม่เช็ค → เข้า step ปลายตรงๆ
- ผลบวกลวงจาก 302: redirect ไป login แต่ body ยังมีข้อมูล admin (ตอบก่อน redirect)
9. Quick Reference
- horizontal (IDOR) + vertical (privesc) + function-level + context
- ทำ role matrix ก่อน: อะไร 'ควรเข้าไม่ได้' → พิสูจน์
- forced browsing: เข้า /admin endpoint ด้วย session ต่ำ
- manipulate: role ใน cookie/body/JWT, X-Original-URL, method override
- path tricks: /Admin, /admin/, /admin%2f, /admin..;/
- frontend ซ่อนปุ่ม ≠ backend ป้องกัน — เรียก endpoint ตรง
- เครื่องมือ: Burp Autorize / AuthMatrix / ffuf / param-miner
- ป้องกัน: deny-by-default, ตรวจสิทธิ์ทุก endpoint ฝั่ง server, centralized RBAC
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเจอเว็บที่มีหลาย role (user/admin) มีแค่ Kali เปล่าๆ ยังไม่รู้ว่ามี broken access control ไหม — ทำตามนี้ทีละขั้นเพื่อเช็คว่าเข้าถึงฟังก์ชันที่ไม่ควรเข้าได้
- 1เปิด Burp Suite ตั้ง proxy แล้ว login ด้วย user สิทธิ์ต่ำสุดที่มี (หรือ guest ถ้าไม่ต้อง login)
- 2เดินดูทุกเมนู/ปุ่มที่เห็น ให้ Burp เก็บ Proxy > HTTP history ไว้ครบ
- 3เปิด view-source หรือ curl ดึง JS bundle มา grep หาคำว่า admin, internal, api/ ที่อาจซ่อนอยู่ในโค้ดฝั่ง client
- 4ลอง forced browsing ด้วย ffuf กวาด path ทั่วไปด้วย session user สิทธิ์ต่ำ (raft-medium-directories.txt)
- 5path ที่เจอ 200/403 ให้ยิงตรงด้วย curl/browser พร้อม cookie ของ user สิทธิ์ต่ำ ดูว่าทำงานได้ไหม
- 6ถ้าเจอ 403 ที่ proxy ลอง path trick เช่น /Admin, /admin/, หรือใส่ header X-Original-URL / X-Rewrite-URL
- 7ลองแก้ role ใน cookie/body/JWT เป็น admin แล้ว replay ด้วย Burp Repeater
- 8ติดตั้ง Autorize หรือ AuthMatrix (BApp Store) ใส่ session user แล้วเดินด้วย admin ให้สแกนทั้งเว็บอัตโนมัติ
- 9ทดสอบทุก HTTP method (GET/POST/PUT/DELETE) แยกกันที่ endpoint เดิม เพราะสิทธิ์อาจเช็คไม่เท่ากัน
- 10ยังตัน → เช็คว่ามี multi-step workflow ที่ข้าม step ได้ไหม (เข้า step ปลายตรงๆ)
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| forced browsing หา endpoint ซ่อน | ffuf | - | - |
| ดักจับ/แก้ role ใน request | Burp Suite Community | - | - |
| ตรวจ authz หลาย role อัตโนมัติ | Burp Extender | BApp Store: Autorize / AuthMatrix | - |
| หา endpoint จาก JS bundle | curl, grep | - | - |
| หา hidden header/param | - | BApp: param-miner / pipx install arjun | - |
| แก้/ปลอม JWT role claim | - | git clone https://github.com/ticarpi/jwt_tool | jwt.io |
| crack weak JWT secret | hashcat | - | crackstation.net |
หัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้