scanrub
Insecure Direct Object Reference (IDOR)high prioritypartial coverage

Insecure Direct Object Reference

5 min read 257 reports analyzed ScanRub Research
Share
Live Playground · Powered by this research
ID Predictability Checker

Paste example object IDs. We'll tell you if they're predictable (sequential/short) - a common IDOR risk.

Total IDs analyzed4
Sequential (predictable)YES
Short (< 8 chars)YES - enumerable
FormatShort numeric/string
Predictable IDs. Combined with weak authz, this is textbook IDOR.
Payloads from this research (10 total)
?id=1, ?id=2, ?id=99999
/api/users/1, /api/users/2
/api/reports/<other-uuid>
POST /transfer with from=<their account>
These payloads were synthesized from real HackerOne disclosures. Click any payload to copy it, then paste it into the tester above to see how our detection classifies it.

Summary

Classic IDOR pattern: server uses a user-supplied identifier without checking that the requesting user is authorized for that resource. Variants:

  • numeric/sequential IDs (?uid=N, /reports/N) where authorization isn't enforced
  • UUID/GUID feels like opaque but is exposed elsewhere (in URLs, in another API response, in mobile-app metadata)
  • cross-tenant - swap shop_id, org_id, business_id to access other tenant's resource
  • GraphQL - pass arbitrary node id to query/mutation
  • cookie-stored identity - UID2 cookie value defines the user, modifying it accesses others
  • attachment IDs that are sequential and download without auth (TAMS getAttachmentBytes)
  • chained IDORs where one IDOR leaks IDs that feed the next
  • write IDOR - modify someone else's resource (add image to other user's issue, transfer credit, modify policy)
  • IDOR on intermediate routes (download links valid for everyone after admin clicks)
  • PII/PHI exposure via medical-record IDORs (DoD pattern). Detection requires authenticated multi-account testing.
◈ flow diagram
Authenticate…API RequestObject ID or…Missing Auth…Other User D…
◈ chart
Critical
26
High
90
Medium
103
Low
39

Top Affected Components / Targets

  • Profile / account-details endpoints
  • Document / file / attachment download endpoints
  • Order / invoice / receipt views
  • Multi-tenant SaaS APIs (tenant_id, shop_id, org_id swap)
  • GraphQL nodes by global ID
  • Admin moderation queues with sequential IDs
  • Mobile API mirrors of authenticated web flows
  • PII/PHI endpoints in healthcare and government
  • Analytics / report download CSVs

Common Attack Vectors

  • Increment / decrement / replace numeric ID in URL or body
  • Replace UUID with one harvested from another response (search result, mention, share link)
  • Swap session and target IDs to test horizontal privilege escalation
  • Use unauthenticated endpoint variants (mobile API, graphql, /v1)
  • Replay request with Authorization header removed
  • Modify identity claim in JWT and access another user's resource
  • Use Burp Autorize / similar to test every authenticated request as anonymous and as a different user
  • Chain IDORs: leak IDs from one endpoint, feed into another
  • Modify cookie with raw user_id (UID2-style)

Common Payloads

  • ?id=1, ?id=2, ?id=99999
  • /api/users/1, /api/users/2
  • /api/reports/<other-uuid>
  • POST /transfer with from=<their account>
  • PATCH /policy/<other org>/voucher
  • Cookie: UID2=4820036
  • GraphQL: { user(id: "<other>") { email phone } }
  • /api/v1/admin/users (no auth)
  • /admin/reports/<sequential-id>
  • /getAttachmentBytes/<id>

Detection Strategy

IDOR detection needs at least two test accounts (Account A and Account B).

Stage 1: Autorize-style replay

For every authenticated request observed during an authenticated scan, replay with (a) Account B's session, and (b) no session. If the response body length / status / content is identical to Account A's response, flag IDOR (read). For state-changing requests where the response body is identical when Account B issues a request that should target Account A's resource, flag IDOR (write).

Stage 2: ID enumeration probe

For endpoints that look like /resource/{id}, probe id-1, id+1, id+1000 with the current session and observe whether the response varies in a way that reveals other users' data.

Stage 3: GraphQL node probe

For GraphQL endpoints, attempt cross-account node lookups using known node IDs harvested from canonical traffic.

Stage 4: cookie/header identity tamper

Identify cookies/headers that look like raw user IDs (uid=, user_id=, UID2=) and tamper to test response variation.

Stage 5: UUID harvest + replay

From the Account A response set, harvest all UUIDs and replay them while authenticated as Account B; tag those that succeed.

Tip: Testing tools that run these checks in parallel across every discovered endpoint can cut the time required substantially compared to fully manual testing, as long as they confirm findings with more than one signal to keep the false-positive rate down.

False-Positive Notes

  • IDOR findings without multi-account validation are weak - the existing single-session id-mutation module produces too many false positives because the response varies for legitimate reasons (the resource doesn't exist for the user).
  • Always require Account-B reproduction.
  • UUIDs are not opaque if they're exposed elsewhere - flag the source (where UUID was leaked) AND the IDOR target.

How to Test

Manual Testing Methodology

Here is a systematic approach to identifying Insecure Direct Object Reference vulnerabilities in a target application.

Step 1: Reconnaissance and Surface Mapping

Before testing, map all input vectors that could be affected. Identify parameters, headers, cookies, and request bodies that interact with the vulnerable component. A proxy such as Burp Suite or OWASP ZAP, paired with normal browsing of the target, is usually enough to build this list.

Step 2: Baseline Request

Send a legitimate request and record the normal response: status code, content length, response time, and any identifying tokens. This baseline matters because it's what you'll compare later responses against once payloads are involved.

Step 3: Payload Injection

Inject test payloads into each identified input vector one at a time. Start with benign detection payloads before escalating to anything that could actually trigger the vulnerability. For Insecure Direct Object Reference specifically, authenticate as a low-privilege test account, then substitute identifiers belonging to another account (sequential IDs, UUIDs harvested from other responses) into every request, and separately try reaching privileged endpoints/actions directly by URL or method regardless of what the UI exposes to that role.

Step 4: Response Analysis

Compare the response against your baseline, looking specifically for a 200 response containing another user's data, or a privileged action completing successfully, when the authenticated user should have received a 401/403 — compare against the expected-denial baseline for that same request from the same account.

Step 5: Confirmation

Once a potential vulnerability is detected, confirm it with at least a few independent test cases to rule out coincidence. Document the exact request and response as proof. For Insecure Direct Object Reference, a confirmed finding typically means showing that attacker-controlled input changes the application's behavior in a way that matters for security, not just that a payload was reflected somewhere harmless.

Real-World Impact

Real-World Impact

Broken access control and IDOR let attackers access or modify resources belonging to other users simply by changing an identifier, or by reaching an endpoint that should have required a higher privilege level. It's one of the most commonly reported vulnerability classes precisely because the underlying mistake is conceptually simple, yet easy to overlook in authorization logic that only checks whether a user is logged in, not whether they're entitled to the specific resource or action being requested.

Real-world exploitation ranges from reading other users' private messages, files, or financial records, to modifying account settings, to reaching admin-only functionality by requesting it directly regardless of what the UI shows. In multi-tenant applications, it can mean cross-tenant data access entirely. The severity scales directly with how sensitive the exposed resource or action is.

This bug class shows up in virtually every kind of application, from social platforms to banking APIs to healthcare systems, which makes it one of the more consistently valuable checks to run regardless of what the target actually does — and one of the hardest for an automated scanner to catch reliably, since confirming it requires understanding what a specific user should and shouldn't be able to reach.

Prevention & Remediation

Prevention and Secure Coding

Preventing Insecure Direct Object Reference takes a defense-in-depth approach — no single control below is sufficient alone, but together they close off both the primary path and the most common bypasses.

Object-level authorization on every request. Verify the authenticated user actually owns or is entitled to the specific resource identified in the request — on every endpoint that accepts an identifier, not just the ones that seemed sensitive during development.

Centralize the authorization logic. Implement authorization checks in one shared layer or middleware instead of re-implementing them per endpoint; re-implementation is exactly where individual endpoints get missed.

Default-deny. Require an explicit permission grant for each action a role can take, rather than granting broad access and trying to enumerate exceptions.

Indirect references where feasible. Opaque, per-user tokens in place of sequential database IDs make horizontal enumeration harder, though this is a hardening measure, not a substitute for the authorization check itself.

Test authorization from the attacker's seat, not the developer's. Authenticate as a low-privilege user and attempt every action a higher-privilege or different-tenant user could take — the UI hiding a button is not an authorization control.

Source reports

A sample of the disclosed HackerOne reports this playbook was synthesized from.

Frequently Asked Questions

What is Insecure Direct Object Reference?
Classic IDOR pattern: server uses a user-supplied identifier without checking that the requesting user is authorized for that resource.
How common is Insecure Direct Object Reference in bug bounty reports?
Scanrub's research corpus for this playbook is built from 257 disclosed HackerOne reports in this category, synthesized for detection and prevention guidance rather than reproduced verbatim.
How do I test for Insecure Direct Object Reference?
Map every input vector, record a baseline response, then inject targeted test payloads one field at a time and compare the response for timing, length, error, or reflection differences from that baseline. The "How to Test" section above walks through the full methodology for this specific vulnerability class.
What is the single most effective fix for Insecure Direct Object Reference?
Verify object-level and function-level authorization on every request that accepts an identifier or reaches a privileged action — check entitlement, not just authentication.
Weekly security research

New vulnerability playbooks, tool updates, and bug bounty insights - delivered to your inbox. No spam.

Unsubscribe anytime. We respect your inbox.
Press ⌘K to search×