nginx misbehaviour in conjunction with non-ASCII characters
Ruslan Ermilov
ru at nginx.com
Thu Dec 19 09:11:40 UTC 2013
On Wed, Dec 18, 2013 at 06:27:31PM -0500, ako673de wrote:
> Found a bug in implementation of MOVE and COPY (webdav) methods. It happens
> if destination header contains non-ASCII characters (that need to be escaped
> with "%").
>
> An example:
>
> Rename (=MOVE) file "<www-root>/TheCore.ogm" to "<www-root>/The_Core.ogm":
>
> Request header:
> --> MOVE http://andinas/TheCore.ogm HTTP/1.1
> --> Destination: http://andinas/The_Core.ogm
> Response header:
> --> HTTP/1.1 204 No Content
> --> Server: nginx/1.5.6
> Result: File renamed to "The_Core.ogm". Fine!
>
> Now rename (=MOVE) file "<www-root>/andinas/The_Core.ogm" to
> "<www-root>/andinas/The_ Core.ogm" (notice the blank after the underscore,
> but the same is true for äöüß and the like!):
>
> Request header:
> --> MOVE http://andinas/The_Core.ogm HTTP/1.1
> --> Destination: http://andinas/The_%20Core.ogm
> Response header:
> --> HTTP/1.1 204 No Content
> --> Server: nginx/1.5.6
> Result: File renamed to "The_%20Core.ogm". Not so fine!
>
> The escaped blank is treated by nginx MOVE as if it was not escaped!
I have a patch for that, would you like to try it?
> Found a similar issue with this config-file line:
> --> if ( $http_destination ~ https?://[^/]+/(.*) ) { set $httpdest
> http://localhost:8008/$remote_user/$1; }
>
> (for this (working!) code that makes the destination header ready for
> proxy_pass to another webdav server with user dependent base folders
> (pyWebDav allows only one user :-/):
> --> proxy_set_header Destination $httpdest;
> --> proxy_pass http://127.0.0.1:8008/$remote_user$request_uri;
> ).
>
> Here again, if $http_destination contains the perfectly correct escaped
> characters from the webdav client, the resulting $httpdest will additionally
> escape the "escape" characters.
> Example:
> Destination File = "<www-root>/The_ Core.ogm"
> $http_destination = "http://andinas/The_%20Core.ogm" (correct)
> $httpdest = "http://andinas/The_%2520Core.ogm" (wrong!)
>
> Obviously here the highly undesirable transformation happens during the
> regex matching. But why? Can I switch that off somehow?
>
> Workaround: Use perl function to replace "%25" by "%". Use the undocumented
> "r->variable()" for that!
Don't use rewrite. nginx's DAV module supports relative URLs.
Using the following config snippet:
http {
server {
listen 8000;
location / {
proxy_set_header Destination /$http_user$http_destination;
proxy_pass http://127.0.0.1:8001/$http_user$request_uri;
}
}
}
and the following request:
printf 'MOVE /foo%%20bar HTTP/1.1\r\nDestination: /bar%%20baz\r\nHost: 127.0.0.1\r\nUser: nobody\r\n\r\n' | nc 127.0.0.1 8000
I get:
$ nc -l 8001
MOVE /nobody/foo%20bar HTTP/1.0
Destination: /nobody/bar%20baz
Host: 127.0.0.1:8001
Connection: close
User: nobody
> If you are still reading :-): There are two very funny things about the
> --> proxy_pass http://127.0.0.1:8008/$remote_user$request_uri;
> line:
> 1) You cannot use localhost here. nginx needs a resolver as soon as there is
> a variable in the string. And at least I didn't manage to find a resolver
> that can resolve localhost.
> 2) Nowhere on the internet it's been said, that you need to add $request_uri
> to that line, but you do need! And it even must not be $uri, because that
> one has the same escaping issues like the other things I mentioned above.
>
>
> OK, now I'm done ;-). Please help!
>
> best regards
> ako673de
More information about the nginx
mailing list