To be continued…
“id”:“1” into JSON POST bodies even when not normally present.json vs .xml vs .csvHigh-value targets: password changes, private documents, receipts, DM systems, payment views.
Merged from Bug Bounty Bootcamp Ch 10 by Vickie Li
IDOR is a missing access control vulnerability. It happens when an application grants access to a resource based directly on the user-supplied object reference (ID, filename, number) without verifying that the requesting user is authorized to access that object.
Read IDOR: https://example.com/messages?user_id=1234 – change to user_id=1233 and you read another user's messages. The server returns whatever ID you ask for without checking your identity.
Write IDOR: the same applies to POST requests that modify data:
POST /change_password (POST body) user_id=1233&new_password=12345
If the server doesn't confirm that user_id corresponds to the logged-in session, you can change any user's password.
File IDOR: endpoints like https://example.com/uploads?file=user1234-01.jpeg follow a predictable naming scheme. Swap in another user's ID to access their files. If the app passes the filename directly to the filesystem, path traversal payloads like file=/PATH/TO/etc/shadow can read system files. Path traversal is covered in Ch 17.
Two defenses, best used in combination:
Randomization alone is not sufficient – IDs can still leak via other endpoints. The best protection is fine-grained access control combined with randomized IDs.
Create an attacker account and a victim account. Create accounts at each permission level if the application has multiple roles (admin, regular user, group member, non-group-member). Also test unauthenticated – some IDORs are accessible without any session at all.
If the application limits account creation, explain to the company that you are participating in their bug bounty and ask for test accounts.
Using your highest-privilege account, go through every application feature and note every endpoint that:
Example inventory for example.com:
GET https://example.com/messages?user_id=1236 (read messages) GET https://example.com/uploads?file=user1236-01.jpeg (read file) POST /delete_message body: message_id=user1236-0111 (delete message) GET https://example.com/group_files?group=group3 (group file access) POST /delete_group body: group=group3 (delete group)
REST APIs and GraphQL endpoints are also frequently vulnerable to IDOR – apply the same testing methodology to them.
Browse through each sensitive feature with Burp intercepting. Look for any parameter carrying a number, username, or ID in:
For efficiency: open two browsers, log into attacker in one and victim in the other. Use Burp to modify requests from the attacker browser to use victim account IDs, and observe whether the victim account is affected in the other browser.
Swap in the victim account's IDs and check if you receive victim data or can modify victim resources. If any request succeeds in returning or modifying another user's data, you have found an IDOR.
When IDs look like random strings, try decoding them:
MTIzNQ is the base64url-encoded version of 1235MTIzNg is 1236Use Burp Decoder's Smart Decode feature to identify the encoding scheme automatically. Once you know the encoding, encode your fake IDs and test.
If the app uses a hashed or randomized ID, check whether it has sufficient entropy. Create several accounts and analyze the ID generation pattern – sometimes low-entropy algorithms produce predictable values.
Even with randomized IDs, they may leak elsewhere. For example, the app might expose a hashed conversation_id on individual messages, but allow you to list all conversation_ids for any user just by supplying a public user_id:
GET /messages?user_id=1236 (returns list of conversation_ids for user 1236) GET /messages?conversation_id=01SUR7GJ43HS93VAR8xxxx (returns the messages)
Look for ID leakage in API responses, profile pages, and any public-facing endpoints.
Some apps identify the current user via session cookie and don't accept an explicit user_id parameter in the request. But a fallback parameter may exist for backward compatibility or developer convenience. If the normal request looks like this:
GET /api/v1/messages Host: example.com Cookies: session=YOUR_SESSION_COOKIE
Try appending an ID:
GET /api/v1/messages?user_id=ANOTHER_USERS_ID
Some IDORs don't return data directly in the HTTP response – the leaked data appears elsewhere: email, export files, text alerts. For example, requesting another user's receipt:
POST /get_receipt (POST body) receipt_id=2983
The HTTP response may not change, but the receipt could be emailed to the account that owns it, or show up in a monthly report. Watch your email inbox after triggering these endpoints.
If one HTTP method is blocked, try others. Applications often enable multiple methods on the same endpoint but apply access controls unevenly:
GET example.com/uploads/user1236-01.jpeg (blocked) DELETE example.com/uploads/user1236-01.jpeg (may work) PUT example.com/uploads/user1236-01.jpeg (may allow overwrite) POST /get_receipt body: receipt_id=2983 GET /get_receipt?receipt_id=2983 (rewrite as GET)
Try appending a different file extension to the request:
GET /get_receipt?receipt_id=2983 (blocked) GET /get_receipt?receipt_id=2983.json (may bypass access check)
Applications that store data in JSON may handle authorization differently depending on how the resource type is requested.
Target the most sensitive functionalities first: