upload-labs全通关

upload-labs pass-01

直接上传一句话木马貌似不行,尝试抓包看看

发现全是get请求抓不到post传参上传一句话木马的包,合理猜测是不是前段验证,F12禁用JavaScript验证试试看

可以看到成功上传并且返回了图片

使用phpinfo()命令发现一句话木马成功上传

同理,是不是我们上传一个图片(此时通过了前段白名单验证是可以抓到包的)再抓包,修改图片内容为一句话木马也可行?

返回了上传文件路径,确实可行(单纯上传一个图片不修改后缀为php可是不可以执行命令的哦)

upload-labs pass-02

这次直接上传一句话木马并且禁止JavaScript验证也不行了,上传一个图片试试

看来图片可以上传

像上一道题一样上传时抓包再修改文件内容后缀,成功了

那能不能上传一句话木马然后修改文件类型呢

将content-type修改为image/jpeg、image/png、image/gif中的任何一种

成功了

upload-labs pass-03

直接上传一句话木马告诉我提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!

这次哪怕开启禁用JavaScript验证也不行,这次的验证不是简单的前段验证了,猜测是检测后缀,这时我们可以使用phtml文件

通常,在嵌入了php脚本的html中,使用 phtml作为后缀名;

完全是php写的,则使用php作为后缀名。



这两种文件,web服务器都会用php解释器进行解析。

修改后缀后为phtml后,可以看到返回上传后的文件路径

upload-labs pass-04

这次也不说什么被过滤了,就告诉你不能上传,看看源码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空

        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

可以看到基本所有的大小写绕过上面的全给你ban了,不是哥们,才第四关就ban这么多绕过?

当然还有办法,可以看到这里并没有禁止上传.htaccess文件,那就可以试试看

二、原理
原理:.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。
提供了针对目录改变配置的方法, 
即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。
作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。

简而言之我们可以撰写.htaccess文件的内容来使我们上传的文件能够被作为php文件解析,题目又要求我们上传图片,那我们就可以先上传.htaccess文件再上传图片马

<IfModule mime_module>
SetHandler application/x-httpd-php    #在当前目录下,所有文件都会被解析成php代码执行
</IfModule>

图片马上传成功,

upload-labs pass-05

跟前面没有对后缀进行过滤的源码比较发现少了个转化为小写,那就尝试一下Php(至于为什么不试试pHp啥的,因为都被过滤了)

成功上传

upload-labs pass-06

可以看到源码少了个首尾去空,猜测在后缀前面或者后面加上空格即可绕过,开始尝试(注意要在抓取的数据包里面进行修改,不然windows重命名是会自动给你去掉空格的)

成功上传了但是一直因为windows会自动删空格导致我无法使用phpinfo()命令,很破防,哪位高人要是成功了辛苦在评论区吱一声

upload-labs pass-07

源码显示少了个删除文件名末尾的点,猜测在php文件名后加上一个.即可绕过

直接在windows里面重新命名在后缀最后加个点会被直接删除,这下又得在数据包里面改了

成功绕过

upload-labs pass-08

查看源码,发现少了去除::$DATA,可以在文件名后加上以进行绕过

补充知识:php在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,
不会检测后缀名,且保持"::$DATA"之前的文件名 他的目的就是不检查后缀名。

不是哥们,windows的文件名后缀不能包括诸如:这样的字符,又只能在数据包里面改了

欧克,也是成功上传了

upload-labs pass-09

其实仔细对比会发现和第四关的源码基本上一模一样,但是第四关没有过滤.htaccess文件,这里他是把.htaccess文件给过滤了的,那该怎么办呢

这里发现既删除了文件名末尾的点还首尾去空,这样我们可以再php后缀后面加上点 空格 点

:::info
补充知识:deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来,而php后面的点会被windows自动视为空

:::

同样,在抓取的数据包中修改后缀

upload-labs pass-10

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = str_ireplace($deny_ext,"", $file_name);
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = UPLOAD_PATH.'/'.$file_name;        
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

可以看到黑名单很长但是没有大小写的过滤,那就试一下大小写

上传成功了但是后缀没了,估计有函数会检测上传的文件名中是否包含php,有的话直接去除(大小写一样过滤),这样的话我们就利用嵌套,在php里面再套一个php

成功了,再看看phpinfo();

upload-labs pass-11

$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 = $_GET['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类型文件!";
    }
}

以上就是该题的源码,最关键的代码如下

:::info
$ext_arr = array('jpg','png','gif');//说明本题只允许上传.jpg,.png,.gif后缀文件

$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);

//这里的strrpos结合参数应该是查找上传的文件名中最后一个点出现的位置,+1是为了跳过'.'

//substr表示在上传文件名中分割出.之后的东西,也就是拓展名

:::

如果是白名单检测的话,我们可以采用00截断绕过。00截断利用的是php的一个漏洞。在 php<5.3.4 版本中,存储文件时处理文件名的函数认为0x00是终止符。于是在存储文件的时候,当函数读到 0x00(%00) 时,会认为文件已经结束。

例如:我们上传 1.php%00.jpg 时,首先后缀名是合法的jpg格式,可以绕过前端的检测。上传到后端后,后端判断文件名后缀的函数会认为其是一个.jpg格式的文件,可以躲过白名单检测。但是在保存文件时,保存文件时处理文件名的函数在遇到%00字符认为这是终止符,于是丢弃后面的 .jpg,于是我们上传的 1.php%00.jpg 文件最终会被写入 1.php 文件中并存储在服务端。

综上所述,我们先上传一个一句话木马php文件,然后再改后缀

然后再访问返回的文件路径,即可获取敏感信息

upload-labs pass-12

$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类型文件!";
    }
}

和上一道题一样的源码和提示

不同的是这一次路径是post传参上去的,这里不得不提POST传参的话不会像GET传参那样自动对%00进行url解码,所以我们可以

:::info
对%00进行解码或在16进制中修改,POST不会像GET那样对%00进行自动解码。

:::

原因

为什么 POST 传参不会自动对 %00 进行 URL 编码?
GET 参数在 URL 中,需要符合 URL 规范,浏览器通常会自动进行 URL 编码,以防止 URL 被截断或解析错误。
POST 的数据在请求体中,并不会影响 URL 解析,因此浏览器或客户端不会主动进行编码,而是按照开发者提供的数据原样发送。
POST 传参的编码依赖于 Content-Type,不同的 Content-Type 处理方式不同:
application/x-www-form-urlencoded 需要手动编码,服务器会解析 key=value 形式的数据。
application/json 不需要 URL 编码,而是以 JSON 格式发送,例如:
json
复制
编辑
{"name": "John", "message": "Hello"}
multipart/form-data 直接发送二进制数据,不进行 URL 编码

upload-labs pass-13

这一关就开始涉及图片马了,这里我想直接修改一句话木马文件为jpg看能不能成功,但是源码里面写了会检查图片的前两个字节

补充:
Png图片文件包括8字节:89 50 4E 47 0D 0A 1A 0A。即为 .PNG
Jpg图片文件包括2字节:FF D8。
Gif图片文件包括6字节:47 49 46 38 39|37 61 。即为 GIF89(7)a。
Bmp图片文件包括2字节:42 4D。即为 BM
    
图片马制作:
在cmd里执行 **copy logo.jpg/b+test.php/a test.jpg**
#logo.jpg为任意图片;test.php 插入的木马文件;test.jpg 生成的图片木马
转载自csdn

直接修改php文件是不能的,所以还是老老实实的用cmd制作图片马吧

制作完以后上传图片马

点击黄色的文件包含漏洞

利用get传参访问上传的图片马即可,位置的话就在抓包软件里面看

upload-labs pass-14

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

源码里面可以看到不仅检查了图片文件前两位,还使用了getimagesize函数

getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。
主要是针对*.php直接更改文件后缀为图片后缀,上一题创建的图片马仍然可以使用。

这边仍然使用正常图片马也可以完成之前操作

upload-labs pass-15

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

这一关使用了一个exif_imagetype函数,第一次见上网查了一下

exif_imagetype() 读取一个图像的第一个字节并检查其签名。如果发现了恰当的签名则返回一个对应的常量,否则返回 FALSE。返回值跟getimagesize() 返回的数组中的索引 2 的值是一样的,但exif_imagetype函数快得多。

用之前的图片马依然可以绕过

upload-labs pass-16

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){
    // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
    $filename = $_FILES['upload_file']['name'];
    $filetype = $_FILES['upload_file']['type'];
    $tmpname = $_FILES['upload_file']['tmp_name'];

    $target_path=UPLOAD_PATH.'/'.basename($filename);

    // 获得上传文件的扩展名
    $fileext= substr(strrchr($filename,"."),1);

    //判断文件后缀与类型,合法才进行上传操作
    if(($fileext == "jpg") && ($filetype=="image/jpeg")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromjpeg($target_path);

            if($im == false){
                $msg = "该文件不是jpg格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".jpg";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagejpeg($im,$img_path);
                @unlink($target_path);
                $is_upload = true;
            }
        } else {
            $msg = "上传出错!";
        }

    }else if(($fileext == "png") && ($filetype=="image/png")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefrompng($target_path);

            if($im == false){
                $msg = "该文件不是png格式的图片!";
                @unlink($target_path);
            }else{
                 //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".png";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagepng($im,$img_path);

                @unlink($target_path);
                $is_upload = true;               
            }
        } else {
            $msg = "上传出错!";
        }

    }else if(($fileext == "gif") && ($filetype=="image/gif")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromgif($target_path);
            if($im == false){
                $msg = "该文件不是gif格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".gif";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagegif($im,$img_path);

                @unlink($target_path);
                $is_upload = true;
            }
        } else {
            $msg = "上传出错!";
        }
    }else{
        $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
    }
}

这一关考的就是二次渲染,会把你上传后的图片重新渲染一遍然后返回再上传,这样的话辛辛苦苦写在图片里的一句话木马就会消失不见,目的就是要防止渲染以后去马

但是本题貌似有点问题,上传jpg以后服务器报错,有问题

本题可以参考以下大佬的wp

https://xz.aliyun.com/news/2337?time__1311=CqRxnD0D9DuDBAYD%2FibiQqqiKTwh1SUeD&u_atoken=37794ef80237d8cc1d329a10bca7f0d0&u_asig=0a47315217424633149734001e00fb#toc-13

gif图片可以正常上传,我们试试gif的二次渲染

将上传后的gif下载后和原来写了马的gif一起放入010editor中对比

发现写入的马真的被删了

关于绕过gif的二次渲染,我们只需要找到渲染前后没有变化的位置,然后将php代码写进去,就可以成功上传带有php代码的图片了

使用010 editor的工具,再点击比较


可以看到,黄色得到部分里面就是两个gif中相同的部分,在黄色部分写入马即可

成功执行

posted @ 2025-09-19 20:43  朱迪Judy  阅读(32)  评论(0)    收藏  举报