漏洞介绍
Nginx解析漏洞与版本无关,是由于用户配置php不当造成的。但在高版本的php中,由于“security.limit_extensions”的引入,使得该漏洞难以被成功利用。
漏洞原理
当用户请求的url后缀为123.jpg/123.php时,location对请求进行选择的时候会使用URI环境变量进行选择,其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由Nginx生成的$fastcgi_script_name决定。
location ~ \.php$ {
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param REDIRECT_STATUS 200;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT /var/www/html;
fastcgi_pass php:9000;
}
而为了较好的支持PATH_INFO的提取,在PHP的配置选项里存在cgi.fix_pathinfo选项,其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。
一般情况下cgi.fix_pathinfo的值默认为1,也就是开启,从而引发该漏洞。当Nginx遇到文件路径“123.jpg/123.php”时,由于其后缀为.php文件,所以会被传到上述所示代码中,在查找文件时,若“123.jpg/123.php”不存在,则会去掉最后的“123.php”,然后判断“123.jpg”是否存在,若存在,则把“123.jpg”当做php解析。
漏洞复现
环境的搭建依靠vulhub。
上传一个nginx.jpg文件,其中的代码为<?php phpinfo(); ?>
结果报错了:
因为这个jpg文件中只有php代码,服务器在进行图片检验的时候,没有检测到图片的标识符,所以没有通过。
那接下来,我们上传一张图片马。
这次图片上传成功了,而且服务器还对文件进行了重命名。可以正常访问:
我们在其后缀加上 /.php
成功解析了php代码。
漏洞修复
1、修改 php.ini
cgi.fix_pathinfo = 0
2、在nginx配置文件(nginx.conf)中加入
if ( $fastcgi_script_name ~ ..*/.*php ) {
return 403;
}
3、前两种方法可能会导致一些伪静态网页或者特殊的路径无法显示。第三种方法将以下代码写在nginx下的fcgi.conf文件中
if ($request_filename ~* (.*).php) {
set $php_url $1;
}
if (!-e $php_url.php) {
return 403;
}