Skip to content

Insecure Direct Object Reference (IDOR)

Prerequisites

  • INSECURE-threat-intel-app running; signed in as analyst / projectx at http://localhost:8081.
  • Burp Suite (setup guide).

Likeliness meter

Likely — Very common in REST APIs (/api/orders/1042), file downloads, and admin panels.

Overview

An Insecure Direct Object Reference (IDOR) is a broken access control bug. The application exposes a direct reference to an object — a numeric ID, UUID, filename, or account slug in the URL or API body — but never checks whether the authenticated user is allowed to access that object.

The UI may only link to “your” document, but if the server loads document?id=1011 based solely on id and ignores who is logged in, any user can swap the ID and read another user’s data. IDOR is not about guessing passwords; it is about missing authorization on the server after authentication succeeds.

On Documents (/documents), your Recent list shows the five notes you own (references 1001–1005), and a New note panel lets you create more — each new note gets its own reference and appears in your Recent list. Reference 1011 belongs to bob, is marked Sensitive, and is not listed anywhere in the UI — yet you can read it just by changing ?id= without being Bob.

Learning objectives

  1. Identify object references in URLs, bodies, and headers.
  2. Test horizontal access (peer user’s objects) with Burp Repeater.
  3. Distinguish “hidden in UI” from “enforced on server.”
  4. Document the flaw in your lab report.

Attacker methodology

Step 1 — Authenticate and map object-heavy routes

Browse while logged in as analyst. In Burp HTTP history, note paths that include identifiers:

  • Panel data on the dashboard uses internal keys — changing them in Repeater typically does not expose other users’ private rows (synthetic shared feeds).

Dead end (worth writing down): “Tampered dashboard panel keys — no private user documents exposed.”

Step 2 — Find a document or record viewer

Open http://localhost:8081/documents.

The search box starts empty. The Recent sidebar lists the five notes you own, plus a New note panel for adding your own. Click a note (for example Shift handover notes) and the address bar shows:

/documents?id=1001

You have found a direct object reference: parameter id.

Post a note of your own from the New note panel and watch it appear in Recent with the next reference number — this confirms the IDs are short, sequential integers an attacker can walk.

Step 3 — Establish your authorized baseline in Burp

  1. Open one of your own notes, e.g. GET /documents?id=1001, in the browser.
  2. In Burp, Send to Repeater.

Repeater: Confirm 200 and body text for one of analyst’s non-confidential notes. This is expected behavior for your own resource.

Step 4 — Enumerate beyond your own notes

The Recent list only shows references you own — the low block 1001–1005:

ID range Title (visible in Recent) Owner
1001–1005 Your operational notes (shift handover, triage, IOCs, …) analyst (you)
1011 (not listed in the UI) ?

The IDs are small sequential integers, so probe nearby references in Repeater (1006, 1007, … 1011). Most return “No document found”, but 1011 is a hit.

Step 5 — Horizontal IDOR: access Bob’s sensitive document

In Repeater, change only the id parameter:

GET /documents?id=1011 HTTP/1.1

Send. You should see SENSITIVE content — Bob’s budget and VPN reset note (note the Sensitive badge) — even though you are logged in as analyst and 1011 was never linked anywhere in the UI.

Key observation: The server returns owner_username: bob in the page but never blocks analyst from reading it. There is no check like “session user must equal owner_username.”

Step 6 — What we did not need (and still note)

  • No second account required for proof (though in other labs you would log in as Bob and confirm he can also read 1011).
  • No UUID cracking — small sequential integer IDs were enough to find a reference outside your own range.

Optional Burp step: Send two Repeater tabs (1001 vs 1011) and use Comparer on responses to show the additional confidential fields in the restricted record.

Step 7 — Document for your report

Field Example
Endpoint GET /documents?id={id}
Parameter id
Authorized access id=10011005 as analyst (your own notes)
Unauthorized access id=1011 — sensitive data for bob
Root cause Lookup by ID only; no server-side authorization
Remediation Enforce ownership/role on every read; unpredictable IDs alone are insufficient

Paste the Repeater request line for id=1011 as evidence.


Remediation

  • Server-side authorization on every object access (policy / RBAC).
  • Use non-guessable IDs plus authorization, not obscurity alone.
  • Integration tests: “user A cannot read user B’s row.”