Search code examples
securitynginxurlreverse-proxydirectory-traversal

why nginx do not deny request when semicolon is in url?


I have a nginx.conf as follows:

server {
    listen 443 ssl;
    # some other ssl config

    server_name home.aaa.com;

    # some access_log and error_log config

    location /actuator/ {
        allow 10.1.1.0/24;
        deny all;
        proxy_pass http://10.1.1.1:8989;
    }   

    location / {
        proxy_pass http://10.1.1.1:8989;
    }   
}

When I access https://home.aaa.com/actuator/prometheus, nginx deny this request and return 403, this is what I expect.

When I access https://home.aaa.com/actuator/prometheus;%2f..%2f..//, nginx output a new line in access.log:

1.203.146.132 - - [15/Jan/2024:11:00:55 +0800] "GET /actuator/prometheus;%2f..%2f..// HTTP/1.1" 200 7889841 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0" "-" https "home.aaa.com" "1.025" "0.270" "10.1.1.1:8989"

and there is not a log in nginx error_log. But I expect nginx deny this request too.

I do not know why the second request was proxied to the backend server, and how can I debug this issue?

Thanks!


Solution

  • The url https://home.aaa.com/actuator/prometheus;%2f..%2f..// after url decode is https://home.aaa.com/actuator/prometheus;/../..//. Which will in the nginx $uri valable will be /. Then it not match the location /actuator/.

    Here is the illustration,

    #nginx config
    location /actuator/ {
         return 403 $uri;
    }   
    
    location / {
        return 200 $uri;
    }
    

    And the curl result

    $ curl -sS 'xxxx/actuator/prometheus;%2f..%2f..//'
    /
    
    $ curl -sS 'xxxx/actuator/prometheus'
    /actuator/prometheus