PHP files being downloaded on condition
Igor Sysoev
igor at sysoev.ru
Wed Aug 3 19:32:47 UTC 2011
On Tue, Aug 02, 2011 at 03:28:16AM -0400, Samael wrote:
> Igor, to cut things short - I'd like to either pass the PHP scripts'
> execution to the fcgi processes or prevent them from being downloaded.
>
> In addition, I tried to prevent PHP scripts in common
> webserver-writeable directories (of course, this list will be extended)
> from being executed in order not to allow user-provided PHP files to be
> passed to php-fpm:
>
> if ($uri ~*
> \/(images?|system|download|upload|cache|logs?)\/(.*\/)?[0-9a-z]+\.php$)
> {
> return 404;
> }
>
> I set this rule: "location ~ \/[0-9a-zA-Z]+\.php$" in order to evaluate
> only PHP files with alphanumeric names as these are the only one valid
> from my perspective. Of course the rule may be improved (not allowing a
> script beginning with a number to be evaluated), but I don't think that
> this is necessary at this point.
>
> "location ~ (/\.|.*conf.*\.php)" - in order to prevent hidden and
> configuration files from being exposed.
>
> I hope I didn't do anything stupid, I'm open to suggestions :)
>
> Edho, thank you for your advice, clearing the browser cache did the
> trick, but still - I'd like to prevent that happening again by somehow
> guarding the PHP scripts from being downloaded because of some
> configuration error, for example.
Any "if ($uri ~* ...)" construction means that it should
be replaced with "locaiton ~* ...".
As to regex locations I personally prefer to not use them at all
for several reasons, and to use only prefix locations, such as
location /download/ {
location /scripts/ {
I consider regex location usage only in legacy setups.
There are several ways to prevent execution of PHP in unexpected
places. 1st, the best one is to use prefix location:
location /scripts/ {
fastcgi_pass ...
fastcgi_param SCRIPT_FILENAME /www/site$uri;
}
then anything such /images, /download, /upload will be hanlded in other
locations as static files.
If you have to use regex, then you can set SCRIPT_FILENAME to directory
separated from user uploadable content:
location ~ \.php$ {
fastcgi_pass ...
fastcgi_param SCRIPT_FILENAME /www/site/scripts$uri;
}
If /download, /upload, etc will be in /www/site/download/,
/www/site/upload, then it will be impossible to execute
/www/site/upload/hack.php, since nginx will use
/www/site/scripts/upload/hach.php instead.
The 3rd way, if you can not place scripts in separate directory, you
should proper order of regex locations:
location ~ ^/download {
root /www/site;
}
location ~ ^/upload {
root /www/site;
}
location ~ \.php$ {
root /www/site;
}
--
Igor Sysoev
More information about the nginx
mailing list