• 欢迎访问挑战自我博客网站,安全研究,web渗透,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入挑战自我博客网站 网站主页

Nginx+PHP+Fastcgi的代码执行漏洞

tool 挑战自我 199次浏览 已收录 0个评论

一、详细说明

今天刚刚挖的一个漏洞,写报告写得比较认真,这边发出来大家一起研究下,为了保护隐私,我这里把厂商的域名全部替换为www.test.com了,该站点存在基于 Nginx+PHP+Fastcgi的代码执行漏洞。
我想首先讨论一下问题的本质,它不是由Nginx本身引起的,或者说它本身不是bug或者安全漏洞。这个漏洞理解起来很简单,当用户访问下面这个链接时

http://www.test.com/1234.jpg

得到的结果是一个图片,当用户在上面这个图片链接后面加上 /1.php 时,也就是访问下面这个链接时,它会用php去解析1234.jpg文件,也就是说如果1234.jpg文件为php木马时,我们就能够控制web服务器了。

http://www.test.com/1234.jpg/1.php

二、漏洞证明

我这里用另外一种方式来证明该漏洞的存在

首先,我访问站点的index.html

GET /index.html HTTP/1.1
Host: www.test.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Cookie: pgv_pvid=4802247680; pgv_info=pgvReferrer=&ssid=s5532283068; eas_sid=S1G5E4H2G1f8J0Q732R2r7h4W2
Connection: close
Upgrade-Insecure-Requests: 1

web响应如下:

HTTP/1.1 200 OK
Date: Wed, 14 Nov 2018 07:55:50 GMT
Content-Type: text/html
Connection: close
Server: nginx/1.4.4
Vary: Accept-Encoding
Content-Length: 164
……

现在,我在 index.html 后面添加/1.php时,如下request

GET /index.html/1.php HTTP/1.1
Host: www.test.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Cookie: pgv_pvid=4802247680; pgv_info=pgvReferrer=&ssid=s5532283068; eas_sid=S1G5E4H2G1f8J0Q732R2r7h4W2
Connection: close
Upgrade-Insecure-Requests: 1

现在web服务器响应如下:

HTTP/1.1 200 OK
Date: Wed, 14 Nov 2018 07:57:49 GMT
Content-Type: text/html
Connection: close
Server: nginx/1.4.4
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.6
Cache-Control: no-cache,no-store
Content-Length: 164
……

可以发现,系统响应仍然为200,但是头部多了一个

 X-Powered-By: PHP/5.3.6 

而且界面还是现实的index.html的内容,而不是显示的404页面内容。
可以查询资料,X-Powered-By这个头部是由PHP产生的,也就是说,系统刚刚是用php去解析index.html的内容的。

审核大大复查这个漏洞的时候,只要在网站根目录新建aa.txt文件,文本文件内容如下:

<?php
 phpinfo(); 
?>

然后把aa.txt重命名为aa.jpg文件,然后访问下面这个链接

http://www.test.com/aa.jpg/1.php

效果出来就是phpinfo的效果,这样就即可证明这个漏洞了

三、漏洞产生的原因分析

实际上这个漏洞和 nginx 没什么关系,nginx 只是个 Proxy,它只负责根据用户的配置文件,通过 fastcgi_param 指令将参数忠实地传递给 FastCGI Server,问题在于 FastCGI Server 是如何处理 nginx 提供的参数的。

Nginx的fashcgi配置信息如下

……
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/verdana/public_html/test/$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
……

当我们访问下面这个链接时

http://www.test.com/aa.jpg/1.php

那么根据上面给出的配置,nginx 传递给 FastCGI 的 SCRIPT_FILENAME 的值为

/home/verdana/public_html/test/aa.jpg/1.php

也就是 $_SERVER[‘ORIG_SCRIPT_FILENAME’]。
当 php.ini 中 cgi.fix_pathinfo = 1 时(这个默认是开启的),PHP CGI 以 / 为分隔符号从后向前依次检查如下路径:

/home/verdana/public_html/test/aa.jpg/1.php
/home/verdana/public_html/test/aa.jpg

直到找个某个存在的文件,PHP 会把这个文件当成 cgi 脚本执行,并赋值路径给 CGI 环境变量——SCRIPT_FILENAME,也就是 $_SERVER[‘SCRIPT_FILENAME’] 的值。所以最后aa.jpg文件时被php执行起来的。

四、修复方案

简单的修复方案就是打开你的php配置文件php.ini,把cgi.fix_pathinfo的值设置为0,但是有些条件下这样简单的设置并不能解决问题,因为可能有其他的脚本会打开这个选项。所以我们还必须有其他的解决方案。下面给出几个作为参考:

首先FastCGI中我们可以先判断我们访问的URI是否真的存在,如下所示:

location \.php$ {
    if (!-f $request_filename) {
        return 404;
    }
    fastcgi_pass 127.0.0.1:9000;
    [...]
}

另外,如果你认为它在资源方面消耗太大,那么可以检查URI是否满足以下要求:
1、访问的URI是否在一个点后面还有一个斜杠(如image.jpg/…)
2、访问的URI是否是以.php结束(如image.jpg/test.php)
如果满足上面条件的话,就返回403错误。
具体配置如下:

location ~ \..*/.*\.php$ {
    return 403;
}
location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    ...
}

或者你可以限制PHP在某些特定的目录才可以执行,而且这些目录又不能上传文件

location ~ ^/(scripts|sources|src)/.*\.php$ {
    fastcgi_pass 127.0.0.1:9000;
    ...
}

五、漏洞的深层危害分析

如果该站点的某些功能可以供用户上传头像、图片、文件等等,用户就可以通过上述方法获取WEB服务器的控制权。


挑战自我博客, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明Nginx+PHP+Fastcgi的代码执行漏洞
喜欢 (7)
支付宝[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址