Security Glossary

Vertical Privilege Escalation

An access control vulnerability where a user gains a higher privilege level than their account should have, such as a regular user reaching administrator functions.

Vertical Privilege Escalation occurs when a user gains a higher privilege level than their account should have, such as a regular user reaching administrator functionality. This is the axis that distinguishes it from horizontal escalation, where the attacker stays at the same privilege level but reaches a peer's data.

How It Works

The application decides what a user may do based on a value it fails to re-verify: a role in the request, a claim in a token, or nothing more than the client not being shown the admin UI. Attackers reach privileged functions by hitting the endpoint directly, editing a role field, or replaying a token whose elevated claims were never invalidated.

Example

// Admin endpoint with no server-side role check
GET /api/admin/delete-user/123     -- reachable by any authenticated user

// Role field trusted from the request body
POST /user/update
{"username": "attacker", "role": "admin"}

// Token still carries a stale role claim
Authorization: Bearer <jwt with "role":"admin" issued before demotion>

Common Attack Vectors

  • Direct access to admin URLs and APIs that only hide their links in the UI
  • Setting a role or permission field the server copies into the user record
  • Tampering with a JWT/session claim, or replaying an old token after a role change

Prevention

  • Re-check the required role on the server for every privileged endpoint, reading it from the user record, not from any request field. Hiding a link in the UI is not access control
  • Deny the request when the check is absent: an endpoint with no explicit authorization must fail closed, not default to allow
  • Re-issue the session and any JWT when a user's role changes, and reject tokens issued before the change, so a demoted user cannot keep acting on an old elevated claim
  • Keep role and permission attributes off the mass-assignable parameter list so role=admin in a request body is ignored

See Also