บทที่ 8 · Part 2 — Identity & Web Security

Authorization & Access Control

RBAC, ABAC, ReBAC, BOLA/IDOR, function/property authorization, multi-tenant isolation และ maker-checker สำหรับ privileged action

API อาจตรวจ access token และ role ถูกต้องทุก request แต่ยังเปิด statement ของ account อื่นได้ เมื่อเปลี่ยน account_id ใน URL ปัญหาไม่ได้อยู่ที่ Authentication เพราะ identity ถูกต้อง แต่อยู่ที่ระบบไม่ตรวจความสัมพันธ์ระหว่าง identity, action และ resource

Learning Outcomes

  • เขียน authorization decision ด้วย subject, action, resource และ context ได้
  • เลือกและผสม RBAC, ABAC, ReBAC ตามโดเมนได้
  • ป้องกัน object-, function- และ property-level authorization failure ได้
  • ออกแบบ Policy Decision Point และ Enforcement Point แบบ default deny ได้
  • ทดสอบ multi-tenant isolation และ maker-checker ที่รักษา transaction integrity ได้

Authentication ไม่ได้ให้สิทธิ์อัตโนมัติ

authorization decision ที่ครบควรตอบ:

Can SUBJECT perform ACTION on RESOURCE under CONTEXT and CURRENT STATE?

ตัวอย่าง:

subject  = operator:8472
action   = payout:approve
resource = payout-batch:pb_01J...
context  = tenant, amount band, device assurance, current time
state    = batch version 7, status PENDING_APPROVAL, creator != subject

การตรวจเพียง role == admin ขาด resource, tenant, state และ purpose ทำให้ privilege กว้างเกิน

Access Control Models

ModelPolicy อาศัยเหมาะกับจุดระวัง
RBACrole/job functioncoarse-grained workforce permissionsrole explosion และ role กว้างเกิน
ABACsubject/resource/environment attributesamount, tenant, risk, data classattribute authority/freshness และ policy ซับซ้อน
ReBACrelationship graphowner, member, delegated accessgraph consistency, traversal และ revocation

ระบบจริงมักผสมกัน เช่น role support-agent เปิด ticket ได้ แต่ดู account ได้เฉพาะ tenant ที่ assigned และเฉพาะเมื่อมี relationship กับ case ที่ active

เริ่มจาก Domain Action

permission อย่าง database:write หรือ api:call กว้างและไม่สื่อ business invariant ชื่ออย่าง refund:request, refund:approve, statement:read-masked review และ audit ได้ชัดกว่า

Default Deny และ Complete Mediation

  • endpoint/action ใหม่ต้อง deny จนมี policy ชัด
  • backend ตรวจทุก request ไม่เชื่อว่า frontend ซ่อนปุ่มแล้ว
  • internal service ไม่เชื่อเพียง network location
  • authorization ถูกตรวจอีกครั้งใกล้ side effect เมื่อ state เปลี่ยนได้
  • deny/error path ไม่ fallback เป็น allow เมื่อ policy service timeout

PDP ตัดสิน policy ส่วน PEP บังคับผล ทั้ง 2อาจอยู่ library/service เดียวกัน แต่ ownership, failure semantics, cache และ telemetry ต้องชัด indeterminate ไม่ควรถูกตีเป็น allow

Three Authorization Layers

Object-Level: BOLA และ IDOR

request นี้อ่าน object ชิ้นใด ได้หรือไม่:

GET /accounts/acc_02/statements
Authorization: Bearer <token>

token ที่ valid ไม่พิสูจน์ ownership ของ acc_02 UUID ที่เดายากลด enumeration แต่ไม่ใช่ control query ควร scope ด้วย subject/tenant/relationship หรือ authorize object หลัง load อย่างสม่ำเสมอ

Function-Level

subject เรียก operation นี้ ได้หรือไม่ เช่น user endpoint กับ admin endpoint การเปลี่ยน HTTP method/path หรือเรียก internal route โดยตรงต้องไม่ข้าม policy

Property-Level

subject อ่านหรือเขียน field ใด ได้หรือไม่ ปัญหาที่พบบ่อย:

  • response ส่ง field ลับแล้วหวังให้ frontend ซ่อน
  • mass assignment รับ role, status, approved_by จาก JSON
  • support เห็น account number เต็มแทน masked view
  • PATCH อนุญาตเปลี่ยน owner/tenant โดยไม่ตั้งใจ

ใช้ explicit request/response schema ต่อ use case ไม่ bind domain/admin model ทั้งก้อน

Enforcement ต้องอยู่ใกล้ Data

รูปแบบ query ที่เสี่ยง:

SELECT * FROM statements WHERE account_id = $1;

รูปแบบที่ scope tenant/ownership ใน query ช่วยลดช่องว่างระหว่าง check กับ use:

SELECT s.*
FROM statements s
JOIN account_members m ON m.account_id = s.account_id
WHERE s.account_id = $1
  AND m.subject_id = $2
  AND m.tenant_id = $3;

ยังต้องพิจารณา role/action และ database policy ตาม architecture แต่หลักคืออย่า load object ด้วย untrusted ID แล้วลืมตรวจ relationship

Multi-Tenant Isolation ครอบคลุมมากกว่า API

Layerตัวอย่าง failure
Query/databaseลืม tenant predicate หรือใช้ connection context ผิด
Cachecache key ไม่มี tenant ID
Object storagesigned URL/prefix policy ข้าม tenant
Search/indexfilter tenant ถูกส่งจาก client และแก้ได้
Queue/jobmessage ไม่มี trusted tenant context
Export/reportbackground report รวมข้อมูลหลาย tenant
Log/tracesupport search เห็นข้อมูลทุก tenant
Admin toolimpersonation ไม่มี scope/approval/audit

tenant context ต้องมาจาก trusted identity/resource mapping ไม่เชื่อ X-Tenant-ID จาก public client โดยไม่ validate membership

Cache Authorization อย่างระวัง

policy cache key ต้องรวม subject, action, resource, tenant, relevant attributes และ policy version พร้อม TTL/invalidation ที่สอดคล้องกับ revoke expectation

การ cache is_admin=true นาน 1 วันทำให้ถอด role แล้วสิทธิ์ยังอยู่ การ cache deny/allow มี trade-off ต่างกัน และ privileged action อาจต้องอ่าน current state สดเสมอ

Maker-Checker และ Separation of Duties

flow อนุมัติที่ปลอดภัยไม่ได้จบที่ “มี 2 role”:

ต้องตรวจว่า:

  • requester และ approver เป็นคนละ independent identity
  • role conflict/temporary delegation ถูกพิจารณา
  • approval ผูกกับ immutable version/content hash
  • เปลี่ยน amount/beneficiary แล้วกลับไปขอ approval ใหม่
  • final execution ตรวจ state/policy อีกครั้งเพื่อกัน TOCTOU
  • break-glass มีขอบเขต, notification และ post-review

Approval Threshold เป็น Human-Owned Policy

วงเงิน, จำนวน approver, cooling period และ exception มีผลต่อเงินและการปฏิบัติงาน code ควร enforce policy ที่ version/audit ได้ แต่ผู้มีอำนาจจากธุรกิจและ Risk/Compliance ต้องเป็นผู้อนุมัติ policy ไม่ใช่ให้ engineer เลือกจากตัวอย่าง

Authorization for Service Identities

workload identity ต้องมีสิทธิ์แคบเหมือน human identity:

  • service A เรียก action ใดของ service B
  • acting as end user หรือทำในนามระบบ
  • delegated subject/context ถูกพิสูจน์และลดสิทธิ์อย่างไร
  • batch/queue message รักษา tenant/resource context อย่างไร
  • credential compromise มี blast radius และ revoke path ใด

confused deputy เกิดเมื่อ service ที่มี privilege ถูกหลอกให้ใช้สิทธิ์แทน caller โดยไม่ตรวจ resource/tenant/delegation context

Decision Logging

บันทึก subject, action, resource reference, tenant, policy version, outcome/reason, correlation ID และ enforcement point โดยไม่เก็บ raw token หรือข้อมูลเกินจำเป็น

deny log มี volume สูงและ attacker สร้าง noise ได้ จึงต้อง sampling/aggregation อย่างระวัง แต่ privileged allow/deny และ policy change ควรมี evidence ครบพร้อม alert ตาม risk

Test เป็น Matrix ไม่ใช่ Happy Path

DimensionCases
Subjectowner, member, non-member, suspended, service
Actionread, create, update, approve, delete, export
Resourceown, same tenant, other tenant, missing, stale version
Propertyallowed field, hidden field, mass-assigned field
Statedraft, pending, approved, executed, closed
Contextassurance, device, time, delegated/break-glass

เพิ่ม tests สำหรับเปลี่ยน object ID, method/path, nested ID, bulk endpoint, cache hit, async job, concurrent state change และ policy service failure

Review Checklist

  • decision ระบุ subject-action-resource-context-current state
  • backend enforce ทุก operation ด้วย default deny
  • RBAC/ABAC/ReBAC มี trusted source และ lifecycle ของ role/attribute/relationship
  • object/function/property authorization ถูกทดสอบแยกกัน
  • query/cache/storage/queue/export/log/admin ครอบคลุม tenant isolation
  • policy cache key/version/TTL สอดคล้องกับ revocation
  • approval ผูกกับ transaction version และ independent actor
  • service identity/delegation ป้องกัน confused deputy
  • deny/indeterminate/failure ไม่กลายเป็น allow
  • decision log มี policy version/outcome โดยไม่มี raw credential

สรุป

Authorization คือการตัดสินความสัมพันธ์ระหว่าง identity, action, resource, context และ state ทุกครั้งที่เกิด side effect Authentication, UUID ที่เดายาก, network ภายใน และการซ่อน UI ไม่สามารถแทน server-side authorization แบบ default deny ได้

Further Reading