root@thehacksparrow:~/writeups$ SYSTEM ONLINE
root@sparrow:~/writeups$ cat vulnerability-pattern-idor-bac.md
// bug-bounty

IDOR & Broken Access Control

23 Jul 2026 · 3 min read

What it is

IDOR: you access another user's data just by changing an identifier —

GET /api/invoices/1001
becomes
GET /api/invoices/1002
and it's not your invoice. Broken Access Control: same idea one level up — you can call an action your role shouldn't be allowed to perform at all, like a normal user successfully hitting
POST /api/admin/delete-user
.

Why it matters

It's the single most common high-impact class in bug bounty, and it needs no exploit — just a browser, two accounts, and the willingness to change a number. That combination of low effort and high impact is exactly why programs take it seriously.

Where to look

  • Any endpoint that addresses a resource by ID: invoices, orders, files, tickets, projects, messages, organizations
  • Admin panels, team/workspace management, billing, invitations, role settings

How I test it

  1. Create two accounts — A and B. Non-negotiable.
  2. With A, create or touch a resource; capture the request in Burp.
  3. Note the identifier — numeric ID, UUID, slug.
  4. Switch to B's session, replay the exact same request but with A's identifier.
  5. If B can read, edit or delete A's resource: IDOR. If a normal account successfully performs an admin-only action: Broken Access Control.
  6. Repeat across every resource type and every verb (GET/PUT/PATCH/DELETE), not just the first one that worked.

Hunting checklist

  • Second test account created
  • Resource created and request captured
  • Identifier replayed under a different account
  • Tested read AND write/delete, not just read
  • Tested at least one admin-only action with a normal account
  • Checked whether the response is 200 with real data, not just 200 with an empty body

Evidence to collect

  • Request as account A
  • Same request replayed as account B
  • Response proving B could read/modify/delete A's resource
  • For BAC: the privileged request and the unprivileged replay side by side

Recommended fix

  • Check ownership/role server-side on every request, not just on the ones the UI exposes
  • Use non-guessable identifiers where feasible, but never rely on that alone
  • Return 403/404 consistently instead of leaking existence via different error codes