文件上传漏洞
文件上传漏洞
前言
文件上传漏洞可以说是⽇常渗透测试用得最多的⼀个漏洞,因为用它获得服务器权限最快最直接。但是想真正把这个漏洞利用好却不那么容易,其中有很多技巧,也有很多需要掌握的知识。俗话说,知⼰知彼⽅能百战不殆,因此想要研究怎么防护漏洞,就要了解怎么去利用。
特点
利用简单
危害大
产生原因
缺少必要的校验
找文件上传点(关键)
管理后台页⾯
用户后台页⾯
前台页⾯
目录扫描 ==>扫描到后台不需要登陆就能访问的上传页⾯
测试思维和流程
测试思维
根据已有信息、条件分析目标⽹站架构,再以此架构为基础,从我们已经掌握的知识中过滤出适合此架构的攻击⽅法。
测试流程
思想指挥⾏动,那有了思想指导,我们就落实好久可以了。
- 分析目标架构
⽹站使用后端语言、中间件、目标服务器类型、版本等 - 根据分析结果使用已有⼿段依次测试。
突破 绕过 文件上传
前端验证的突破
如何探查是为前端验证
右键查看源代码
直接上传文件,如果⽹站⾮常快的弹出提示。
如何绕过前端验证
通过浏览器审查元素对⽹页的代码查看,找到对文件格式或⼤⼩的限制然后修改即可;
通过Burpsuite⼯具对浏览器进⾏代理,抓包对包里的内容进⾏修改。
浏览器禁用JavaScript脚本
什么是前端验证
通过JavaScript对上传操作的控制。如下:
<div id="upload_panel">
<ol>
<li>
<h3>任务</h3>
<p>上传⼀个<code>webshell</code>到服务器。</p>
</li>
<li>
<h3>上传区</h3>
<form enctype="multipart/form-data" method="post" onsubmit="return
checkFile()">
<p>请选择要上传的图⽚:<p>
<input class="input_file" type="file" name="upload_file"/>
<input class="button" type="submit" name="submit" value="上传"/>
</form>
<div id="msg">
</div>
<div id="img">
</div>
</li>
</ol>
</div>
</div>
<div id="footer">
<center>Copyright @ <span id="copyright_time"></span> by <a
href="http://gv7.me" target="_bank">c0ny1</a></center>
</div>
<div class="mask"></div>
<div class="dialog">
<div class="dialog-title">提 示<a href="javascript:void(0)" class="close"
title="关闭">关闭</a></div>
<div class="dialog-content"></div>
</div>
</body>
<script type="text/javascript" src="/upload-labs/js/jquery.min.js"></script>
<script type="text/javascript" src="/upload-labs/js/prism.js"></script>
<script type="text/javascript" src="/upload-labs/js/prism-line-numbers.min.js"></script>
<script type="text/javascript" src="/upload-labs/js/prism-php.min.js"></script>
<script type="text/javascript" src="/upload-labs/js/index.js"></script>
</html>
<script type="text/javascript">
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name) == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:"
+ ext_name;
alert(errMsg);
return false;
}
}
</script>
文件内容检查的突破
测试流程
上传⼀张正常图⽚,验证上传功能是否正常
最好直接上传⼀张图⽚马,可绕过content-type,文件头,getimagesize(),php_exif检查 (先上传JPG文件(确保文件内容合法上传上去),且图片代码里有可执行的一句话木马,先保证上传成功,然后在考虑把后缀变为Php的问题(文件包含,解析漏洞等等),因为现在的网站上传做的好,他的一些规则进行禁用上传)
针对⼆次渲染,寻找图⽚数据中不会被转换的部分,将代码插⼊其中
content-type检查
绕过
使用burp suite抓包直接修改content-type值
什么是content-type检查
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']
['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请⼿⼯创建!';
}
}
=
文件头检查绕过
在文件头部添加gif89a
gif89a
<?php
phpinfo();
?>
图⽚⼀句话
结合文件包含漏洞或者解析漏洞
getimagesize()检查和php_exif模块检查
校验头部
getimagesize()函数
示例
<?php
$remote_png_url = 'http://www.runoob.com/wp-content/themes/w3cschool.cc/assets/img/logo-
domain-green2.png';
$img_data = getimagesize($remote_png_url);
print_r($img_data );
?>
输出
Array
(
[0] => 290
[1] => 69
[2] => 3
[3] => width="290" height="69"
[bits] => 8
[mime] => image/png
)
解释
索引 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 头信息中发送正确的信息,如:
header("Content-type: image/jpeg");
绕过
在文件头部添加gif89a
图⽚⼀句话,结合解析漏洞或文件包含漏洞
image create from jpeg⼆次渲染
⼆次渲染:就是根据用户上传的图⽚,新生成⼀个图⽚,将原始图⽚删除,将新图⽚添加到数据库中。⽐如⼀些⽹站根据用户上传的头像生成⼤中⼩不同尺⼨的图像。
绕过
寻找渲染前后不变的地⽅,替换成⼀句话
白名单验证的突破
修改MIME类型绕过白名单限制(Content-type验证)
MIME(Multipurpose Internet Mail Extensions)多用途互联⽹邮件扩展类型。是设定某种扩展名的文件用⼀种应用程序来打开的⽅式类型,当该扩展名文件被访问的时候,浏览器会⾃动使用指定应用程序来打开。多用于指定⼀些客户端⾃定义的文件名,以及⼀些媒体文件打开⽅式。
id 后缀名 MIME
0 gif image/gif
1 jpg image/jpeg
2 png image/png
3 bmp image/bmp
4 psd application/octet-stream
5 ico image/x-icon
6 rar application/octet-stream
7 zip application/zip
8 7z application/octet-stream
9 exe application/octet-stream
10 avi video/avi
11 rmvb application/vnd.rn-realmedia-vbr
12 3gp application/octet-stream
13 flv application/octet-stream
14 mp3 audio/mpeg
15 wav audio/wav
16 krc application/octet-stream
17 lrc application/octet-stream
18 txt text/plain
19 doc application/msword
20 xls application/vnd.ms-excel
21 ppt application/vnd.ms-powerpoint
22 pdf application/pdf
23 chm application/octet-stream
24 mdb application/msaccess
25 sql application/octet-stream
26 con application/octet-stream
27 log text/plain
28 dat application/octet-stream
29 ini application/octet-stream
30 php application/octet-stream
31 html text/html
32 ttf application/octet-stream
33 fon application/octet-stream
34 js application/x-javascript
35 xml text/xml
36 dll application/octet-stream
37 dll application/octet-stream
00截断绕过白名单限制
条件
php版本⼩于5.3.4 详情关注CVE-2006-7243
php的magic_quotes_gpc为OFF状态
能够进⾏截断的点 :所有跟 路径和文件命名的地方,都可以去测试尝试
GET和POST请求进⾏截断时的区别
post不会像get对%00进⾏解码,所以需要在⼗六进制中⼿动修改。
解析漏洞绕过白名单限制
双重拓展名
apache 文件名解析时,是从后⾯开始检查后缀,按最后⼀个合法后缀执⾏。如: shell.php.xxx 因为 xxx 不被apache解析,所以apache会跳过 .xxx ,⽽解析最后⼀个后缀名,即.php,从⽽把这个文件当php文件解析了
iis解析漏洞
iis6.0
*.asp;1.jpg
iis7.0/7.5/Nginx<8.03
php.ini里默认cgi.fix_pathinfo=1,对其进⾏访问的时候,在URL路径后添加.php后缀名会当做php文件进⾏解析,漏洞由此产生。
上传1.jpg,访问http://www.xxx.com/1.jpg/.php,此时1.JPG会被当做PHP脚本文件来解析。
⼤⼩写
黑名单验证的突破
操作系统特性
windows操作系统对⼤⼩写不敏感,即php和Php在windows看来是⼀样的
Windows系统下,如果上传的文件名中test.php::$DATA会在服务器上生成⼀个test.php的文件,其中内容和所上传文件内容相同,并被解析。即上传文件xxx.php::$DATA = xxx.php
Windows下文件名结尾加⼊.,空格,<,·>,>>>,0x81-0xff等字符,会被windows⾃动去除
语言特性
语言 | 可解析后缀 |
---|---|
php | php,php5,php4,php3,php2,pHp,pHp5,pHp4,pHp3,pHp2,html,htm,phtml,pht,Html,Htm,pHtml |
jsp | jsp,jspa,jspx,jsw,jsv,jspf,jtml,jSp,jSpx,jSpa,jSw,jSv,jSpf,jHtml |
asp/aspx | asp,aspx,asa,asax,ascx,ashx,asmx,cer,aSp,aSpx,aSa,aSax,aScx,aShx,aSmx,cEr |
中间件特性
-
解析漏洞
iis6.0,iis7.0/7.5,iis8.0/10.0
apache -
.htaccess
代码不严谨
双写绕过 (只做了一次的校验删除) 1.ASaspp -> 1.ASp
对于空格,点只做了单次过滤 (只做了一次的校验删除) 1.php. . -> 1.php.
测试思路
使用字典+burp,去fuzz后缀名寻找成功上传的思路
⼿⼯测试
https://gv7.me/articles/2018/make-upload-vul-fuzz-dic/
上传点要么验证做的很好,要么很垃圾,我们没必要盯着一个大的网站的站点去找上传漏洞,可以通过信息收集,去找它一个犄角旮旯地方的上传点,上传绕过机率高..
解析漏洞
如何探查目标是什么类型的web服务器
通过查看相应的http请求,会在头部暴露出web服务器类型
安装浏览器插件
通过第三⽅⽹站
解析漏洞详解
IIS
IIS5.X~6.0
- 目录解析漏洞
服务器默认会把.asp,.asa目录下的文件都解析成asp文件。前提是可以控制文件上传的路径或者是文件名
xxx.asp/xxx.jpg
- 文件命解析漏洞
服务器默认不会取解析分号后⾯的内容。前提是可以控制文件名。
xx.asp;.jpg
- 畸形文件命解析漏洞
iis6.0下的可执⾏文件还有 asa、cer、cdx ,注意,不⼀定能解析aspx,因为aspx是.net环境。
IIS7.0/7.5
- 利用解析图⽚中的代码上传webshell
如果开启Fast-CGI模式,上传1.jpg,内容如下:
<?PHP fputs(fopen('dark5.php','w'),'<?php eval($_POST[cmd])?>');?>
访问 1.jpg/.php ,那么1.jpg就会被解析执⾏。
- fck+iis7.5
a.aspx.a.aspx.jpg..jpg
Apache
不可识别解析后缀
- Apache的文件解析过程是从右到左开始判断解析,如果为不可识别的后缀解析,就再往左判断。
- 在Apache的解析中,除了“php|php3|phtml”等规定的后缀中,任何的后缀加⼊,都是不会被识别解析的,也会被跳过后缀处理。
dark5.php.k1.w2.a3 -> dark5.php
.htaccess
- htaccess文件是Apache服务器中的⼀个配置文件,它负责相关目录下的⽹页配置。通过htaccess文件,可以帮我们实现:⽹页301重定向、⾃定义404错误页⾯、改变文件扩展名、允许/阻⽌特定的用户或者目录的访问、禁⽌目录列表、配置默认文档等功能。
- 该漏洞适用于目标web服务器为apache,并且.htaccess可以被上传执⾏的情况。
- 当.htaccess文件内容为SetHandler application/x-httpd-php时,即设置当前目录所有文件都使用PHP解析,那么⽆论上传任何文件,只要文件内容符合PHP语言代码规范,就会被当作PHP执⾏。不符合则报错。
- 在Apache中如果需要启动 .htaccess,必须在http.conf中设置 AllowOverride 为All
<FilesMatch "1.jpg"> SetHandler application/x-httpd-php </FilesMatch>
Nginx
CGI 和上面IIS7.0/7.5 一样
空字节代码执⾏
dark5.jpg%00.php //类似00截断
双文件上传和竞争上传
双文件上传
应用场景
- 南⽅/良精CMS
- 正则默认匹配第⼀个filename的情况下
利用原理
服务端默认取第⼆个文件作为真正的上传文件,但是在检测时只检测了第⼀个文件。或者只验证了第⼀个filename
的拓展名。
利用⽅法
- 直接在审查元素中添加⼀个上传表单 (在原上传表单下添加一个上传表单)
- burp抓包之后在数据包中添加 (复制多一份原表单的数据并更改为php上传)
竞争上传
应用场景
访问webshell的时候,短时间内可以访问到,再次访问就访问不到了
利用原理
代码逻辑为:先将文件上传到服务器,然后检测后缀名,如果不符合再通过unlink删除文件,因此可以通过条件竞争的⽅式在unlink之前,访问webshell。
利用⽅法
使用burp suite不停的上传,同时用python脚本不停的访问上传的文件。
<?php fputs(fopen("./info.php", "w"), '<?php @eval($_POST["drops"]) ?>'); ?> // 不断的访问上传的文件