文件上传漏洞原理
在文件上传的功能处,若服务端脚本语言未对上传的文件进行严格验证和过滤,导致恶意用户上传恶意的脚本文件时,就有可能获取执行服务端命令的能力,这就是文件上传漏洞。
文件上传漏洞对Web应用来说是一种非常严重的漏洞。一般情况下,Web应用都会允许用户上传一些文件,如头像、附件等信息,如果Web应用没有对用户上传的文件进行有效的检查过滤,那么恶意用户就会上传一句话木马等Webshell,从而达到控制Web网站的目。
诱因:服务端脚本语言未对上传的文件进行严格验证和过滤
文件上传漏洞原理图解:
文件上传漏洞高危触发点
- 相册、头像上传
- 视频、照片分享
- 附件上传(论坛发帖、邮箱)
- 文件管理器:编辑器
文件上传漏洞分类
- 任意上传
- JS验证:能在可控制台能改
- MIME-type检测
- 文件头检测
- 文件扩展名黑白名单检测
- 文件加载检测
文件上传漏洞分类图解
任意文件上传:
没有任何校验
绕过JS上传:
校验发生在前端
绕过后端校验上传:
校验发生在后端
绕过文件类型校验
绕过扩展名校验
绕过文件头校验
解析漏洞上传:
中间件解析漏洞
其他类型
文件上传漏洞成因
-
未过滤或Web前端过滤被绕过
-
文件检测被绕过
-
中间件解析
-
不完善的黑名单扩展名
-
文件路径截断
-
HTTP不安全方法(PUT协议)
漏洞成因分析及案例
1、 未过滤或者web前端过滤被绕过
未过滤是没有对文件上传格式做限制,前端绕过是指当前页面中js对上传文件做限制,可通过HTTP抓包工具进行改包上传。
这类相对好理解,前部分是可以任意上传文件,后部分是因为只是前端限制,只用上传可以上传的文件,然后抓包对后缀进行修改就可以成功。
2、文件内容检测被绕过
检测CONTENT-TYPE内容(判断是否为特定数据类型),检测文件头,检测文件扩展功能相关内容。
(1) Content-Type绕过
这里看到让我们上传一个php文件,但是上传后显示[非图片文件]
这里我使用burpsuite进行截包然后重放。
发现并没用但是将Content-Type:改为 image/jpeg则成功上传
可以看到这里只是对content-Type进行验证,我们只需要修改成图片的格式就上传成功。
(2) 文件头检测绕过
//检查是否图片
if(function_exists('getimagesize')) {
$tmp_imagesize = @getimagesize($new_name);
list($tmp_width, $tmp_height, $tmp_type) = (array)$tmp_imagesize;
$tmp_size = $tmp_width * $tmp_height;
if($tmp_size > 16777216 || $tmp_size < 4 || empty($tmp_type) || strpos($tmp_imagesize['mime'], 'flash') > 0) {
@unlink($new_name);
return cplang('only_allows_upload_file_types');
}
}
这是php的一串检查图片代码,使用getimagesize函数无法判断其图片是无效的
我们只需要再上传的文件头加入GIF89a 便可以欺骗服务器认为我们的文件是图片。
这里举几个常见的文件头对应关系:
(1) .JPEG;.JPE;.JPG,"JPGGraphic File"
(2) .gif,"GIF 89A"
(3) .zip,"Zip Compressed"
(4) .doc;.xls;.xlt;.ppt;.apr,"MS CompoundDocument v1 or Lotus Approach APRfile"
3、中间件解析
由于中间件本身的缺陷,再对上传文件进行解析时会出现一些不可预料的错误从而导致被利用进行上传绕过。
(1) IIS6.0解析漏洞
第一种,当建立*.asp、*.asa格式的文件夹时,其目录下任意文件都会被iis当作asp文件来解析。
例如:创建xxx.asp目录那么在xxx.asp目录下如果存在1.txt文件会被当做1.asp文件来执行。
第二种,在IIS6.0下分号后的不被解析。
例如:xxx.asp;.jpg会被服务器看作为xxx.asp文件
(2) IIS7.0/7.5畸形解析漏洞
IIS7.0/7.5中:任意文件名/任意文件名.php就会被解析为php
(3) Apache解析漏洞
在Apache 1.x和Apache 2.x中存在解析漏洞。
Apache在解析文件时有一个原则,当碰到不认识的扩展名时,将会从后向前解析,直到碰到认识的扩展名为止,如果都不认识,则会暴露其源代码。
如:1.php.rar.sa.xs就会被解析为php,可以据此来绕过文件名限制
(4) Nginx<8.03畸形解析漏洞
在默认Fast-CGI开启的情况下上传一个xxx.jpg,内容为<?php eval($POST[‘cmd’])?>的文件然后访问xxx.jpg/.php在该目录下就会生成一句话木马文件xxx.php。
(5) PHP CGI解析漏洞
当php的配置文件中的选项cgi.fix_pathinfo= 1开启时,当访问http://www.example.com/xxx.txt/xxx.php时,若xxx.php不存在,则PHP会递归向前解析,将xxx.txt当作php脚本来解析
4、不完善的黑名单扩展名
因为程序员在开发文件上传时加入了不允许上传类型的黑名单,但是黑名单内容并不完善,这时候我们可以利用一些其他扩展名绕过黑名单限制,这里就不进行详细的赘述了,这里列举一些可用于绕过的文件名:
- PHP: php2、php3、php5、phtml、pht
- ASP: aspx、ascx、ashx、cer、asa
- JSP: jspx
5、文件路径截断
(1)php%00截断
利用条件:php版本小于5.3.4,php的magic_quotes_gpc
为OFF状态
详情:CVE-2006-7243
(2)Nginx<8.03空字节代码执行漏洞
影响版本:0.5,0.6,0.7<=0.7.65,0.8<=0.8.37
Nginx在图片中嵌入PHP代码然后访问xxx.jpg%00.php来执行其中的代码
(3)截断后缀上传
部分上传功能在对后缀名进行验证时存在缺陷,导致在文件写入过程中产生错误,导致可通过十六进制截断符(%00)对后缀进行截断。
例如:
POST /Upload HTTP/1.1
Host: www.example.com
Proxy-Connection: keep-alive
Content-Length: 363
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5YpmA9D3wW207kB7
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
------WebKitFormBoundary5YpmA9D3wW207kB7
Content-Disposition: form-data; name="uploadfile"; filename="xxx.php%00.jpg"
Content-Type: image/jpg
<?php eval($POST[‘CMD’]);?>
------WebKitFormBoundary5YpmA9D3wW207kB7--
上传处理时将对检测到%00(这里需要对%00进行urldecode)并对.jpg字符串进行截断删除,最终文件名为xxx.php导致可成功上传动态脚本到服务器上
6、HTTP不安全方法(PUT协议)
(1)WebDav漏洞
WebDav是一种基于HTTP1.1协议的通信协议,它扩展了HTTP协议。在开启WebDav后若支持PUT、Move、Copy、Delete等方法,就会存在安全隐患。
测试流程:
首先提交options 请求看服务器是否支持此类方法
OPTIONS /HTTP/1.1
Host:www.example.com
通过PUT方法上传脚本文件
PUT /xxx.txtHTTP/1.1
Host:www.example.com
Content-Length:30
1 <?php eval($POST[‘cmd’]); ?>
通过move或者copy方法移动文件
COPY /xxx.txtHTTP/1.1
Host:www.example.com
Destination:http://www.example.com/cmd.asp
(2)发布的tomcat漏洞
http://blog.csdn.net/u011499747/article/details/78108240
其他的上传利用
1、结合文件包含
很多时候网站检测的过于严格,我们只能上传白名单的文件格式,这时我们可以尝试去看看网站是否存在一些文件包含漏洞,结合我们上传的文件进行联合利用。
2、黑白名单共存
之前我遇到过这样一个网站,就是黑白名单共存。该网站的架构是这样的,在后台有个地方是可以设置上传的白名单内容,在代码层面又含有黑名单检测。当时猜测他网站的判断是这样的:
if(正则匹配在白名单中==正则匹配不在黑名单中)
上传成功
Else:
上传失败
于是我清空了白名单的内容,然后上传了在黑名单中的文件格式于是,代码false==false 上传成功。
3、利用源代码进行文件上传
很多时候我们通过各种源码泄露,例如:.svn、.git、网站备份、任意文件下载等等获取到了网站的源码,我们可以进行代码审计寻找文件上传的接口,我之前测试过的很多网站他们的代码都有一个api接口用来处理上传的文件,而黑白名单仅仅是进行了上传检测,我们可以在本地直接构造一个上传页面然后调用这个api接口直接上传文件解析。
4、操作系统解析
由于windows会将文件的后缀中的空格以及点进行过滤,如果遇到是黑名单校验的,如限制不允许上传PHP文件,而系统又是windows系统,那么我们可以上传xx.php ,或者xx.php.,通过这种方式就可以绕过黑名单检验的文件上传!
5、htaccess文件解析
如果Apache中.htaccess可被执行并可被上传,那么可以尝试在.htaccess中写入:
<FilesMatch"xxx.jpg"> SetHandler application/x-httpd-php </FilesMatch>
然后再上传xxx.jpg的木马,这样xxx.jpg就可被解析为PHP文件了。
文件上传的防御
- 客户端检测,使用 js 对上传图片检测,包括文件大小、文件扩展名、文件类型等
- 服务端检测,对文件大小、文件路径、文件扩展名、文件类型、文件内容检测、对文件重命名等
- 服务器端上传目录设置不可执行权限
- 检查网站有没有文件解析漏洞和文件包含漏洞
- 将文件上传到单独的文件服务器,并且单独设置文件服务器的域名
总结
作为获取shell最直接的方法,上传地方检测是最为严密的,我们需要想方设法的去尝试各种思路才能绕过各种限制。随着信息安全发展的不断壮大,文件上传也越来越难以被利用,但是在很多系统管理层后台是并没有限制的,看上去越强壮的网站内部越脆弱不堪。我们需要细心挖掘每一个点并加以利用。比起基础来说更多的是经验,只有经验不断增加才会有更多的思路拓展。