IDOR Explained with a Simple Lab Scenario

IDOR stands for Insecure Direct Object Reference. It is a common access control vulnerability where an application exposes a direct reference to an internal object and fails to verify whether the current user is allowed to access that object.

In simple terms:

If changing an ID in a request lets you access another user’s data, you may be looking at IDOR.

IDOR is part of the broader Broken Access Control category. It is especially common in APIs because object IDs often appear directly in paths, query parameters, or request bodies.

Image: Type: Context, Mô tả: “A simple diagram showing User A requesting /api/invoices/1001 and then changing the ID to /api/invoices/1002, which belongs to User B.”. caption: “IDOR happens when the server trusts the object ID but does not verify whether the current user is authorized to access it.”

The Core Concept

Consider this request:

GET /api/invoices/1001 HTTP/1.1
Host: lab.example
Authorization: Bearer token-for-user-a

If invoice 1001 belongs to User A, the request is legitimate.

Now consider this modified request:

GET /api/invoices/1002 HTTP/1.1
Host: lab.example
Authorization: Bearer token-for-user-a

If invoice 1002 belongs to User B, the server should reject the request.

If the server returns User B’s invoice to User A, the application is vulnerable to IDOR.

Root Cause

The root cause is missing object-level authorization.

The application checks:

Is the user logged in?

But fails to check:

Is this user allowed to access this specific object?

Authentication is not enough. The server must enforce authorization for every object and action.

A Simple Lab Scenario

Use only legal labs or authorized test environments such as PortSwigger Web Security Academy, DVWA, or OWASP Juice Shop.

Imagine a training application with two accounts:

AccountRoleObject owned
AliceNormal userInvoice 1001
BobNormal userInvoice 1002

Alice logs in and views her invoice:

GET /account/invoices/1001 HTTP/1.1
Host: vulnerable-lab.local
Cookie: session=alice-session

The application returns Alice’s invoice.

The tester then changes the object ID:

GET /account/invoices/1002 HTTP/1.1
Host: vulnerable-lab.local
Cookie: session=alice-session

Expected secure behavior:

HTTP/1.1 403 Forbidden

Vulnerable behavior:

HTTP/1.1 200 OK

Invoice owner: Bob
Amount: $500

This is IDOR because Alice can access Bob’s object by modifying a direct object reference.

Image: Type: Test case, Mô tả: “A PortSwigger-style lab screenshot or Burp Suite Repeater screenshot showing an object ID changed from one authorized object to another test user’s object.”. caption: “A safe IDOR test compares access between two authorized lab accounts.”

Where IDOR Appears

IDOR can appear in many places.

URL Paths

/users/1024
/orders/7788
/files/9001

Query Parameters

/download?file_id=9001
/profile?user_id=1024
/report?id=7788

JSON Bodies

{
  "userId": 1024,
  "invoiceId": 7788
}

HTTP Headers

X-User-ID: 1024
X-Account-ID: 7788

GraphQL Variables

{
  "id": "VXNlcjoxMDI0"
}

The object reference does not have to be a simple number. It can be a UUID, hash, base64 value, slug, file name, or encoded global ID.

Numeric IDs vs UUIDs

Some teams believe that replacing numeric IDs with UUIDs fixes IDOR.

UUIDs can reduce guessability, but they do not replace authorization.

If a user obtains another user’s UUID through search results, logs, shared links, browser history, API responses, or leaked data, the same issue may still exist.

The real fix is server-side authorization.

IDOR Impact

Impact depends on the object and action.

Read-only IDOR may expose:

  • Personal data
  • Invoices
  • Documents
  • Support tickets
  • Private messages
  • API keys
  • Internal reports

Write-based IDOR may allow:

  • Updating another user’s profile
  • Deleting another user’s files
  • Changing shipping addresses
  • Modifying project settings
  • Canceling orders
  • Approving actions

Write-based IDOR is often more severe because it affects integrity, not only confidentiality.

How to Test IDOR Safely

A proper test requires at least two accounts.

Step 1: Create or obtain two test accounts

Use accounts that are explicitly authorized for testing.

User A: alice@example.test
User B: bob@example.test

Step 2: Capture User A’s request

Use Burp Suite Proxy or browser dev tools.

Example:

GET /api/documents/501

Step 3: Identify User B’s equivalent object

Log in as User B and find a similar request:

GET /api/documents/702

Step 4: Replay User A’s request with User B’s object ID

While authenticated as User A, change 501 to 702.

Step 5: Evaluate the response

Secure outcomes:

  • 403 Forbidden
  • 404 Not Found
  • Empty result
  • Generic error without data exposure

Vulnerable outcome:

  • User B’s object is returned
  • User B’s object is modified
  • The action succeeds without authorization

What to Include in a Report

A good IDOR report should include:

  • Affected endpoint
  • Roles/accounts used
  • Original authorized request
  • Modified unauthorized request
  • Evidence of unauthorized access
  • Business impact
  • Clear remediation

Example root cause statement:

The endpoint validates that the requester is authenticated but does not verify that the requested invoice belongs to the authenticated user. As a result, an authenticated user can modify the invoice ID and retrieve invoices belonging to other users.

Remediation

Enforce Object-Level Authorization

For every object access, the server should verify ownership or permission.

Example:

invoice.owner_id == current_user.id

or:

current_user has organization permission: invoice:read

Avoid Trusting Client-Supplied Ownership

Do not trust values like:

{
  "ownerId": 123,
  "userId": 456
}

The server should derive ownership from the authenticated session and database records.

Apply Authorization to Every Action

Authorization must be enforced for:

  • Read
  • Create
  • Update
  • Delete
  • Export
  • Share
  • Approve
  • Batch operations

Use Centralized Authorization Policies

Centralized policies reduce inconsistent authorization logic across endpoints.

Common Mistakes

Avoid these assumptions:

  • “The endpoint requires login, so it is safe.”
  • “The ID is a UUID, so users cannot guess it.”
  • “The frontend hides the button, so users cannot access it.”
  • “Only mobile apps use this API, so users cannot modify requests.”
  • “The object ID is encoded, so it is protected.”

These assumptions fail because clients are under user control.

Conclusion

IDOR is simple to understand but still very common. The vulnerability appears when an application exposes object references and fails to enforce object-level authorization.

For pentesters, the key is to test with multiple authorized accounts and compare access boundaries. For developers, the key is to enforce authorization on the server for every object and action.

References

Need Help?

KevinSec helps teams test object-level authorization across web applications and APIs. If you want to validate whether your application is vulnerable to IDOR or BOLA, contact KevinSec through the Contact page.