IDOR Vulnerability: 6 Steps to Test and Fix for Developers
Hands on, test first IDOR guide for developers: follow a 6 step checklist of account swaps, method checks, and server side authorization fixes.
Hands on, test first IDOR guide for developers: follow a 6 step checklist of account swaps, method checks, and server side authorization fixes.

An IDOR is an object-level access control failure where the server trusts a client-supplied identifier instead of verifying whether the requesting user is actually authorized to touch that object. Change an ID in a URL, a form field, or an API payload and you might pull up someone else's invoice, medical record, or account settings. The primary fix is not a smarter ID scheme. It's enforcing server-side authorization checks on every single request that touches an object.
TL;DR:
- Server-side authorization checks must be enforced on every request, not just the initial login, to prevent IDOR exploitation.
- Testing involves mapping all object references, creating separate user accounts, and manually swapping IDs across all HTTP methods to confirm leaks.
- Automated scanners often miss IDOR flaws, so human testing with account swapping and method switching is essential for reliable detection.
- Using non-sequential or opaque identifiers adds a layer of defense but does not replace the need for proper authorization verification.
- Fixes require a design-level approach, embedding consistent authorization logic and normalizing input to prevent procedural mistakes and leaks.
The classic case is a URL path parameter. A logged-in user visits /invoices/1042 and, out of curiosity, tries /invoices/1041. If the app returns someone else's invoice without checking ownership, that's insecure direct object reference in its purest form.
But IDOR shows up well beyond the address bar. Common patterns include:
account_id or user_id field hidden in a form submission, editable with browser dev tools or a proxy like Burp Suite./files/receipt_2024.pdf that skip a permission check entirely.orderId argument and returns full order details, or a batch endpoint that leaks other users' records in an array response.Read-only IDOR is a privacy problem. Write-based IDOR is an integrity problem, and it tends to get discovered a lot faster because someone notices their data changed.
Exploiting object-level authorization failures rarely requires exotic tooling. It requires patience and a habit of asking "what happens if I change this number?"
/orders/500 to /orders/501) and watches for a successful response instead of a 403.GET requests to another user's object but forget to apply the same check to PUT, PATCH, or DELETE.Scanners regularly miss this class of bug because they can't infer business logic. A tool has no way of knowing that /api/orders/8842 should belong exclusively to the customer who placed order 8842. Automated DAST tools can catch some IDOR cases when fed API documentation, but the reliable finds still come from a human trying the swap by hand.
Pro Tip: Keep a second browser profile logged in as your "victim" test account at all times during a review. Nothing exposes IDOR faster than pasting a request from one session into a proxy tab authenticated as someone else.
Testing for insecure direct object reference is mechanical once you have the right setup. The steps below follow the same logic as the OWASP Web Security Testing Guide approach to authorization testing.
200 OK returning another user's data. That evidence is what turns a suspicion into a verified finding.The single most important control is server-side, object-level authorization enforced on every request, not just the ones a developer remembered to protect. Everything else on this list is secondary to that.
SELECT * FROM orders WHERE id = ?, use SELECT * FROM orders WHERE id = ? AND user_id = ?, and centralize that pattern in one data-access layer instead of repeating it in every controller.200 responses on requests involving swapped identifiers during test cycles.Pro Tip: Centralize authorization logic in one reusable function or middleware layer. Every time a developer copy-pastes an ownership check into a new endpoint, there's a real chance one copy gets the condition wrong, and that's exactly how IDOR slips into production.
That same advisory points to real-world cases like CVE-2022-0732, where IDOR-class flaws exposed records at scale, which is the whole reason authorization checks belong in the design phase, not the bug-fix backlog.
IDOR is classified under Broken Access Control in the OWASP Top 10, which is exactly why Earthshaker Security treats it as a manual-verification priority rather than a checkbox for automated scanners. Every engagement pairs automated coverage with a human tester who actually attempts the account-swap and method-switching techniques described above, because that's where object-level authorization failures actually surface.
Findings are documented at Earthshaker Security with enough technical detail for an engineer to reproduce them and enough plain language for a non-technical stakeholder to understand the risk.

Most teams treat IDOR as a bug to squash on discovery. That's backwards. Object-level authorization belongs in the architecture, not the bug tracker, which means it needs a decision at design time about who owns what and how every layer of the stack checks it.
The advisories agencies keep publishing on this exact flaw aren't a coincidence. Secure-by-default development, with authorization checks written into code review checklists and CI gates, is the only approach that holds up as an application grows past the handful of endpoints a lone developer can keep straight in their head. Treat IDOR testing as continuous, not a one-time audit, and it stops being a recurring finding.
— caleb
Finding IDOR reliably takes a tester who actually tries the account swap, not just a scanner report full of maybes. Earthshaker Security combines automated coverage with hand-verified testing across web application penetration tests, API and endpoint testing, and configuration audits, so confirmed access-control findings arrive with a clear fix, not raw noise.

Every engagement includes a written report built for both your engineering team and your non-technical stakeholders, plus a re-test to confirm the fix actually closes the gap. You can see what that looks like in a sample report before committing to anything. Engagements start at a base price for a one-off test, with a monthly retainer available for ongoing coverage; larger scopes incur a custom daily rate. Current pricing details are on the pricing page. Check current pricing and engagement tiers and book a test before an attacker finds your IDOR first.
Yes. IDOR falls under Broken Access Control, which OWASP identifies as a top category, and it maps to CWE-639. It covers horizontal issues (accessing a peer's data) and vertical issues (accessing data meant for a higher privilege level).
Enforce an object-level authorization check on the server for every request that reads, writes, or deletes a resource, never trusting the client-supplied ID alone. Pair that with non-sequential identifiers as defense-in-depth, centralized authorization logic, and recurring manual testing rather than a one-time fix.
A user logged in as Account A views their profile at one URL with an ID, then simply changes the numeric ID in the URL. If the server returns another user's data without checking ownership, that's a working IDOR exploit, and it took nothing more than editing a number in a browser.
The same flaw as a web IDOR, just delivered through JSON instead of HTML. An API endpoint like GET /orders/{id} or a GraphQL query accepting an orderId argument is vulnerable if it returns another user's order data without verifying ownership, and it often carries higher risk because APIs return structured data that's trivial to script into a mass-enumeration exploit.
Create two accounts with separate data, capture a request as one account, and replay it with the other account's object ID substituted in. Try this across every HTTP method (GET, POST, PUT, DELETE) on the same endpoint, since a resource often protects reads while leaving writes exposed, and a service like Earthshaker Security's penetration testing runs this exact workflow by hand during an engagement.