n1book


文件上传

知识点:服务器把上传的文件放在随机数路径下的话,使用路径穿越进行绕过

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

image-20241208013928661

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

image-20241208012045228

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

image-20241208012120028

image-20241208005800160


文章作者: 0x00dream
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 0x00dream !
  目录