In the world of pentesting, deciding on an appropriate name for a vulnerability is an art. Being able to condense the root cause of a vulnerability into a few select words takes quite a bit of practice. While creativity is required, we should also not be so creative that we create unique names every time, which would make it challenging to consolidate in any kind of vulnerability management system. Given this, it confuses me (the author of this post specifically) why the collective security community decided that the appropriate name, the words that should capture the absolute essence of the vulnerability, should be Insecure Direct Object Referencing. In this blog post, I will explain why I think this name is misleading, and why we as MWR, always prefer to use the name Authorisation Bypass instead.
Authentication and Authorisation
It is quite common to find vulnerabilities in the authentication mechanism of an application. This is because even with the best intentions, it is easy for mistakes to creep in. Common findings include vulnerabilities such as username enumeration, a weak password policy, and even sometimes the ability to leverage a logic flaw to bypass multi-factor authentication.
Authorisation, also called access control, is an entirely different can of worms. Usually, a permission matrix is created that governs what functionality and data each user role is allowed and able to interact with. The goal of access control is to enforce this matrix and to ensure that users cannot perform actions reserved for other roles. While this sounds simple enough in theory, in practice it is easy to make a mistake here.
Authorisation bypasses are usually divided into two categories, namely vertical and horizontal bypasses. Vertical bypasses are usually well-defended against, since we simply have to enforce the permission matrix and ensure that actions can only be performed by a specific user role, i.e. not allowing a threat actor to escalate their privileges and perform actions reserved for more privileged user roles.
The trickier category is horizontal bypasses. This is where two users have the same user role but can access and/or manipulate each other’s data without the permission to do so. This is a very common bypass to encounter, since additional authorisation checks have to be implemented to protect against these attacks.
However, even with these types of bypasses, the root cause remains the same. An authorisation check that should have been performed, isn’t being performed, thereby allowing a threat actor to access or modify data that they shouldn’t be able to. Similarly, the remedial action remains the same; implement the corresponding access check server-side to ensure that these kinds of bypasses are not possible.
If this is the case, then why is an authorisation issue that leads to a horizontal bypass so often referred to as Insecure Direct Object Referencing (IDOR)? Surely, it’s not just because it’s a cool acronym, right?
Direct Object References
With the rise of modern web application frameworks such as Vue, Angular, and React, it has become a lot more popular to build web applications using web services, or API endpoints. Rather than have the application return the complete HTML in the response, API calls are made to simply populate the data fields created by these modern web application frameworks. By using web services in this way, the User Interface (UI) can be anything. As an example, this means that it is then possible to use the same API for both web and mobile applications.
A software architectural pattern that is commonly used with web services is Model View Controller (MVC). This design technique splits the web services into Models, which indicate how data is packaged, Views, which indicate how data can be represented for different views, and Controllers, which indicate how data is processed.
It is at this point that object references become relevant. A common approach to API design uses the same endpoint to return different variations of data, based on the parameters in the call. Take, for instance, the following two API calls:
- https://mywebsite.com/api/v1/accounts
- https://mywebsite.com/api/v1/accounts?id={userID}
The same endpoint is used, however, the controller accepts user requests made in two different ways. If we make a normal GET request without specifying the ID parameter, and we have the relevant permissions, the server would respond with a list of all of the accounts. If we make the same request but also specify an ID value, the server would respond with only the specific account that matches that ID value.
This is where the direct part of the direct object reference comes into play. Instead of creating random and long values, we can just simply use direct references. An ID value of 1, corresponds to the first account, an ID value of 2, the second, and so forth.
It does beg the question though, is this actually a vulnerability?
Insecure Direct Object References
This is where it all comes together. Testing the application, we find that we are able to change that ID parameter to retrieve information about accounts that our user should not necessarily have access to. At this point, we are meant to report to the client that we have found IDOR but I (again, me personally as the author of this specific blog post) would object to this. I would argue that this is not a good name for this vulnerability, especially if only a quarter of the vulnerability name captures the actual problem. Is the problem the DOR portion, or the Insecure part? Let’s dive into the root cause analysis.
If we look at the root cause of the problem, we once again see that the core problem is that we had the ability to bypass access control and successfully request access to resources that we shouldn’t have been able to request. If we review the root fix of the problem, it will be to again ensure that access control is adequately applied, making sure that if we try to request access to an ID that does not belong to us, the server will deny access. Fundamentally, we have an authorisation bypass that needs to be fixed.
My personal issue then with the name IDOR is that it shifts focus away from this. It is often mentioned that additional mitigations can be applied to the Direct Object Reference part by making these references into long and random identifiers. But we as a security community should know better. This is a form of security through obscurity. Sure, if the reference was long and random, guessing other references would be hard — but not impossible — if other vulnerabilities existed in the application. Furthermore, we still haven’t resolved the true root cause of permission checks not being performed.
If the root cause of the problem was resolved by implementing authorisation checks, would we have a vulnerability at all? I honestly don’t believe so. The direct object reference might give an indication of how many accounts there are, but this isn’t really sensitive right? It is the information stored in the account record itself that matters.
This is where my soap box speech to the security community ends. I will continue to report on this vulnerability as an Authorisation Bypass, drilling down directly into the heart of the true problem. Care to join me?