0x00 前言
文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
0x01 服务器解析漏洞
-
IIS解析漏洞
1.当建立*.asa、*.asp格式的文件夹时,其目录下的任意文件都将被IIS当作asp文件来解析。例如,建立文件夹hack.asp,在其中的文件会被当作asp脚本执行。
2.当文件为*.asp;1.jpg,IIS6.0会以asp脚本来执行(’;'之前的后缀名才有效)
3.WebDav漏洞:一种基于HTTP1.1协议的通信协议,它拓展了HTTP协议,在GET、POST等几个标准方法外添加了一些新的方法,使得HTTP协议更强大,但却增加了安全隐患。IIS Write可快速探测服务器是否存在WebDav的安全隐患。
-
Apache解析漏洞
Apache1.x和2.x存在解析漏洞,当解析文件遇到不认识的扩展名时,将会从后往前解析,知道遇到认识的扩展名为止,然后将其解析。
Apache详细解析扩展名列表:Apache\conf\mime.types -
PHP CGI解析漏洞
PHP配置文件中:cgi.fi: x_pathinfo选项在某些版本默认开启
当访问不存在的文件时,PHP会向前递归解析
http://www.xxx.com/1.jpg/1.php 1.php不存在时,1.jpg会被当做脚本解析。
0x02 绕过上传漏洞
程序员在防止上传漏洞时可以分为以下两种
-
客户端检测:客户端使用JavaScript检测,在文件未上传时,对文件进行验证。
Upload.html页面使用JavaScript对文件扩展名验证,如果不是白名单中的扩展名,那么Form表单将不会提交至服务器,代码如下:
<html> <head> <title>图片上传</title> <script type="text/javascript"> function checkFile() { var flag = false; //是否可以上传的标志位 var str = document . getElementById("file") .value; //获取文件名 str = str.substring (str. lastIndexOf('.') + 1); //得到扩展名 var arr = new Array('png', 'bmp', 'gif', 'jpg'); //允许上传的扩展名 for(var i = 0 ;i< arr.length; i++) { if(str==arr[i]) { flag = true; } } if(!flag) { alert('文件不合法!!'); return flag ; } //循环判断文件名是否合法 } </script> </head> <body> <form action="upload. php" method="post" onsubmit=" checkFile " enctype="multipart/ form-data"> <input type="file" name="file" id="file" /><br/> <input type="submit" value="提交" name="submit" /> </ form> </body> </html>
Upload.php用来接收文件,在接收文件后,将文件重命名保存,代码如下:
<?php ; if (isset($_ POST ["submit"])) { $name = $_ FILES[' file'l ['name']; //接收文件名 $name = md5 (date('Y-m-d h:m:s')) .strrchr ($name, ".") ; //文件重命名操作,保留原有扩展名 $size = $_ FILES['file']['size']; //接收文件大小 $tmp = $_ FILES['file']['tmp_ name']; //临时路径 move_ uploaded_ file ($tmp, $name) ; //移动临时文件到当前文件目录 echo "文件上传成功! path:". Sname; } ?>
绕过方法:
1.使用FireBug
当单击“提交”按钮后,Form表单将会出发onsubmit事件,该事件将会调用 checkFile函数来检测文件扩展名是否合法,并返回一个布尔值。可以使用FireBug将onsubmit事件删除,绕过JavaScript函数验证。
2.中间人攻击
中间人攻击这种方式与FireBug完全不同,FireBug 是删除客户端的JavaScript 验证,而使用Burp Suite则是按照正常的流程通过JavaScript验证,然后在传输中的HTTP层做手脚。首先把木马文件扩展名改为一-张正常图片的扩展名,比如JPG扩展名,在上传时使用Burp Suite拦截上传数据,再将其中的扩展名jpg修改为php,就可以绕过客户端验证。
注:在HTTP协议中有请求头Content-Length,代表实体正文长度,如果此
时的filename 修改也就意味着实体正文长度增加或者减少了,这时就应该修改Content-Length请求头,如: Content-Length长度为200,把文件流中的filename= "xxser.jpg”修改为filename=“1.php”。 更改后,实体正文少了4个字符,所以需要把Content-Length修改196, 如果不修改上传可能会失败。 -
服务器端检测:服务器端脚本一般会检测文件的MIME类型,检测文件扩展名是否合法,甚至检测文件中是否嵌入恶意代码。
1.黑名单过滤:定义一系列不安全的扩展名,服务器端在接受文件后与黑名单扩展名对比,如果发现匹配,则认为文件不合法。代码如下:
<?php $Blacklist = array('asp','php','jsp','php5','asa','aspx'); if(isset($_POST["submit"])) { $name = $_FILES['file']['name']; $extension = substr(strrchr($name, "."), 1); $boo = false; foreach ($Blacklist as $key => $value) { if($value==$extension) { $boo = true; break; } } if(!$boo) { $size = $_FILES['file']['size']; $tmp = $_FILES['file']['tmp_name']; move_uploaded_file($tmp, $name); echo "文件上传成功!"<br/> path:".$name; } else { echo "文件不合法!!"; } } ?>
绕过方法:从黑名单中找到web开发人员忽略的扩展名、Windows系统下,文件名以".“或者空格结尾,系统会自动去除,如上传"asp.”、"asp "。
2.白名单过滤:定义允许上传的扩展名,在获取到文件扩展名后对扩展名进行迭代判断,如果匹配,则认为合法。代码如下:
<?php $WhiteList = array('rar', 'jpg', 'png', 'bmp', 'gif', 'jpg', 'doc'); //白名单 if (isset($_ POST ["submit"])) { $name = $_ FILES[' file'l [ 'name'l ; //接收文件名 $extension = substr (strrchr ($name, ".") ,1); //得到扩展名: $boo = false; foreach (SWhiteList as Skey => $value) { if ($value==$extension) { //迭代判断是否有命中 $boo = true ; } } if ($boo) { //如果有命中,则开始文件上传操作 $size = $_ FILES['file']['size']; //接收文件大小 $tmp = $_ FILES['file'] ['tmp_ name']; //临时路径 move_ uploaded_ file ($tmp, $name) ; //移动临时文件到当前文件目录 echo "文件. 上传成功!<br/> path:" . $name; } else { echo "文件不合法! !"; } } ?>
3.MIME验证:MIME类型用来设定某种扩展名文件的打开方式,当具有该扩展名的文件被访问时,浏览器会自动使用指定的应用程序打开。上传文件时,对文件MIME类型做验证。代码如下:
if($_ FILES['file']['type']==" image/jpeg" ){ //判断是否是JPG格式 $ imageTempName=$_ FILES['file'l ['tmp_ name']; $ imageName =$_ FILES['file'] ['name'l ; $last = substr ($ imageName, strrpos ($ imageName, ".")) ; if(!is_ dir ("uploadFile")) { mkdir ("uploadFile") ; $ imageName = md5 ($ imageName) . $last; move_ uploaded_ file ($imageTempName, " ./uploadFile/" . $ imageName) ; //指定.上传文件到uploadFile目录 echo("文件上传成功!! path = /uploadFile/ $ imageName") ; }else{ echo("文件类型错误,请重新上传..."); exit() ;
绕过方法:使用burp suite拦截查看MIME类型,将HTTP请求中的content-type修改为image/jpeg类型,即可通过验证。
4.截断上传攻击
使用burp suite拦截请求,将文件上传名称更改为1.asp xx.jpg,然后单击hex选项卡进入十六进制编辑模式,将文件名中的空格的十六进制数20改为00,即NULL,单击GO选项,最终上传的文件为1.asp,其余字符被截断。
0x03 文本编辑器上传漏洞
常见的文本编辑器有FCKEditor、Ewebeditor、UEditor、KindEditor、XHeditor等,这类编辑器的功能类似,都具有图片上传、视频上传、远程下载等功能。
1.敏感信息暴露
查看版本信息/FCKeditor/editor/dialog/fck_about.html
默认上传页面/FCKeditor/editor/filemanager/browser/default/browser.html
/FCKeditor/editor/filemanager/browser/default/connectors/test.html
/FCKeditor/editor/filemanager/upload/test.html
/FCKeditor/editor/filemanager/connectors/test.html
/FCKeditor/editor/filemanager/connectors/uploadtest.html
其他敏感文件/FCKeditor/editor/filemanager/connectors/aspx/connector.aspx
/FCKeditor/editor/filemanager/connectors/asp/connector.asp
/FCKeditor/editor/filemanager/connectors/php/connector.php
2.黑名单策略错误:在FCKeditor<=2.4.3版本中采用黑名单机制,忽略了asa和cer等未知风险扩展名。
3.二次上传、建立畸形文件夹
0x04 修复上传漏洞
上传漏洞形成的主要原因:
- 目录过滤不严,攻击者可能建立畸形目录
- 文件未重命名,攻击者可能利用Web容器解析漏洞
解决方案:
- 文件扩展名与白名单进行比较,不合法则不能上传
- 对文件进行重命名
- 服务器、Web容器合理搭配