IDOR (insecure direct object reference) is a broken access control vulnerability in which an application exposes the identifier of an internal resource (the id of an invoice, an order number, the UUID of a document) and trusts that value to serve the object without checking whether the requesting user is authorised to access it. The attacker does not break authentication or steal credentials: they sign in with their own legitimate account, change a parameter and reach other people's data. That is why IDOR is classified within Broken Access Control (A01), the number one category of the OWASP Top 10.
The essentials. IDOR appears when authorisation is delegated to a client controllable identifier instead of being verified on the server against the session identity. The defense is not to hide the identifier (UUIDs do not protect on their own), but to check object ownership on every request, apply deny by default and centralise access control at the object level. Tools such as Burp Suite with the Autorize extension detect it by comparing two sessions.
What IDOR and broken access control are
Broken access control groups every flaw in which a user can perform actions or reach data beyond their permitted scope. Within that category, IDOR is the most common and direct pattern: the application receives a reference to an object (usually in the URL, a form parameter, a JSON request body or a header) and returns that object without verifying that it belongs to the authenticated user.
The name describes it precisely. The reference is direct because it points to the real backend identifier of the resource (the database primary key, a file name, a position in an array). And it is insecure because the only control applied is authentication (knowing who you are), not authorisation (knowing whether you may access that specific object). The application assumes that if the browser sends id=1043, the user is entitled to see object 1043, when all they have done is type a different number.
The difference between authentication and authorisation is the core of the problem. Authentication resolves identity: the session is valid, the token has not expired, the cookie is correct. Authorisation resolves permission: this specific user may read, modify or delete this specific resource. An IDOR occurs when the first control exists and the second is missing. It is a design flaw, not a misconfiguration, which is why automated scanners handle it poorly: the request is syntactically perfect and the response is a legitimate 200.
Technical example of an IDOR exploit
The canonical case is an endpoint that serves a resource from its identifier. An authenticated user requests their own invoice:
GET /api/invoices/1043 HTTP/1.1
Host: victim-app.tld
Cookie: session=<attacker's valid session>
If the server retrieves invoice 1043 and returns it without checking that it belongs to the requester's account, enumerating adjacent identifiers is enough to read other people's invoices:
GET /api/invoices/1044 HTTP/1.1
GET /api/invoices/1042 HTTP/1.1
The same pattern repeats in write parameters. An endpoint that updates a profile by trusting the user_id sent by the client lets an attacker modify someone else's account:
POST /api/profile/update HTTP/1.1
Content-Type: application/json
{ "user_id": 5012, "email": "attacker@malicious.tld" }
Identifiers are not always sequential. When the application uses UUIDs, blind enumeration stops working, but the IDOR is still alive if those UUIDs leak in other endpoints (listings, search responses, notifications, logs, shared URLs or the Referer). The lesson is clear: a hard to guess identifier reduces mass enumeration, but does not replace the authorisation check. Relying only on the value being unguessable is security through obscurity.
These patterns are reproducible in controlled labs such as PortSwigger Web Security Academy, OWASP Juice Shop or in house environments, and are part of any responsible web audit.
Horizontal and vertical IDOR: types of escalation
Improper accesses via IDOR are classified by where the attacker moves within the permission model.
| Type | What the attacker achieves | Example |
|---|---|---|
| Horizontal escalation | Reaching another user's objects at the same privilege level | Reading another customer's invoice, message or order |
| Vertical escalation | Reaching functions or objects reserved for a higher role | Invoking an admin endpoint by changing a role_id or account_id |
| BOLA (API) | Object level IDOR in an API | API1:2023 of the OWASP API Security Top 10 |
| BFLA (API) | Access to unauthorised functions in an API | API5:2023, invoking another role's operations |
In the API world, IDOR is called BOLA (broken object level authorization) and is in fact the number one risk of the OWASP API Security Top 10. The variant affecting whole functions rather than individual objects is BFLA (broken function level authorization). The distinction matters because remediation differs: BOLA requires checking ownership object by object, while BFLA requires verifying the role before exposing the function.
How to test IDOR in an audit
IDOR is an assisted manual review finding. The typical flow requires at least two test accounts with different data:
- Authenticate with account A and capture every request that references an object (identifiers in the URL, parameters, JSON body and headers) with Burp Suite.
- Replay account A's request using account B's session. If the response returns A's object, there is horizontal IDOR.
- Automate the comparison with Burp's Autorize extension, which replays each request with the cookies of a lower privilege session and flags in green, orange or red whether access control is enforced, doubtful or missing. Auth Analyzer offers an equivalent function.
- Enumerate adjacent identifiers with Intruder when they are sequential, and hunt for UUID leaks in other endpoints when they are not.
- Try method variants (swap GET for POST, PUT or DELETE), duplicate parameters, array wrappers (
id[]=1044) and alternative routes that point to the same object.
The critical point is that automated scanners (DAST) rarely detect IDOR on their own, because they do not understand which object should belong to which user. Confirmation always requires the context of at least two identities and the auditor's judgement. These techniques are a standard part of a web application and REST and GraphQL API audit.
Defenses and remediation
Server side object level authorisation
The only defense that solves the problem at its root is to check, on every request and on the server, that the requested object belongs to the session identity. In practice this means the database query includes ownership as a condition: instead of SELECT * FROM invoices WHERE id = :id, use SELECT * FROM invoices WHERE id = :id AND owner_id = :session_user. Never trust a user_id, account_id or role sent by the client to decide scope.
Deny by default and ownership validation
Access control must start from denial by default: if there is no explicit rule granting access, it is denied. Every endpoint that receives an object reference must validate ownership or membership before reading, writing or deleting. Failing closed (403) is preferable to failing open.
Session scoped indirect references
An additional defensive pattern is to replace the real identifier with a session scoped indirect reference: the application keeps a map that translates, for example, 1, 2, 3 (the user's local indices) to the real primary keys, so that an index in one user's session means nothing in another's. It does not replace the authorisation check, but it reduces the enumeration surface and avoids exposing the internal structure.
Centralised access control (RBAC and ABAC)
Scattering permission checks across every controller guarantees that sooner or later one is forgotten. The mature practice is to centralise the decision in a single layer or policy (role based RBAC, attribute based ABAC, or engines like OPA) that all endpoints consult. Frameworks such as Spring Security, Django, Laravel or ASP.NET provide declarative object level authorisation that is worth using instead of reinventing the control in each route.
Logging and detection
Logging denied accesses and monitoring spikes of requests to adjacent identifiers helps detect enumeration in progress. A legitimate user does not sequentially walk through thousands of other people's invoices in a few seconds.
IDOR in REST and GraphQL APIs
APIs concentrate most real IDORs today because they expose object identifiers explicitly and abundantly. In REST, every nested resource (/users/{id}/orders/{orderId}) is a potential failure point if authorisation is not checked at each level. In GraphQL, the risk moves to query and mutation arguments: a node(id: ...) or a field that accepts an identifier can serve other people's objects if the resolver does not validate ownership. GraphQL introspection, moreover, makes it easy for the attacker to discover which types and fields exist. The in depth treatment is in GraphQL pentesting.
It is worth remembering that IDOR is a close cousin of other misplaced trust flaws. Just as CSRF exploits the server's trust in the browser, SSRF the server's trust in its own outbound requests and CORS the relaxation of the same origin policy, IDOR exploits the server's trust in an identifier that the client controls.
Real cases and public CVEs
IDOR is not a theoretical problem. In 2019, First American Financial Corporation exposed close to 885 million sensitive financial documents because modifying a record number in a URL was enough to reach other people's documents, a textbook IDOR. The USPS Informed Delivery service suffered a BOLA that allowed querying data for tens of millions of accounts. Later cases of mass social media scraping relied on sequential identifiers with no access control.
In the NVD, searches for IDOR, insecure direct object reference or broken access control return a steady stream of entries affecting CMS platforms, plugins, admin panels, devices with web interfaces and SaaS software. The common pattern repeats: manipulable identifier, authentication present, object level authorisation absent.
Fit with the OWASP Top 10
Broken Access Control is category A01 and has topped the OWASP Top 10 since 2021, ahead of injection and cryptographic failures. IDOR is its most frequent manifestation and appears explicitly in the category description. In the API domain, BOLA holds first place in the OWASP API Security Top 10. The takeaway is direct: if a single flaw type had to be prioritised in a modern web or API audit, object level access control would be the candidate. The category detail is in the OWASP Top 10 2025 guide and an overview in the five most common web vulnerabilities.
Frequently asked questions
How does IDOR differ from an authentication flaw?
Authentication works. The attacker signs in with a legitimate account of their own and the session is valid. What fails is authorisation: the application does not check whether the requested object belongs to that user. An authentication flaw lets in someone who should not be there; an IDOR lets someone already inside see data that is not theirs.
Does using UUIDs instead of numeric IDs eliminate IDOR?
No. A UUID makes mass enumeration harder, but does not prevent access if the value leaks in a listing, a shared URL, a notification or a log. Relying solely on the identifier being unguessable is security through obscurity. The correct defense is to check object ownership on the server.
What is the difference between horizontal and vertical IDOR?
In horizontal escalation the attacker reaches objects belonging to another user at the same privilege level (another customer's invoice). In vertical escalation they reach functions or objects reserved for a higher role (an admin operation). Both are broken access control, but the vertical variant usually carries greater impact.
What is BOLA and how does it relate to IDOR?
BOLA (broken object level authorization) is the name the OWASP API Security Top 10 gives to IDOR in the API context, and it holds the API1 position. It is exactly the same flaw: an exposed object identifier without an authorisation check. BFLA (API5) is its function level equivalent.
Do automated scanners detect IDOR?
Rarely in a reliable way. A scanner does not know which object should belong to which user, and the vulnerable request is syntactically correct with a 200 response. Detection requires at least two test accounts and manual comparison, usually with Burp and the Autorize extension or Auth Analyzer.
Related resources
- Web application penetration testing
- API penetration testing for REST and GraphQL
- What is CSRF: cross-site request forgery
- What is SSRF: server-side request forgery
- OWASP Top 10 2025 for businesses
- The 5 most common web vulnerabilities in 2025
Auditing IDOR and access control with Secra
Secra performs web application and API audits aligned with the OWASP Top 10, the OWASP API Security Top 10 and the OWASP Web Security Testing Guide. We test object and function level access control with multiple identities, identifier enumeration, horizontal and vertical escalation, and review the framework authorisation logic to confirm that ownership is verified on the server and not on the client.
We deliver prioritised findings, reproducible proofs of concept with two accounts and concrete hardening recommendations: queries with an ownership condition, deny by default, centralised access control and regression cases that integrate into CI to prevent reintroducing IDOR when adding endpoints.
If you need a professional review of broken access control, IDOR and the rest of the OWASP catalogue, write to us through our web and mobile audit service or via /en/contact/ and we will plan an audit adapted to the scope of your platform.
About the author
Secra Solutions team
Ethical hackers with OSCP, OSEP, OSWE, CRTO, CRTL and CARTE certifications, 7+ years of experience in offensive cybersecurity, and authors of CVE-2025-40652 and CVE-2023-3512.

