3

Is there any advantage using:

location ~ \.php {

                location ~ \..*/.*\.php$ {
                        return 403;
                }

                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_split_path_info ^(.+\.php)(/.*)$;
                include fastcgi_params;
                fastcgi_param  SCRIPT_FILENAME  $realpath_root$fastcgi_script_name;
                fastcgi_param DOCUMENT_ROOT $realpath_root;
                fastcgi_intercept_errors on;
        }

Compared to

location ~ \..*/.*\.php$ {
                        return 403;
                }

location ~ \.php {

                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_split_path_info ^(.+\.php)(/.*)$;
                include fastcgi_params;
                fastcgi_param  SCRIPT_FILENAME  $realpath_root$fastcgi_script_name;
                fastcgi_param DOCUMENT_ROOT $realpath_root;
                fastcgi_intercept_errors on;
        }

I would like to avoid arbitrary code execution that is shown here: https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#passing-uncontrolled-requests-to-php

In my simple browser test domain/somedir/file.jpg/1.php it returns 403 in both ways, but I'm still not sure if this is all security I need. Also, if there is any difference in "performance".

1
  • You could use something like Siege in benchmarking mode to work out if it makes a difference to performance. I suspect the performance of PHP will be so slow compared with Nginx rule evaluation that it will make little or no difference. If you benchmark I find running Siege on a different server more effective.
    – Tim
    Jan 11, 2016 at 1:24

1 Answer 1

2

I'm personally not a fan of the approach you outlined as you might end up with false positives if there's ever a dot in the actual URL of a .php file.

Generally there are three approaches to avoid instructing nginx to execute arbitrary files. I've listed them in my preferred order.

#1 is to configure PHP with cgi.fix_pathinfo set to 0. This will make sure that even if someone passes a URL of /uploads/avatar32.jpg/index.php then PHP will look for that file instead of trying to helpfully "fix" the path and execute /uploads/avatar32.jpg. If the full filepath is not found it will return the error "no input file specified" or "primary script unknown" depending on your version of PHP.

#2 is to have nginx test for the existence of an actual file and if not found then return 404. However, This will not work if you're using nginx as a reverse proxy/load balancer to your PHP servers. Your PHP location would end up looking like:

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

#3 is the blacklist approach which takes advantage of the fact that this vulnerability only works if the attacker can upload files to your server. So for instance if your user uploads go into /uploads/ then you would have a location specifically for that.

location /uploads {
    location ~ \.php$ {return 403;}
}
2
  • I've read also that FPM's limit_extensions is for preventing this also, do you know about it?
    – JorgeeFG
    Jan 11, 2016 at 13:11
  • In theory it could be used yes if it re-evaluates the extension after applying fix_pathinfo. Jan 11, 2016 at 13:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .