关于lnmp目录禁止执行的绕过与正确方法

无意中看到了这篇文章:http://www.freebuf.com/articles/system/49428.html

对于下面我莫名其妙中枪的事。。。我就不多说了:

08.jpg

于是我详细地把文章看了一遍,文章比较基础但也不失为一个引导新手的一个方法。但其中对于禁止执行的方式,我就不敢苟同了。在某种配置下,这个方法是能够很容易被绕过的。

文中提到,使用lnmp1.1搭建的nginx环境,正好我的vps也是lnmp搭建的环境,所以我可以在我的vps里做实验。

看到文中的解决方案:

11.jpg

在location中,将匹配到/(avatar|uploads|ups)/.*.(php|php5)?$的请求全部禁用掉。

似乎是一个很好的方法,那我们怎么绕过?

在web世界里,有一种请求方式叫pathinfo,我们在图中也可以看到,倒数第二行注释掉了一个include pathinfo.conf。前面的说明里也说到了,如果要开启pathinfo,只要注释掉try_files $uri =404即可。

很多框架、CMS的默认请求方式就是pathinfo,如著名php框架codeigniter,所以可见pathinfo用的是比较广的,所以也会有大量vps在这里是允许pathinfo的。

那么,当开启了pathinfo后,前面的deny all;就完全失效了,我们只需要在upload目录里上传xxx.php后,如下方式访问:

http://xxx/upload/xxx.php/xxx

即可让location /(avatar|uploads|ups)/.*\.(php|php5)?$这条规则完全失效,因为上述请求并不以.php结尾。

那么,怎样才能有效禁止某目录下解析php?

那还是应该回到nginx解析php的方式上。我们看到上图,我们可以发现,实际上进入这个location块:location ~ [^/]\.php(/|$),才真正将请求交给fastcgi去解析。

所以,我们只需要阻止请求进入这个location块,那么这个请求不论是怎样的后缀,怎样的方式,都不会被php-fpm解析的。

所以,我的方法是:

location ^~ /upload/ {
default_type text/plain;
expires 30d;
}
location ~ [^/]\.php(/|$)
{
# comment try_files $uri =404; to enable pathinfo
#try_files $uri =404;
fastcgi_pass  unix:/tmp/php-cgi-leavesongs.sock;
fastcgi_index index.php;
include fastcgi.conf;
include pathinfo.conf;
}

在php的解析块前,加上location ^~ /upload/块,^~的意思是“一旦匹配上该块,则不再匹配其他块,一般匹配目录”。所以,这里正好满足我的要求,只要在/upload/目录下的文件,都将匹配到这个块中,而且不会再匹配别的块,所以也不会再进入下面的php解析块中。

附location匹配命令的一些说明:http://www.nginx.cn/115.html

赞赏

喜欢这篇文章,扫码和我成为赞友!

评论

wskwsk 回复

include pathinfo.conf;
# comment try_files $uri =404;

我yum的官方nginx 1.6.2包,怎么发现没有上面2行? 也找不到 pathinfo.conf 文件

phithon 回复

@wskwsk:你看默认是否支持pathinfo。如果支持,就不需要这个了,这不是重点,这只是lnmp下开启pathinfo的方法。debian下nginx默认是直接开启的,不需要这么麻烦。

phithon 回复

@wskwsk:nginx官方的配置文件里是没这个东西的,这是LNMP这个一键环境自己加的,因为它将pathinfo禁用了,但有些环境需要pathinfo,于是提供给管理员能够随时开启pathinfo。

大牛你好赞 回复

大牛你好赞,转走了。好爱你

我是TJ 回复

啊啊啊。 挺不错的

4c 回复

你咋么这么叼

captcha