Broken Access Control: The Complete Practical Guide
URL-Matching Discrepancies in Access Control
Bypassing access gates when the gate and the app normalize URLs differently: trailing slashes, dot-segments, encoded dots, case, and matrix params.
Published
Sometimes the gate and the application agree on authorization but disagree on what URL you requested. A proxy blocks /admin, but it compares the raw path while the app canonicalizes it, so a slightly different spelling sails past the gate and still resolves to the protected route. These bypasses are pure string-normalization mismatches, and they are everywhere there is a proxy in front of a framework.
When the gate and the app normalize differently
Access rules at a gateway typically match the request path against a list. The weakness is that the gateway and the back-end router rarely canonicalize URLs identically. The gate sees one string and allows it, and the app rewrites that string into the canonical path and serves the resource the gate meant to block. Your job is to find a spelling the two layers read differently.
Trailing slash and dot-segments
The simplest variants change the path shape without changing where it resolves:
/admin vs /admin/ (trailing slash)
/admin vs /admin/. (current-dir segment)
/admin vs /./admin (leading dot-segment)
/admin/users vs /admin/../admin/usersA gate matching the exact string /admin may not match /admin/. while the app collapses it right back to /admin.
Encoded dots and double-encoding
Percent-encoding the dots, or encoding twice, hides the dot-segments from a gate that does not decode before matching:
/%2e/admin (%2e is an encoded ".")
/admin%2f..%2fadmin (encoded slashes hide the traversal)
/%252e/admin (double-encoded ".")If the gate matches on the still-encoded string and the app decodes before routing, the two see different paths.
Case sensitivity mismatches
URL path matching is case-sensitive in some layers and not others:
/admin vs /Admin vs /ADMINA gate that blocks lowercase /admin may allow /Admin, while a case-insensitive router sends it to the same handler.
Path parameters and matrix params
Matrix parameters (a ; segment in the path) and extra path parameters can change what the gate matches without changing the route:
/admin;foo /admin;jsessionid=1/users
/admin/..;/ (dot-segment plus matrix separator)Some routers strip the ; portion when resolving, so /admin;foo runs the /admin handler while the gate saw a different string.
Extension tricks
Static-file handling and route matching can diverge on extensions:
/admin vs /admin.json vs /admin;.cssA gate that only protects extensionless /admin, or that treats anything ending in .css as a public static file, may let /admin.json or /admin;.css through to a handler that still serves admin content.
The fix and the mindset
The defense is singular: normalize the URL to its canonical form once, and perform the authorization check at the same layer and on the same canonical path that actually serves the resource. Never let a proxy match a raw string that the app will later rewrite. As an attacker, treat a blocked path as a challenge to re-spell, and work through the variants above until the response flips from blocked to served. When the gate instead trusts a header or the request method, see platform misconfiguration. Practice the variants on a free live target.
← Back to Broken Access Control: The Complete Practical Guide