Unraveling the IDOR Vulnerability: A Comprehensive Guide to Understanding and Testing Insecure Direct Object References

Insecure Direct Object Reference (IDOR) vulnerability stands as a significant concern for web developers and security professionals alike. This vulnerability, though often overlooked, can have severe implications if exploited by malicious actors. In this blog post, we will delve into the intricacies of IDOR, explore various scenarios where it might occur, and provide a step-by-step guide to testing and identifying this vulnerability.
What is an IDOR Vulnerability?
An Insecure Direct Object Reference (IDOR) vulnerability occurs when an application provides direct access to objects based on user-supplied input. Objects, in this context, can refer to database records, files, application pages, and more. The vulnerability arises when attackers are able to bypass authorization and access these resources directly, without the necessary permissions.
The IDOR vulnerability is particularly concerning because it can lead to unauthorized access to sensitive information, such as personal data, financial records, or confidential documents. It essentially breaks down the barriers that are supposed to protect data, allowing attackers to reach into areas they should not have access to.
Identifying Points of Vulnerability
Mapping Out Object References
The first step in crafting a payload for an IDOR vulnerability is to identify points where object references may occur. This involves mapping out all locations in the application where user input is used to reference objects directly.
For example, consider a scenario where user input is used to access a specific database row. If the application takes the value of a parameter (such as a customer number) and uses it directly in a query to the database, it may be vulnerable to IDOR.
Assessing Parameters and Authorization
Next, the value of the parameter used to reference objects should be modified, and it should be assessed whether it is possible to retrieve objects belonging to other users or otherwise bypass authorization. This requires having at least two (often more) users to cover different owned objects and functions.
By having multiple users, the tester saves valuable testing time in guessing different object names, as they can attempt to access objects that belong to the other user. This multi-user approach allows for a more efficient and effective testing process.
Typical Scenarios and Testing Methods
Scenario 1: Retrieving a Database Record
In this case, the value of the parameter is used as an index in a table in the database. Since the value of the parameter goes directly into the query, by modifying the value of the parameter, it is possible to retrieve any object, regardless of the user to whom it belongs.
Testing Method: To test for this case, the tester should obtain the identifier of an object belonging to a different test user (ensuring they are not supposed to view this information per application business logic), and then check whether it is possible to access objects without authorization.
Scenario 2: Accessing Files
Another common scenario is when the value of a parameter is used to access a file directly. If the application takes the value of this parameter and uses it to retrieve a file from the server, it may be vulnerable to IDOR.
Testing Method: To test for this case, the tester should modify the value of the parameter to point to a file belonging to another user or a restricted file, and then check whether it is possible to access the file without proper authorization.
Scenario 3: Accessing User Profiles
Description: In many web applications, users have profiles that contain personal information. If the application uses a direct reference to the user ID in the URL or a hidden field, an attacker might manipulate this reference to gain unauthorized access to other users’ profiles.
Example: Consider a URL like https://example.com/user_profile?id=123
. Here, the user ID is directly referenced in the URL.
Code Snippet (Vulnerable):
$user_id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = " . $user_id;
$result = mysqli_query($connection, $query);
Testing Method: To test for this vulnerability, an attacker might change the id
parameter value in the URL to another user's ID, such as https://example.com/user_profile?id=456
. If the application does not properly verify the user's permissions, the attacker could access other users' profiles.
Scenario 4: Manipulating Shopping Cart Items
Description: In e-commerce applications, users often have shopping carts associated with their accounts. If the application uses direct object references to identify cart items, an attacker might manipulate these references to modify or delete items in another user’s cart.
Example: Consider a URL like https://example.com/cart?item_id=789
. Here, the item ID is directly referenced in the URL.
var itemId = req.query.item_id;
var query = "DELETE FROM cart WHERE item_id = " + itemId;
db.execute(query);
Testing Method: An attacker might change the item_id
parameter value in the URL to another user's item ID, such as https://example.com/cart?item_id=321
. Without proper authorization checks, the attacker could delete items from another user's cart.
Scenario 5: Accessing Administrative Functions
Description: Some applications might have administrative functions that are only intended for users with specific privileges. If these functions are referenced directly without proper authorization checks, an attacker might gain unauthorized access to these functions.
Example: Consider an administrative page accessed via https://example.com/admin?func=manageUsers
. Here, the function is directly referenced in the URL.
func = request.GET.get('func')
if func == 'manageUsers':
# Code to manage users
Testing Method: An attacker might access the URL directly, such as https://example.com/admin?func=manageUsers
. If the application does not verify the user's administrative privileges, the attacker could access administrative functions.
Scenario 6: Downloading Restricted Files
Description: In some applications, users might have the ability to download files that are associated with their accounts. If the application uses direct references to these files without proper authorization checks, an attacker might download files that belong to other users.
Example: Consider a URL like https://example.com/download?file=report.pdf
. Here, the file name is directly referenced in the URL.
String fileName = request.getParameter("file");
File file = new File("/user_files/" + fileName);
// Code to download the file
Testing Method: An attacker might change the file
parameter value in the URL to another user's file name, such as https://example.com/download?file=confidential.pdf
. Without proper authorization checks, the attacker could download files that belong to other users.
Scenario 7 : Adding Secondary Users in PayPal Business Management
Description: PayPal, a widely used online payment system, had an IDOR vulnerability that allowed an attacker to add secondary users to any PayPal business account. This vulnerability could have led to unauthorized access to sensitive financial information and control over business accounts.
Bounty Awarded: $10,500
Example: Consider a URL like https://www.paypal.com/businessmanage/users/api/v1/users
. This endpoint might be used to manage users within a business account.
var userId = req.body.userId;
var businessId = req.body.businessId;
// Adding a secondary user without proper authorization checks
var query = "INSERT INTO users (user_id, business_id) VALUES (" + userId + ", " + businessId + ")";
db.execute(query);
Complexities:
- Sensitive Financial Data: PayPal business accounts contain critical financial information, including transaction history, balance, and payment methods.
- Multi-Level Access Control: Different users within a business account might have varying levels of access, such as view-only, edit, or full control.
- Potential for Fraud: Unauthorized access to a business account could lead to fraudulent transactions, unauthorized transfers, and other malicious activities.
Testing Method:
- Identify the Vulnerable Endpoint: Analyze the application to identify the endpoint used to add secondary users to a business account.
- Craft a Malicious Request: Create a request to add a secondary user to a business account that the attacker does not own.
- Assess the Impact: Determine whether the request successfully adds the secondary user and what level of access is granted.
Example Attack: A malicious user discovers the IDOR vulnerability and crafts a request to add themselves as a secondary user to a high-profile business account. By manipulating the userId
and businessId
parameters, the attacker gains unauthorized access to the business account, enabling them to view transactions, initiate transfers, and potentially commit fraud.
Mitigation:
- Implement Proper Access Control: Verify that the user making the request has the necessary permissions to add secondary users to the specified business account.
- Use Indirect Object References: Replace direct references to business accounts with indirect references that are mapped to the user, ensuring that they can only modify accounts they are authorized to access.
- Logging and Monitoring: Implement robust logging and monitoring to detect and respond to suspicious activities.
var userId = req.body.userId;
var businessId = req.body.businessId;
// Verify user's permissions
if (isAuthorizedToAddUser(req.user, businessId)) {
var query = "INSERT INTO users (user_id, business_id) VALUES (" + userId + ", " + businessId + ")";
db.execute(query);
} else {
// Log the unauthorized attempt and respond with an error
}
Real-World Case: This scenario is inspired by a real-world vulnerability reported to PayPal through their bug bounty program on the HackerOne platform. The vulnerability was disclosed, and a bounty of $10,500 was awarded to the researcher who identified it. The detailed report can be found here.
Scenario 8: Modifying User Profile Links in a Social Media Platform
Description: Consider a social media platform like Reddit, where users can add custom links or social media profile links to their Reddit profile and redirect other users. An IDOR vulnerability in this system could allow an attacker to modify any user's custom profile links.
Example: The custom links on the profile could be changed with the following vulnerable request:
POST / HTTP/2
Host: gql.reddit.com
Content-Type: application/json
Authorization: Bearer <token>
Referer: https://www.reddit.com/
{
"id": "c558e604581f",
"variables": {
"input": {
"socialLinks": [
{
"outboundUrl": "https://www.hackerone.com",
"title": "hacker",
"type": "CUSTOM",
"id": "<custom_link_id>"
}
]
}
}
}
In this request, the id
parameter in the JSON body is a direct reference to the custom link object. By changing this id
parameter, an attacker can modify any Reddit user's profile links.
Testing Method: The attacker can use the following request to get the custom link IDs on other users' profiles:
POST / HTTP/2
Host: gql.reddit.com
Content-Type: application/json
Authorization: Bearer <token>
Referer: https://www.reddit.com/
{
"id": "11a239b07f86",
"variables": {
"username": "<target_username>"
}
}
By replacing <target_username>
with the username of another Reddit user, the attacker can retrieve the custom link IDs for that user's profile. These IDs can then be used in the previous request to modify the user's custom profile links.
Real-World Case: This exact vulnerability was discovered in Reddit, where the attacker was able to change any Reddit user’s profile links by changing the id
parameter in the request. As this could have a significant impact on Reddit users, the hacker was rewarded a well-deserved $5000 bounty.
This scenario illustrates the potential severity of IDOR vulnerabilities in real-world applications. It underscores the importance of proper authorization checks and the dangers of using direct object references without validation. By understanding these vulnerabilities and implementing secure coding practices, developers can build more secure applications and protect their users from such threats.