๐ What Is It?
Broken Access Control occurs when an application fails to enforce restrictions on what authenticated users may do, letting them read or modify data and reach functionality outside their intended permissions. It is an authorization problem, not an authentication one, and consistently ranks as the most prevalent category in the OWASP Top 10.
A01
OWASP Rank
94%
Apps With Some Form
34
Mapped CWEs
โ ๏ธ Common Attack Vectors
- IDOR: Insecure Direct Object References
- Privilege escalation: horizontal & vertical
- Parameter tampering: injecting role / is_admin
- Forced browsing: guessing unlinked URLs
- Path traversal to reach restricted files
- Missing function-level access checks
๐ด Attack Flow (IDOR)
1. Logs in, views /user/profile?id=12345
โ
2. Notices IDs are sequential
โ
3. Changes URL to /user/profile?id=12346
โ
4. Server performs no ownership check
โ
5. BREACH: reads another user's data!
โ
2. Notices IDs are sequential
โ
3. Changes URL to /user/profile?id=12346
โ
4. Server performs no ownership check
โ
5. BREACH: reads another user's data!
โ Vulnerable Code
# Anyone can access any profile by changing user_id
@app.route('/api/profile/<user_id>')
def get_profile(user_id):
user = database.get_user(user_id)
return jsonify(user.to_dict())
โ Secure Code
@app.route('/api/profile/<user_id>')
def get_profile(user_id):
if not current_user.is_authenticated:
abort(401, "Authentication required")
user = database.get_user(user_id)
if not user:
abort(404, "User not found")
# Verify ownership (or admin) before returning
if current_user.id != user_id and not current_user.is_admin:
abort(403, "Access denied")
return jsonify(user.to_dict())
โ Prevention Checklist
- Deny by default; grant permissions explicitly
- Enforce all authorization server-side
- Check authorization on every request
- Verify resource ownership in the query
- Use one centralized access-control mechanism
- Prefer non-sequential references (UUIDs)
- Validate and whitelist input
- Set Secure, HttpOnly, SameSite cookies; strict CORS
- Log access-control failures and alert
- Test every role (horizontal & vertical) in CI/CD
๐ Real-World & Pitfalls
It bites the biggest names: Facebook's 2018 access-token flaw exposed ~50M accounts (later a $5B FTC settlement), and Equifax's 2017 breach exposed ~147M records.
Common pitfall: Hiding a button or link in the UI is not access control โ the endpoint is still reachable. Enforce authorization on the server, for every request, not just on page render.
Common pitfall: Hiding a button or link in the UI is not access control โ the endpoint is still reachable. Enforce authorization on the server, for every request, not just on page render.
๐ Tools & Takeaway
Burp Suite
OWASP ZAP
Postman
Selenium
pytest
Flask-Login
Key Takeaway: Enforce access control on the server for every request, default to deny, and verify ownership. Never rely on hidden UI, client-side checks, or obscure URLs for security.