Broken function level authorization
Exploiting improperly secured API functions
Select your ecosystem
What is broken function level authorization?
Broken function level authorization occurs when APIs fail to enforce adequate authorization checks, allowing attackers to access or manipulate sensitive functions or data they are not authorized to. This vulnerability is common in systems where the security mechanisms depend heavily on URL paths or inconsistent role verification.
Attackers often exploit these vulnerabilities by guessing API endpoints, manipulating HTTP methods, or modifying parameters to perform unauthorized actions. Examples include accessing administrative APIs as a regular user or using a public API to perform sensitive operations like deleting data or escalating privileges.
About this lesson
In this lesson, you will learn how broken function level authorization vulnerabilities occur and how attackers exploit them. We'll step into the shoes of an attacker exploiting misconfigured API endpoints to escalate their privileges. Additionally, you'll learn defensive techniques and best practices to prevent such attacks.
Your friend Steve is developing his own web application. He sent out an invite to an exclusive streaming platform to a friend of his, but not you! You're pretty bummed out about not being invited but you just happened to be intercepting some packets when Steve sent out this exclusive request. Let's see what we can do.
Let’s break down what happened above to understand how broken function level authorization vulnerabilities work.
Unauthorized access through misconfigured endpoints
In the example above, the attacker exploited an administrative endpoint intended for privileged users. Due to missing or improperly configured authorization checks, the system assumed that anyone who reached the endpoint had permission to perform the requested action. This is a common oversight in API design, where developers may assume security can be enforced based solely on the endpoint’s URL structure or obscurity.
Endpoints such as /api/admin/v1/users/all
or /api/invites/new
should always validate the user’s role and permissions against the request, regardless of the path or method being accessed.
The attacker demonstrated how HTTP method changes could bypass security controls. For example, while GET /api/invites/{invite_guid}
may only retrieve information, switching to POST /api/invites/new
allowed the creation of new resources. Each method should have its own unique access controls, preventing unauthorized users from exploiting less protected operations.
In the scenario, the attacker successfully created an invite with elevated privileges by exploiting the lack of server-side validation for roles. The application blindly trusted the role value ("role": "admin") in the attacker’s request without verifying whether the requester had the authority to assign such privileges.
This example shows a Flask endpoint that accepts a JSON payload through a POST
request at /api/invites/new
. It uses the request.get_json()
method to extract the payload and appends the email
and role
values to an invites
list.
The vulnerability arises from the lack of role-based authorization. There is no check to ensure that only administrators can access the endpoint or assign roles. As a result, any user (or even attackers who discover this endpoint) can create an invite, including assigning high-privilege roles like admin. The absence of user authentication or validation compounds the risk.
How do you mitigate broken function level authorization?
To protect your application against broken function level authorization, you must ensure consistent, robust authorization checks for all endpoints and methods. Below are several strategies:
Implement a centralized authorization mechanism
Adopt a single, centralized module for handling authorization across all API endpoints. This ensures consistency and minimizes the risk of missing checks in individual routes.
There are two common ways to achieve this, they should be used in conjunction:
- Implementing Role-Based Access Control: Permissions to "roles" like
admin
ornormal_user
, and then those roles are assigned to users. - Authorization middleware (in languages like JS, Python, or Go) or filters (in frameworks like ASP.NET or Java Spring) that intercept and filter requests before they reach the endpoint. Permissions can then be assigned and viewed at a high level, such as in a routes file.
Enforce a deny-by-default policy
Once a centralized auth mechanism has been set up, configure your endpoints to deny all access by default. Only explicitly granted permissions should allow access to specific functions or endpoints. This way, it's very difficult for a developer to "forget" to assign authorization controls to an endpoint.
Verify user roles for every API action
Always verify that the user has the necessary role or group membership for the requested operation. Avoid assuming that an API endpoint or HTTP method is only accessed by authorized users
On a similar note, it's important to define roles and permissions clearly, ensuring that each function or resource has a precise access control policy based on your application’s business logic.
Use API gateways for additional security
It's possible to implement cloud-based API gateways to enforce access control policies at the network layer. Gateways can log, monitor, and block unauthorized requests before they even reach your application. This may also be an effective way to thwart resource-consumption vulnerabilities such as DoS, depending on your setup.
In Flask, you can use decorators for role validation.
This mitigated example uses a decorator named authorize to enforce role validation. This decorator ensures that the request.user
object contains the required role (admin
) before proceeding to execute the create_invite
function. If the user does not meet the role requirements, the decorator returns a 403 Forbidden response.
This approach mitigates the vulnerability by explicitly validating user roles for sensitive operations. By wrapping the handler with the authorize
decorator, the code ensures that only authorized users can interact with the endpoint. The decorator pattern also promotes reusability, allowing other endpoints to easily adopt similar protections.
Test your knowledge!
Keep learning
To deepen your understanding of API security and authorization vulnerabilities, explore the following resources:
- OWASP API Top 10: Broken Function Level Authorization: https://owasp.org/API-Security/editions/2023/en/0xa5-broken-function-level-authorization/
- Snyk's Blog About OWASP API Top 10