第1章 文件上传漏洞基础
1.1 漏洞概述
文件上传是很多站点常用的功能,比如上传图片、视频、文档等,常在评论功能区、头像修改、提交文档等场景下出现。
文件上传漏洞是指用户利用站点文件上传功能,上传了一个可执行的脚本文件(asp、aspx、php、jsp等),并通过执行此脚本文件获得了执行服务器端命令的能力。恶意脚本文件又称webshell(网页后门),具有强大的功能,如查看服务器目录/文件、执行系统命令等。
1.2 漏洞成因
- 站点开放了文件上传功能,但却对上传的文件没有进行足够的限制
- 程序开发部署时,没有考虑到系统特性、过滤不严格
- 站点服务器存在解析漏洞,被黑客利用后导致可以上传任意文件
1.3 漏洞危害
- 文件上传漏洞最直接的威胁就是上传任意文件,包括恶意脚本、可执行程序等
- 如果站点服务器用于保存上传文件的目录具有执行权限,恶意文件被执行后黑客可获取服务器命令执行能力,导致站点沦陷
- 如果攻击者通过其他漏洞进行提权操作,拿到系统管理员权限,那么直接导致服务器沦陷
- 同服务器下的其他网站无一幸免,均会被攻击者控制(旁站攻击)
1.4 漏洞利用姿势
- 直接上传可执行文件,如PHP、JSP、ASP等,然后利用webshell工具连接可执行文件,从而获取服务器命令执行权限,常见webshell工具有菜刀、蚁剑等。
- 配合文件包含漏洞写shell
第2章 文件上传漏洞检测与绕过
文件上传漏洞的检测,一般有两个思路,一是在web前端借助JavaScript来实现,二是在后台服务器进行检测,本章节将对这两种检测方式进行介绍,并讲解如何绕过这些检测来达到恶意文件上传的目的。
2.1 前端检测和绕过
1、检测原理
使用javascript脚本语言,先将上传的文件名转换成小写(toLowerCase()函数),然后通过substr()函数获取文件名的后缀,最后匹配预定义的白名单,如果后缀名在白名单之内,则允许上传,否则不允许上传。
一、上传表单
<form class="upload" method="post" enctype="multipart/form-data" action="">
<input class="uploadfile" type="file" name="uploadfile" onchange="checkFileExt(this.value)"/><br />
<input class="sub" type="submit" name="submit" value="开始上传" />
</form>
二、Javascript检测文件
<script>
function checkFileExt(filename)
{
var flag = false;
var arr = ["jpg","png","gif","jpeg"];
var index = filename.lastIndexOf(".");
var ext = filename.substr(index+1); //取出上传文件的扩展名
for(var i=0;i<arr.length;i++) //比较
{
if(ext == arr[i])
{
flag = true; //一旦找到合适的,立即退出循环
break;
}
}
if(!flag) //条件判断
{
alert("上传的文件不符合要求,请重新选择!");
location.reload(true);
}
}
</script>
2、绕过手段
由于服务器端没有对文件做任何检测,所以只要绕过前端JavaScript的校验就可以上传WebShell
- 禁用浏览器Javascript解析器:以FireFox为例,地址栏输about:config-->找到javascript.enabled并将其关闭(默认开启)
- 利用BurpSuite抓包修改文件后缀:先将待上传木马文件后缀修改成合法后缀,然后BP抓包,修改文件后缀为php、asp等类型,然后提交即可绕过检测。
2.2 服务器端检测和绕过
对于文件上传,只从Web前端进行检测显然防护不足,那么服务器端检测就特别重要了。一般服务端检测包括后缀名检测、MIME类型检测、文件内容检测、00截断、条件竞争检测等,下面将分别介绍检测原理及其绕过方法。
1、检测原理
0x01 白名单检测:
所谓白名单,指的是服务器预定义的允许上传的文件类型,前端上传文件后,服务器检测其文件类型是否在白名单之中,如果白名单包含该文件类型,则上传成功,否则服务器会返回上传失败,并删除临时文件。
0x02 黑名单检测:
所谓黑名单,指的是服务器预定义的不允许上传的文件类型,前端上传文件后,服务器检测其文件类型是否在黑名单之中,如果黑名单不包含该文件类型,则上传成功,否则服务器返回上传失败,并删除临时文件。
0x03 MIME类型检测:
MIME是描述消息类型的因特网标准,MIME消息可描述文本、图像、音频、视频等数据。在HTTP协议中,使用Content-Type字段表示文件的MIME类型,常见MIME类型如下:
.js application/x-javascript
.html text/html
.jpg image/jpeg
.png image/png
.pdf application/pdf
.gif image/gif
.php application/octer-stream
在PHP语言中,通过判断$_FILES['file']['type']来获取文件的MIME类型,获取MIME类型后再结合白名单或黑名单思想进行过滤。$_FILES['file']['type']的值是从HTTP请求数据包Content-Type字段中获取的。下面代码是一个通过MIME类型过滤文件上传的典型用例
<?php
if(isset($_POST['submit'])){
$mime=array('image/jpg','image/jpeg','image/png'); //指定MIME类型,这里只是对MIME类型做了判断。
if(!in_array($_FILES['file']['type'], $mime)){
$return_data['error']='只允许上传jpg,jpg,png格式的文件!';
$return_data['return']=false;
return $return_data;
}else{
//对上传的文件进行后续处理
}
}
?>
**0x04 文件幻数检测: **
当一个文件以16进制打开时,文件头部字段标识了不同的文件类型,这个文件头部标识被称为文件幻数,其作用类似文件后缀名,可以用来标记文件或者协议的格式,很多文件都用幻数标志来表示该文件类型。下表展示了常见的文件幻数
0x05 getimagesize()函数检测
getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。可以测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。
当一个非图片格式的文件作为getimagesize()参数传入时,函数会返回FALSE,以此来达到文件检测的效果。
索引 0 给出的是图像宽度的像素值
索引 1 给出的是图像高度的像素值
索引 2 给出的是图像的类型,返回的是数字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
索引 3 给出的是一个宽度和高度的字符串,可以直接用于 HTML 的 <image> 标签
索引 bits 给出的是图像的每种颜色的位数,二进制格式
索引 channels 给出的是图像的通道值,RGB 图像默认是 3
索引 mime 给出的是图像的 MIME 信息,此信息可以用来在 HTTP Content-type 头信息中发送正确的信息
**2、绕过方法 **
0x01 绕过黑名单/白名单检测
1).htaccess文件攻击
.htaccess文件是apache服务器中的配置文件(IIS中不存在),该配置文件会覆盖apache服务器的全局配置,作用于当前目录及其子目录;如果一个web应用允许上传.htaccess文件,那就意味着攻击者可以更改apache的配置,这是十分危险的;在httpd.conf配置文件中,allowOverride参数用于指明apache服务器是否去找.htaccess文件作为配置文件,如果设置为none,那么服务器将忽略.htaccess文件;如果设置为all,那么.htaccess文件所包含的配置将覆盖httpd.conf里面的全局配置
- .htaccess攻击姿势一:匹配文件内容,将以下.htaccess文件上传至web站点目录下,则只要文件内容符合PHP语法规则,便可解析执行
- .htaccess攻击姿势二:匹配文件后缀名中的关键字,只要后缀名中存在关键字,便可解析执行
- .htaccess攻击姿势三:匹配文件名中的关键字,只要文件名中存在关键字,便可解析执行
2)大小写绕过
当php未进行上传文件后缀名大小写转换时,可以在上传文件时修改后缀名大小写达到文件上传的目的,比如将.php修改为.pHp,此时服务端能正常解析.pHp的文件。
3)利用windows特性绕过
一些特殊的文件名命名方式在windows下是不被允许的,利用burpsuit抓包修改后缀名,绕过验证上传文件,windows会自动修正异常的后缀名,但unix/linux没有这个特性;
例如:通过文件上传test.php.(借助BurpSuit抓包)这个文件以绕过检测.php上传的限制,当test.php.上传到winodws系统进行本地保存时,会自动将文件后缀名进行修正,变为test.php
4)利用apache解析漏洞绕过
apache文件解析时,从右向左开始解析文件后缀,若后缀名不可识别,则继续判断直到遇到可解析的后缀名为止。
** 5)配合文件包含漏洞绕过名**
首先制作包含恶意代码的图片马,但是图片马在上传之后不能直接解析;此时如果网站同时存在文件包含漏洞,利用文件包含无视后缀名的特性,只要被包含的文件内容符合PHP语法规范,任何扩展名都可以被PHP解析的特点来解析上传的图片马。
** 常见图片马制作方法:**
- Windows:copy 1.jpg/b + 1.php/a hack.jpg (将1.php中的代码写入图片中)
- Linux:echo "<?php @eval($_POST[666]);?>" >> eval.jpg
- 直接notepad++打开图片,在尾部写入恶意代码
0x02 绕过MIME类型检测
通过burpsuit抓取数据请求包,直接修改content-type字段的值,达到文件上传的目的。如下图所示,web站点在服务器端通过检测MIME类型来过滤上传,只允许jpg、jpeg、png、gif等图片格式,此时使用BuripSuite抓包后,修改HTTP请求的Content-Type字段为image/png,此后服务器端检测的时候就会被欺骗,把php误认为png文件
0x03 绕过文件幻数检测
若web站点通过检测文件幻数来达到只允许上传图片文件的效果,则在脚本文件开头补充图片对应的幻数值,达到欺骗的效果,可用16进制编辑器进行幻数插入操作。
0x04 远古截断绕过
- 00截断
0x00是十六进制表示,是ASCII为0的字符,有些函数处理时会把这个字符当做结束符,在对文件名读取时,如果遇到0x00,就会认为读取已经结束。攻击者可以利用手动添加字符串标识符的方式来将后面的内容进行截断,00截断通常用来绕过白名单限制。%00与0x00效果相同,不过%00用于url截断。
另外,只有同时满足php版本小于5.3.4、php.ini中magic_quotes_gpc为OFF状态才能进行截断。
- ....................................和././././././././././././././././绕过
和00截断类似,也是在低版本php中存在的一种截断方式,大量的……………或者大量的./././././能实现和00截断类似的效果。
0x05 绕过getimagesize()检测
对于使用getimagesize()函数来实现文件检测的场景,一般有两种绕过思路:
- 思路一:
结合文件包含漏洞,上传图片马,然后进行文件包含,从而解析图片马中的恶意代码。
- 思路二:
由于getimagesize()函数实际上是通过文件幻数来判断文件格式的,因此可以在文件头部插入图片的幻数,从而绕过getimagesize()函数的检测:
首先,给脚本文件头部插入图片幻数,如下所示在getimagesize.php文件头部插入png的文件幻数:
其次,进行验证是否可以绕过getimagesize()检测,如下所示,发现getimagesize()将php文件识别成了png文件,最终达到了绕过检测的效果。
另外, 除了以16进制方式写入幻数,也可以直接写入十进制GIF的幻数,如下所示:
0x06 条件竞争绕过
- 检测原理
以form表单向服务器上传任意文件时,都会生成临时文件,通过pathinfo()可以获取临时文件的存放路径以及名称,临时文件会在极短的时间内被删除,此时可利用时间差竞争上传,只要在文件被删除之前访问上传的php文件,即可执行相应的php代码,这就是所谓的竞争。
若文件to_shell.php为生成一句话木马的php代码,内容如下所示,只要在to_shell.php对应的临时文件被删除前成功被解析,则可在服务器目录生成一句话木马文件shell.php
- ** 绕过方法**
由于后台执行文件检测的时间是很快的,基本上来不及在删除前运行上传的php文件,此时可不断上传、不断执行,利用大量数据流找到时间差,完成竞争上传,此操作一般借助BurpSuite工具自动化完成:
第一步:BP截取上传页面请求,然后在intruder模块设置payload为NULL Payload,并设置攻击次数,最后执行,达到不断上传的效果;
第二步:BP截取访问to_shell.php的请求,然后在intruder模块设置payload为NULL Payload,并设置攻击次数,最后执行,达到不断包含文件的效果。
等待BP执行intruder任务结束后,验证是否可以利用蚁剑连接一句话木马shell.php获取shell
第3章 文件上传漏洞防御
常见的文件上传漏洞防御手段有:
- 将文件上传的目录设置为不可执行
- 多手段检测文件类型 1. 不依赖单独检测手段,比如将MIME检测和后缀名检测结合2. 使用白名单策略
- 使用随机数来存储文件:防止.php.jpg等多后缀名引起的漏洞
- 单独设置文件服务器的域名 1. 该服务器不能运行任何动态网页2. 只能静态访问HTML、图片等
版权归原作者 AkangBoy 所有, 如有侵权,请联系我们删除。