• Upload Labs


    Upload Labs做题记录

    记录一下,让自己了解上传的一些常见姿势,同时学习学习php代码,增加自己代码审计的能力。

    pass-01   js前端验证

    只是在前端进行验证,这时候可以使用firefox的Noscript插件,来禁用JS,达到上传目的。

     前端判断代码为:

       function checkFile() {
            var file = document.getElementsByName('upload_file')[0].value;
            if (file == null || file == "") {
                alert("请选择要上传的文件!");
                return false;
            }
            //定义允许上传的文件类型
            var allow_ext = ".jpg|.png|.gif";
            //提取上传文件的类型
            var ext_name = file.substring(file.lastIndexOf("."));
            //判断上传文件类型是否允许上传
            if (allow_ext.indexOf(ext_name) == -1) {
                var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
                alert(errMsg);
                return false;
            }
        }

    可以直接F12,在文件上传类型中添加.php就可以上传php文件了。

    我这里是进行BP抓包:

    然后访问,蚁剑链接

    pass-02  Content-Type

     文件类型绕过

    BP抓包,将文件类型改为图片即可

    源码审计:

    $is_upload = false; //初始的上传状态
    $msg = null;
    if (isset($_POST['submit'])) { //判断是否是点了submit传过来的
        if (file_exists(UPLOAD_PATH)) {    //判断上传路径是否存在,也就是说在根目录下,是否存在upload这么一个文件夹,如果自己本地搭建的话,需要创建这么一个文件夹
            if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
                $temp_file = $_FILES['upload_file']['tmp_name'];  //判断允许上传的文件类型,BP抓包可以看到,他的文件类型是application/octet-stream,将其改为上面三个中的一个就行了
                $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']    //上传的路径  upload/你上传文件的名字   我这里就是:upload/test.php        
                if (move_uploaded_file($temp_file, $img_path)) {
                    $is_upload = true;
                } else {
                    $msg = '上传出错!';
                }
            } else {
                $msg = '文件类型不正确,请重新上传!';
            }
        } else {
            $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
        }
    }

    pass-03   文件后缀的判断

     上传文件可以看到,他不允许上传以下后缀的文件,那么我们用其他php别名就行了,常见的别名有:pht,phpt,phtml,php3,php4,php5,php6

    这里使用的是php3后缀

    蚁剑访问成功

    源码审计:

    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
            $deny_ext = array('.asp','.aspx','.php','.jsp');  //定义了一个黑名单数组
            $file_name = trim($_FILES['upload_file']['name']);   //使用trim函数去掉文件名前后的字符
            $file_name = deldot($file_name);//删除文件名末尾的点
            $file_ext = strrchr($file_name, '.');   //strchr函数是strstr函数的别名,这里返回 .后缀名。
            $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 = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
            }
        } else {
            $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
        }
    }

    pass-04   .htaccess解析

     上传之后,发现文件不允许,应该在第三题的基础上加了其他别名到黑名单了,基本上是都过滤掉了,不过没有过滤 .htaccess。.htaccess文件可以实现重写文件解析的规则。

    创建一个.htaccess的文件,里面写的内容为:SetHandler application/x-httpd-php,然后上传,这样就可以实现把锁上传的文件当成php来执行了。

    在上传一个图片马,或者是将一句话文件改为图片形式上传就行了

    蚁剑连接成功

    源码审计:

    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
         //这里可以看到,他几乎是把所有的php别名都给ban了,其他地方和之前的都一样,就不审了。 $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 . '文件夹不存在,请手工创建!'; } }

    pass-05  大小写绕过

     这里和上面一个题一样都,把.htaccess添加进去了。但是没有进行小写的转换,所以说可以使用大小写绕过

    蚁剑连接成功

    源码审计:

    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
         //可以看到,在最后面,他把.htaccess加进去了,但是在下面的变量里,没有像之前那样,使用strtolower函数将分离出来的后缀,都改为小写。 $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

     相较与上一题的没有进行小写转换,这一题是对文件名没有进行严格的检查,没有使用trim函数将文件名前后的字符去点,所以说可以BP抓包之后,在php后面加一个空格就行了

    然后访问,蚁剑连接,这里只是没有时候trim函数进行首尾去空而已,就不审了。

    pass-07  deldot,windows特性

     在这一关,去掉了,也就是说,可以在文件名末尾加上点进行绕过,根据windows的特性,test.php.这样,最后执行的时候会把php.后面的点去掉。

     $file_name = deldot($file_name);//删除文件名末尾的点

    蚁剑连接成功

    pass-08   ::$DATA文件流

     由于之前burp suite一直抓不到本地包,所以上面做的几个题都是在 https://buuoj.cn/ 做的,现在终于可以本地复现了,开心,之前抓不到包,好像 是8080端口的锅

    将端口改为8081,终于可以抓本地包,可以更加清楚的知道上传文件的变化了。

    在这一关,缺少了这个函数对文件后缀的限定,

    str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

    ::$DATA是windows上的一个文件流特性,必须在windows上,且是php文件,源文件的时候加上::$DATA,windows会把::$DATA之后的数据当作文件流来处理

    不会检测后缀名.且保持"::$DATA"之前的文件名。

    这里上传成功之后,在upload下的文件名自动的去掉了::$data,之后直接访问php就行了,然后蚁剑连接

    pass-09  代码逻辑漏洞

     这一关,其实和第四关差不多,只不过,第四关没有过滤掉.htaccess,而在这一关,过滤了。之前第四关的第二种做法也可以和这一关一样

    利用代码执行的一个漏洞,可以一个函数一个函数的从上往下绕过。

            $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); //首尾去空

    访问shell.php,蚁剑连接

    pass-10   后缀名双写绕过

     看一下这一关关键的源代码

     $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;

    可以看到,直接去掉了黑名单里面存在的文件名后缀,不过只是进行了一次,所以说可以后缀名双写绕过

    可以看到上传之后又两个文件,访问php文件,蚁剑连接即可

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

    从代码上可以看出,设置了一个白名单,只允许jpg/png/gif后缀的文件上传,但是在后面的保存的时候,文件名是拼接的,其中前面是可控的

    $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;   //save_path是可控的部分

    这时候就可以使用00截断进行尝试,00截断使用的条件:

    PHP版本小于5.3.4
    php.ini配置文件里magic_quotes_gpc=Off

     这样就可以上传成功了,然后访问upload/13.php,蚁剑连接

    pass-12 00截断

     还是和上面一样,不过将save_path的传参方式变成了POST,GET传参的时候,会自动进行URL解码,POST不会,

     访问,连接即可。

    pass-13  图片马文件包含

     根据关卡要求,需要上传图片马,以及使用文件包含

    来看一下源代码

    function getReailFileType($filename){
        $file = fopen($filename, "rb");
        $bin = fread($file, 2); //只读2字节
        fclose($file);
        $strInfo = @unpack("C2chars", $bin);    
       //pcak函数是将对应参数打包成二进制字符串,uppack($format,$data)就是进行解包,format是解包时使用的数据格式,C是无符号字符 $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 = "上传出错!"; } } }

    pack函数例子:

    test.php

    <?php
    echo pack('C3',80,72,80);
    ?>

     test.php里面的C表示无符号的字符,3就是后面对应的参数个数,前面的数字必须小于等于后面的参数个数。

    从源码可以知道,后端是对上传文件进行了文件头的的检测。图片马上传成功之后,还不能直接访问到

    还需要文件包含才能成功执行php代码

    包含之后还是出错了

     网上查了发现,发现是我自己phpstudey使用的php版本低了,做上面的00截断的题的时候,用了5.2版本的php,没改过来,所以这里报了这样的错误

    将php改为5.4.45之后就可以成功了

    pass-14 图片马/getimagesize

     核心源代码

     $types = '.jpeg|.png|.gif';
        if(file_exists($filename)){
            $info = getimagesize($filename);  //判断文件,如果是图片,就返回一个数组,数组里面有图片大小和后缀
            $ext = image_type_to_extension($info[2]);   //$info[2]=后缀名

    这里使用getimagesize函数来判断文件,用来获取图像的大小及后缀名,成功的话,返回一个数组,失败返回false

    也是只检查了文件头,绕过的话,只需要制造一个图片马,或者是上传一个一句话木马,抓包,然后在一句话内容前面加上图片的文件头就行了

     然后访问,蚁剑连接

    pass-15 图片马/exif_imagetype

     这题也是一样,和上面两个图片马,也是检查了文件的文件头格式

    这里使用的是exif_imagetype函数来判断

    方法个上面一样,就不多说了。

    pass-16 

    pass-17

    pass-18

    pass-19

    pass-20

  • 相关阅读:
    Lily.Core.FileDataProvider文件管理使用范例。
    CruiseControl.NET,Nant持续集成(1)
    如何为当前进程设置环境变量?
    unix时间戳与datetime的转换函数
    Mac 平台下功能强大的Shimo软件使用指南
    如何解决源码包安装时的依赖性问题
    《Linux企业应用案例精解》一书配套视频发布
    ZoneMinder配置与使用
    网站优化IIS7下静态文件的优化
    WIN7常用功能的介绍
  • 原文地址:https://www.cnblogs.com/mortals-tx/p/11373979.html
Copyright © 2020-2023  润新知