文件上传
知识点:服务器把上传的文件放在随机数路径下的话,使用路径穿越进行绕过
copy 001.jpeg/b + test.php/a 2.jpg # 图片马制作 图片马必须配合文件包含漏洞才能使用
题目源码
<?php
header("Content-Type:text/html; charset=utf-8");
// 每5分钟会清除一次目录下上传的文件
require_once('pclzip.lib.php');
if(!$_FILES){
//题目html省略
show_source(__FILE__);
}else{
$file = $_FILES['file'];
if(!$file){
exit("请勿上传空文件");
}
$name = $file['name']; //这里获取的文件名包含后缀
$dir = 'upload/'; //上传路径第一层---> /upload
$ext = strtolower(substr(strrchr($name, '.'), 1)); //strrchr($name,'.')找到$name中最后一个点号的位置,然后substr将最后一个点号后面的字符串截取出来作为文件的后缀名。
$path = $dir.$name;
//检查当前路径下的所有子孙目录中是否有非jpg gif png的文件,如果有则删除掉
function check_dir($dir){
$handle = opendir($dir);
while(($f = readdir($handle)) !== false){
if(!in_array($f, array('.', '..'))){ //确保当前路径不是 . 和 ..
if(is_dir($dir.$f)){ //如果当前路径是$dir下的子目录
check_dir($dir.$f.'/'); //再继续检查下一级目录
}else{ //如果当前路径是$dir下的文件
$ext = strtolower(substr(strrchr($f, '.'), 1)); //把它最后一个点号后面的后缀取出来
if(!in_array($ext, array('jpg', 'gif', 'png'))){
unlink($dir.$f); //如果该文件后缀不是jpg gif png的话,就删除
}
}
}
}
}
//如果当前还没有upload目录,就创建
if(!is_dir($dir)){
mkdir($dir);
}
//创建一个随机数值作为文件上传的路径--->tmp_dir=/upload/随机数/
$temp_dir = $dir.md5(time(). rand(1000,9999));
if(!is_dir($temp_dir)){
mkdir($temp_dir);
}
if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){
if($ext == 'zip'){
//如果是压缩文件,则进行解压
$archive = new PclZip($file['tmp_name']); //使用PclZip函数进行解压
foreach($archive->listContent() as $value){ //递归解压后的文件
$filename = $value["filename"]; //此文件名包含后缀
if(preg_match('/\.php$/', $filename)){ //正则匹配每个文件结尾的位置是否为.php($是匹配行尾)
exit("压缩包内不允许含有php文件!");
}
}
//extract方法将压缩包解压到$temp_dir目录下,如果==0则表示解压失败
if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {
check_dir($dir); //将upload子孙目录下中所有后缀名不在白名单中的文件都删除掉
exit("解压失败");
}
//即使解压成功也会将其中所有后缀名不在白名单中的文件删除
check_dir($dir); //删除upload子孙目录中所有后缀不在白名单中的文件
exit('上传成功!');
}
else{ //如果不是压缩文件,则将上传的文件放到tmp_dir目录下,文件名为上传文件的文件名
move_uploaded_file($file['tmp_name'], $temp_dir.'/'.$file['name']);
check_dir($dir);
exit('上传成功!');
}
}else{
exit('仅允许上传zip、jpg、gif、png文件!');
}
}
解题思路:
做法1:目录穿越
因为它检查的后缀名是最后一个点号后的后缀名,上传后放到的目录为/upload/随机数/filename所以构造/../../shell.php.jpg来进行目录穿越,使shell.php.jpg被放到根目录下,而且文件末尾的后缀为jpg,可以绕过服务器端的检测。
将shell.php.jpg压缩为一个压缩包,然后用010Editor直接打开压缩包,修改其中的文件名为../../shell.php.jpg

做法2:直接上传shell.php.jpg,然后访问url/upload页面

点击去上传的目录,查看文件,拿到flag

