秤陷曲 发表于 2025-6-20 22:59:35

upload-labs靶场通关教程

upload-labs靶场通关教程

Pass-01


我们先上传带有一句话木马的1.php


查看页面源代码发现是前端js弹窗,我们直接禁用前端即可。
再进行上传1.php,我们就可以上传了。

Pass-02

做完每一题之后,我们最好清理一下上传的文件,以免对后续操作产生影响。
依旧上传1.php,但是发现不行

我们抓包,将content-Type改成image/png,再次上传发现成功上传

从源码上的角度去看

只判断了file的type的值,就可以绕过了
Pass-03

依旧先上传1.php

提示:不允许上传.asp,.aspx,.php,.jsp后缀文件
我们只需要上传.phtml就可以绕过,上传

从源码上看

这里只对后缀进行了限制,并没有对content-type,所以我们可以原封不动
Pass-04

之后过滤的会越来越多,因为是靶场,我们可以直接从源码入手
关键过滤代码为
$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",".ini");过滤了非常多,但仔细发现并没有过滤.htaccess文件
我们可以先上传.htaccess文件
AddType application/x-httpd-php .jpg .txt .png再去上传1.png,内容为一句话木马


Pass-05

关键过滤代码为
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess");这里过滤了上一题的.htaccess但没有过滤.user.ini
auto_prepend_file=1.jpg然后再去上传1.jpg

Pass-06

直接看源码

可以发现少了一行转小写的代码,那我们直接大小写绕过

放包即可上传
Pass-07


这关源码删去了trim()函数,也就是用来去除字符串两端的空格,所以我们如果在上传文件的后缀名里面加上空格,不属于黑名单内容,我们就可以成功进行上传
https://img2023.cnblogs.com/blog/3588329/202506/3588329-20250621002804380-531222922.png
放包上传即可
Pass-08


可以看到没有使用deldot()过滤文件名末尾的点,可以使用文件名后加 .进行绕过,即1.php.

Pass-09


缺少了
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATAphp在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持"::$DATA"之前的文件名 他的目的就是不检查后缀名。


注意这里url中要删掉最后的::$DATA
Pass-10

使用 deldot() 删除文件名末尾的点
deldot() 函数从末尾向前检测,检测到第一个点后,会继续向前检测,但遇到空格会停下来
可以构造文件名:1.php. .绕过检测

url中依旧是去掉后面的字符,保留到1.php
Pass-11


查看源码我们可以发现他仅仅对文件名称进行了替换,替换之后的后缀没有进行黑名单验证,这里我们就可以使用双写文件后缀进行文件上传

Pass-12


这一关白名单,通过%00截断可绕过白名单限制,但需确保PHP版本低于5.3.4且magic_quotes_gpc已关闭。
原理简述:PHP函数如move_uploaded_file在底层C语言实现时,会因遇到0x00(URL编码为%00)截断字符串。利用此特性,可绕过某些文件上传限制。

即可上传成功
代码分析:
$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类型文件!";
    }
}

知识补充:
php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00。
strrpos(string,find[,start]) 函数查找字符串在另一字符串中最后一次出现的位置(区分大小写)。
substr(string,start[,length])函数返回字符串的一部分(从start开始 [,长度为length])
magic_quotes_gpc 着重偏向数据库方面,是为了防止sql注入,但magic_quotes_gpc开启还会对$_REQUEST, $_GET,$_POST,$_COOKIE 输入的内容进行过滤Pass-13

第13题与12题思路一样使用白名单限制上传文件类型,但上传文件的存放路径可控,
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;但因为是POST型,需要对%00进行解码或在16进制中修改,POST不会像GET那样对%00进行自动解码。

Pass-14

本关会读取判断上传文件的前两个字节,判断上传文件类型,并且后端会根据判断得到的文件类型重命名上传文件

使用 图片马 + 文件包含 绕过
补充:
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 生成的图片木马
然后将test.png上传


再点击黄色的文件包含漏洞字眼

然后打一个很简单的文件包含漏洞

Pass-15

使用getimagesize()检查是否为图片文件

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


exif_imagetype()读取一个图像的第一个字节并检查其后缀名。
返回值与getimage()函数返回的索引2相同,但是速度比getimage快方法同Pass-14
Pass-17

$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的图片文件!";
    }
}根据源码和题目提示可以得知这是一个二次渲染
上传的图片经过了后缀名、内容类型和imagecreatefromgif函数的严格验证,确保其为GIF格式。随后,图片经过了二次渲染处理。然而,在后端的二次渲染过程中,需要识别并标记出渲染后未发生改变的十六进制(Hex)区域。通过利用文件包含漏洞,可以在这些未变区域嵌入恶意代码,进而使用蚁剑工具进行远程连接和操作。
这里的二次渲染图片使用大菜鸡师傅的。
先上传一张原始jpg,然后直接下载二次渲染后的jpg
脚本如下:
页: [1]
查看完整版本: upload-labs靶场通关教程