OSA
Task 1

What is an IDOR?

Web applications rely on identifiers to distinguish one object from another. A user profile, an invoice, a support ticket, and a private document each have some kind of reference (often a number or a string) that the application uses internally to locate them. When an application allows the user to supply that reference and then retrieves the corresponding object without checking whether the user is permitted to access it, the result is an Insecure Direct Object Reference (IDOR).

IDOR is classified as an access control vulnerability. It sits within the Broken Access Control category at position one in the OWASP Top 10. The same underlying flaw appears in the OWASP API Security Top 10 under the name Broken Object Level Authorisation (BOLA). The terminology differs depending on context, but the root cause is identical: the server does not verify that the authenticated user has permission to interact with the specific object they are requesting.

What makes IDOR significant is the gap between its simplicity and its impact. Exploiting the vulnerability often requires nothing more than changing a number in a URL or request body. There is no need for injection, no need for session hijacking, and no need for any specialised tooling. Yet the consequences can range from mass data disclosure to full account takeover, depending on what the vulnerable endpoint exposes.

In this room, we cover what IDOR vulnerabilities are, the different forms object references can take, where to look for them in a web application, and how to exploit them. The final task provides a practical exercise against a simulated target.

Learning Objectives

By the end of this room, you will be able to:

  • Explain what an IDOR vulnerability is and how it relates to broken access control
  • Identify the different forms object references can take, including plaintext, encoded, and hashed identifiers
  • Recognise the locations in a web application where IDOR vectors commonly appear
  • Exploit an IDOR vulnerability in a practical scenario to access another user's data

?Answer the questions below

  1. What does IDOR stand for?
Task 2

An IDOR Example

The simplest form of IDOR occurs when an application places an object identifier directly in a URL parameter and uses it to query a back-end database without any authorisation check.

Suppose you sign up for an online service and navigate to your profile page. The URL reads:

http://online-service.thm/profile?user_id=1305

The user_id parameter tells the server which record to retrieve from its database. In this case, record 1305 corresponds to your account, and the page displays your name, email address, and other personal details as expected.

Now suppose you change the parameter value to 1000:

http://online-service.thm/profile?user_id=1000

If the page returns a completely different user's profile, including their personal information, the application has an IDOR vulnerability. The server took the modified parameter, looked up record 1000, and handed back the result. At no point did it verify whether your session was permitted to view that record.

Why does this happen? The application's authentication layer is working correctly. It knows who you are because you are logged in with a valid session. However, the authorisation layer is missing entirely. There is no server-side logic that asks: "Does this session belong to user 1000?" or "Is this user allowed to view this profile?" The server assumes that any authenticated user is entitled to access any object they reference.

This flaw is not limited to read operations. Depending on how the endpoint is built, modifying the identifier might allow an attacker to update another user's email address, reset their password, delete their resources, or perform other privileged actions. A single missing authorisation check on a write endpoint can turn a data disclosure issue into a full account takeover.

Click the View Site button to open the exercise for this task. Discover and exploit an IDOR vulnerability to retrieve the flag.

?Answer the questions below

  1. What is the Flag from the IDOR example website?
Task 3

Finding IDORs in Encoded IDs

Not every application exposes object references as plaintext values. Developers frequently encode identifiers before including them in query strings, POST data, or cookies. Encoding converts raw data into an ASCII-safe string using the characters a-z, A-Z, 0-9, and = for padding. The purpose is to ensure the receiving server can process the value without misinterpreting special characters.

The most common encoding scheme on the web is base64. Base64 strings tend to be noticeably longer than the value they represent and often end with one or two = padding characters. For example, the integer 123 becomes MTIz when base64-encoded. A small JSON structure like {"user_id": 5} might appear as eyJ1c2VyX2lkIjogNX0=.

Exploiting an encoded IDOR reference involves four steps:

  1. Decode the value from the request using a tool such as base64decode.org or the terminal command echo 'value' | base64 -d.
  2. Modify the decoded output to reference a different object (for example, changing a user ID from 5 to 1).
  3. Re-encode the modified value using base64encode.org or echo 'value' | base64.
  4. Substitute the re-encoded string back into the request and submit it.

If the server returns data belonging to a different user, the endpoint is vulnerable.

The image below illustrates this decode, modify, and re-encode workflow:

Encoded IDOR workflow

A common misconception is that encoding provides security. It does not. Base64 is a reversible transformation, not a form of encryption. Any encoded value can be decoded by anyone who has access to the string. An application that relies on encoded identifiers without performing server-side authorisation checks is exactly as vulnerable as one that uses plaintext IDs.

?Answer the questions below

  1. What is a common type of encoding used by websites?
Task 4

Finding IDORs in Hashed IDs

Some applications hash identifiers before including them in requests. A hashed value appears as a fixed-length string of hexadecimal characters, which can give the impression that the reference has been obscured. However, if the input to the hash function is predictable (such as a sequential integer), an attacker can reproduce the hashing process and generate valid references to any object in the system.

For example, if an application uses MD5 to hash its user IDs, the integer 123 produces the hash 202cb962ac59075b964b07152d234b70. On its own, that output reveals nothing about the original value. But if the attacker suspects sequential integers are being hashed, they can compute the MD5 hash for 1, 2, 3, 4, and so on, then compare the results to the hashes observed in the application's requests. A match confirms the scheme and makes every object reachable.

Unlike encoding, hashing is a one-way function. There is no mathematical operation that reverses an MD5 hash to its original input. However, for short and predictable inputs like small integers, this property offers little real protection. Services such as CrackStation maintain lookup tables containing billions of precomputed hash-to-value pairs. Looking up a hashed integer through one of these services is typically instantaneous.

When you encounter a hashed identifier in a request, the first step is to determine which algorithm was used. The length of the hash is a reliable indicator: MD5 produces 32 hexadecimal characters, SHA-1 produces 40, and SHA-256 produces 64. Tools such as hash-identifier or hashid on Kali Linux can automate this step. Once the algorithm is known, hashing a range of likely input values and comparing the output to the observed hashes will confirm or rule out the pattern.

Hashing an identifier does not replace a proper authorisation check on the server side. It adds a layer of obfuscation, but once the scheme is understood, an attacker can craft valid references with the same ease as plaintext IDs.

?Answer the questions below

  1. What is a common algorithm used for hashing IDs?
Task 5

Finding IDORs in Unpredictable IDs

Some applications use randomly generated strings, UUIDs, or other identifier formats that cannot be guessed or enumerated. A UUID such as d3b07384-d9a0-4e9b-8b3c-2f1a6c7e4a90 has no relationship to the identifiers assigned to other users, so incrementing or hashing sequential values will not produce valid references.

However, an unpredictable identifier does not eliminate the IDOR risk. It only removes one attack path: enumeration. If the server still fails to verify that the requesting user is authorised to access the referenced object, the vulnerability exists. The attacker simply needs to obtain a valid identifier through a different channel.

The standard approach for testing in this situation is the two-account technique:

  1. Create two accounts on the application (Account A and Account B).
  2. Log into Account A and record the identifiers associated with its resources (profile IDs, order references, document paths, and so on).
  3. Log into Account B and substitute Account A's identifiers into Account B's requests.

If the server returns Account A's data to Account B, the endpoint lacks proper authorisation checks. The identifier format is irrelevant to this test. What matters is whether the server validates ownership before returning the object.

This technique works because it separates two questions. The first is whether an attacker can obtain a valid identifier for another user's object. The second is whether the application will serve that object without verifying permissions. The application is only secure if the answer to the second question is "no," regardless of how difficult the first question is to answer.

In practice, unpredictable identifiers leak through a variety of channels. They can appear in shared URLs, API responses that reference other users' resources, HTML source code, JavaScript files, notification emails, or exported data such as CSV reports. Once a valid identifier has been obtained from any of these sources, exploiting the IDOR is no different from the plaintext case.

?Answer the questions below

  1. What is the minimum number of accounts you need to create to check for IDORs between accounts?
Task 6

Where are IDORs located

IDOR vectors are not confined to URL parameters visible in the browser's address bar. Vulnerable endpoints can exist anywhere the application processes a user-supplied object reference. Restricting your testing to the address bar alone will cause a significant proportion of IDOR flaws to go undetected.

Background Requests

Modern web applications load data dynamically through asynchronous HTTP requests that the browser sends in the background. When a page renders, it may trigger several API calls to retrieve the data it displays. These requests never appear in the address bar, but they are fully visible in the browser's developer tools under the Network tab and in intercepting proxies such as Burp Suite. For example, loading the "Your Account" page might trigger a background request to /api/v1/customer?id=15. If the id parameter in that request is not validated against the current session, it is exploitable in the same way as a parameter in the URL.

JavaScript Files

JavaScript files loaded by the application frequently contain references to API endpoints and parameter names that are not exposed through the visible interface. Reviewing these files (manually or with automated tools) can reveal endpoints the developer did not intend users to interact with directly.

Parameter Mining

Some endpoints accept parameters that the front end never sends. These parameters may have been introduced during development for debugging or testing and were never removed before deployment. For example, the endpoint /user/details might normally return the current user's profile based solely on the session cookie, with no ID in the request. However, appending ?user_id=123 to the URL might cause the endpoint to honour that parameter and return a different user's record. This technique, known as parameter mining, is a common method for uncovering hidden IDOR vectors that would otherwise go unnoticed.

Common Locations

To summarise, you should test for IDOR in all of the following locations: query string parameters, POST body data, cookie values, HTTP request headers, REST API path segments (such as /api/users/123/orders), and background AJAX requests. The key principle is to intercept and inspect every request the browser makes, not just what is visible in the address bar.

?Answer the questions below

  1. Read the above.
Task 7

A Practical IDOR Example

This task provides a hands-on exercise against a simulated web application. You will identify an API endpoint vulnerable to IDOR and exploit it to retrieve other users' data.

Press the Start Lab Machine button. Once the machine has started, open the following link in a new browser tab:

https://LAB_WEB_URL.p.thmlabs.com

Creating an Account

Click on the Customers section and use the sign-up form to create an account. Any username, email address, and password will work. Once registered and logged in, navigate to the Your Account tab.

The Your Account page allows you to change your username, email address, and password. The username and email fields are pre-filled with the details you provided during registration.

Identifying the Vulnerable Endpoint

Open your browser's developer tools (F12 in most browsers), select the Network tab, and refresh the page. Among the requests that appear, you will see one to the endpoint /api/v1/customer?id={user_id}, where {user_id} is your account's numeric identifier.

Click on this request to inspect its response. The server returns a JSON object containing your user ID, username, and email address. The data returned is determined entirely by the id query string parameter, making it a direct object reference to your user record.

Network tab showing the API request

Exploiting the Vulnerability

You can now test this endpoint by modifying the id parameter. Right-click the request in your developer tools and select Edit and Resend (in Firefox), or use a tool such as Burp Suite or curl to replay the request with a different value.

Set the id parameter to 1 and submit the request. If the server returns a different user's details, the endpoint has no authorisation check in place. The server accepts the id value without verifying that the current session has permission to access that record.

Repeat this process with an id of 3 to answer the second question below.

?Answer the questions below

  1. What is the username for user id 1?
  2. What is the email address for user id 3?