早就知道nginx有安全漏洞,一直没放在心上,今天抽空做了一个测试,果真非常危险,请用nginx 构建服务器的朋友要一定小心了,不采取防范措施将会造成严重的安全隐患。

2010年5月23日14:00前阅读本文的朋友,请按目前v1.1版本的最新配置进行设置。

昨日,80Sec 爆出Nginx具有严重的0day漏洞,详见《Nginx文件类型错误解析漏洞》。只要用户拥有上传图片权限的Nginx+PHP服务器,就有被***的可能。

其实此漏洞并不是Nginx的漏洞,而是PHP PATH_INFO的漏洞,详见:http://bugs.php.net/bug.php?id=50852&edit=1 例如用户上传了一张照片,访问地址为http://www.domain.com/p_w_picpaths/test.jpg,而test.jpg文件内的内容实际上是PHP代码时,通过http://www.domain.com/p_w_picpaths/test.jpg/abc.php就能够执行该文件内的PHP代码。

张宴的博客里提到了至少四种方案,罗列如下:

方法①、修改php.ini,设置cgi.fix_pathinfo = 0;然后重启php-cgi。此修改会影响到使用PATH_INFO伪静态的应用,例如我以前博文的URL:http://blog.s135.com/read.php/348.htm 就不能访问了。

方法②、在nginx的配置文件添加如下内容后重启:if ( $fastcgi_script_name ~ \..*\/.*php ) {return 403;}。该匹配会影响类似 http://www.domain.com/software/5.0/test.php(5.0为目录),http://www.domain.com/goto.php/phpwind 的URL访问。

方法③、对于存储图片的location{...},或虚拟主机server{...},只允许纯静态访问,不配置PHP访问。

方法四:张宴提供一种修改nginx.conf配置文件的临时解决方法,兼容“http://blog.s135.com/demo/0day/phpinfo.php/test”的PATH_INFO伪静态,拒绝“http://blog.s135.com/demo/0day/phpinfo.jpg/test.php”的漏洞***:

location ~* .*\.php($|/) 
   
 { 
   
 if ($request_filename ~* (.*)\.php) { 
   
 set $php_url $1; 
   
 } 
   
 if (!-e $php_url.php) { 
   
 return 403; 
   
 } 
   

 fastcgi_pass 127.0.0.1:9000; 
   
 fastcgi_index index.php; 
   
 include fcgi.conf; 
   
 } 
   
  
 也可将以下内容写在fcgi.conf文件中,便于多个虚拟主机引用:
 
  

    if ($request_filename ~* (.*)\.php) { 
   
 set $php_url $1; 
   
 } 
   
 if (!-e $php_url.php) { 
   
 return 403; 
   
 } 
   

 fastcgi_param GATEWAY_INTERFACE CGI/1.1; 
   
 fastcgi_param SERVER_SOFTWARE nginx; 
   

 fastcgi_param QUERY_STRING $query_string; 
   
 fastcgi_param REQUEST_METHOD $request_method; 
   
 fastcgi_param CONTENT_TYPE $content_type; 
   
 fastcgi_param CONTENT_LENGTH $content_length; 
   

 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
   
 fastcgi_param SCRIPT_NAME $uri; 
   
 fastcgi_param REQUEST_URI $request_uri; 
   
 fastcgi_param DOCUMENT_URI $document_uri; 
   
 fastcgi_param DOCUMENT_ROOT $document_root; 
   
 fastcgi_param SERVER_PROTOCOL $server_protocol; 
   

 fastcgi_param REMOTE_ADDR $remote_addr; 
   
 fastcgi_param REMOTE_PORT $remote_port; 
   
 fastcgi_param SERVER_ADDR $server_addr; 
   
 fastcgi_param SERVER_PORT $server_port; 
   
 fastcgi_param SERVER_NAME $server_name; 
   

 # PHP only, required if PHP was built with --enable-force-cgi-redirect 
   
 fastcgi_param REDIRECT_STATUS 200;

没有看太懂,这里做一个记录,供参考查阅

我自己用了第三种方案,也就是在能上传图片的目录,做一个处理,禁止运行php程序,代码如下:

1. location ^~ /uploadfile/{ 
2.             location ~ "\.php.*$"{ 
3.                     return 403; 
4.         } 
经过测试是可以的,正则学的不好,见笑了!
上面这段话,还是有些问题的,使用之后发现,所有的图片都看不到了,张宴的方法也试过,不知为什么没有起作用。
最终采用的是方案二:if ( $fastcgi_script_name ~ \..*\/.*php ) {return 403;}。
非常管用的,测试了几种执行漏洞的方式,都不起作用。
仔细琢磨了下这个正则:
\. 代表一个点,.* 代表任意多个字符,\/代表一个 "/", .*代表任意多个字符,php,这里并不是用php结尾,只是说出现了php即命中。
翻译过来为:.jpg(任意字符)/(任意字符)php(任意字符)
比如:.jpg/xxx.php ; .jpg/?xcccc/1.php ; .jpg/ccc.php?x=8;(总之,通杀)