Opened 12 years ago
Last modified 5 years ago
#348 accepted defect
Excessive urlencode in if-set
Reported by: | Petr Messner | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-core | Version: | |
Keywords: | rewrite | Cc: | |
uname -a: | Darwin messamac.local 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64 | ||
nginx -V: |
nginx version: nginx/1.4.0
configure arguments: --prefix=/opt/local --with-cc-opt='-I/opt/local/include -O2' --with-ld-opt=-L/opt/local/lib --conf-path=/opt/local/etc/nginx/nginx.conf --error-log-path=/opt/local/var/log/nginx/error.log --http-log-path=/opt/local/var/log/nginx/access.log --pid-path=/opt/local/var/run/nginx/nginx.pid --lock-path=/opt/local/var/run/nginx/nginx.lock --http-client-body-temp-path=/opt/local/var/run/nginx/client_body_temp --http-proxy-temp-path=/opt/local/var/run/nginx/proxy_temp --http-fastcgi-temp-path=/opt/local/var/run/nginx/fastcgi_temp --http-uwsgi-temp-path=/opt/local/var/run/nginx/uwsgi_temp --with-ipv6 |
Description
Hello,
I had setup Apache with mod_dav_svn behind nginx acting as front-end proxy and while commiting a copied file with brackets ([]) in filename into that subversion I found a bug in nginx.
How to reproduce it (configuration file is as simple as possible while still causing the bug):
$ cat nginx.conf error_log stderr debug; pid nginx.pid; events { worker_connections 1024; } http { access_log access.log; server { listen 8000; server_name localhost; location / { set $fixed_destination $http_destination; if ( $http_destination ~* ^(.*)$ ) { set $fixed_destination $1; } proxy_set_header Destination $fixed_destination; proxy_pass http://127.0.0.1:8010; } } } $ nginx -p $PWD -c nginx.conf -g 'daemon off;' ...
In second terminal window:
$ nc -l 8010
In third terminal window:
$ curl --verbose --header 'Destination: http://localhost:4000/foo%5Bbar%5D.txt' '0:8000/%41.txt' * About to connect() to 0 port 8000 (#0) * Trying 0.0.0.0... * Adding handle: conn: 0x7fa91b00b600 * Adding handle: send: 0 * Adding handle: recv: 0 * Curl_addHandleToPipeline: length: 1 * - Conn 0 (0x7fa91b00b600) send_pipe: 1, recv_pipe: 0 * Connected to 0 (0.0.0.0) port 8000 (#0) > GET /%41.txt HTTP/1.1 > User-Agent: curl/7.30.0 > Host: 0:8000 > Accept: */* > Destination: http://localhost:4000/foo%5Bbar%5D.txt >
Back in the second terminal window:
($ nc -l 8010) GET /%41.txt HTTP/1.0 Destination: http://localhost:4000/foo%255Bbar%255D.txt Host: 127.0.0.1:8010 Connection: close User-Agent: curl/7.30.0 Accept: */*
The problem is that the Destination header was changed from ...foo%5Bbar%5D.txt
to ...foo%255Bbar%255D.txt
. This happens only when
- that
if ( $http_destination ~* ^(.*)$ )
is processed - and URL (HTTP GET URL, not that Destination URL) also contains urlencoded (%41) character(s).
In other cases (URL does not contain urlencoded character or that if
is not matched) the Destination header is proxy_passed untouched, which is expected behavior.
Note: Why do I need that if ( $http_destination ~* ^(.*)$ )
? In this example it is simplified, but for that Subversion setup I have mentioned I need to rewrite the Destination from https to http when nginx proxy_passes from https to Apache over http.
This bug also happens on nginx/0.7.67 in Debian Squeeze.
Looks like unexpected urlencode happens in "set $fixed_destination $1;", much like during rewrite handling. As a quick workaround named captures should work.
Needs additional investigation, see also ticket #52.