Horizontal vs Vertical Privilege Escalation in Web Apps
Hunters say “priv esc” for two different bugs. Mixing them up muddies severity. OWASP’s privilege escalation page draws the line; here is how I apply it on web and API targets.
Horizontal — same role, wrong object
You stay a normal user. You access another normal user’s data or actions.
Examples:
- Change
account_idand read someone else’s invoices (classic IDOR/BOLA) - Unlock another user’s messages via predictable share tokens
- Cancel a peer’s subscription from a mobile API
Impact is confidentiality/integrity across tenants or accounts at the same privilege tier. Payouts track data sensitivity, not a fancy role name.
Vertical — climb the ladder
You start as user (or anonymous) and gain admin, support, billing, or other elevated functions.
Examples:
- Mass-assign
role=admin(BOPLA/mass assignment) - Call
POST /api/admin/userswithout role checks (BFLA) - Reuse an old admin JWT alg confusion
- Register with
userType=internalhonored by the server
Impact is control-plane power: list all users, read secrets, change payouts. Often Critical when reproducible.
How I test in one session
- Map roles: anon, user, power-user, admin.
- For horizontal: two users, swap IDs only.
- For vertical: replay admin requests with a user session; try hidden fields that declare role.
- Never confuse “I found an admin URL” with vertical esc — the server must accept the action.
Feature flags and “staff only” UI hides are not vertical esc until the API enforces nothing.
Report language cheat sheet
- Horizontal → “Broken object-level authorization / IDOR between users A and B”
- Vertical → “Broken function-level authorization / role escalation to admin”
Cite OWASP ASVS access-control chapters or CWE-269 when helpful. Spell out the before/after role and the exact request.
Severity instincts
Horizontal PII read across tenants can outrank a weak vertical bug that only reveals a harmless admin banner. Match impact to data and actions, not the vocabulary.
I label every authorization finding horizontal or vertical in the first sentence. Triagers parse it faster, and I stop arguing with myself mid-report about what I actually proved.