Security Cipher

Security Resources

⌘K
  1. Home
  2. Security Resources
  3. Vulnerability Explain
  4. Broken Access Control

Broken Access Control

This Vulnerability Explain post covers Broken Access Control, the number one risk in the OWASP Top 10. It is a broad category covering every way an application fails to enforce what a user is allowed to do. IDOR is one flavor; there are many more. Let’s look at the whole picture.

What is Broken Access Control?

Broken Access Control means the application does not properly enforce restrictions on what authenticated (or unauthenticated) users can access or do. The user ends up able to act outside their intended permissions.

It shows up in many ways: a regular user reaching an admin page by typing its URL, changing a role parameter to gain privileges, accessing another user’s record, or calling an API endpoint that the UI hides but the server never protects. The common thread is the server trusting the client to stay in its lane.

How does Broken Access Control work?

Broken access control appears through several recurring patterns:

  • Missing Function-Level Checks
    • Sensitive endpoints are protected only by hiding them in the UI, not by server-side authorization.
  • Forced Browsing
    • An attacker directly requests admin or privileged URLs and the server serves them.
  • Parameter and Role Tampering
    • Changing values like role=admin or account ids grants unintended access.
  • Insecure Direct Object References
    • Object identifiers can be swapped to reach other users’ data.
  • Metadata and Method Gaps
    • Access rules enforced on one HTTP method or one route but not others let attackers slip through.

Access control must be decided on the server, for every request, based on the authenticated identity. Anything left to the client is not access control at all.

Broken access control diagram showing a normal user reaching an admin-only endpoint due to missing authorization

How broken access control works: missing server-side checks let users reach actions beyond their role.

Tools and Techniques for Broken Access Control Testing

Testing access control is mostly manual and role-driven, with tooling to scale comparisons.

Manual Testing Methodologies

  • Role Comparison – Capture requests as a high-privilege user and replay them as a low-privilege or anonymous user.
  • Forced Browsing – Request admin and privileged URLs directly without going through the UI.
  • Parameter Tampering – Modify ids, roles, and flags to test for privilege escalation.
  • Method and Route Fuzzing – Try alternate HTTP methods and undocumented routes for the same resource.

Automated Scanning Tools

  • Autorize – Burp extension that replays requests with different roles to find access gaps.
  • OWASP ZAP – Has access control testing support across roles.
  • Burp Suite Scanner – Helps surface access control issues.
  • ffuf – Discovers hidden privileged endpoints through content discovery.

Broken Access Control Protection Mechanisms

Best Practices for Secure Coding

  • Deny by Default
    • Description: Require explicit authorization for every resource; deny unless allowed.
    • Benefits: New endpoints are protected automatically.
    • Implementation Tip: Apply access checks in shared middleware, not per handler.
  • Enforce on the Server
    • Description: Never rely on hidden UI elements for security.
    • Benefits: Forced browsing and tampering fail.
    • Implementation Tip: Re-check permissions on every request, including APIs.
  • Check Ownership and Role
    • Description: Validate both the user’s role and their ownership of the object.
    • Benefits: Stops both IDOR and privilege escalation.
    • Implementation Tip: Scope queries to the current user and verify roles server side.

Best Practices for Organizations

  • Central Authorization Model
    • Define a single, well-tested policy layer.
    • Review every endpoint against it before release.
  • Regression Testing
    • Add automated tests that run with multiple roles.
    • Fail builds when low-privilege users reach protected actions.
  • Audits and Pentests
    • Make access control a core focus of every pentest.
    • Log and alert on access control failures.

Top Broken Access Control payloads used by Security Researchers

As a security researcher, knowing the most common payloads helps you detect and prevent these attacks. Use this knowledge ethically and only on systems you are authorized to test. Some sample payloads are shown below.

// Forced browsing to an admin route
GET /admin/users HTTP/1.1
Cookie: session=<low-privilege-user>
// Role tampering in a request body
POST /api/profile
{ "username": "alice", "role": "admin" }
// Method override to bypass a check
GET /api/orders/55 -> 403
PUT /api/orders/55 -> 200 (check missing on PUT)
// Accessing another tenant's resource
GET /api/v1/org/2/invoices  (attacker belongs to org 1)

Real-World Example: Admin Panel by URL

An internal tool hid the admin dashboard link from non-admin users, but the /admin routes themselves performed no server-side role check.

A regular employee simply typed /admin/users into the browser and reached the full user management panel, where they could change roles and reset passwords – all because the only barrier was a hidden menu item.

The fix added deny-by-default authorization middleware that checks the role on every admin route. Broken access control is the most common serious bug there is, and it always comes back to one rule: enforce permissions on the server, every time.

Vulnerable and secure code of Broken Access Control

The following example shows the contrast between vulnerable and secure code for Broken Access Control. It helps you see how the flaw creeps into real code and the changes that shut it down.

🥺 Vulnerable Code:

// Vulnerable: route assumes only admins know the URL
app.get("/admin/users", (req, res) => {
  // No role check - any authenticated user can reach this
  const users = db.getAllUsers();
  res.json(users);
});
  • The endpoint relies on the UI hiding the link, not on a real authorization check.
  • Any logged-in user who requests the URL gets full admin data.

😎 Secure Code:

// Secure: deny-by-default role check in middleware
function requireRole(role) {
  return (req, res, next) => {
    if (!req.user || req.user.role !== role) {
      return res.status(403).send("Forbidden");
    }
    next();
  };
}

app.get("/admin/users", requireRole("admin"), (req, res) => {
  res.json(db.getAllUsers());
});
  • Authorization is enforced server-side on every request to the route.
  • Centralizing the check in middleware protects new admin routes automatically.

Conclusion

Broken Access Control tops the OWASP list because it is so easy to get wrong and so damaging when you do. Deny by default, enforce authorization on the server for every request, check both role and object ownership, and centralize the logic so new endpoints inherit protection. Never let a hidden link or a client-side flag stand in for real access control.

How can we help?