Broken Access Control: The Complete Practical Guide

Platform Misconfiguration: Header and Method Bypass

Slipping past access gates at the platform layer: X-Original-URL and X-Rewrite-URL path overrides, HTTP method tampering, and X-Forwarded-For source-IP trust.

Published

Sometimes the application's own authorization is fine, but the gate in front of it can be fooled. Proxies, gateways, and framework routers make assumptions about which path, which method, or which source a request represents, and those assumptions can be rewritten with a header or a verb. When the gate and the app disagree about your request, you walk through the gap.

Gates that check only path or method

Platform-level access control is often a coarse rule: "block /admin," or "only allow GET here." These rules are brittle because they gate on one property of the request, and that property can be changed or interpreted differently downstream. Your job is to find what the gate keys on, then change that specific thing.

Header overrides that rewrite the routed path

Some frameworks and proxies let a request header override the path the application routes on. A front proxy blocks /admin by inspecting the request line, but the back end honours an override header and routes elsewhere:

GET /public HTTP/1.1
X-Original-URL: /admin
 
GET /public HTTP/1.1
X-Rewrite-URL: /admin

The proxy sees GET /public and allows it, while the application sees the header and serves /admin. The two layers disagree, and the disagreement is the bypass.

HTTP method and verb tampering

When a rule blocks one verb, try the others the route still accepts:

# GET /admin/delete?id=5 is blocked -> try another verb on the same route
POST   /admin/delete?id=5
DELETE /api/users/52
PATCH  /api/users/52    {"role":"admin"}

Frameworks that read a method-override header or body field will treat a plain POST as something stronger:

X-HTTP-Method-Override: DELETE
X-Method-Override: PUT
_method=DELETE            (form/body override in some frameworks)

Also try verbs a gate may not cover at all, like HEAD, OPTIONS, or TRACE.

Case and trailing-slash quirks at the proxy

A proxy and an app can normalize URLs differently, so /admin, /admin/, and /Admin may be treated as different by the gate but the same by the app. That whole family of mismatches has its own spoke, URL-matching discrepancies, because it is a rich enough topic on its own.

Source-IP trust via X-Forwarded-For

Internal-only admin panels are often gated on the client IP, trusting that only internal traffic reaches them. When the app reads the client IP from a header a proxy is supposed to set, you can set it yourself:

X-Forwarded-For: 127.0.0.1
X-Real-IP: 127.0.0.1
X-Forwarded-For: 10.0.0.1
True-Client-IP: 127.0.0.1

If the gate believes you are coming from localhost or an internal range, it lets you into the panel it thought only insiders could reach.

The common thread

Every bypass here comes from the same root: a gate that trusts a property of the request the client can control (a header, a method, a spoofed IP) instead of enforcing authorization on the server against the authenticated identity. Defensively, normalize and authorize at the same layer that serves the resource, and never trust X-Original-URL, X-Forwarded-For, or a method-override from the client. Test these bypasses on a free live target.

← Back to Broken Access Control: The Complete Practical Guide