All articlesAttack Techniques

IDOR Vulnerabilities: Detection, Proof of Concept & Fix Guide

March 10, 2026·10 min read·Nautillo Pro Security Team

Insecure Direct Object Reference (IDOR) is one of the most frequently confirmed vulnerabilities in Nautillo Pro simulations. It's also one of the most impactful — a single IDOR can expose the entire user database. This guide covers real HTTP examples, CVSS scoring, and a structured testing methodology.

What is an IDOR vulnerability?

An Insecure Direct Object Reference occurs when an application uses a user-supplied input — an ID, filename, username, or other identifier — to access a resource, without verifying that the requesting user is authorized to access that specific resource.

The vulnerability isn't in how the object is referenced. It's in the missing authorization check. The application trusts the client to send a valid ID for resources they own. An attacker simply sends someone else's ID.

IDOR falls under OWASP A01:2021 — Broken Access Control, the top-ranked web application risk category.

The classic HTTP proof of concept

Here is a minimal IDOR example. An authenticated user with account ID 1042 fetches their own order:

GET /api/orders/1042 HTTP/1.1
Host: app.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 1042,
  "user_id": 58,
  "total": 249.00,
  "items": [...]
}

The attacker changes the ID to 1041:

GET /api/orders/1041 HTTP/1.1
Host: app.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...  ← attacker's own token

HTTP/1.1 200 OK  ← should be 403 Forbidden
Content-Type: application/json

{
  "id": 1041,
  "user_id": 57,       ← different user
  "email": "victim@email.com",
  "total": 189.00,
  "items": [...]       ← victim's order data exposed
}

The application returned another user's data using the attacker's authentication token. The authorization check was missing entirely — the server only verified that someone was authenticated, not that they owned order 1041.

IDOR attack surface — where to look

IDORs appear anywhere an application exposes object references to clients. Common locations:

REST API path parameters

/api/users/842/profile, /api/invoices/3891

Query string parameters

GET /documents?id=552, GET /export?user=91

POST / PUT body fields

{"account_id": 182, "action": "transfer"}

File download endpoints

/files/report_user_58_q3.pdf

Account settings / preferences

PATCH /settings/notifications with user_id in body

Admin functions with user-supplied target

POST /admin/impersonate with user_id

Horizontal vs vertical privilege escalation

IDOR vulnerabilities enable two types of unauthorized access:

Horizontal escalation

User A accesses User B's data. Same privilege level, different account. Example: viewing another customer's invoices, reading another user's private messages.

Vertical escalation

A regular user accesses an admin resource. Example: hitting /api/admin/users/list with a standard user token, or invoking an admin action endpoint by guessing its ID.

CVSS 3.1 scoring

A typical IDOR giving read access to another user's data scores:

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Base Score: 6.5 (MEDIUM → HIGH depending on data sensitivity)

Attack Vector:      Network       (exploitable remotely)
Attack Complexity:  Low           (no special conditions)
Privileges Required: Low          (authenticated user)
User Interaction:   None          (no victim action needed)
Scope:              Unchanged
Confidentiality:    High          (full object data exposed)
Integrity:          None          (read-only in this example)
Availability:       None

An IDOR that also allows writes (modifying another user's data, deleting records) scores Integrity: High, pushing the score to 8.1 (High) or above.

Testing methodology

Step 1: Map all object references

Using a proxy (Burp Suite, OWASP ZAP, or browser DevTools), intercept all requests while using the application as a normal user. Capture every request that contains an ID-like parameter — numeric IDs, UUIDs, slugs, filenames.

Step 2: Create two test accounts

Register two separate accounts (Account A and Account B). Log all requests from Account A, noting every object ID that appears. These are your test candidates.

Step 3: Replay with Account B's credentials

For each request captured from Account A, replay it using Account B's authorization token, substituting Account A's object IDs:

# Original request from Account A
GET /api/profile/reports/77 HTTP/1.1
Authorization: Bearer <account_A_token>

# Test: replay with Account B's token, keeping Account A's resource ID
GET /api/profile/reports/77 HTTP/1.1
Authorization: Bearer <account_B_token>

# Vulnerable if response is 200 with Account A's data
# Correct behavior: 403 Forbidden or 404 Not Found

Step 4: Test numeric enumeration

For sequential numeric IDs, test ±1 and ±10 relative to your known IDs. Also test boundary values (0, 1, -1, very large numbers).

Note on UUIDs

UUIDs make enumeration harder but don't prevent IDOR. If UUID-identified resources are referenced in other API responses, emails, or shared links, an attacker can still obtain valid UUIDs and exploit missing authorization checks.

Remediation

Server-side authorization on every request

The fix is not obscuring IDs. The fix is checking on the server, for every resource access, that the authenticated user owns or has permission to access the requested object. This check must happen in the business logic layer, not just at the route middleware level.

Never use client-provided IDs as implicit authorization

The pattern 'user sends ID, server returns that resource' is inherently unsafe. The correct pattern: 'server looks up resources owned by the authenticated user, then filters by ID'. The user ID comes from the validated session token, not from the request body.

Per-user indirect references

Map publicly-visible IDs to internal IDs on the server. User sees order reference 'REF-7823', server maps this to internal ID 1041 for that specific user's session. Even if another user submits 'REF-7823', the server resolves it within the context of their session and finds nothing.

Automated regression tests

Add authorization tests to your CI pipeline: for every sensitive endpoint, verify that a valid token for User B cannot access resources belonging to User A. These tests catch regressions when new endpoints are added without authorization checks.

Confirm IDOR with a simulation

Nautillo Pro actively pursues IDOR as a primary attack goal — testing horizontal and vertical access across discovered endpoints and returning the exact HTTP request that proves impact.