
Introduction
Privilege escalation is the process by which an attacker (or a legitimate tester, in the context of authorized security assessments) gains access to resources, functions, or data that should be restricted to a different user or role. It’s one of the most consistently exploited weaknesses in modern applications and infrastructure, and it appears in nearly every category of security assessment — from web application penetration tests to cloud misconfiguration reviews to Active Directory attack paths.
Privilege escalation is typically split into two categories: horizontal and vertical. Understanding the distinction is essential not just for finding these bugs, but for communicating impact clearly in a report — the difference between “user A can see user B’s invoices” and “a standard user can become a domain admin” is the difference between a medium and a critical finding.
Horizontal Privilege Escalation
Horizontal privilege escalation occurs when a user gains access to the resources or functions of another user at the same privilege level. No elevation of role occurs — the attacker isn’t becoming an admin — but they are stepping outside their own authorization boundary to access someone else’s data or actions.
Common Causes
- Insecure Direct Object References (IDOR): An endpoint like GET /api/orders/1042 returns order data without verifying that the requesting user actually owns order 1042. Simply incrementing or guessing the ID exposes another user’s data.
- Missing object-level authorization checks: The application checks authentication (is this a valid session?) but not authorization (does this session own this specific resource?).
- Predictable identifiers: Sequential IDs, unhashed UUIDs derived from predictable seeds, or reused tokens make it trivial to enumerate other users’ resources.
- Broken session or token scoping: A JWT or API token that doesn’t properly bind to a specific user’s resource scope can be replayed against a different user’s endpoint.
Example
A SaaS billing platform exposes:
GET /invoices/{invoice_id}If the backend only checks that the requester is logged in — not that invoice_id belongs to that account — then any authenticated customer can enumerate invoice_id values and read other customers’ billing details. This is a textbook IDOR-driven horizontal escalation.
Real-World Relevance
Horizontal escalation is extremely common in bug bounty programs because it’s often the fastest path to a valid, reproducible finding: create two test accounts, perform an action as account A, replay the request with account B’s session token or swap out the object ID, and observe whether access is granted. Programs on platforms like Intigriti and HackerOne see a steady stream of these, particularly in multi-tenant SaaS products where tenant isolation wasn’t rigorously enforced at the data-access layer.
Vertical Privilege Escalation
Vertical privilege escalation occurs when a user or process gains access to a higher privilege level than they were originally granted — a standard user becoming an administrator, a low-privileged service account gaining root, or a read-only role gaining write/delete capabilities.
Common Causes
- Broken function-level authorization: Admin-only endpoints (e.g., /admin/users/delete) are reachable by any authenticated user because the server only checks the frontend UI, not the backend permission on the request itself.
- Misconfigured role-based access control (RBAC): Overly permissive default roles, or roles that inherit permissions they shouldn’t (a common issue in AWS IAM policies and Kubernetes RBAC).
- Kernel and OS-level exploits: Local privilege escalation (LPE) via unpatched kernel vulnerabilities, misconfigured SUID binaries, writable service paths, or scheduled tasks running as SYSTEM/root but editable by low-privileged users.
- Credential and token mismanagement: Leaked service account credentials, overly broad API keys, or improperly scoped OAuth tokens that grant more access than the calling context requires.
- Active Directory misconfigurations: Kerberoasting, unconstrained delegation, ACL abuse (e.g., GenericAll on a privileged object), or exploitable trust relationships that let a standard domain user pivot to domain admin.
Example
A web application exposes an internal endpoint:
POST /api/admin/promote-user
which is only hidden from the UI for non-admin users, but not actually protected server-side by a role check. A standard authenticated user who discovers this endpoint (via JS bundle inspection, API documentation leakage, or simple guessing) can call it directly and elevate their own account to administrator — a clear vertical escalation.
On the infrastructure side, a classic example is a misconfigured cron job on a Linux host that runs as root but executes a script writable by a low-privileged user. Editing that script grants root-equivalent code execution — no application logic involved, purely an OS-level trust misconfiguration.
Why the Distinction Matters
Beyond severity scoring, the distinction shapes remediation guidance. Horizontal issues are almost always fixed by enforcing object-level authorization — verifying not just who is asking, but what they’re allowed to touch. Vertical issues require enforcing function-level authorization and hardening privilege boundaries at the OS, cloud IAM, or application-role level.
It’s also worth noting that these categories aren’t mutually exclusive in a real attack chain. A common real-world pattern is a horizontal-to-vertical pivot: an attacker first moves laterally between peer accounts (horizontal) to find one with slightly broader access or a stored credential, then uses that foothold to escalate vertically into an administrative or system-level context.
Detection and Testing Methodology
When assessing an application or environment for privilege escalation issues, a structured approach helps ensure coverage of both categories:
- Map the authorization model. Understand roles, tenants, and resource ownership before testing. You can’t test for broken authorization until you know what “correct” authorization looks like.
- Test horizontally first. Create two or more accounts at the same privilege level. Attempt to access, modify, or delete each other’s resources by manipulating IDs, tokens, and parameters.
- Test vertically. Attempt to reach higher-privilege functionality directly — via direct URL/API access, parameter pollution (e.g., adding “role”:”admin” to a registration request), or JWT claim tampering.
- Fuzz for hidden endpoints. Review JS bundles, API specs (Swagger/OpenAPI), and mobile app binaries for endpoints not exposed in the standard UI.
- Check the underlying infrastructure. For vertical escalation beyond the application layer, review IAM policies, SUID binaries, writable cron jobs/services, container escape vectors, and AD ACL misconfigurations.
- Automate where possible. Tools like Autorize (Burp extension) and custom scripts can systematically replay authenticated requests across different user contexts to catch authorization gaps at scale.
Mitigation Best Practices
- Enforce authorization checks server-side, on every request, for both object ownership (horizontal) and role/function (vertical) — never rely on the client or UI to hide unauthorized actions.
- Use indirect object references (opaque, non-sequential identifiers) where feasible, combined with ownership checks regardless.
- Apply the principle of least privilege consistently across application roles, cloud IAM policies, and OS-level service accounts.
- Regularly audit RBAC configurations and Active Directory ACLs for privilege creep and unintended inheritance.
- Patch and harden the OS/kernel layer against known LPE vectors, and audit SUID binaries, writable service paths, and scheduled tasks.
- Log and monitor for anomalous privilege changes or repeated authorization failures, which often precede successful escalation attempts.
Conclusion
Horizontal and vertical privilege escalation represent two distinct but related failure modes in access control: one breaks isolation between peers, the other breaks the hierarchy of privilege itself. Both stem from the same underlying principle — access control decisions must be enforced authoritatively on the server side, checked against both resource ownership and role, on every single request. Recognizing which category a finding falls into isn’t just an academic exercise; it directly informs severity, remediation, and how a broader attack chain might unfold from a single initial foothold.