Authorization and Access Control Testing
Authorization questions dominate real engagements and this exam. The domain tests whether you can prove that a request performed by one identity reaches data or functions belonging to another, and whether you can distinguish a genuine control gap from a UI convenience.
The taxonomy
- Vertical escalation. A low-privilege user reaches an administrative function:
POST /admin/users/deletesucceeds with a standard token because the check exists only in the UI. - Horizontal escalation (BOLA/IDOR). Same role, different object owner. The classic:
/api/invoices/1001returns another tenant's record when you swap the identifier. - Object property-level (mass assignment / excessive data exposure). Sending
"role":"admin"or"isVerified":truein a profile update binds to a model field; conversely, responses return fields the UI hides. - Function-level and method-level gaps.
GETis checked butPUTandDELETEon the same route are not; internal/v1endpoints outlive the hardened/v2. - Forced browsing. Reaching unlinked paths, backup routes, and status pages.
- Tenant isolation. Two organizations in one deployment; the tenant is derived from a header, subdomain, or token claim rather than server-side.
Method
Build a role-by-endpoint matrix from captured traffic, then replay every request with a second identity. Change identifiers, methods, content types, and headers (X-User-Id, X-Org-Id, X-Forwarded-Host). Compare bodies, not just status codes - graphQL and batch endpoints frequently return partial data with 200. Test child and nested resources (/users/7/orders/9) because parent checks are often copied without the child.
Worked example
Account A (id=1001) fetches GET /api/v2/invoices/5501 and receives an invoice. Account B uses its own valid token and requests the same URL: 200 with A's data. Then B sends DELETE on the same path: 204. Reasoning: the endpoint checks authentication but never compares invoice.owner_id with the token subject, and the state-changing method inherits the same gap - so this is both data disclosure and destructive tampering. Report the read and delete as separate evidence items under one finding, with both request/response pairs and the owning account identified.
Traps that cost marks
- Assuming UUIDs prevent enumeration; they prevent guessing, not authorization failure.
- Testing only the UI-visible flow and missing parallel API versions.
- Treating a 403 on one identifier as proof the whole endpoint is safe.
- Forgetting that caching layers can serve one user's authorized response to another.