#2225 closed enhancement (wontfix)
location-matching on undecoded paths
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-core | Version: | 1.18.x |
Keywords: | location encoding decoding | Cc: | |
uname -a: | Linux nb-sbreunig 5.8.0-63-generic #71~20.04.1-Ubuntu SMP Thu Jul 15 17:46:08 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux | ||
nginx -V: |
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 1.1.1f 31 Mar 2020 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-KTLRnK/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module |
Description
Dear devs,
is there a way to configure nginx to location-match on undecoded URLs? Ideally matching on "only semantically" decoded URLs would be possible. Currently, nginx decodes (and compresses) everything, including characters that change the semantics of the URL. For example this nginx configuration
location /aaa { return 412; } location /bbb { return 411; }
will return 411 on this curl:
curl -vs localhost/aaa%2f..%2fbbb
The RFCs I found recommend treating these reserved characters specially if they change the semantics, but I can see how this would fail in many real world use cases. My use case is preventing directory traversal on a non-public nginx in a "security in depth" fashion.
A potential workaround is matching on $request_uri, but it is rather brittle to regex-match on an URL like that, plus it's of course much less performant:
if ($request_uri ~* "^[^?#]*%2F") { return 405; }
Is there a better solution?
For completeness, the RFCs I am referring to:
https://www.rfc-editor.org/rfc/rfc3986.html#section-2.4
https://www.rfc-editor.org/rfc/rfc2616.html#section-3.2.3
https://www.rfc-editor.org/rfc/rfc2396.html#section-2.2
Thanks
Stefan
Change History (2)
comment:1 by , 3 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
comment:2 by , 22 months ago
I've submitted a patch for a new configuration option called uri_normalization_percent_decode
which should address this issue.
The option has two values: "all" and "all-except-reserved". "all" is the default value and is the current behaviour. When the option is set to "all-except-reserved", nginx percent-decodes all characters except those in the reserved set. In addition, when "all-except-reserved" is used, nginx will not re-encode "%" from the request URI when it observes that it is part of a percent-encoded reserved character.
This allows you to location match on /
and %2f
separately.
There is no concept of the "only semantical" decoding in nginx. Rather, it provides a way to fully decode URLs matching typical filesystem semantics, and does location matching based on this decoded URI. If that's not enough for some reason, the
$request_uri
can be used to inspect the original URI as sent by the client.In your particular use case there seems to be two basic options:
%2f
as in the snippet you've provided.Note though that both approaches might break valid requests. See also ticket #786, which is somewhat relevant.