I'd like to disable directory traversal like example.com/page/../other-page
(even to real pages) in my IIS website. I've tried Request Filtering and URL Rewrites with a custom response.
The Microsoft documentation on the denyUrlSequences
part of Request Filtering actually uses ..
as an example:
The following example
Web.config
file will deny access to three URL sequences. The first sequence prevents directory traversal, […]<configuration> <system.webServer> <security> <requestFiltering> <denyUrlSequences> <add sequence=".." /> [...]
…but it doesn't work; example.com/page/../other-page
has already become example.com/other-page
before the Deny rule ever runs. You can prove this by setting a Deny rule for page/sub
and visiting example.com/page/./sub-page
. The normalized path is blocked by the rule, but it wouldn't have matched in the original state.
I've tested this on IIS v7.5 and v10, and I imagine it exists in each intervening version, too.
- What is doing the normalization? (Probably this library?)
- When does it happen in the request lifecycle?
- How do I successfully block the following sequences without opening up some security hole?
..
,./
, and//
Internet searches only want to tell me about a circa-2000 vulnerability in an old version of IIS, or how to enable MVC routes with dots in them.
Debug note: If you use curl
to test this behavior, make sure to add the --path-as-is
option, so it doesn't do the normalization in the client. Some browsers also appear to be doing client-side normalization.
Usage note: I'm nominally trying to shut down example.com/clubs-baby-seals/../about-us
lest someone take the link's successful load as an endorsement of seal mistreatment.