A01:2021 - Broken Access Control

A01:2021 - Broken Access Control

Celia Catalán


Access control on a website defines whether a user is allowed to access a certain resource or perform a certain action. This control can occur horizontally and vertically:

  • Vertical access control: An unprivileged user would not be able to access the resources of an administrator user.
  • Horizontal access control: A user, for example, on a banking website, can access their cards and accounts, but not those of other users.

How is this access control lost?

For this control to work correctly, security measures must be well implemented, and this is not always the case. Bad configurations, vulnerable software versions or poor security design can result in poor access control, thus violating the confidentiality, integrity and availability of information.

Just as we classify access control as vertical or horizontal, these vulnerabilities can result in vertical privilege escalation or horizontal movement.


Vertical privilege escalation

Vertical privilege escalation occurs when an attacker exploits a vulnerability to elevate their access level from a low-privileged user (such as a standard user) to a more privileged role, such as administrator. In other words, you gain control over functionalities or data that should be reserved only for users with higher access levels, compromising the security of the application. Here are some examples of privilege escalation:
  • Unauthorized access to the administration panel.
  • Modification of the role of a platform user.
  • Access to administrator functionalities (delete a user, modify a user's password...).

Horizontal movement

Horizontal movement occurs when an attacker with access to one user account on the system gains access to other user accounts of similar privileges. This horizontal movement occurs whether you are able to directly access a user account or if you are able to access functionalities or data of said non-privileged user.

Unlike vertical movement, where the attacker gains greater permissions within the system, horizontal movement focuses on compromising other unprivileged accounts to discover new attack vectors in the application. Some examples of this horizontal movement are:

  • Discovery of the credentials of another system user.
  • A user profile access control based on a predictable ID.
  • Access to files owned by other system users.


From horizontal scaling to vertical scaling

Although it is true that we distinguish these two types of movement, cases of horizontal movement that lead to a vertical escalation of privileges are common. This occurs when an attacker, through horizontal movement techniques, gains access to a system user with administrative privileges. For example, if an attacker changes the user ID in the URL to access another user's profile, they would be performing a horizontal movement. However, using this technique you end up accessing an administrator user of the website.

In this way we observe that it is not so easy to discern between what is an escalation of privileges and what is a horizontal movement, given that it does not depend so much on the technique or attack carried out, but on the result obtained once said attack has been carried out.

Access control vulnerabilities

As we have explained in the previous section, due to the difficulty of classifying attacks between privilege escalation attacks and horizontal movement attacks, in this section we will stick to explaining different attacks, how to carry them out and the result that can be obtained.


IDOR (Insecure Direct Object Reference)

IDOR is a subcategory of access control, where user-modifiable parameters are used to access resources. An example would be a button in the user profile to download the chat history.

This button makes a request to an example.txt file, but this parameter can be modified through a proxy, so you can access the chat history of other users.
In this example, when trying to download our user's chat history, by intercepting the request with a proxy, we see that it makes a query to a 2.txt file. After this GET request we obtain the following response:


However, this parameter is modifiable, so if we replace this 2.txt with 1.txt we obtain the chat history of another user, in which we can find their password:


Unprotected functionality

This is a very simple attack and requires an almost complete lack of access control on the part of the server. It is possible to find web pages where an administrator's resources are hidden, but not protected. In that case, we can find these resources in different ways:

  1. One method is to access the robots.txt file. This file is usually available at the root of the web page and contains information about which resources and directories the Google, Microsoft bots are allowed to visit... Many times we can find hidden or administration directories under the Disallow label, thus revealing the location of administration panels or sensitive files:
  2. Another source to find these types of hidden directories is the JavaScript code itself. It is common to find references to sensitive files and directories in functions of this programming language, as we see in the following image:


Again, despite the relevance of the information that we can find in these sources, if we want to access these directories and resources as an unprivileged user, the absence of access control is essential.

Parameter-based access control

There are other cases in which a user's permissions are based on stored values ​​that the user can modify, such as a hidden field, a cookie, or a predefined value when making queries.

In this example, the user's permissions are in the hands of the user themselves, since a cookie stored in the browser with a value of false is used. Just by modifying the value of said cookie we can access sensitive resources without the need for an administrator user:



We can see another case in the following example. When making an email change with our user, if we intercept the request made and the response obtained with a proxy, we observe that in the POST request, we are sending our new email in JSON format and we receive the following information, also, in JSON format:


As shown in the image above, when changing the email we receive in the response JSON a roleid parameter with a value of 1. If when making the request, instead of only sending the email we also send a roleid parameter with a value of 2, we see that the server returns this value to us, indicating that our user's privileges have changed:


In this way, by sending a parameter to the server that it did not expect, we managed to alter the privileges of our user, turning him into a privileged user.

Bad configuration

In cases of poor configuration, it is possible to find websites that restrict requests based on the URL, for example, so that a user is not allowed to make a POST to the URL /admin/delete. However, if this same website allows us to use URL rewriting headers such as X-Original-URL or X-Rewrite-URL we can bypass these security controls.

As we see in this case, we are restricted from accessing the URL /admin/delete?username=carlos, which would allow us to delete the user carlos. But by entering the root URL of the page, using the X-Original-URL header to rewrite said URL, we see that we are able to bypass this access control to that URL:


In other cases, if the page is flexible in the methods it processes, if it is restricted by method and URL, we can change the method to and thus bypass access control. In this example, when trying to change the permissions of user Carlos with an unprivileged user, we see that we do not have authorization to make said modification:


However, due to the flexibility of the web page, we can make this same request in GET format, the server processes it correctly but does not apply access control, so we manage to bypass the security control:


URL Matching Discrepancies

There are also pages that restrict access to certain URLs using character strings, but then internally map “similar” results to that same URL.

For example, when you type a URL in all caps like /ADMIN/DELETEUSER internally redirects to /admin/deleteuser, but, since it is not exactly the same string of characters, access control does not apply. In Spring, for example, when entering a URL to access a file (that has an extension), if said file is not found, it resolves to that same resource, but without the extension, which can lead to a bypass of the control. access:

/admin/deleteUser.anything → /admin/deleteUser

It should be noted that this redirection is enabled by default in Spring versions prior to version 5.3.

Multi-step process without access control

When there is more than one request or more than one step to perform a certain action, such as deleting a user, it is possible that one of the requests is properly secured while the second or third steps are vulnerable.

In this example we clearly see this multiple process to elevate a user's privileges. When making the initial request to change privileges with a non-privileged user, we get the following response from the server indicating that we do not have permission to perform that action:




However, if we were to continue with the privilege escalation process with a privileged user, we would see a confirmation page asking if we are sure we want to perform that action.

If we intercept this request and try to make that same request with the unprivileged user's cookie, we see that it allows us to perform this action, bypassing the security control:




It is important to keep in mind that many times we need prior knowledge of what the functionalities of an administrator user are to be able to carry out this type of attacks. In this case, as a normal user we should never be able to access this confirmation page, since it would block the process from the beginning.

These vulnerabilities are much easier to detect if you have an administrator user beforehand to analyze their functions. For this reason, in web audits it is often essential to have both an unprivileged user and a privileged one.

Access control based on the Referer header

Sometimes, to limit access to subpages such as /admin/deleteUser, The Referer header is checked to see if it contains the main URL /admin. In this way, the server attempts to verify that the user comes from a directory unique to an elevated user. However, since it can be modified by the user, it can lead to a breach of this access control.

In the following case, we see exactly that. By indicating in the Referer that the request is made previously coming from the URL /admin (even if this is not true), the system allows a modification of user permissions using a non-privileged user cookie, since the web server is only checking the Referer header:


Simple examples of horizontal movement

Finally, we present some simple horizontal movement techniques. A very recurring case is usually access to the user profile through an identifier in the URL itself. Just by changing this identifier we can access other users' profiles:


To avoid this, it is usual to randomize these identifiers so that they cannot be guessed. But from time to time it is possible to find references to this identifier somewhere on the website.
In this example, browsing to a blog published by Carlos, we can see that his user identifier is found in the blog URL itself:


Another fairly common case is finding information in redirects. When we cannot access a resource, such as the administrator panel, the server returns a 302 code to redirect us, for example, back to the root of the page. However, there are times when, if we intercept the server's response, we can find in the body of the redirect response itself all the HTML code of the resource we wanted to access:


Remediation

All of these attacks are possible due to poor access control on the part of the website. For this reason, it is recommended to follow the following principles when implementing correct access control:
  • Don't rely solely on obfuscation for access control.
  • Unless a resource is intended to be publicly accessible, by default deny access to that resource.
  • If possible, use a single access control mechanism for the entire application.
  • At the code level, declare allowed access to each resource and deny access by default.
  • Thoroughly audit and test access controls to ensure they are working as intended.
return to blog

Leave a comment

Please note that comments must be approved before they are published.