Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#1504 closed defect (invalid)

Redirect issue when equaling $request_uri and $uri with unicode characters

Reported by: insekticid@… Owned by:
Priority: major Milestone:
Component: nginx-core Version: 1.13.x
Keywords: Cc:
uname -a: Linux 541bb2841bf8 4.9.60-linuxkit-aufs #1 SMP Mon Nov 6 16:00:12 UTC 2017 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.13.9

Description

Nginx version: nginx:latest from docker (v1.13, tested in 1.12 too)

server {
    #root /var/www/html/public;
    
    location / {
        set $test_uri https://$host$request_uri;
        if ($test_uri != https://$host$uri) {
            #rewrite ^ $scheme://$host$uri$is_args$args? permanent;
            rewrite ^ http://test?uri=$uri&request_uri=$request_uri&test_uri=$test_uri;
        }
        
        root   /usr/share/nginx/html;
        index  index.html index.htm;

    }
}

  • curl -I http://localhost:8081/čřčžřčž
  • you get http://test/?uri=/%C4%8D%C5%99%C4%8D%C5%BE%C5%99%C4%8D%C5%BE&request_uri=/%C4%8D%C5%99%C4%8D%C5%BE%C5%99%C4%8D%C5%BE&test_uri=https://localhost/%C4%8D%C5%99%C4%8D%C5%BE%C5%99%C4%8D%C5%BE

https://github.com/insekticid/nginx-redirect-bug

Attachments (1)

nginx-redirect-unicode-bug.png (78.8 KB ) - added by insekticid@… 3 years ago.

Download all attachments as: .zip

Change History (9)

by insekticid@…, 3 years ago

comment:1 by insekticid@…, 3 years ago

the same problem with this config

server {
    #root /var/www/html/public;
    
    location / {
        set $test_uri https://$host$request_uri;
        set $test_uri2 https://$host$request_uri;
        if ($test_uri != test_uri2) {
            #rewrite ^ $scheme://$host$uri$is_args$args? permanent;
            rewrite ^ http://test?uri=$uri&request_uri=$request_uri&test_uri=$test_uri;
        }
        
        root   /usr/share/nginx/html;
        index  index.html index.htm;

    }
}

comment:2 by Maxim Dounin, 3 years ago

Resolution: invalid
Status: newclosed

It is not clear what are you trying to do, but the if directive when used with the = and != operators only allows comparing a variable with a string. As such, the condition used is always true, as you compare with the https://$host$uri static string.

comment:3 by insekticid@…, 3 years ago

this example will solve for example duplicates versions of urls
http://example.com/test//test2/ will make redirect to http://example.com/test/test2/

        set $test_uri $scheme://$host$request_uri;
        if ($test_uri != $scheme://$host$uri) {
            rewrite ^ $scheme://$host$uri$is_args$args? permanent;
        }

but
if your url contains nonASCI symbols like ůěščřžýáíé ... condition matcher will do infinite redirect because if (/%C4 != /%C4) => true
it is bug in equal condition matcher

Last edited 3 years ago by insekticid@… (previous) (diff)

comment:4 by insekticid@…, 3 years ago

Resolution: invalid
Status: closedreopened

comment:5 by Maxim Dounin, 3 years ago

Resolution: invalid
Status: reopenedclosed

Ah, I was actually wrong: the second operand of != can contain variables, hence the test actually works.

You misunderstand the difference between $uri and $request_uri though. Among other things, $uri is unescaped, hence it is never equal to $request_uri if the latter contains any escaped characters. This is obvious if you'll actually try to use curl with an actual escaped URL and the configuration you've provided:

$ curl -I http://127.0.0.1:8080/%C4%8D
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.13.10
Date: Tue, 13 Mar 2018 02:46:40 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: http://test?uri=/č&request_uri=/%C4%8D&test_uri=https://127.0.0.1/%C4%8D

Note that unescaped non-ASCII characters are not permitted in URIs, and browsers will escape them automatically, confusing things.

comment:6 by insekticid@…, 3 years ago

and what about this forgotten? patch 5years ago?

http://nginx.2469901.n2.nabble.com/ngx-unescape-uri-bug-td7584520.html

I think there should be 2 variables for $uri: $uri_escaped and $uri_unescaped

in reply to:  6 comment:7 by Maxim Dounin, 3 years ago

Replying to insekticid@…:

and what about this forgotten? patch 5years ago?

http://nginx.2469901.n2.nabble.com/ngx-unescape-uri-bug-td7584520.html

The "patch" in question doesn't really make sense - see my response there. And, more importantly, it is completely unrelated to your case, as the ngx_unescape_uri() function is not used to unescape request URIs, it happens in the ngx_http_parse_complex_uri() function (and it rejects invalid escaping).

I think there should be 2 variables for $uri: $uri_escaped and $uri_unescaped

See ticket #52.

comment:8 by insekticid@…, 3 years ago

Ok, understand. Thanks for your time

Note: See TracTickets for help on using tickets.