Articles

What Is IDOR? Insecure Direct Object References Explained

IDOR is an access control flaw where an app trusts a user-supplied ID to fetch a record without checking the requester actually owns it.

Chisato Chisato · · 4 min read
An unlocked padlock resting on a keyboard

IDOR, short for Insecure Direct Object Reference, is an access control vulnerability where an application uses a user-supplied identifier — an ID in a URL, form field, or API request — to fetch a record, without verifying that the requester is actually authorized to access that specific record. The classic example: GET /api/invoices/1042 returns your invoice, but changing the URL to GET /api/invoices/1043 returns someone else’s, because the server checked that an invoice with that ID exists but never checked that it belongs to the requester.

The vulnerability, minimally

IDOR isn’t a bug in encryption, input sanitization, or a memorable exploit chain — it’s a missing if. A typical vulnerable handler looks something like:

GET /api/orders/:orderId
  order = db.orders.find(orderId)
  return order

The endpoint correctly authenticates the request (the caller is logged in) but never checks authorization — whether the logged-in user is allowed to see this particular order. Authentication answers “who are you”; authorization answers “are you allowed to do this.” IDOR is what happens when a system does the first check and skips the second. The fix is almost always as small as the bug:

GET /api/orders/:orderId
  order = db.orders.find(orderId)
  if order.userId != currentUser.id: return 403
  return order

Why it’s so common

IDOR sits on the OWASP Top 10 as part of the broken access control category, consistently one of the most reported classes of vulnerability in web applications. It’s common for a few structural reasons:

  • It’s invisible in normal testing. The endpoint works perfectly when you test it with your own account and your own IDs. The bug only appears when someone tries an ID that isn’t theirs — which automated functional tests rarely do.
  • Sequential and guessable IDs make it trivial to exploit. Auto-incrementing integer primary keys mean an attacker can enumerate ?id=1, ?id=2, ?id=3 and harvest records without any special tooling.
  • It scales across every resource type independently. A codebase can correctly enforce ownership checks on orders but miss them on shipping addresses, support tickets, or exported reports — each endpoint needs its own check, and one miss is enough.
  • It often survives code review. The code reads as correct — it fetches a record and returns it — unless the reviewer is specifically looking for the missing ownership check.
IDORCSRFSSRF
What failsObject-level authorizationOrigin verification of a requestServer-side URL trust
Attacker needsA valid ID to substituteA victim to visit a malicious pageAn input field that accepts a URL
Typical fixOwnership check per resourceAnti-forgery tokens, SameSite cookiesURL allowlisting, blocking internal ranges
Where it livesApplication authorization logicSession/cookie handlingServer-side request logic

IDOR is also distinct from broken authentication — a user exploiting IDOR is fully, legitimately logged in as themselves. See CSRF and SSRF for how those adjacent flaws differ in mechanism.

Where IDOR shows up beyond URLs

The pattern isn’t limited to REST path parameters. Any place a client supplies an identifier that the server trusts without an ownership check is a candidate:

  • Query parameters and request bodies ({"userId": 4821} in a PATCH request)
  • File paths and download endpoints (/files/download?name=report-4821.pdf)
  • GraphQL resolvers that fetch by node ID without a permission check in the resolver itself
  • Bulk or batch endpoints that accept an array of IDs — often the ownership check gets applied to the first ID and forgotten for the rest
  • API responses that leak internal IDs in one place, which then work as valid input elsewhere in the same API

Preventing IDOR systematically

Point fixes on individual endpoints don’t scale — the goal is to make the missing check the exception, not something engineers have to remember on every route.

  • Enforce authorization centrally. Middleware or a policy layer that runs an ownership or permission check before a handler touches the database, rather than trusting each handler to remember it. RBAC or ABAC models formalize what “authorized” means so the check is consistent across resource types.
  • Prefer indirect references. Instead of exposing raw database primary keys, use per-user or per-session opaque tokens that map to the real record server-side. This doesn’t replace authorization checks, but it removes the trivial enumeration attack.
  • Use non-sequential identifiers. UUIDs don’t fix IDOR — the authorization check still has to exist — but they remove the “just increment the number” shortcut that makes exploitation nearly automatic.
  • Test for it deliberately. Functional tests confirm a user can access their own data; authorization tests confirm they can’t access someone else’s. The second kind needs to be written on purpose — nothing about normal testing produces it. This is exactly the class of flaw dynamic application security testing is well suited to catch, since it needs a live request with a substituted ID rather than static code inspection alone.

The takeaway

IDOR is what happens when an application checks that you’re logged in but never checks that the specific record you’re asking for is yours. It requires no special exploit tooling — just substituting an ID — which is exactly why it’s stayed near the top of real-world vulnerability reports for years. The fix is a per-resource ownership check, ideally enforced centrally rather than left to each handler to remember, plus opaque or non-sequential identifiers to raise the cost of blind enumeration.

Chisato Chisato · · 5 min read

What Is Session Fixation?

Session fixation tricks a victim into using an attacker-known session ID, so logging in hands the attacker an authenticated session too.

#Security #Authentication #Web Development
Chisato Chisato · · 4 min read

The OAuth PKCE Flow Explained

PKCE hardens the OAuth authorization code flow against interception, and is now recommended for every client type, not just mobile and single-page apps.

#Security #Authentication #Web Development
Chisato Chisato · · 4 min read

Cookie Attributes Explained: HttpOnly, Secure, SameSite

HttpOnly, Secure, and SameSite are cookie attributes that block script access, force HTTPS, and limit cross-site sending. Here's what each one actually stops.

#Security #Web Development #Authentication