Infosec

Exploiting and Remediating Access Control Vulnerabilities

Today marks the start of a new series to help bridge the gap between development and security. I’ll cover web security vulnerabilities for developers, starting with the critical issue of broken access control. We’ll dive into everything I’ve learned, using resources like the OWASP Web Security Testing Guide and solutions for each access control lab in Portswigger Web Security Academy. Plus, I’ll share ways to remediate and prevent these vulnerabilities in web applications. Let’s go!

What is Broken Access Control?

Authentication and Authorization are critical components of applications. Authentication verifies a user’s identity through credentials like a username and password, email, or single sign-on methods such as Okta or Google. Once authenticated, users typically receive a token (e.g., a cookie) to interact with the application.

Authorization determines what actions or data users can access based on their permissions. Broken Access Control occurs when vulnerabilities in authorization logic allow users to access unauthorized data or perform restricted actions, potentially compromising sensitive information or application functionality.

There are three types of Broken Access Control:

  • Horizontal Privilege Escalation– Horizontal access control ensures that users can only access or modify their own data or perform actions limited to their permission level. A vulnerability in horizontal access control allows attackers to access or manipulate data belonging to other users of the same privilege level. Simply put, Profile A shouldn’t be able to access the data of Profile B.

Let’s consider a user profile accessible via the endpoint:

GET /api/v1/account?id=1

If we’re able to fuzz the id parameter and access the profiles of other profiles then there lies an access control vulnerability.

  • Vertical Privilege Escalation – Vertical Access Control allows a user to access functionality or data that is intended for a user of a higher role. A clear example is a standard user being able to access a portion of an application reserved for an admin user such as /admin portal or perform privileged functionality such as deleting or modifying the account of another user.
  • Context-Dependent Access Control – This type of vulnerability arises from flaws in the state management of an access control functionality. For example, consider a multi-step process for deleting a user profile:

Other Types of Access Control vulnerabilities:

  • Exploit CORS Misconfiguration: Taking advantage of improper CORS (Cross-Origin Resource Sharing) settings that allow API access from unauthorized or untrusted origins.
  • Modifying Parameters: Changing parameters in the URL or HTML page to bypass access controls (e.g., altering a user ID in a query string).
  • Exploiting API methods: Accessing API endpoints with missing or inadequate access controls on methods like POST, PUT, or DELETE, enabling unauthorized actions.
  • Manipulating Metadata: Tampering with or replaying metadata such as JSON Web Tokens (JWTs) or cookies to gain unauthorized access.
  • Try to access authenticated pages as an unauthenticated user

Methodology

Black-Box Testing

  1. Request accounts of every possible privilege level – In the rule of engagement document, request at least 2 accounts of each privilege level to test for both vertical and horizontal privilege escalation.
  2. Map the application – Visit the URL and walk through every page within the user context that I’m running as and make note of every input vector that can be potentially used to make access control decisions (URL parameters, hidden parameters, cookies) and have Burp running in the background intercepting every request in the application. The key is to understand how access control is implemented in the application for each privilege level.
  3. Manipulate client side parameters that are used to make access control decisions in the backend; we can automate testing using Burp Suite extensions like Autorize

White-Box Testing

  1. Review the source code to identify how access control is implemented in the application
  2. Look up for violations of least privilege principle – Essentially we’re looking for a system that doesn’t deny access by default
  3. Look for weak or missing access control checks on functions or resources (modifying a profile, making a transaction, etc)
  4. Look for missing access control rules for POST, PUT, and DELETE methods at the API level
  5. Look for instances where applications rely solely on client-side input to perform access control decisions such as a cookie like admin=true
  6. Validate any potential access control issues in a running application

Examples

Unprotected Admin Functionality

When I’m exploring an application, I’ll typically look for low-hanging fruit which includes robots.txt, which is a file that lists potentially sensitive endpoints such as the admin portal. In this instance. the admin portal lacks any authorization checks allowing us full access to the admin portal.

Unprotected Admin Functionality with Unpredictable URL

There are instances where an application may not utilize a predictable endpoint such as /administrator-panel and will instead use a URL that is not easily guessable. However, the URL may be leaked in the source code that can be found in the homepage for example.

User Role Controlled by Request Parameter

The application in this instance implements a layer of defense by not allowing unprotected access to the admin page.

However the flaw in this application lies in the access control mechanism relying on client-side input, specifically in the admin cookie. By simply setting the value of the cookie to true, we can access the protected admin endpoint.

Now we can abuse the admin cookie to perform vertical privilege escalation in subsequent requests.

User Role Can Be Modified in User Profile

I explored the authenticated functionality for updating the user email and noticed the response from the POST request to /my-account/change-email.

The roleid parameter is the access control logic used to determine what level of access our user has. By modifying the parameter to 2, we can elevate our user to admin-level privileges. Now I’m able to perform subsequent requests to /admin, which grants us access due to us changing our profile’s roleid.

User ID Controlled By Request Parameter, With Unpredictable User IDs

Let’s test for horizontal privilege escalation vulnerability on the user account page. When we successfully authenticate with our user credentials, we’re redirected to /my-account which contains an id parameter with the value containing a GUID, a string of characters unique to our account. GUIDs are generally considered more secure than sequential numbers because they are not easily guessable. Sequential IDs, like id=1, can be fuzzed by incrementing or decrementing the value to access other resources, making them predictable and vulnerable to enumeration attacks..

The userid parameter of the blog posts in the application reveal each author’s GUID. For example, we see the GUID of Carlos is leaked.

As a result, we can forward our initial request to /my-account and modify the id parameter value to the GUID of Carlos and as a result we can access their account page.

User ID Controlled By Request Parameter With Data Leakage in Redirect

When we login, we’re redirected to /my-account?id=wiener where the access control logic is determined by the id parameter.

By simplifying modifying the value of the id parameter to our target user, we can access that user’s account information.

User ID Controlled By Request Parameter With Password Disclosure

When we go to our account endpoint /my-account, our existing password is masked and revealed in a hidden input value. I changed the id parameter in the URL to administrator and as a result we’re given the account page of administrator containing their masked password. In Firefox we can reveal the password pretty easily by right clicking in the input field and selecting reveal password. But in any other case, we can reveal the password in the source.


<input required type=password name=password value='jm1jbibma2bvm6vl50bi'/>

Insecure Direct Object References

The application stores user chat logs directly on the server’s file system and retrieves them using static URLs. /chat represents the live chat feature:

When I select view transcript, it makes a GET request to download the file and the file is identified by 2. I changed it to 1.txt and was able to access the transcript containing sensitive information such as another user’s password.

URL-Based Access Control Can Be Circumvented

In this application, there’s an unauthenticated admin panel located at /admin but a front-end system has been configured to block external access to the path. The backend application is built on a framework that supports the X-Original-url header which allows overriding the target URL in requests with the one specified in that header value. We can test to see if the application supports the X-Original-Url header by specifying a non-existing endpoint. If it returns a 404 response, it works.

Exploit this header by pointing it to /admin

We can exploit this further by passing the query we need to delete the account of Carlos in the URL path of the request

Method-Based Access Control Can Be Circumvented

In this application, access control is implemented partly on the HTTP method requests. I authenticated as administrator to explore the natural flow of logic of promoting a user to admin. When I promote the user carlos to administrative level, a POST request is made to /admin-roles.

I tried to bypass admin functionality by utilizing the same request in my account with my session cookie to the same endpoint to upgrade my user. It didn’t work as an intended POST request but I converted it to a GET request and it worked.

Multi-Step Process With No Access Control On One Step

The application has an admin panel with a flawed multi-step process for changing a user’s role.

Our objective is to use our standard credentials to exploit the flawed access control logic to promote ourselves to administrator

To look for flaws in a multi-step process, let’s work out the natural and intended steps for upgrading the user role.

  1. Login as administrator /login
  2. Go to admin panel where we can view users to modify permissions /admin

3. Go to /admin-roles where we confirm we want to modify role permissions of user

Now to exploit this process as a standard user, we bypass the natural mutli-step process to perform the administrative action by sending a POST request with our standard user cookie.

Referer-Based Access Control

This application controls access to certain admin functionality based on the Referer header.

The referer header is an optional HTTP header that a browser sends to indicate the web page that initiated the request and intended to help track how users navigates between pages on a website

  1. We logged into the admin panel as admin and observe the request made for upgrading a user contains a Referer header pointing to /admin

2. Now we login as wiener and use the session cookie for our standard user to recreate this same request as us and because we’re specifying the referer header, we’re able to bypass authorization and access admin functionality

Remediation

  1. Enforce a centralized access control mechanism – A proper application will have a centralized access control component that all requests will go through that checks access control rules and the application will deny access to resources unless explicitly given permission to do so
  2. Deny access by default unless explicitly given permission
  3. All client-side input should be untrusted unless validated on the server side
  4. Enforce least privilege – Users should only be given the least amount of privileges to perform an action or access a resource
  5. Consider attribute or feature-based access control checks instead of role-based access control (RBAC) – A type of access control mechanism that grants access based on the attribute of each system component, helpful if you have a multi-tenant application that allows you to have groups of users to have specialized features of an application

References: