Access Control Testing
Access control testing confirms whether the application enforces authorization on every request. Authentication proves who you are. Authorization decides what you can do. A working login means nothing if the server hands over resources it should deny.
The core tests:
Vertical privilege escalation: accessing admin functions as a regular user
Horizontal privilege escalation: accessing another user's data at the same privilege level
Method-based bypass: switching HTTP methods to skip access checks
Referer-based bypass: spoofing the Referer header to pass weak checks
Multi-step access control: skipping to a later step that lacks its own authorization check
Vertical Privilege Escalation
Vertical escalation means a low-privilege user reaching admin-level functions. Start by browsing the application as a regular user and collecting every URL, then request admin endpoints directly. Many applications hide the link but serve the page to anyone who requests it.
HTTP/1.1 200 OK ... <h1>Admin Dashboard</h1>
Explain command
| -sk | Silent mode, skip TLS certificate verification. |
| -H 'Cookie: ...' | Send the session cookie for an authenticated low-privilege user. |
A 200 with admin content means no server-side role check on this endpoint. A 403 or redirect to login is correct behavior. Check other admin paths too: /admin/users, /admin/settings, /admin/logs, /management, /console.
Some applications use request parameters or hidden fields to determine the user's role. Look for parameters like admin=true, role=admin, or access_level=1 in the request:
Try injecting role parameters in GET, POST, and JSON bodies. If the application updates your session or returns elevated content, the role assignment is client-controllable.
Horizontal Privilege Escalation
Horizontal escalation is accessing data belonging to another user at the same privilege level. The mechanism is the same as IDOR: change an identifier in the request and check if the server returns another user's data.
For in-depth testing of identifier tampering across endpoints, see IDOR testing by parameter tampering. For turning a confirmed IDOR into full data extraction or account takeover, see IDOR exploitation.
{"id":1002,"username":"victim","email":"victim@corp.local"}
Getting back user 1002's profile while authenticated as user 1001 confirms the server is not scoping queries to the session owner. Look for this in profile endpoints, order history, messages, download links, and any request carrying a user identifier.
Horizontal to Vertical Escalation
Horizontal access can become vertical when you discover an admin account through enumeration. If the application does not restrict which user IDs you can reference, iterate through IDs until you find an admin account, then use a state-changing function against it.
ID 1: admin administrator ID 2: john user ID 3: sarah user ID 4: mike moderator
Once you know the admin's ID, target a function that changes account state. A password reset or email change against the admin account gives you full control:
{"status":"success","message":"Password updated"}
If the password change succeeds against the admin account, this is full vertical escalation from a horizontal access control flaw.
Method-Based Access Control Bypass
Some frameworks apply access control rules only to specific HTTP methods. An endpoint locked down for POST might be wide open for GET, PUT, or PATCH. Additionally, certain middleware and reverse proxies honor method override headers that let you bypass front-end routing entirely.
HTTP/1.1 403 Forbidden
POST is blocked. Try overriding the method:
Some reverse proxies and frameworks use X-Original-URL or X-Rewrite-URL to route requests internally. If the front-end proxy denies /admin but passes the override header to the backend, the backend processes the restricted path:
Also try different HTTP methods directly. An endpoint that blocks GET might accept PUT or PATCH:
GET: 403 POST: 403 PUT: 200 PATCH: 200 DELETE: 403
A 200 on PUT or PATCH while other methods return 403 confirms the access control rule does not cover all methods.
Referer-Based Access Control
Weak implementations check only the Referer header to decide if a request is authorized. If the admin page at /admin is access-controlled but a sub-function only checks that the Referer contains /admin, you can spoof the header:
{"status":"success","message":"User deleted"}
The Referer header is fully client-controlled. Any access check that relies on it alone is trivially bypassable.
Multi-Step Access Control
Some applications enforce authorization only on the first step of a multi-step process. For example, step one of an admin function checks your role, but steps two and three assume you would not have reached them without passing step one. Skip directly to a later step to test this:
{"status":"success","message":"Role updated to admin"}
If the final step processes the request without re-validating the caller's role, the entire multi-step flow is compromised. Look for hidden form fields, CSRF tokens, or step identifiers that indicate multi-step workflows in the application.
References
-
PortSwigger - Access Control VulnerabilitiesTOOL: PortSwigger - Access Control Vulnerabilities, portswigger.net/web-security/access-control (opens in new tab)
Covers vertical and horizontal escalation, IDOR, and method-based bypasses with labs.
-
OWASP Testing Guide - Authorization TestingLINK: OWASP Testing Guide - Authorization Testing, owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing (opens in new tab)
Authorization testing methodology from the OWASP Web Security Testing Guide.
-
OWASP Top 10 - Broken Access ControlLINK: OWASP Top 10 - Broken Access Control, owasp.org/Top10/A01_2021-Broken_Access_Control (opens in new tab)
A01:2021, the top web application security risk.