Back to glossary

Insecure direct object reference (IDOR)

2 min read

In web and API testing, an insecure direct object reference (IDOR) is a flaw where the application takes an identifier straight from the request and uses it to fetch or change a record without checking that the caller owns it. Changing one number in a URL returns somebody else’s data.

July 29, 2026
Compartir:

How it works

The application exposes a handle to a stored object: a numeric row id, a filename, a document reference, an account number. The client sends that handle back, and the server uses it to look the object up. The flaw is not that the handle is visible. The flaw is that the lookup is the only check performed, so the server answers the question “does this record exist” instead of the question “may this caller see this record”.

Exploitation is arithmetic. Increment the identifier, replay the request with your own valid session, and read the response. Sequential integers make it trivial to enumerate the whole table. Long random identifiers make guessing impractical but fix nothing, because the identifiers leak through exports, share links, search results and other endpoints. That is why obscurity is not a remedy: authorisation is. In an API report the same defect is normally written up as broken object level authorisation, which is the name the OWASP list uses.

What goes wrong

The pattern we find most often is an application that gets it right on the page the developers thought about and wrong everywhere else. Read is guarded and delete is not. The HTML view checks ownership and the JSON endpoint behind it does not. The main object is protected and the attachment, the audit log, the invoice PDF or the export job is not.

The second pattern is a check that runs in the wrong place. An application that filters the list view by tenant looks correct until you request an identifier that was never in your list, because the detail handler trusts that you could only have got the identifier from the list. On a test this is usually the fastest route to another customer’s data, and it needs no exploit, no tooling and no privilege escalation: two accounts and a proxy.

Where this shows up in an audit

We ask for two accounts precisely so we can prove this class. The reproduction in the report is account A issuing a request that belongs to account B, with the response showing B’s data, and the same request repeated after logout to separate a broken check from a missing one. We record which verbs were affected, because read-only exposure and write access are different findings. The count of records reachable decides severity. This is part of how we test object-level access in an API.

¿Quieres ver cómo trabajamos en Asperis Security?

Agenda 30 minutos con uno de nuestros especialistas. Revisamos tu stack y te decimos qué conviene probar primero.