文件上传漏洞靶场upload-labs学习(pass16-pass21)

Upload-Labs关卡

  • 0x00 Pass16(exif_imagetype函数绕过)
    • 环境准备
    • exif_imagetype函数
  • 0x01 Pass17(二次渲染绕过)
    • move_uploaded_file函数
    • imagecreatefromjpeg、imagecreatefrompng、imagecreatefromgif函数
    • imagejpeg、imagepng、imagegif函数
    • 过关思路
      • GIF文件插入payload
      • png、jpg文件插入payload
  • 0x02 Pass18(条件竞争绕过)
    • 抓取上传数据包
    • 抓取访问数据包
  • 0x03 Pass19(条件竞争绕过+Apache解析漏洞)
  • 0x04 Pass20(move_uploaded_file函数/.绕过)
  • 0x05 Pass21(explode数组绕过)

0x00 Pass16(exif_imagetype函数绕过)

环境准备

首先需要在本机环境中开启php_exif扩展,否则将会提示如下错误:
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第1张图片
开启php_exif扩展方法详见这篇博客。

分别去掉php_mbstring、php_exif扩展的注释,再将exif块的注释全部清除,此时再执行相应的代码。

文件上传漏洞靶场upload-labs学习(pass16-pass21)_第2张图片

文件上传漏洞靶场upload-labs学习(pass16-pass21)_第3张图片

exif_imagetype函数

从代码可以看到,本关主要考查exif_imagetype($filename)函数的使用,首先了解一下exif_imagetype函数。

exif_imagetype()读取一个图像的第一个字节并检查其签名。 返回值和getimagesize()返回的数组中的索引 2 的值是一样的,但本函数快得多。

常见的返回值有:

1 IMAGETYPE_GIF
2 IMAGETYPE_JPEG
3 IMAGETYPE_PNG
4 IMAGETYPE_SWF
5 IMAGETYPE_PSD
6 IMAGETYPE_BMP

例如选择一张jpg类型的图片上传,返回值应为2
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第4张图片
本关代码为:

function isImage($filename){
    //需要开启php_exif模块
    $image_type = exif_imagetype($filename);
    switch ($image_type) {
        case IMAGETYPE_GIF:
            return "gif";
            break;
        case IMAGETYPE_JPEG:
            return "jpg";
            break;
        case IMAGETYPE_PNG:
            return "png";
            break;    
        default:
            return false;
            break;
    }
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $res = isImage($temp_file);
    if(!$res){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}

由于只检查第一个字节,因此我们使用copy /b 1.png+test.php upload.png生成的图片马尝试绕过。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第5张图片

0x01 Pass17(二次渲染绕过)

move_uploaded_file函数

move_uploaded_file(string $filename, string $destination): bool
本函数检查并确保由 filename 指定的文件是合法的上传文件(即通过 PHP 的HTTP POST上传机制所上传的)。如果文件合法,则将其移动为由 destination指定的文件。

imagecreatefromjpeg、imagecreatefrompng、imagecreatefromgif函数

imagecreatefromgif(string $filename): resource
imagecreatefromgif()返回一图像标识符,代表了从给定的文件名取得的图像。 成功后返回图象对象,失败后返回 false。

imagejpeg、imagepng、imagegif函数

imagepng(resource $image, string $filename = ?): bool
imagepng()将 GD 图像流(image)以 PNG 格式输出到标准输出(通常为浏览器),或者如果用 filename给出了文件名则将其输出到该文件。

过关思路

在这里把每张用户上传的图片都重新生成了,也就是类似于生成缩略图的方式,我们首先使用正常的图片马,上传后下载下来,看看被代码重新生成的文件与源文件有什么不同。

GIF文件插入payload

使用010edit的比较功能。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第6张图片

使用GIF成功的可能性更大,灰色的部分即为相等的部分,因此将要插入的话包含在灰色部分即可。

文件上传漏洞靶场upload-labs学习(pass16-pass21)_第7张图片

插入后上传可成功访问。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第8张图片

png、jpg文件插入payload

而png和jpg相对而言都较难成功, 这里参考了国光的文件上传靶场知识总结的部分内容。
引用他人的项目hxer /imagecreatefrom实现。
使用命令

python poc_png.py -p "$_REQUEST[1]); ?>" -o test.png indexcolor.png

生成带有payload的文件。上传渲染后使用010edit打开。发现payload仍然存在,数据在PLTE块中。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第9张图片而jpg 的渲染图片马我的环境中一直无法成功,后期再进行学习。

0x02 Pass18(条件竞争绕过)

代码如下:

$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 = '上传出错!';
    }
}

抓取上传数据包

在本关中所有符合条件的上传的文件都会被 rename,所有不符合条件的伤处啊都会被unlink,因此上传的文件内容应该为:

 fputs(fopen('xiao.php','w'),'');?>
这里内容pass使用1而不使用字符串也是为了避免引号问题。

首先在未unlink之前将生成木马文件的脚本上传,然后在删除之前访问即可。
抓取上传文件的数据包。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第10张图片
发送到Intruder模块,选择空载荷和无限期的重复。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第11张图片

抓取访问数据包

开始攻击后可以发现upload目录下的test文件会闪烁存在,但时间很短,因此需要抓取一个访问test.php的数据包,重复以上操作。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第12张图片当状态码由404变为200时,文件已经写入成功了。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第13张图片访问shell文件成功执行。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第14张图片

0x03 Pass19(条件竞争绕过+Apache解析漏洞)

这里也是需要用到条件竞争,先使用上面的脚本。

 fputs(fopen('xiao.php','w'),'');?>

根据代码可知,上传的文件必须在以下后缀名中。

 var $cls_arr_ext_accepted = array(
      ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
      ".html", ".xml", ".tiff", ".jpeg", ".png" );

根据Apache解析漏洞规则,无法被解析的文件名会向前解析,因此需要找到一个不被解析的白名单后缀。
且其他zip、ppt、xml等后缀名要么不被重命名,要么直接下载或被解析, 无法完成访问,只有7z不被解析也不会被下载。
此时上传test.php.7z,但会被重命名,因此要在重命名之前上传并访问他。
使用18关的方法上传并访问即可。

0x04 Pass20(move_uploaded_file函数/.绕过)

move_uploaded_file($temp_file, $img_path)中的path可控时,不仅在一定的条件下可以使用%00截断,还可以使用/.使其忽略后面的内容,从而上传恶意文件。

将保存文件的路径修改为/.结尾即可。文件上传漏洞靶场upload-labs学习(pass16-pass21)_第15张图片访问。

http://127.0.0.1/upload-labs/upload/upload-19.php/

文件上传漏洞靶场upload-labs学习(pass16-pass21)_第16张图片

0x05 Pass21(explode数组绕过)

代码如下:

$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'];
        if (!is_array($file)) {
            $file = explode('.', strtolower($file));
        }

        $ext = end($file);
        $allow_suffix = array('jpg','png','gif');
        if (!in_array($ext, $allow_suffix)) {
            $msg = "禁止上传该后缀文件!";
        }else{
            $file_name = reset($file) . '.' . $file[count($file) - 1];
            $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 = "请选择要上传的文件!";
}




根据三目运算符的含义

$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];

即为优先取我们传递的save_name,只有save_name为空时才会使用本身的名字。
再使用

if (!is_array($file)) {
$file = explode('.', strtolower($file));}

将文件名以点.分割为数组。
使用$ext = end($file);函数取最后一个元素为后缀名。
使用reset($file) . '.' . $file[count($file) - 1];将文件名以最后一个元素为后缀重新命名。
当我们传入0=>'test.php',2=>'png'这样一个file时,各部分的输出为:

文件上传漏洞靶场upload-labs学习(pass16-pass21)_第17张图片可以看到满足了本关中后缀的检查、也生成了新的php类型文件。
因此在数据包中构造如下。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第18张图片访问即可成功执行命令。
文件上传漏洞靶场upload-labs学习(pass16-pass21)_第19张图片

你可能感兴趣的:(Upload-Labs,web,安全,网络安全,php)