NGINX 文件类型解释漏洞整理

nginx文件类型错误解析漏洞

www.xxx.com/1.jpg

内容为PHP 代码,如
<?php
phpinfo();
?>

后面加任意 .php
www.xxx.com/1.jpg/xxx.php
导致代码被执行

php.ini
cgi.fix_pathinfo=1
PHP_INI_ALL 从 PHP 4.3.0 起可用 请注意:默认为1

两者访问时的区别
www.xxx.com/1.jpg

HTTP/1.1 200 OK
Server: nginx/版本
Date: XXX
Content-Type: text/plain
Content-Length: XX
Last-Modified: XX
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes

www.xxx.com/1.jpg/xxx.php
HTTP/1.1 200 OK
Server: nginx/版本
Date: XXX
Content-Type: text/html
Content-Length: XX
Last-Modified: XX
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes

就在Content-Type: text/plain与Content-Type: text/html


如果 jpg 是普通文件,内容直接显示,但如内容是php代码就杯具了,代码直接执行
即使是最普通的配置
location ~ \.php$ {
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    include       fastcgi_params;
    fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
}

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


http://xx.com/foo.jpg/a.php/b.php/c.php
nginx 传递给 FastCGI 的 SCRIPT_FILENAME 的值为:
/foo.jpg/a.php/b.php/c.php
也就是 $_SERVER['ORIG_SCRIPT_FILENAME']

php.ini 中 cgi.fix_pathinfo = 1 时,PHP CGI 以 / 为分隔符号从后向前依次检查如下路径:

/foo.jpg/a.php/b.php/c.php
/foo.jpg/a.php/b.php
/foo.jpg/a.php
/foo.jpg
直到找个某个存在的文件,如果这个文件是个非法的文件,悲剧


PHP 会把这个文件当成 cgi 脚本执行,并赋值路径给 CGI 环境变量——SCRIPT_FILENAME,也就是 $_SERVER['SCRIPT_FILENAME'] 的值


解决办法
1,上传时代码判断文件类型
2,  nginx 解析
if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}

http://www.54chen.com/php-tech/nginx-php-cgi-of-security-hole.html
http://www.st0p.org/blog/tag/cgi-fix_pathinfo

你可能感兴趣的:(NGINX 文件类型解释漏洞整理)