What is Broken Access Control? Ways to Exploit, Examples and Impact

Explore Broken Access Control, IDOR, and privilege escalation. Learn how to exploit and prevent the #1 OWASP vulnerability with technical code examples.

What is Broken Access Control? Ways to Exploit, Examples and Impact

In the current landscape of web application security, Broken Access Control has ascended to the top spot on the OWASP Top 10 list. It is no longer just a common bug; it is the most prevalent and critical vulnerability category facing modern digital infrastructure. When access controls are broken, attackers can bypass authorization checks to perform actions outside of their intended permissions, leading to data breaches, unauthorized modifications, or total system takeover. Understanding how these vulnerabilities manifest and how to defend against them is essential for any cybersecurity professional.

What is Broken Access Control?

Access control is the security policy that dictates which users, programs, or processes are allowed to access specific resources or perform specific actions. It acts as the gatekeeper of an application. When this gatekeeper fails, we have Broken Access Control (BAC). This occurs when an application does not properly enforce restrictions on what authenticated users are allowed to do.

While authentication verifies who a user is (e.g., logging in with a password), authorization determines what they can do. Broken Access Control is fundamentally a failure of authorization. If a regular user can access an administrator's dashboard or view another user's private billing information simply by changing a URL or a parameter, the application is vulnerable.

Authentication vs. Authorization: The Critical Difference

To understand why access control fails, we must first distinguish between its two pillars. Beginners often confuse authentication with authorization, but in the context of Jsmon and infrastructure security, the distinction is vital.

  1. Authentication (AuthN): The process of verifying identity. Example: "I am User A, and here is my password."
  2. Authorization (AuthZ): The process of verifying permissions. Example: "User A is allowed to read File X but not Delete File X."

Broken Access Control happens after a user is successfully authenticated but performs an action that should be forbidden by the authorization logic.

Common Types of Broken Access Control

Access control vulnerabilities are diverse, ranging from simple URL manipulations to complex logic flaws in microservices.

1. Insecure Direct Object References (IDOR)

IDOR is perhaps the most famous form of Broken Access Control. It occurs when an application uses user-supplied input to access objects directly without performing an authorization check.

Consider a profile page URL: https://example.com/api/v1/users/1005.
If a user logged in as ID 1005 changes the URL to 1006 and can see another user's private data, the system has an IDOR vulnerability. The application correctly identified the user (AuthN) but failed to check if user 1005 had permission to view user 1006's data (AuthZ).

2. Vertical Privilege Escalation

Vertical privilege escalation happens when a lower-privileged user (like a guest or a standard customer) gains access to functions reserved for higher-privileged users (like an administrator).

Example: An attacker discovers that by navigating to /admin/delete-user?id=50, they can delete accounts even though they are logged in as a standard user. The server-side code likely checks if the user is logged in, but fails to check if the user has the 'Admin' role.

3. Horizontal Privilege Escalation

Horizontal privilege escalation occurs when a user accesses resources belonging to another user with the same level of permissions.

Example: User A and User B are both standard customers. User A modifies a POST request to update their email address, but changes the user_id parameter in the request body to User B's ID. If the server updates User B's email, User A has successfully performed horizontal privilege escalation.

4. Missing Function Level Access Control

Sometimes, developers protect the UI (hiding the "Admin Panel" button) but forget to protect the actual API endpoints or server-side functions. An attacker can use automated tools or manual discovery to find these "hidden" endpoints.

Technical Scenarios and Exploitation Examples

Let's look at how these vulnerabilities appear in code and how an attacker might exploit them.

Scenario 1: IDOR in a REST API

Imagine a banking application where you can download your statement. The request looks like this:

GET /api/statements/download?id=98221 HTTP/1.1
Host: bank.com
Cookie: session_id=abc123xyz

If the server-side code looks like this (Node.js/Express example):

app.get('/api/statements/download', async (req, res) => {
  const statementId = req.query.id;
  const statement = await db.statements.find({ id: statementId });
  res.json(statement);
});

This code is vulnerable. It takes the id from the query string and fetches it from the database without checking if the currently logged-in user owns that statement. An attacker could script a loop to download every statement in the database by incrementing the id parameter.

Scenario 2: Parameter Tampering for Role Escalation

During registration or profile updates, some applications allow users to pass JSON objects that include their role.

The Attack:

POST /api/update-profile HTTP/1.1
Content-Type: application/json

{
  "username": "attacker",
  "email": "attacker@example.com",
  "role": "admin"
}

If the backend uses a "Mass Assignment" pattern where it saves the entire JSON object directly to the database user record, the attacker has now granted themselves administrator rights.

Scenario 3: Metadata Manipulation (JWTs)

JSON Web Tokens (JWTs) are often used for session management. If the JWT is not properly signed or if the application trusts the claims within the token without verification, an attacker can modify it.

Original JWT Payload:

{
  "user_id": 55,
  "role": "user"
}

Modified JWT Payload:

{
  "user_id": 55,
  "role": "admin"
}

If the application checks the role claim in the JWT to grant access to the /settings/system page but doesn't validate the cryptographic signature correctly, the attacker gains admin access.

The Impact of Broken Access Control

The consequences of failing to secure access controls are often catastrophic.

  1. Data Exfiltration: This is the most common impact. Sensitive personal information (PII), financial records, and intellectual property can be stolen in bulk.
  2. Data Corruption/Loss: Attackers can delete records, modify prices in an e-commerce store, or change password recovery emails for other users.
  3. Full System Compromise: If an attacker escalates to an administrative role, they can gain control over the entire application infrastructure, potentially leading to remote code execution or lateral movement within the network.
  4. Compliance Violations: Under regulations like GDPR, HIPAA, or PCI-DSS, failing to protect data through proper access control can result in massive fines and legal action.

How to Prevent Broken Access Control

Securing access control requires a "Defense in Depth" strategy. It is not a single fix but a design philosophy.

1. Deny by Default

This is the most important principle. Unless a resource is specifically intended to be public (like a homepage or a CSS file), all access should be denied by default. Every endpoint should require authentication and a specific authorization check.

2. Implement Centralized Access Control Logic

Avoid writing authorization checks manually in every single function. This leads to "spaghetti security" where some endpoints are protected and others are forgotten. Instead, use a centralized middleware or a library that enforces access control consistently across the application.

Corrected Node.js Example:

// A middleware to check ownership
const ensureOwnership = (req, res, next) => {
  const statementId = req.query.id;
  const userId = req.user.id; // From authenticated session

  db.statements.find({ id: statementId }).then(statement => {
    if (statement.ownerId !== userId) {
      return res.status(403).send("Unauthorized access");
    }
    next();
  });
};

app.get('/api/statements/download', ensureOwnership, (req, res) => {
  // Logic here is now safe
});

3. Use Attribute-Based Access Control (ABAC) or RBAC

Role-Based Access Control (RBAC) is great for simple applications (User vs. Admin). However, for complex systems, Attribute-Based Access Control (ABAC) allows for more granular rules, such as "User A can only edit this document if they are the creator AND it is currently during business hours."

4. Disable Directory Browsing

Ensure that web servers do not list the contents of directories. Attackers often use directory listing to find backup files, configuration files, or hidden admin scripts that lack proper access controls.

5. Log and Monitor Access Failures

Repeated 403 Forbidden or 404 Not Found errors from a single IP address often indicate an attacker is probing for Broken Access Control vulnerabilities. By monitoring these events, you can block attackers before they find a hole.

Conclusion

Broken Access Control remains a top threat because it is often logic-based rather than syntax-based. Unlike SQL injection, which can be caught by automated scanners looking for patterns, access control flaws require a deep understanding of the application's business logic. Developers must be diligent in verifying that every single request is checked against the user's actual permissions.

As organizations scale, their attack surface grows, making it harder to track every endpoint and its associated permissions. This is where continuous monitoring and reconnaissance become vital for maintaining a secure posture.

To proactively monitor your organization's external attack surface and catch exposures before attackers do, try Jsmon.