คลัง
web

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 อย่างเป็นระบบ

IntermediateAdvanced#access-control#authorization#privilege-escalation#forced-browsing#rbac#web#ctf

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 สูงกว่า

Vertical vs Horizontal access control
ADMIN role /admin, delete-user USER A order 1001 USER B order 1002 vertical ↑ (privesc) horizontal → (IDOR)

2. สร้าง Role/Access Matrix

ก่อนยิงมั่ว ให้ทำ matrix ของ role × ฟังก์ชัน ให้ครบก่อน — จะได้รู้ว่าอะไร 'ควรเข้าไม่ได้' แล้วไปพิสูจน์ว่าจริงไหม ใช้ทุกบัญชีที่มี (guest, user, manager, admin) map ว่าใครเห็น endpoint อะไร

endpointguestuseradminต้องทดสอบ
GET /dashboardguest เข้าได้ไหม
GET /admin/usersuser เข้าได้ไหม (vertical)
POST /admin/users/{id}/banuser เรียกได้ไหม
GET /orders/{id}เจ้าของuser เข้า order คนอื่น (horizontal)
PATCH /users/{id}ตัวเองแก้ role/คนอื่นได้ไหม
  1. 1รวบรวมทุก endpoint จาก proxy history, JS bundle, sitemap, API docs/Swagger
  2. 2map ว่าแต่ละ role เห็น/เรียกอะไรได้ตามปกติ (baseline)
  3. 3ทำเครื่องหมายช่องที่ 'ควรเข้าไม่ได้' — นี่คือรายการที่ต้องพิสูจน์
  4. 4ยิงแต่ละช่องด้วย role ที่ต่ำกว่า แล้วดูว่า server บังคับสิทธิ์จริงไหม
  5. 5บันทึกทุกผลลง matrix — ช่องไหน 200 ทั้งที่ควร 403 = ช่องโหว่

3. Forced Browsing & Function-level bypass

แนวคิด: frontend ซ่อนปุ่ม/เมนู admin ไว้ แต่ backend อาจไม่เช็คสิทธิ์ที่ endpoint จริง — เดา/หา URL ของ admin แล้วเรียกตรงด้วย session สิทธิ์ต่ำ

จุดที่ลอง forced browsing บ่อย
# เดา 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.json
หา endpoint ที่ซ่อนได้จาก JS bundle (grep 'admin', 'api/'), จาก /robots.txt, sitemap, และ Swagger
brute-force path ด้วย ffuf (พร้อม session)Linux
ffuf -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 ต่อ
อย่าเชื่อว่า 'ปุ่มไม่โชว์ = เข้าไม่ได้' — client-side access control (ซ่อน DOM/route guard ใน SPA) กันได้แค่ตา ผู้โจมตีเรียก API ตรงเสมอ เช็ค backend response ไม่ใช่ UI

4. Manipulate role / header / token

ถ้า endpoint ตัดสินสิทธิ์จากค่าที่ ผู้ใช้ควบคุมได้ (cookie, body field, custom header) ก็แก้ค่านั้นเพื่อยกระดับได้เลย

จุด manipulate ที่พบบ่อย
# 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"}
X-Original-URL / X-Rewrite-URL ใช้ bypass ได้เมื่อ front proxy กรอง path แต่ backend (เช่น Symfony) เชื่อ header นี้
URL-based access control bypass (front vs back)
# 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

เจอ role/endpoint ที่สงสัย — ไล่ตามนี้
ทำ role matrix: ใครควรเข้าอะไร
endpoint ที่ 'ควรเข้าไม่ได้' → ยิงด้วย session ต่ำ
ผลลัพธ์?
200 + ทำงานได้Broken access control ยืนยัน
403 ที่ proxyลอง X-Original-URL / case / path trick
ต้องเป็น adminลอง manipulate role/JWT claim
สิทธิ์ตัดสินจากอะไร?
cookie/body rolemanip
JWT claimไป JWT Attacks (alg=none/weak secret)
id ในทรัพยากรไป IDOR (horizontal)
แก้ role → admin แล้ว replay
ยืนยันด้วย Autorize ทั้งเว็บ
หา endpoint อื่นที่ bypass เหมือนกัน
privesc / เข้าถึงฟังก์ชัน admin สำเร็จ

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)
AuthMatrix workflow ย่อ
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)
การป้องกัน (blue team): ใช้ deny-by-default — ทุก endpoint ต้อง opt-in สิทธิ์ ตรวจ authorization ที่ server ทุกครั้งจาก session/token (ไม่ใช่จาก input ที่ผู้ใช้ส่ง) รวมสิทธิ์ไว้ที่ middleware/policy layer เดียวไม่กระจาย, อย่าเชื่อ X-Original-URL/X-Forwarded-* จากภายนอก, และทำ centralized RBAC + log การเข้าถึงที่ถูกปฏิเสธเพื่อ detect การ probe

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. 1เปิด Burp Suite ตั้ง proxy แล้ว login ด้วย user สิทธิ์ต่ำสุดที่มี (หรือ guest ถ้าไม่ต้อง login)
  2. 2เดินดูทุกเมนู/ปุ่มที่เห็น ให้ Burp เก็บ Proxy > HTTP history ไว้ครบ
  3. 3เปิด view-source หรือ curl ดึง JS bundle มา grep หาคำว่า admin, internal, api/ ที่อาจซ่อนอยู่ในโค้ดฝั่ง client
  4. 4ลอง forced browsing ด้วย ffuf กวาด path ทั่วไปด้วย session user สิทธิ์ต่ำ (raft-medium-directories.txt)
  5. 5path ที่เจอ 200/403 ให้ยิงตรงด้วย curl/browser พร้อม cookie ของ user สิทธิ์ต่ำ ดูว่าทำงานได้ไหม
  6. 6ถ้าเจอ 403 ที่ proxy ลอง path trick เช่น /Admin, /admin/, หรือใส่ header X-Original-URL / X-Rewrite-URL
  7. 7ลองแก้ role ใน cookie/body/JWT เป็น admin แล้ว replay ด้วย Burp Repeater
  8. 8ติดตั้ง Autorize หรือ AuthMatrix (BApp Store) ใส่ session user แล้วเดินด้วย admin ให้สแกนทั้งเว็บอัตโนมัติ
  9. 9ทดสอบทุก HTTP method (GET/POST/PUT/DELETE) แยกกันที่ endpoint เดิม เพราะสิทธิ์อาจเช็คไม่เท่ากัน
  10. 10ยังตัน → เช็คว่ามี multi-step workflow ที่ข้าม step ได้ไหม (เข้า step ปลายตรงๆ)
ตัดสินใจ: เจอ broken access control ไหม แล้วไปต่อทางไหน
หา endpoint ที่ 'ควรเข้าไม่ได้' จาก JS bundle / forced browsing (ffuf)
ยิงด้วย session user สิทธิ์ต่ำ ผลลัพธ์?
✅ 200 + ทำงานได้→ ยืนยัน broken access control แล้วหาเพิ่มด้วย Autorize
❌ 403 ที่ proxy→ ลอง path trick / X-Original-URL / case
หา endpoint อื่นที่ bypass เหมือนกันด้วย Autorize/AuthMatrix ทั้งเว็บ
ลอง /Admin, /admin/, X-Original-URL, method override, แก้ role ใน cookie/body
✅ ผ่านสักท่า→ กลับไปยืนยันด้วย Autorize
❌ ยังไม่ได้เลย→ role ตัดสินจาก JWT claim ไหม?
ยืนยันสำเร็จ → เก็บ request/response เป็นหลักฐาน
ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
forced browsing หา endpoint ซ่อนffuf--
ดักจับ/แก้ role ใน requestBurp Suite Community--
ตรวจ authz หลาย role อัตโนมัติBurp ExtenderBApp Store: Autorize / AuthMatrix-
หา endpoint จาก JS bundlecurl, grep--
หา hidden header/param-BApp: param-miner / pipx install arjun-
แก้/ปลอม JWT role claim-git clone https://github.com/ticarpi/jwt_tooljwt.io
crack weak JWT secrethashcat-crackstation.net
🚑 ถ้าตันสนิท ลองท่าถัดไป: IDOR — ถ้าปัญหาเป็นเรื่อง ownership ของข้อมูลระดับเดียวกัน (horizontal) ไม่ใช่ role ต่างระดับ · JWT Attacks — ถ้า role ถูกกำหนดใน JWT claim ที่ปลอมได้ · Business Logic — ถ้าเป็นการข้าม step ของ workflow มากกว่าเรื่องสิทธิ์ · Auth Testing — ถ้า session ผูกกับ role ผิดตั้งแต่ตอน login/2FA

หัวข้อที่เชื่อมโยง

โน้ตของฉัน

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