nginx漏洞上传图片可入侵100万服务器 nginx+php的注意了

国内顶级安全团队80sec于5.20日下午6点发布了一个关于nginx的漏洞通告,由于该漏洞的存在,使用nginx+php组建的网站只要允许上传图片就可能被黑客入侵,直到5.21日凌晨,nginx尚未发布补丁修复该漏洞。

根据Netcraft的统计,直到2010年4月,全球一共有1300万台服务器运行着nginx程序;非常保守的估计,其中至少有600万台服务器运行着nginx并启用了php支持;继续保守的估计,其中有1/6,也就是100万台服务器允许用户上传图片

由于nginx有漏洞,这100万台服务器可能通过上传图片的方法被黑客轻易的植入木马。植入木马的过程也非常简单,就是把木马改成图片上传就是了,由于危害非常大,就不说细节了。有兴趣的请访问http://www.80sec.com/nginx-securit.html

说了那么多,我想大家对80sec这个顶级安全团队比较好奇吧,素包子简单介绍一下。

80sec团队由一群年轻、充满活力、充满体力、充满激情、富有创造力的未婚dota男组成,他们均在各大互联网公司从事信息安全工作,他们的口号是knowitthenhackit,素包子非常认同这个观点:“我们只要非常熟悉一个事物,就有可能客观的发现它的不足之处,同时我们也能的发现该事物的优点”。

80sec的意思是“80端口的安全”,也就是“web安全”;同时由于该团队成员都是80后的年轻人,我们也可以理解为“80后安全”;另外由于sec的发音是seke,我们还可以理解为“80后色客”、“80后摄客”或“80后S客”,我们对80sec的理解仅受限于想象力。

下面介绍一下他们的丰功伟绩,他们曾发现IIS、IE、FireFox、Maxthon、世界之窗、PHPWind、DeDeCMS、QQmail、QuarkMail、EXTMail等软件的漏洞,可见硕果累累。

既然介绍了80sec,就不得不介绍另外一个非常专注WEB安全的顶级安全团队80vul,该团队同样也是由80后的男童鞋组成(90后表示压力很大:p),他们也发现了大量WEBAPP的安全漏洞,例如IE、Gmail、wordpress、PHPWind、DISCUZ、MYBB等。

看到这里,想必大家心里都有那么点遗憾,那就是为何没有80后女黑客(我不歧视伪娘,但我必须说明不是伪娘),我也有相同的遗憾。

最后发一个小道消息,据说黑客已经在行动了;安全人员、系统管理人员、行动起来吧,赶紧修复该漏洞;最好不要有侥幸心理,否则下一个被黑客入侵的可能就是你的网站。根据80sec安全公告的描述,临时修复方法如下,可3选其一。

1、设置php.ini的cgi.fix_pathinfo为0,重启php。最方便,但修改设置的影响需要自己评估。

2、给nginx的vhost配置添加如下内容,重启nginx。vhost较少的情况下也很方便。

if($fastcgi_script_name~\..*\/.*php){

return403;

}

3、禁止上传目录解释PHP程序。不需要动webserver,如果vhost和服务器较多,短期内难度急剧上升;建议在vhost和服务器较少的情况下采用。

作者:Hily原始链接:http://hily.me/blog/2010/05/nginx-php-configure-security-problem/

版权声明:可以转载,转载时务必以超链接形式标明文章原始出处和作者信息及版权声明

漏洞危险等级:毁灭性。

这个漏洞严格上说并不是Nginx和PHP本身的漏洞造成的,而是由配置造成的。在我之前写的许多配置中,都普遍存在这个漏洞。

简易检测方法:

打开Nginx+PHP服务器上的任意一张图片,如:

如果在图片链接后加一串/xxx.php(xxx为任意字符)后,如:

图片还能访问的话,说明你的配置存在漏洞。

漏洞分析:

下面通过分析一个很常见的Nginx配置来解释下漏洞的成因:

server{

listen80;

server_nametest.local;

access_log/work/www/logs/test.access.logmain;

error_log/work/www/logs/test.error.log;

location/{

root/work/www/test;

indexindex.htmlindex.htmindex.php;

}

location~\.php${

root/work/www/test;

fastcgi_indexindex.php;

fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;

includefastcgi_params;

fastcgi_passunix:/tmp/php-fpm.sock;

}

}

我们在/work/www/test/目录下新建一个文件test.png,内容如下:

那么访问时,输出为文本内容:

但是当在后面加上/xxx.php时,即http://test.local/test.png/xxx.php,可怕的事情发生了:

Array

(

[HOSTNAME]=>

[PATH]=>/usr/local/bin:/usr/bin:/bin

[TMP]=>/tmp

[TMPDIR]=>/tmp

[TEMP]=>/tmp

[OSTYPE]=>

[MACHTYPE]=>

[MALLOC_CHECK_]=>2

[USER]=>www

[HOME]=>/home/www

[FCGI_ROLE]=>RESPONDER

[SCRIPT_FILENAME]=>/work/www/test/test.png

[QUERY_STRING]=>

[REQUEST_METHOD]=>GET

[CONTENT_TYPE]=>

[CONTENT_LENGTH]=>

[SCRIPT_NAME]=>/test.png/xxx.php

[REQUEST_URI]=>/test.png/xxx.php

[DOCUMENT_URI]=>/test.png/xxx.php

[DOCUMENT_ROOT]=>/work/www/test

[SERVER_PROTOCOL]=>HTTP/1.1

[GATEWAY_INTERFACE]=>CGI/1.1

[SERVER_SOFTWARE]=>nginx/0.7.62

[REMOTE_ADDR]=>192.168.1.163

[REMOTE_PORT]=>4080

[SERVER_ADDR]=>192.168.1.12

[SERVER_PORT]=>80

[SERVER_NAME]=>test.local

[REDIRECT_STATUS]=>200

[HTTP_ACCEPT]=>image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,application/x-shockwave-flash,application/QVOD,application/QVOD,application/x-ms-application,application/x-ms-xbap,application/vnd.ms-xpsdocument,application/xaml+xml,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/*

[HTTP_ACCEPT_LANGUAGE]=>zh-cn

[HTTP_ACCEPT_ENCODING]=>gzip,deflate

[HTTP_USER_AGENT]=>Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1;QQPinyin689;QQDownload627;Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1);.NETCLR2.0.50727;.NETCLR3.0.4506.2152;.NETCLR3.5.30729;InfoPath.2;TheWorld)

[HTTP_HOST]=>test.local

[HTTP_CONNECTION]=>Keep-Alive

[ORIG_SCRIPT_FILENAME]=>/work/www/test/test.png/xxx.php

[PATH_TRANSLATED]=>/work/www/test

[PHP_SELF]=>/test.png/xxx.php

[REQUEST_TIME]=>1274125615

)

环境变量中,SCRIPT_FILENAME是Nginx传过来的:

fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;

$fastcgi_script_name变量说明请参考:

http://wiki.nginx.org/NginxHttpFcgiModule

Nginx传给PHP的值为/work/www/test/test.png/xxx.php,即$_SERVER中ORIG_SCRIPT_FILENAME的值,但是$_SERVER中SCRIPT_FILENAME却是/work/www/test/test.png。

原因是,/work/www/test/test.png/xxx.php并不存在,对于这些不存在的路径,PHP会检查路径中存在的文件,并将多余的部分当作PATH_INFO。

这里,/work/www/test/test.png被PHP解析为SCRIPT_FILENAME,/xxx.php被PHP解析为PATH_INFO后被丢弃,因此并没有在$_SERVER中出现。

解决方法:

解决这个漏洞的方法很显然:关闭上面所述的解析即可。

这个解析可以在PHP的配置文件中设置,默认为开启。在这里我们需要将它关闭:

;cgi.fix_pathinfoprovides*real*PATH_INFO/PATH_TRANSLATEDsupportforCGI.PHP's

;previousbehaviourwastosetPATH_TRANSLATEDtoSCRIPT_FILENAME,andtonotgrok

;whatPATH_INFOis.FormoreinformationonPATH_INFO,seethecgispecs.Setting

;thisto1willcausePHPCGItofixitspathstoconformtothespec.Asetting

;ofzerocausesPHPtobehaveasbefore.Defaultis1.Youshouldfixyourscripts

;touseSCRIPT_FILENAMEratherthanPATH_TRANSLATED.

;http://php.net/cgi.fix-pathinfo

;cgi.fix_pathinfo=1

cgi.fix_pathinfo=0

其中cgi.fix_pathinfo=0为新增的配置行,表示关闭PHP的自动PATH_INFO检测。关闭后,该配置漏洞即可消除。

更好的解决方案?

以上方案并不是最完美的,如果你先前有用到cgi.fix_pathinfo这个特性,影响会很大,比如关闭后,我的Blog(Wordpress)文章的URL目录形式就得用rewrite来实现了。

如果可以将PHP设置成只解析.php为扩展名的文件,那么这个问题解决起来会更合理。

不过我没找到相关的设置项,或许今后应该出现在php-fpm的配置文件中?

总结:

这类问题基本上是无法预料的,但是如果架构设计良好的话,即使存在这个问题,也不会影响安全性。这里给出架构上的安全建议:

*尽可能使动静内容分离,所有的静态内容存在于静态内容服务器,静态内容服务器上不解析PHP,这样静态文件就永远不能被解析了。

相关推荐