渗透测试方法论之文件上传

通常web 站点会有用户注册功能,而当用户登入之后大多数情况下都会存在类似头像上传、附件上传一类的功能,这些功能点往往存在上传验证方式不严格的安全缺陷,详解见正文哦~

论坛里面讲文件上传的很多,但是里面讲的都不全面,我就借鉴各位前辈的结晶总结了一个相对全面的。

通常web 站点会有用户注册功能,而当用户登入之后大多数情况下都会存在类似头像上传、附件上传一类的功能,这些功能点往往存在上传验证方式不严格的安全缺陷,是在web 渗透中非常关键的突破口,只要经过仔细测试分析来绕过上传验证机制,往往会造成被攻击者直接上传web 后门,进而控制整个web 业务的控制权,复杂一点的情况是结合webserver 的解析漏洞来上传后门获取权限。

一个简单的图来说明文件上传检测的流程:

1.png

通常一个文件以 HTTP 协议进行上传时,将以 POST 请求发送至 web 服务器,web 服务器接收到请求后并同意后,用户与 web 服务器将建立连接,并传输 data。

而一般一个文件上传过程中的检测如下图红色标记部分:

2.png

A 客户端javascript 检测(通常为检测文件扩展名)

B 服务端MIME 类型检测(检测Content-Type 内容)

C 服务端目录路径检测(检测跟path 参数相关的内容)

D 服务端文件扩展名检测(检测跟文件extension 相关的内容)

E 服务端文件内容检测(检测内容是否合法或含有恶意代码

客户端检测绕过(javascript 检测)

3.png

这类检测通常在上传页面里含有专门检测文件上传的javascript 代码,最常见的就是检测扩展名是否合法。

打开http 反向代理工具burp,先随便点击上传一个1.php

4.png

点上传,burp 里也还没出现任何内容,便弹出了一个警告框,一看就知道是个客户端验证javascript,只需要把它禁掉或者通过burp 进行代理修改。

5.png

burp 行代理修改,先将文件扩展名改成jpg

7.png

然后上传 现在的文件名是1.jpg 通过

7.png

在burp 里将jpg 改成php

8.png

然后继续上传,最后可以看到1.php 成功上传。

服务端验证绕过(MIME 类型检测)

9.png


假如服务器端上的upload.php代码如下:


<?php
if($_FILES['userfile']['type'] != "image/gif") { //检测Content-type
echo "Sorry, we only allow uploading GIF images";
exit;
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
}
?>

然后我们可以将request包的Content-Type 修改

POST /upload.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name="userfile";filename="1.php"
Content-Type: image/gif (原为Content-Type: text/plain)
<?php system($_GET['command']);?>
--xYzZY--

得到服务端的应答:

HTTP/1.1 200 OK
Date: Thu, 31 May 2017 14:02:11 GMT
Server: Apache
Content-Length: 59
Connection: close
Content-Type: text/html
<pre>File is valid, and was successfully uploaded.</pre>

我们成功绕过了服务端MIME 类型检测,这种服务端检测http 包的Content-Type 都可以用这种类似的方法来绕过检测。

10.png

服务器检测绕过(目录路径检测)

11.png

一般就检测路径是否合法,但稍微特殊一点的都没有防御。比如比较新的fckeditor php <= 2.6.4 任意文件上传漏洞,地址:

http://user.qzone.qq.com/1299183598/main

郊果如下:

12.png

因为对目录路径的检测不够严谨而导致可以用0×00 截断进行攻击,可以看到图中,在最后将要进行写文件之前的变量状态:

sFilePath =C:/wamp/www/userfiles/image/fuck.php .gif/fvck.gif (.php 后面是0×00)

当右图执行move_uploaded_file($oFile['tmp_name'], $sFilePath) 这个函数时

1. 先将sFilePath写入到指定位置,但是底层操作应该是调用的类似于c 语言,遇到0×00会自动截断,所以真正写入的实际地址是C:/wamp/www/userfiles/image/fuck.php

2. 把原本fvck.gif里的内容(目前应该存在临时文件,类似于C:/Temp/phpf3at7b这样的文件)然后把C:/Temp/phpf3at7b 的内容写入到C:/wamp/www/userfiles/image/fuck.php 里,这样便获得了我们所想要的webshell

13.png

问题出在了io.php 里的ServerMapFolder 函数

14.png

当POST 下面的URL 的时候

/

fckeditor264/filemanager/connectors/php/connector.php?Command=FileUpload&Type=Image&CurrentFolder=fuck.php%00.gifHTTP/1.0
CurrentFolder 这个变量的值会传到ServerMapFolder($resourceType, $folderPath, $sCommand)中的形参$folder 里,而$folder 在这个函数中并没做任何检测,就被CombinePaths()了。

服务端检测绕过(文件扩展名检测)

15.png

对于扩展名检测不强的,时常还可以结合目录路径攻击,比如filename=”test.asp/evil.jpg” 之类

**黑名单**

黑名单检测黑名单的安全性比白名单的安全性低很多,攻击手法自然也比白名单多,一般有个专门的blacklist 文件,里面会包含常见的危险脚本文件。

服务端通过获取上传文件的扩展名来匹配预先定义的非法扩展名数组,如果能成功匹配的话,认为上传文件不合法,返回报错信息,如果扩展名没有匹配到,则认为上传文件合法,进行文件保存操作。拿上传图片举例,服务端定义的黑名单:

$BlackList=array("php","htaccess","asp","aspx");

根据黑名单列表可以看出服务器不允许上传攻击中常用的php、htaccess、asp、aspx等脚本文件,也就是说这些文件都会被服务端所拦截,不能上传成功。

文件名大小写绕过

用像AsP,pHp 之类的文件名绕过黑名单检测

名单列表绕过

用黑名单里没有的名单进行攻击,比如黑名单里没有asa 或cer 之类

特殊文件名绕过

比如发送的http 包里把文件名改成test.asp. 或test.asp_(下划线为空格),这种命名方式在windows 系统里是不被允许的,所以需要在burp 之类里进行修改,然后绕过验证后,会被windows 系统自动去掉后面的点和空格,但要注意Unix/Linux 系统没有这个特性。

0×00 截断绕过

给个简单的伪代码

name= getname(http request) //假如这时候获取到的文件名是test.asp.jpg(asp 后面为0x00)
type= gettype(name) //而在gettype()函数里处理方式是从后往前扫描扩展名,所以判断为jpg
if(type == jpg)
SaveFileToPath(UploadPath.name,name) //但在这里却是以0x00 作为文件名截断
//最后以test.asp存入路径里

双扩展名解析绕过攻击 (1)- 基于web 服务的解析逻辑

比如在Apachemanual 中有这样一段描述:

“Files can havemore than one extension, and the order of the extensions is normallyirrelevant.For example, if the file welcome.html.fr maps onto content typetext/html and language Frenchthen the file welcome.fr.html will map onto exactlythe same information. If more than oneextension is given which maps onto thesame type of meta-information, then the one to the right will be used, exceptfor languages and content encodings. For example, if .gif maps to the MIME-typeimage/gif and .html maps to the MIME-type text/html, then the filewelcome.gif.html will be associated with the MIME-type text/html.”

如果上传一个文件名为help.asp.123 首先扩展名123 并没有在扩展名blacklist 里,然后扩展名123 也没在Apache 可解析扩展名list 里,这个时候它会向前搜 寻下一个可解析扩展名,或搜寻到.php,最后会以php 执行。

htaccess 文件攻击

配合名单列表绕过,上传一个自定义的.htaccess,就可以轻松绕过各种检测

解析调用/漏洞绕过

这类漏洞直接配合上传一个代码注入过的非黑名单文件即可,再利用解析调用/漏洞

双扩展名解析绕过攻击(2) – 基于web服务的解析方式

如果在Apache的conf 里有这样一行配置 AddHandlerphp5-script .php 这时只要文件名里包含.php 即使文件名是test2.php.jpg 也会以php 来执行。

危险解析绕过攻击- 基于web 服务的解析方式

如果在Apache的conf 里有这样一行配置 AddTypeapplication/x-httpd-php .jpg 即使扩展名是jpg,一样能以php 方式执行。

**白名单检测**

服务端通过获取上传文件的扩展名来匹配预先定义的合法扩展名数组,如果未能成功匹配的话,认为上传文件不合法,返回报错信息,如果扩展名能成功匹配,则认为上传文件合法,进行文件保存操作。

拿上传图片举例,服务端定义的白名单:“`$WhiteList=array(“png”,”jpg”,”jpeg”,”gif”);“`只允许上传png、jpg、jpeg、gif文件,如果攻击者上传恶意脚本文件(例如php、asp文件)就会被服务端拦截,让攻击者无法攻击服务器

相对来说比黑名单安全一些,但也不见得就绝对安全了.

0×00 截断绕过

用像test.asp%00.jpg的方式进行截断,属于白名单文件,再利用服务端代码的检测逻辑漏洞进行攻击,目前我只遇到过asp 的程序有这种漏洞

解析调用/漏洞绕过

这类漏洞直接配合上传一个代码注入过的白名单文件即可,再利用解析调用/漏洞

.htaccess文件攻击

无论是黑名单还是白名单,直接点就是直接攻击.htaccess 文件(其实目前我只见过结合黑名单攻击的,在后面的攻击分类里,我会把它归到黑名单绕过攻击里。但网上是把这个单独分类出来的,可能别人有一些我不知道的方式和技巧吧,所以在这里我也暂时保留这个单独分类)

在PHP manual 中提到了下面一段话:

move_uploaded_filesection, there is a warning which states

‘Ifthe destination file already exists, it will be overwritten.’

如果PHP安全没配置好,就可以通过move_uploaded_file 函数把自己写的.htaccess 文件覆盖掉服务器上的,这样就能任意定义解析名单了。

服务端检测绕过(文件内容检测)

16.png

如果文件内容检测设置得比较严格,那么上传攻击将变得非常困难,也可以说它是在代码层检测的最后一道关卡,如果它被突破了,就算没有代码层的漏洞,也给后面利用应用层的解析漏洞带来了机会。我们这里主要以最常见的图像类型内容检测来举例:

主要是检测文件内容开始处的文件幻数,比如图片类型的文件幻数如下:

要绕过jpg 文件幻数检测就要在文件开头写上下图的值

17.png

要绕过gif 文件幻数检测就要在文件开头写上下图的值

18.png

要绕过png 文件幻数检测就要在文件开头写上下面的值

19.png

然后在文件幻数后面加上自己的一句话木马代码就行了

文件相关信息检测

图像文件相关信息检测常用的就是getimagesize()函数,只需要把文件头部分伪造好就ok 了,就是在幻数的基础上还加了一些文件信息,有点像下面的结构:

GIF89a
(...some binary data for image...)
<?php phpinfo(); ?>
(... skipping the rest of binary data ...)

文件加载检测

这个是最变态的检测了,一般是调用API 或函数去进行文件加载测试,常见的是图像渲染测试,再变态点的甚至是进行二次渲染(后面会提到)。对渲染/加载测试的攻击方式是代码注入绕过;对二次渲染的攻击方式是攻击文件加载器自身。
先说下对渲染/加载测试攻击-代码注入绕过,可以用图像处理软件对一张图片进行代码注入。用winhex看数据可以分析出这类工具的原理是在不破坏文件本身的渲染情况下找一个空白区进行填充代码,一般会是图片的注释区。对于渲染测试基本上都能绕过,毕竟本身的文件结构是完整的.

但如果碰到变态的二次渲染,基本上就没法绕过了,估计就只能对文件加载器进行攻击了。

一般进行遇到二次渲染,想绕过,就目前个人经验还没想出方法,它相当于是把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染,在这个过程中非图像数据的部分直接就被隔离开了。能想到的一个思路就是基于数据二义性,即让数据既是图像数据也包含一句话木马代码,就像shellcode 通过数据二义性绕过IDS 检测特殊字符一样的道理,但现在我还不知道怎么构造出这样的图像文件。

如果要对文件加载器进行攻击,常见的就是溢出攻击,上传自己的恶意文件后,服务器上的文件加载器会主动进行加载测试,加载测试时被溢出攻击执行shellcode比如access/mdb 溢出,大家可以参考下http://lcx.cc/?FoxNews=1542.html

总之对文件完整性检测的绕过,通常就直接用个结构完整的文件进行代码注入即可没必要再去测到底是检查的幻数还是文件头结构之类的了。

解析攻击

攻击角度来分是这样的:

直接解析(完全没防御或有一点简单的防御)

比如我们直接就可以上传一个扩展名是.php的文件,只需要简单地绕过客户端javascript 检测或者服务端MIME 类型检测就行了。

配合解析(有一定程度的防御)

我们可以理解为先代码注入到服务器上,上传一个带有一句话木马的图片或文件之类

让它待在某个位置,等待这一个解析的配合。(比如php 的文件包含解析,web 服务器的解析漏洞,.htaccess 解析等)

本地文件包含解析

主要是php 的本地文件包含(远程文件包含不属于上传攻击绕过范畴)

htaccess解析

就不用多说了,看看之前.htaccess 文件攻击的那个案例,用户自己定义如何去调用解析器解析文件就可以了。

web应用程序解析漏洞以及其原理

Apache 解析漏洞

解析: test.php.任意不属于黑名单且也不属于Apache解析白名单的名称

描述: 一个文件名为x1.x2.x3 的文件,Apache 会从x3 的位置往x1 的位置开始尝试解析,

如果x3 不属于Apache 能解析的扩展名,那么Apache会尝试去解析x2 的位置,这样一直往前尝试,直到遇到一个能解析的扩展名为止

IIS 解析漏洞

解析- test.asp/任意文件名|test.asp;任意文件名| 任意文件名/任意文件名.php

描述- IIS6.0 在解析asp 格式的时候有两个解析漏洞,一个是如果目录名包含”.asp”字符串,那么这个目录下所有的文件都会按照asp 去解析,另一个是只要文件名中含有”.asp;”会优先按asp 来解析。

IIS7.0/7.5 是对php 解析时有一个类似于Nginx的解析漏洞,对任意文件名只要在URL后面追加上字符串”/任意文件名.php”就会按照php 的方式去解析。

Nginx 解析漏洞

解析- 任意文件名/任意文件名.php | 任意文件名%00.php

描述- 目前Nginx 主要有这两种漏洞,一个是对任意文件名,在后面添加/任意文件名.php

的解析漏洞,比如原本文件名是test.jpg,可以添加为test.jpg/x.php进行解析攻击。还有一种是对低版本的Nginx 可以在任意文件名后面添加%00.php 进行解析攻击。

总结:写的有点多,这次就先这样了,代码层,应用层等等漏洞出现在多个层面,总之安全学习之路还很长,很长…………..

2

更多精彩
发表评论

已有 3 条评论

取消
Loading...

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php