第十一关:%00截断
源码中保存路径是通过参数传递的,可以使用%00截断代码读取的文件扩展名(截断的就是波浪线那块代码生成的文件名),自己设置文件名和扩展名。有两个利用条件:
① php版本小于5.3.4
②php魔术引号关闭
第十二关:00截断
十二关采用POST传输存储路径,而POST不会对%00进行URL解码,所以需要在抓包的hex中修改为0x00,从而进行内存截断。第十三关:图片马制作
copy 1.png /b + phpinfo.php /a phpinfo.png
/A 表示一个 ASCII 文本文件。
/B 表示一个二进位文件。
1.png是一张真正的图片。然后利用文件包含执行phpinfo.jpg。
第十四关:图片马上制作
使用上一关的手法已经无法绕过,可以尝试上传真正的PNG图片,并在末尾添加一句话木马,启用文件包含执行。第十五关:图片木马制作
相比于前几关更关注真实文件格式,使用了exif_imagetype() 读取一个图像的第一个字节并检查其签名。没啥用,用同样方式也可以上传。
第十六关:文件渲染绕过
说多都是泪,百度下载的图片好多不行,要不就是解析出错,我奉上我测试可行的gif。我是用的gif图片绕过。需要找到渲染前后没有变化的位置,然后将php代码写进原gif图片。先上传一个test.gif,然后下载它773.gif,hex对比。我使用的对比工具是beyond compare 4,工具很多,关键是会用。然后点击保存那个图标,重新上传,最后使用文件包含执行。
其他渲染绕过方法。我试了jpg的,没生成所谓的php代码,可能是图片问题。
第十七关:条件竞争
源码存在逻辑漏洞,先上传文件,然后再删除非白名单文件。可以通过大量的上传导致删除跟不上上传,此时再去访问,即可。
第十八关:条件竞争
相比于上一关,这一关用的是上传一个包含php的图片文件。第十九关:CVE-2015-2348
上传图片马,抓包00截断图片扩展,留下php的后缀即可。特别要注意php的版本,小于5.3.4才可以,还有魔术引号关闭。
网传大小写绕过和黑名单绕过都可以,还有/.绕过,实现方法很多。记得访问的时候是1.php,因为后面的jpg后缀已经被内存截断了。
第二十关:数组绕过
$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
//检查MIME
$allow_type = array('image/jpeg','image/png','image/gif');
if(!in_array($_FILES['upload_file']['type'],$allow_type)){//这一步是检查上传的文件是否为规定的类型
$msg = "禁止上传该类型文件!";
}else{
//检查文件名
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];//如果通过post传递的参数save_name为空,$file就为上传文件本来的名字的值,否则为post传递的save_name的值
if (!is_array($file)) {//因为我们都是填写了保存名称,即用post传递了save_name的值,所以这里判断我们填写的保存名称是否为一个数组
$file = explode('.', strtolower($file));//不是一个数组就利用.对文件名进行分割
}
$ext = end($file);//数组最后一个值即文件后缀名给$ext
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {//再一次进行判断是否为允许上传的类型
$msg = "禁止上传该后缀文件!";
}else{
$file_name = reset($file) . '.' . $file[count($file) - 1];//将数组count($file)-1的值给了$file_name,最后拼接到数组第一个元素后后,reset()为将读取数组第一个元素
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$msg = "文件上传成功!";
$is_upload = true;
} else {
$msg = "文件上传失败!";
}
}
}
}else{
$msg = "请选择要上传的文件!";
}
它用end()读取最后数组最后一个值来进行过滤,又将file[count(file) - 1]的值拼接到数组第一个元素后后,所以可以上传save_name为一个数组,数组第一个元素为*.php,第二个元素为空,第三个元素为jpg。此时利用jpg通过判断,将空拼接到.php后文件仍为.php。构造payload。