Insecure Direct Object References


Insecure Direct Object References (also known as IDOR) happen when it’s possible to get direct access to different data objects within a web application which are exposed to users. As a result of this vulnerability it is possible for potential attackers to bypass authorization or access data like files or database records in the system directly. It can be done by modifying the value of a parameter used to directly point to an object. This is caused by the fact that the web application takes user supplied input and uses it to retrieve an object without performing authorization checks.

Example with the object unchanged for user Peter Parker: IDOR example

Example with the object changed to view the admin account information (in this example the acct parameter value has been changed from peterparker to admin). If no additional authorization is required from the user then we have a security breach: IDOR example changed

Why Should I Care?

IDOR has had a major part in big security breaches and scandals worldwide. A few cases worth mentioning:

How Do I Test For IDOR?

A good way to test for IDOR is to first have 2 or more users who have access to different objects on the same website. Both users have to be logged in first. Then one user needs to modify the value of the parameter used to reference objects to be the same as the other user’s. If he is able to retrieve the object that only the other user should see then IDOR is present. The reason to have more than one user is that it saves a lot of time by not guessing the object values to test.

What Can Someone Do With Insecure Direct Object References?

Insecure Direct Object References are very easy to exploit and because of that it is very likely that they will be abused. This of course varies as well, as it may not always be obvious how to enumerate the links for the files.

A Few Examples…

The value of a parameter can be used directly to retrieve a database record. In the example 1337 is the key of the database entry and changing that could display another entry in the database. This could reveal sensitive information that should not be accessible to the user.

https://www.example.com/somepage?receipt=1337


The value of a parameter can be used directly to access application functionality. In the example 4 could be a normal users profile view. Changing that to another number could result in getting access to an administrators profile view or some other view that should be restricted.

https://www.example.com/accessPage?menuitem=4


The value of a parameter can be used directly to retrieve a file system resource (like Path Traversal). In the example img056.png is the name of the image file that is opened. Changing that value could result in getting access to other images OR, even worse, other files in the system.

https://www.example.com/showImage?img=images/img056.png


The value of a parameter can be used directly to perform an operation in the system. In the example bob is the user whos password is going to be changed. Changing the username could result in changing a another users password. Unless Bob is an administrator I’m pretty sure he’s not allowed to do that.

https://www.example.com/changepassword?user=bob

What’s Going On Behind The Curtain?

Let’s take the first example where a receipt is shown to the user. What happens in the background is that a database entry is selected using the receipt_id database key. If the receipt parameter is changed for instance to 855 in the URL then it will fetch the receipt information which has the receipt_id 855. If the authorization is not verified, the user can access any receipt, instead of only the intended user’s own receipt.

Example:

// the database query which selects a row from the 'receipt' table where all the receipts are located
String query = "SELECT * FROM receipts WHERE receipt_id = ?"; 

// creates a prepared statement from that database query
PreparedStatement pstmt = connection.prepareStatement(query , … );

// sets the value for the placeholder
// this is where the user can manipulate the input from the URL to view other receipts
pstmt.setString( 1, request.getParameter("receipt"));

// executes the query
ResultSet results = pstmt.executeQuery( );

How Do I Prevent This In My Code?

There are several ways to prevent users from accessing direct object references.

  • Implement an authorization scheme in the application that maintains control about which information a user is authorized to see.
  • Use object references that are challenging to guess, like using UUIDs instead of autoincremented IDs.
  • Don’t expose internal keys or identifiers. Don’t use directory listings nor allow direct access to data objects.
  • Use per user or session indirect object references or implemend reference mapping.

So In Conclusion?

IDOR is still widespread because it is really easy to forget to add authorization code to all the places where objects, which are visible to users, are accessed. Since exploiting IDOR usually is just manipulating the URL of a webpage to get data not meant for everyone. To avoid IDOR you have to apply access control to your code.

Roland Kaur