文件上传漏洞在渗透测试中是一个非常重要的漏洞,因为这个漏洞可以很快的拿到服务器的权限,下面介绍一下文件上传漏洞的效验方法,绕过方式,和一些修复建议。
文件上传校验姿势
- 客户端javascript校验(一般只校验后缀名)
- 服务端校验
- 文件头content-type字段校验(image/gif)
- 文件内容头校验(GIF89a)
- 后缀名黑名单校验
- 后缀名白名单校验
- 自定义正则校验
- WAF设备校验(根据不同的WAF产品而定)
客户端JS验证
验证代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051//文件上传漏洞演示脚本之js验证$uploaddir = 'uploads/';if (isset($_POST['submit'])) {if (file_exists($uploaddir)) {if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploaddir . '/' . $_FILES['upfile']['name'])) {echo '文件上传成功,保存于:' . $uploaddir . $_FILES['upfile']['name'] . "\n";}} else {exit($uploaddir . '文件夹不存在,请手工创建!');}//print_r($_FILES);}<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html;charset=gbk"/><meta http-equiv="content-language" content="zh-CN"/><title>文件上传漏洞演示脚本--JS验证实例</title><script type="text/javascript">function checkFile() {var file = document.getElementsByName('upfile')[0].value;if (file == null || file == "") {alert("你还没有选择任何文件,不能上传!");return false;}//定义允许上传的文件类型var allow_ext = ".jpg|.jpeg|.png|.gif|.bmp|";//提取上传文件的类型var ext_name = file.substring(file.lastIndexOf("."));//alert(ext_name);//alert(ext_name + "|");//判断上传文件类型是否允许上传if (allow_ext.indexOf(ext_name + "|") == -1) {var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;alert(errMsg);return false;}}</script><body><h3>文件上传漏洞演示脚本--JS验证实例</h3><form action="" method="post" enctype="multipart/form-data" name="upload" onsubmit="return checkFile()"><input type="hidden" name="MAX_FILE_SIZE" value="204800"/>请选择要上传的文件:<input type="file" name="upfile"/><input type="submit" name="submit" value="上传"/></form></body></html>
客户端JS验证通常做法是验证上传文件的扩展名是否符合验证条件
绕过姿势
1.通过firefox的F12修改js代码绕过验证
2.使用burp抓包直接提交,绕过js验证
文件头content-type字段校验(image/gif)
验证测试代码
|
|
以上是一个简单的服务器上传验证代码,只要content-type符合image/gif就允许上传
绕过方式
使用Burp截取上传数据包,修改Content-Type的值,改为image/gif即可成功绕过上传webshell
服务端文件扩展名检测
测试代码
|
|
默认上传后的文件保存的名字是以获取到名字
绕过技巧
- 使用大小写绕过(针对对大小写不敏感的系统如windows),如:PhP
- 使用黑名单外的脚本类型,如:php5,asa 和 cer等
能被解析的文件扩展名列表:
jsp jspx jspf
asp asa cer aspx - 配合文件包含漏洞
前提:校验规则只校验当文件后缀名为asp/php/jsp的文件内容是否为木马。
绕过方式:(这里拿php为例,此漏洞主要存在于PHP中)
(1)先上传一个内容为木马的txt后缀文件,因为后缀名的关系没有检验内容;
(2)然后再上传一个.php的文件,内容为
此时,这个php文件就会去引用txt文件的内容,从而绕过校验 - 配合服务器解析漏洞
如:test.jpg.xxx(apache解析漏洞) - 配合操作系统文件命令规则
(1)上传不符合windows文件命名规则的文件名
test.asp.
test.asp(空格)
test.php:1.jpg
test.php:: $DATA
会被windows系统自动去掉不符合规则符号后面的内容。
(2)linux下后缀名大小写
在linux下,如果上传php不被解析,可以试试上传pHp后缀的文件名。 - 双扩展名之间使用00截断,绕过验证上传恶意代码
0x00截断:基于一个组合逻辑漏洞造成的,通常存在于构造上传文件路径的时候
test.php(0x00).jpg
test.php%00.jpg
路径/upload/1.php(0x00),文件名1.jpg,结合/upload/1.php(0x00)/1.jpg - 借助.htaccess文件上传恶意代码并解析。如:上传一个.htaccess文件,内容为AddTypeapplication/x-httpd-php .jpg,上传的jpg文件就可以当作php来解析
- 超长文件名截断上传(windows 258byte | linux 4096byte)
- CMS、编辑器漏洞
(1)CMS漏洞:比如说JCMS等存在的漏洞,可以针对不同CMS存在的上传漏洞进行绕过。
(2)编辑器漏洞:比如FCK,ewebeditor等,可以针对编辑器的漏洞进行绕过服务端检测文件头
文件头简介
不同的图片文件都有不同文件头,如:
PNG: 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A
JPEG: 文件头标识 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识)
GIF: 文件头标识 (6 bytes) 47 49 46 38 39(37) 61绕过方式
绕过这个检测只需要在恶意脚本前加上允许上传文件的头标识就可以了
在木马内容基础上再加了一些文件信息,有点像下面的结构
GIF89a服务器段安装WAF
服务器段安装安全狗等安全防御软件绕过方法
- 垃圾数据
有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验; - filename
针对早期版本安全狗,可以多加一个filename - POST/GET
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。
此种情况可以上传一个POST型的数据包,抓包将POST改为GET安全建议
- 使用白名单限制可以上传的文件扩展
- 验证文件内容,使用正则匹配恶意代码限制上传
- 对上传后的文件统一随机命名,不允许用户控制扩展名
- 修复服务器可能存在的解析漏洞
- 严格限制可以修改服务器配置的文件上传如:.htaccess
- 隐藏上传文件路径。