Skip to main content
An IDOR happens when an application uses a user-supplied identifier (an ID in a URL, a filename, a reference in a JSON body) to fetch an object, but only checks that you’re logged in, not that you’re allowed to access that specific object. Change the ID, see someone else’s data. It’s one of the simplest vulnerability classes to understand and one of the easiest to miss in a quick scan, since there’s no payload to detect, just a number that happens to belong to someone else.

Horizontal IDOR

Accessing another user’s data at the same privilege level, someone else’s invoice, profile, or order instead of your own.

Vertical IDOR

Accessing data or functionality meant for a higher privilege level, an admin-only object or action, without actually having that role.
IDOR testing is inherently a two account strategy. Register (or get) two accounts at the same privilege level, perform an action as account A, note every ID it touches, then try to access those same IDs as account B. Without a second account, you’re just guessing at what “someone else’s object” would look like.

Finding the Reference Point

Start by identifying every place an object reference shows up, not just the obvious URL parameter.
  • POST body fields: {"user_id": 1042, "action": "view"}
  • Custom headers: X-User-ID: 1042
  • Cookies: a session or preference cookie carrying a raw user/account ID
  • File paths: /invoices/INV-1042.pdf, /uploads/1042/profile.jpg
  • Hidden form fields: an <input type="hidden"> carrying an account or object ID
  • API responses and page source: a GUID or internal ID leaked in a JS variable, an API response’s metadata, or an email notification link

Testing Numeric IDs

Simple increment/decrement is the first thing to try, sequential integer IDs are still extremely common.
Fuzzing a range at once is faster once you’ve confirmed the parameter is exploitable at all, filtering on response size separates real objects from “not found” pages.
Don’t stop at read access. The same ID swap against a DELETE, PUT, or state-changing POST request (cancel an order, change an email, delete a document) is often more impactful than just viewing someone else’s data, and is just as easy to test with the same tooling.

Bypassing Non-Sequential IDs

A random-looking GUID isn’t guessable by incrementing, but it’s rarely actually unguessable, it’s just not visible in the current request. Check everywhere else the same object’s GUID might already be exposed: another API response, a notification email, page source, or a different endpoint that happens to list GUIDs alongside more guessable data (like a username).
A common flawed implementation: the backend checks “is this user an authenticated member” rather than “does this user own this specific object.” If horizontal IDOR (same role, different user) fails, try vertical: does a regular user’s token work against an endpoint clearly meant for a different role, just because the role check itself is missing rather than the object-ownership check?
An authorization check implemented for the JSON endpoint sometimes isn’t mirrored on an XML or form-encoded version of the same endpoint. Try sending the identical request with Content-Type: application/xml or application/x-www-form-urlencoded instead of application/json, and see if the authorization logic still applies.
Sending the same parameter twice, or wrapping it in an array, sometimes causes the backend’s authorization check and its actual data fetching logic to read different values of the “same” parameter.
If an update endpoint accepts a JSON body, try adding fields beyond what the form actually exposes, a role, isAdmin, or balance field the client never sends but the backend might still bind.

Blind IDOR

Not every IDOR gives you a response to read, deleting, disabling, or modifying another user’s object often returns a generic success message either way. Confirm impact out-of-band instead of relying on the response body.
1

Perform the action against a known victim ID

E.g. attempt to cancel or modify an object belonging to your second test account.
2

Check from the victim's side

Log back in as the victim account (or have a teammate check) to confirm whether the state actually changed, a generic “Success” response from account A proves nothing on its own.

Tooling

Autorize (extension) automates exactly the two-account comparison this vulnerability class needs: it replays every request you make as a low-privileged user’s session and flags any that still return data, catching IDOR and broken access control across an entire app as you browse normally.Intruder works for straightforward numeric ID brute forcing, same idea as the FFUF command above, just inside Burp if you’re already working there.

Quick Reference Tools

Hackviser: IDOR

Reference used for this page.

HackTricks: IDOR

Deeper dive into additional bypass tricks.

Autorize

Burp extension automating authorization/IDOR testing across an entire browsing session.