關于lnmp目錄禁止執行的繞過與正確方法

phith0n | 2014-11-02 17:50

#

    無意中看到了這篇文章: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

    附drops中關于lnmp安全配置的方法:

    http://drops.wooyun.org/tips/1323 (其中就包含這個有問題的方法)

    http://drops.wooyun.org/tips/2866

    測試:http://www.leavesongs.com/upload/1.php