IDOR Exploitation
IDOR exploitation moves from confirming unauthorized access on a single object to extracting full datasets, modifying other users' data, and escalating to admin functions when vertical references are accessible. Start from a confirmed IDOR found in IDOR testing and expand the scope before reporting.
Identify the reference type before scaling. Sequential integers enumerate quickly but generate noticeable log volume. GUIDs and UUIDs are not authorization controls, so test them even when the ID space looks unpredictable. Version-1 UUIDs encode a timestamp and MAC address, making them partially guessable. Hash-based IDs appear in export endpoints and password reset links. MD5 or SHA1 of an email address is common. Determine the ID space, verify one unauthorized access, then scale the extraction.
Common IDOR exploitation and access control bypass techniques covered here:
- Bulk horizontal data extraction by enumerating sequential or predictable IDs
- Write IDORs to modify other users' records via PUT, PATCH, or POST
- Vertical escalation by accessing admin API endpoints with a regular user session
- Parameter pollution to bypass authorization checks using duplicate parameters
Bulk Horizontal Data Extraction
With a confirmed read IDOR, enumerate the full ID range to extract all accessible objects. Watch for inconsistent response codes across the ID space. A 403 on some IDs and 200 on others means access control is applied inconsistently, which is worth noting separately in the report. A uniform 404 beyond a certain point means the range ends there. Empty JSON arrays or objects are not the same as 404s. Endpoints returning empty data for unauthorized IDs are attempting to hide an access control failure. Collect all 200 responses with non-empty bodies and filter out records belonging to your own account.
1: admin@company.com 2: user@company.com 47: finance@company.com
Extracted 347 records
Write IDOR: Modify Other Users' Data
When PUT, PATCH, or POST endpoints accept object references in the body without authorization checks, modify other users' records. Baseline the request with your own account first. Confirm the correct fields and what a successful response looks like. Then swap the user ID to a target account and resend. Some applications authorize on the URL parameter but process the body, or vice versa. Try both positions. PATCH requests are worth testing separately from PUT. PATCH often has weaker validation because it is designed to accept partial updates rather than a full resource replacement.
{"id":1,"email":"pwned@attacker.com","role":"admin"}
A successful response modifying user ID 1 (admin) confirms write IDOR. If the role field was accepted, this is also a mass assignment vulnerability enabling privilege escalation. Verify the write actually took effect by reading the record back with a GET request. Some applications accept writes silently but discard fields they do not recognize. If the response echoes back the changed data but a subsequent GET shows the original values, the application is filtering on read but not on write. That is still a reportable finding, but with lower impact. If the role change persists on read, use the new session to confirm admin access works and document the full escalation path.
Vertical IDOR: Admin Function Access
Test admin endpoints with a regular user session. Admin panels often apply access controls on navigation but not on the underlying API endpoints. Log in as an admin in one browser session and as a regular user in another. Use Burp Suite to capture the API calls the admin panel makes, then replay those requests using the regular user session token. A redirect to a login page is not a block. Redirects often happen at the frontend routing layer while the API still returns 200 with data. Send the request directly to the API endpoint without following the redirect.
[{"id":1,"username":"admin","role":"admin"},{"id":2,"username":"editor"}]
200
Parameter Pollution for IDOR Bypass
Some applications check authorization on one parameter but process another. Test duplicate parameters to see which one takes precedence. PHP and classic ASP typically use the last occurrence. Express.js and some Java frameworks use the first. Rails merges duplicates into an array. The behavior depends on the framework and parser, so test both positions. Also try JSON body injection: if the endpoint accepts a JSON body, send the same key twice. Most JSON parsers take the last occurrence. If the authorization check reads the first value and the database query reads the last, you bypass the check entirely. Combine this with array wrapping: send the user_id field as both a scalar and as an array containing the target ID to probe how the application deserializes the input.
Static File IDOR
Applications that store user uploads at predictable paths are vulnerable to static file IDOR. The server does not check ownership when serving static files because the web server (nginx, Apache) handles them directly, bypassing application-level authorization. Common patterns include sequential user IDs in the path, sequential filenames, and timestamp-based filenames.
200
user_1: accessible user_3: accessible user_14: accessible user_27: accessible
Also check for sequential document filenames like /documents/invoice_001.pdf through /documents/invoice_999.pdf, and timestamp-based patterns like /exports/report_20260101120000.csv where the timestamp is predictable from the creation date visible in the UI. Some applications use MD5 or SHA1 hashes of the original filename or user email as the directory name. If you can determine the hash input (often visible in other API responses or the user profile), compute the hash and access files directly.
References
-
PortSwigger: IDORTOOL: PortSwigger: IDOR, portswigger.net/web-security/access-control/idor (opens in new tab)
Horizontal and vertical IDOR exploitation patterns