BOLA (Broken Object Level Authorization): API IDOR Hunting Guide
BOLA is OWASP API1 for a reason. The UI hides other people’s objects. The API often does not. Change orderId, doc_id, or a UUID in a path and the server returns another tenant’s record because auth checked “logged in,” not “owns this object.”
If you hunt APIs, this should be muscle memory.
Two accounts, one method
Register User A and User B (or use the program’s dual-account guidance). As A, create an object — invoice, message, file, booking. Capture the request that reads or updates it. Replay as B with A’s object identifier. If B sees or mutates A’s data, you have BOLA.
Sounds basic. Most of my valid API bugs still start here.
Where IDs hide
- Path:
/api/v2/orders/18422 - Body:
{"project_id":"..."} - Nested resources:
/teams/{tid}/members/{uid} - “Export” and “share” endpoints that take raw keys
- Mobile traffic — often clearer than the website
- Batch endpoints that accept arrays of IDs (one unauthorized ID in the list is enough)
UUIDs are not authorization. Opaque IDs slow guessing; they do not prove ownership.
Severity without hype
Triagers want: object type, sensitivity (PII, payment, private messages), and whether read-only or write. Horizontal access to another user’s private notes beats “I can see a public profile ID.” Vertical jumps (user → admin object) deserve separate framing.
I avoid claiming “full account takeover” unless the object actually yields session secrets or password reset material.
False friends
- IDs that resolve to 404 for everyone including the owner (broken feature, not BOLA)
- Content the product intentionally shares by link
- Numeric IDs on public catalog items
Read the feature. Then swap the ID.
Fixes worth recommending
Server-side ownership checks on every object access. Prefer opaque references that still enforce ACL. Centralize authorize(user, object, action) instead of copying if (session) in each handler. Add regression tests that call User B against User A’s fixtures.
Hunter checklist I keep sticky-noted
- Map object-rich endpoints while clicking as A.
- Diff A vs B responses for the same ID.
- Try verbs: GET, PUT/PATCH, DELETE, export.
- Test related IDs (attachment under a message you cannot read).
- Stop at your own accounts; no scraping strangers.
BOLA is the API name for IDOR. Swap the object key across sessions you control — that single habit still funds a lot of reports.