OWASP Broken Access Control
Broken Access Control is A01 — the number one risk in the OWASP Top 10. It appeared in 94% of applications tested in the 2021 data set. Authentication asks "who are you?". Access control asks "what are you allowed to do?". When access control breaks down, logged-in users reach data and functions they should never be able to touch.
The Office Building Analogy
A company issues ID badges for the lobby, the cafeteria, and the public meeting rooms. The server room requires a special badge. Broken access control is like a door that checks whether you have any badge — not whether your badge grants server room access. Every employee, from intern to CEO, can walk into the server room.
Types of Broken Access Control
Insecure Direct Object Reference (IDOR)
This is the most common form. The application exposes a direct reference to a resource (like a database ID) in the URL, and anyone can change that number to access someone else's data.
Alice is logged in and views her order: https://shop.com/orders?id=1042 She changes the URL to: https://shop.com/orders?id=1041 The server returns Bob's order — including his name, address, and items. The server never checked whether Alice owns order 1041.
Privilege Escalation (Vertical)
A regular user accesses admin-only functions by navigating directly to admin URLs.
Regular user URL: https://app.com/user/settings Admin URL: https://app.com/admin/users/delete Application only hides the link — it never checks permissions server-side. Any user who types the admin URL gets full access.
Privilege Escalation (Horizontal)
A user accesses another user's resources at the same privilege level. This is what happened in the IDOR example above.
Forced Browsing
The application does not link to certain pages, but those pages exist and are accessible if you guess or know the URL.
Unlinked but accessible: https://payroll.company.com/reports/all-salaries-2024.xlsx
Missing Function-Level Access Control
API endpoints that perform sensitive actions (delete user, export data, change role) are never protected by permission checks. Attackers discover them through trial and error or by reading JavaScript files.
Full Attack Scenario: IDOR on a Healthcare App
1. Attacker creates an account and books appointment ID 5500
2. Attacker visits:
https://clinic.com/appointment?id=5500
-- Sees their own data
3. Attacker tries IDs 5499, 5498, 5497 ...
-- Sees other patients' names, dates of birth, diagnoses
4. Attacker writes a script to pull IDs 1 through 6000
-- Downloads 6,000 patient records in minutes
5. Data sold or used for fraud
How to Prevent Broken Access Control
1. Enforce Access Control Server-Side, Every Request
Never trust the client to enforce access. Every API call and every page load must verify on the server that the currently logged-in user has permission to access the requested resource.
Correct check:
GET /orders?id=1041
|
Server checks: Does the session user own order 1041?
If NO --> Return 403 Forbidden
If YES --> Return order data
2. Use Indirect Object References
Instead of exposing the database ID in the URL, map it to a random, unpredictable token per user session.
Database ID 1041 maps to token "x9f2kz" for Alice's session Alice's URL: /orders/x9f2kz Token is valid only for Alice — Bob cannot use it
3. Deny by Default
Start with no permissions and grant them explicitly. If a check is missing, the user gets no access. This is safer than allowing everything by default and trying to block individual actions.
4. Log Access Control Failures
When a user gets a 403 response, log it. A burst of 403s from one account is a strong signal of an IDOR enumeration attack.
5. Test Access Control in Every Security Review
Use different test accounts at different privilege levels. Confirm that low-privilege users cannot reach high-privilege functions, and that users cannot access each other's resources.
Quick Prevention Checklist
[✓] Server-side permission check on every request [✓] Deny by default for all protected resources [✓] No sequential predictable IDs exposed in URLs [✓] Log and alert on access control failures [✓] Test with multiple user roles during development
Key Takeaway
Access control must be enforced on the server for every single request. Hiding links or relying on the client provides zero security. Deny by default and verify permissions explicitly for every action.
