Horizontal & Vertical Access Control
Author: Johan Beysen
1. Vertical Access Control
Vertical Access Control is about privilege levels and roles:
- Admin vs User vs Guest
- "Am I allowed to perform this function based on my role?"
- Typical example: a regular user tries to reach the admin panel
Hierarchical thinking: "Am I important enough?"
2. Horizontal Access Control
Horizontal Access Control is about ownership within the same level:
- User A vs User B (both with the role "user")
- "Am I allowed to access this specific resource?"
- Typical example: user A tries to edit user B's profile
Lateral thinking: "Is this mine?"
3. Comparison
| Vertical | Horizontal | |
|---|---|---|
| Question | Am I authorized enough? | Is this object mine? |
| Direction | Hierarchical (up/down) | Lateral (sideways) |
| Example attack | A user escalates to admin | User A reads User B's data |
| OWASP name | Broken Function Level Authorization | BOLA / IDOR |
Both can involve functions and resources
- Vertical: An admin may view all user records (resource) and delete users (function)
- Horizontal: User A may edit their own profile (function) and view their own orders (resource)
4. In an IDOR Context
| Vulnerability | Type |
|---|---|
| A user escalates to admin | Missing vertical AC |
| User A reads user B's data | Missing horizontal AC (IDOR) |
5. Multi-Step Process Bypass
The Vulnerability
The developer assumes step 2 is only reachable after step 1 was completed correctly. But HTTP has no state — every request stands on its own.
Step 1: POST /admin/promote → 403 (authorization check present)
Step 2: POST /admin/promote/confirm → 200 OK (no check on this step)
Step 2 has no authorization check of its own → the confirmation step can be executed by anyone who knows the request.
Approach
- Log in as admin, run through the full flow
- Intercept both requests in Burp
- Log in as a regular user
- Resend step 2 — with the regular user's session cookie
Core lesson
Every step in a multi-step flow must be authorized separately. Never assume the order will be respected.
How Does an Attacker Find the Step-2 Request?
- Brute force / fuzzing the endpoint — if
/admin/promoteexists,/admin/promote/confirmprobably does too - JS source code analysis — admin paths are sometimes hardcoded in JavaScript files
- Naming conventions — predictable URL patterns (
/confirm,/execute,/finalize) - Previously intercepted requests — via shared environments or leaks in log files