16 - 注意事項

 

 


Off-By-Slash

 

i.e.

location /api {
        proxy_pass http://apiserver/v1/;
}

request

http://server/api/user -> http://apiserver/v1//user

/../

# Nginx normalize "/v1/../" to "/"

http://server/api../ -> http://apiserver/v1/../ -> http://apiserver/

風險

Apache server-status being exposed with the URL http://server/api../server-status

Checking

http://server/api/user -> http://apiserver/v1//user

http://server/apiuser -> http://apiserver/v1/user

 


Missing "root" location on "server {...}" block

 

If you add a root to every location block then a location block that isn’t matched will have no root.

server {
    server_name www.example.com;
    location / {
        root /var/www/nginx-default/;
        # [...]
      }
    location /foo {
        root /var/www/nginx-default/;
        # [...]
    }
}

 


Server Name (If)

 

Since you’re requesting NGINX to check for the Host header for every request, it’s extremely inefficient.

server {
    server_name example.com *.example.com;
        if ($host ~* ^www\.(.+)) {
            set $raw_domain $1;
            rewrite ^/(.*)$ $raw_domain/$1 permanent;
        }
        # [...]
    }
}

建議做法

server {
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}
server {
    server_name example.com;
    # [...]
}

 


Incorrect return context

 

The return directive applies only inside the topmost context it’s defined in.

A request to /a/test.html will return a 301.

server {
    location /a/ {
        try_files test.html =404;
    }
    return 301 http://example.org;
}

 


Passing Uncontrolled Requests to PHP

 

[1] Proxy Everything

server {
    server_name _;
    root /var/www/site;
    location / {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}

[2]

當 non-exist.php 不存在時, php 會嘗試執行 exist.jpg

location ~* \.php$ {
    #/forum/avatar/exist.jpg/non-exist.php
    fastcgi_pass backend;
    ...
}

php setting

Set cgi.fix_pathinfo=0 in php.ini.

This causes the PHP interpreter to only try the literal path given and to stop processing if the file is not found.

i.e.

http://example.com/path/to/script.php/THIS/IS/PATH/INFO?query_args=foo

SCRIPT_FILENAME gets "/path/to/script.php"
PATH_INFO gets "/THIS/IS/PATH/INFO"
QUERY_STRING gets "query_args=foo"

cgi.fix_pathinfo=1

設置完整的路徑信息PATH_TRANSLATED的值為SCRIPT_FILENAME,並且設置PATH_INFO信息

Another Fix

security.limit_extensions = .php

[3] SCRIPT_NAME

Setting

location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
}

GET /index.php/<script>alert(1)</script>/index.php

SCRIPT_NAME  =  /index.php/<script>alert(1)</script>/index.php

[Fix]

1. $request_filename

Use $request_filename instead of $document_root$fastcgi_script_name.

2. cgi.fix_pathinfo=0 in php.ini

cgi.fix_pathinfo

3. try_files

location ~* \.php$ {
    try_files $uri =404;
    fastcgi_pass backend;
    # [...]
}

4. Ensure that NGINX only passes specific PHP files for execution:

location ~* (file_a|file_b|file_c)\.php$ {
    fastcgi_pass backend;
    # [...]
}

 


"try_files $uri" directive with "alias"