
About these case studies. The techniques below are drawn from real assessment and research work, fully anonymized. Every screenshot is illustrative and mocked — the hostnames (target.com), identifiers, emails, and any record fields shown are AI-generated and fabricated for demonstration; they do not represent any real user, record, or client system. Where a technique depends on framework-specific behavior, that behavior is described from public documentation, not from any customer’s configuration.
Insecure Direct Object Reference (IDOR) is an access control vulnerability that occurs when an application allows users to access resources directly using identifiers such as user IDs, order IDs, or document IDs without properly verifying ownership. For example, if a user can access their profile using user_id=212, an attacker may modify the value to user_id=213 and gain unauthorized access to another user's information if proper authorization checks are missing.
When testing for IDOR vulnerabilities, it is important to understand the type of identifiers used by the application. Some applications use simple, predictable identifiers such as sequential numeric IDs (121, 122, 123), which are easy to enumerate by modifying the parameter value and observing the response. In such cases, discovering unauthorized resources is often straightforward. However, many modern applications use complex, unpredictable identifiers such as UUIDs, random strings, or tokens (for example, 1sdse32ew3wedsws or 550e8400-e29b-41d4-a716-446655440000). These identifiers are difficult to guess through brute force or manual testing. While such identifiers reduce the risk of enumeration, they do not prevent IDOR vulnerabilities. If an attacker can obtain another valid identifier through application functionality, API responses, shared resources, logs, exports, or other information disclosure issues, they may still be able to access unauthorized data if proper authorization checks are not enforced. Therefore, the security of an application should never rely solely on making identifiers difficult to guess. Every request must be validated on the server side to ensure that the authenticated user is authorized to access the requested resource.

One of the most common forms of IDOR occurs when an application uses predictable identifiers to reference resources. These identifiers are typically sequential numbers such as 101, 102, 103, or similar values that can be easily be guessed by an attacker. If the application fails to perform proper server-side authorization checks, an attacker can simply modify these identifiers to access resources belonging to other users. Depending on the affected functionality, this may result in unauthorized access to sensitive information, modification of another user's data, or deletion of protected resources.
GET /profile?user_id=212 → your profile
GET /profile?user_id=213 → someone else’s profile ← IDOR
Although IDOR vulnerabilities involving predictable identifiers are relatively simple to discover, they are frequently overlooked because researchers fail to test every functionality within the application. A thorough assessment requires reviewing all areas of the application and analyzing every request that interacts with user-controlled data. Researchers should inspect requests sent through URLs, API endpoints, POST bodies, JSON parameters, cookies, hidden fields, and HTTP headers, as object identifiers can appear anywhere within the request. Always perform testing with at least two different user accounts. Capture requests using Burp Suite Proxy, replay them using Repeater, replace the object identifiers with those belonging to another account, and verify whether the application enforces authorization. Using multiple accounts helps eliminate false positives and confirms whether the application properly restricts access between users.

During the reconnaissance and application mapping phase, I noticed that the application relied heavily on a single backend endpoint (/_serverFn/) to perform almost every operation. Modern frameworks commonly serialize request data into a single payload that is processed by the backend. The request headers gave the framework away immediately (x-tsr-serverfn: true, x-tss-serialized: true, and Accept: application/x-tss-frame. This is TanStack Start, whose server functions serialize their arguments into a single structured payload (via the seroval serializer) rather than exposing conventional named parameters.
GET /_serverFn/...?...payload=%7b...%7d HTTP/1.1
Host: target.com
At first glance, the payload appeared encoded and difficult to understand. After decoding it, the underlying structure became visible. The payload was a nested object where each node is tagged by type and index rather than by readable field names:
{
"t": {
"t": 10,
"i": 0,
"p": {
"k": ["data"],
"v": [{
"t": 10,
"i": 1,
"p": {
"k": ["portalUserId"],
"v": [{
"t": 0,
"s": 11
}]
}
}]
}
}
}
The request structure was framework-specific, so I analyzed the serialized format to understand how values were passed to the backend. During this analysis, I identified the portalUserId field and determined that the value "s":11 represented the authenticated user's identifier.
After modifying this value and replaying the request, the server returned another user's portal information. Further testing showed that numerous backend functions accepted user-controlled identifiers without verifying ownership. By following the same methodology across different functionalities, multiple identifiers were found to be vulnerable, resulting in a critical site-wide IDOR affecting numerous user resources.

Takeaway: Never skip encoded or serialized requests. Modern frameworks TanStack Start, Next.js server actions, tRPC, GraphQL routinely pack identifiers into a single opaque-looking payload. Decode it, find the object reference, and test it exactly like a URL parameter, because to the authorization layer it is one.
While testing an e-commerce application, I noticed a feature that allowed users to send purchase invoices to their registered email address. The intercepted request contained an order identifier similar to: orderId=COMP-21234
Initially, I modified the identifier manually, but random values did not return any results. I moved on to testing other areas of the application. Several weeks later, while reviewing my notes, I revisited the same functionality. I realized that although the identifier contained a prefix, only the numeric portion changed between orders. The request was sent to Burp Intruder, where the numeric sequence was enumerated. After several minutes, invoices belonging to other customers began arriving in my email. The application generated invoices based solely on the supplied order identifier and failed to verify whether the requested invoice belonged to the authenticated user.This vulnerability resulted in unauthorized disclosure of customer invoices and was rewarded with a bug bounty.

Takeaway: Sometimes the vulnerability is not obvious during the first assessment. Revisiting previously tested functionality often reveals attack paths that were initially overlooked.
Unlike predictable numeric identifiers, many modern applications use UUIDs, random strings, hashes, or tokens to reference resources. At first glance, these identifiers appear secure because brute-forcing them would require an enormous amount of time and computational effort. However, Unpredictable identifiers do not eliminate IDOR. They change the attacker’s job from guessing the identifier to discovering it. The entire game becomes: where does the application hand out a valid identifier belonging to someone else?
Instead of userId=212 an application may use: userId=8f4c9a7d-4e7b-4c13-9f1d-5f7a0f3d6b12 or resourceId=1sdse32ew3wedsws

When every user has the same role and the same functionality, there is no higher-privileged view leaking lower-privileged objects, making it harder to obtain identifiers belonging to other users. In these situations, researchers should look for identifiers exposed through other sources, including:
One effective technique is reviewing archived URLs: waybackurls target.com
Historical records sometimes expose resource identifiers that remain valid even after the URLs are removed from the application.
During one assessment, all resource identifiers consisted of long random strings that were practically impossible to guess. Instead of attempting brute force, historical URLs and archived API responses were reviewed. Several archived URLs contained valid resource identifiers. Supplying those identifiers to the application's API allowed access to resources belonging to other users because authorization checks were missing. This demonstrates that UUIDs do not prevent IDOR. They simply change the attack from guessing identifiers to discovering them elsewhere.

Applications supporting multiple roles such as Administrator, Manager, Employee, Merchant, Vendor, Customer Support, or Organization Owner often provide the best opportunities for discovering IDOR vulnerabilities involving UUIDs. Different roles naturally exchange information with one another. During these interactions, identifiers that cannot be guessed are frequently disclosed through legitimate application workflows. Common places where identifiers are exposed include:
• User management
• Organization members
• Audit logs
• Reports
• Notifications
• Approval workflows
• Administrative dashboards
• Shared API responses
Testing should always involve multiple accounts with different privilege levels while observing how identifiers move between roles.
During an assessment, the user verification functionality accepted a parameter named selfUserId, which contained a 24-character random identifier. Initially, the identifier appeared secure because brute-forcing it was unrealistic. However, while mapping the application, another endpoint used to retrieve public project details exposed the project owner's selfUserId. After obtaining another user's identifier, the verification request was replayed with the modified value.
Because the application trusted the client-supplied identifier and failed to verify ownership, another user's verification details including name, phone number, address, country, and uploaded identification documents could be modified.

Key Takeaway: Complex identifiers should never be treated as authorization. If another endpoint exposes them, the application remains vulnerable.
During another assessment, two accounts were available:
• Administrator
• View-Only User
The administrator account could delete users using a request that accepted a complex user identifier.Although the identifier appeared impossible to guess, further testing revealed that the View-Only profile response exposed the administrator's internal identifier through the createdBy field. After replacing the identifier in the delete request with the exposed administrator identifier, the request was replayed using the View-Only account. Because the server failed to validate permissions, the low-privileged account successfully performed an administrator-only action. This demonstrates a common attack chain in modern applications: one endpoint leaks a privileged identifier, while another endpoint trusts that identifier without enforcing authorization.

Key Takeaway: UUIDs hide resources; they never replace authorization. When you find a leaked privileged identifier, check whether the sensitive function is also reachable by the wrong role. The chain is usually worse than either link alone.
Every case above has the same root cause and, therefore, the same class of fix: authorize on the server, on every request, against the authenticated session never against a value the client supplied. That is the control we test for, and it is worth being specific about what “good” means, because a paper policy that says “we check authorization” is not the same as a control that holds under a replayed request.
That last point is the ioSENTRIX position, and it is the whole reason IDOR keeps reaching production: a control that exists in the codebase is not the same as a control that holds when a real request tries to bypass it. The only way to know which one you have is to prove it.
What is an IDOR vulnerability?
Insecure Direct Object Reference is an access-control flaw where an application exposes a reference to an internal object — a user ID, order ID, or document ID — and fails to verify that the requesting user is authorized to access that object. Changing the identifier grants access to another user’s resource. It is a form of Broken Access Control (OWASP A01) and, at the API layer, of Broken Object Level Authorization (BOLA, API1:2023).
Do UUIDs prevent IDOR?
No. UUIDs make a resource harder to discover by brute force, but they do not authorize requests. If an attacker obtains a valid UUID from an API response, a shared link, an archived URL, or a leak from another endpoint, the resource is exposed unless the server independently verifies ownership on every request.
How do you test for IDOR?
Map every place the application references an object — URLs, path segments, POST bodies, JSON and GraphQL fields, cookies, headers, and serialized payloads. Using at least two accounts at different privilege levels, capture requests from one account and replay them with the other account’s identifiers, checking whether the server enforces ownership. Burp Suite’s Repeater, Intruder, and the Autorize extension are the core toolset.
What is the difference between BOLA and BFLA?
BOLA (Broken Object Level Authorization) is accessing an object you shouldn’t — another user’s record via its identifier. BFLA (Broken Function Level Authorization) is invoking a function you shouldn’t — a low-privilege user calling an admin-only operation. They frequently chain: one endpoint leaks a privileged identifier (BOLA) and another lets the wrong role use it (BFLA).
What is the correct fix for IDOR?
Enforce authorization on the server for every request, derived from the authenticated session rather than from client-supplied values, checking both the specific object and the specific operation. Default to deny, add rate limiting and monitoring, and treat unguessable identifiers as defense-in-depth against enumeration — not as an access-control boundary.
ioSENTRIX is a CREST-accredited, ISO/IEC 27001 certified penetration testing firm. Broken access control is the most common serious finding we report, and IDOR is its most persistent form precisely because it hides behind identifiers that look safe. Our web and API penetration testing exercises every object reference and every privileged function with the same discipline shown above — multiple accounts, adversarial replay, and evidence — so you learn whether your authorization actually holds, not just whether the code says it should. If you’re shipping APIs, multi-tenant features, or role-based access, we can help you prove those controls work before an attacker tests them for you.