IDOR and BOLA Test Plan: How Multi-Session Authorization Testing Works

A manual test plan for IDOR/BOLA flaws: comparing two user contexts, mass assignment, and predictable ID checks. With notes on Eresus Guard's multi-session approach.

4 min read
ibrahimsql
659 words

Disclosure: I am the founder of Eresus Security. This post explains IDOR/BOLA testing methodology, including how Eresus Guard approaches it. Product details are on the Eresus page.

IDOR (Insecure Direct Object Reference) and BOLA (Broken Object Level Authorization) are among the most common findings in API security testing — and the ones single-session scanners miss most often. It ranks number one in the OWASP API Security Top 10, for a simple reason: authorization is checked at the request level, not the object level.

Why one session is not enough

A classic DAST scanner logs in as one user, crawls endpoints, and looks at status codes. But catching IDOR requires comparing the same request across two users' contexts:

User A (account 1001):  GET /api/orders/9001  -> 200, A's order
User B (account 1002):  GET /api/orders/9001  -> 200, A's order   <-- vulnerable
User B (account 1002):  GET /api/orders/9001  -> 403               <-- expected

You cannot make that comparison with one session. You need both sessions at once.

Manual test plan

1. Target inventory

Map the API surface first:

Bash
# If an OpenAPI/Swagger document exists, download it
curl -s https://target.example.com/api/openapi.json | jq '.paths | keys'
 
# Otherwise build a site map in Burp Suite, collect API calls from JS bundles
grep -rhoE '/api/[a-zA-Z0-9/_{}-]+' app.js | sort -u

List every endpoint that takes an ID: /api/users/{id}, /api/orders/{id}, /api/files/{id}, /api/invoices/{id}.

2. Create two test users

User A and user B — same role, different data. Grab both session tokens:

Bash
# Log in as user A
curl -s -X POST https://target.example.com/api/auth/login \
  -H 'content-type: application/json' \
  -d '{"username":"test-a","password":"Test123!"}' -c cookies-a.txt
 
# Log in as user B
curl -s -X POST https://target.example.com/api/auth/login \
  -H 'content-type: application/json' \
  -d '{"username":"test-b","password":"Test123!"}' -c cookies-b.txt

3. Comparison matrix

Run this matrix for every ID-bearing endpoint:

RequestExpectedVulnerability signal
A → own object200, own data—
B → A's object403/404200 + A's data
B → nonexistent ID404200 or a different error
Unauthenticated → any ID401200
# Request A's order with B's session
curl -s https://target.example.com/api/orders/9001 -b cookies-b.txt | jq .
# 200 + A's data: IDOR confirmed

4. ID predictability

Sequential integer IDs (/api/users/1001, /api/users/1002) are enumerable. UUIDs resist enumeration but are still exposed without authorization checks — an attacker learns IDs from logs, responses, or sibling endpoints.

Bash
# Sequential ID sweep (within authorized test scope)
for id in $(seq 9001 9020); do
  echo "=== $id ==="
  curl -s -o /dev/null -w '%{http_code}\n' https://target.example.com/api/orders/$id -b cookies-b.txt
done

5. Mass assignment

IDOR's cousin: inject extra fields into the request body and see if the server accepts them:

Bash
curl -s -X PUT https://target.example.com/api/users/me \
  -H 'content-type: application/json' -b cookies-b.txt \
  -d '{"name":"Test","role":"admin","accountId":1001}' | jq .
# role: admin reflected back: mass assignment flaw

6. Evidence and reporting

For each finding:

  1. Full request and response, with both sessions compared.
  2. The affected object and data sensitivity.
  3. Fix: server-side ownership check — if (order.userId !== req.user.id) return 403.

The role and limits of automation

This matrix is repeatable, so it can be automated — but that means managing two sessions at once, comparing responses semantically, and filtering false positives. That is why we designed Eresus Guard for multi-session authenticated testing: it compares what different users can reach to catch IDOR and authorization bypass.

But the honest limit: automation does not replace human review. Business-logic authorization rules (e.g. "a manager sees their own team's data") can only be validated by a tester who knows the scope. The scanner surfaces candidates; a human decides.

---
Share this post:

What do you think?

React to show your appreciation

Related Posts