freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

文件上传及其bypass
2023-03-03 17:52:54
靶场采用upload-labs

截屏2023-03-03 下午5.30.41.png
docker部署 chenhuan@MacBook-Pro ~ % docker pull c0ny1/upload-labs Using default tag: latest latest: Pulling from c0ny1/upload-labs 357ea8c3d80b: Pull complete 85537f80f73d: Pull complete 3d821ad560e1: Pull complete b4ae91aad522: Pull complete 66e1c1a53c95: Pull complete 5d1f306a8912: Pull complete 37733078a51e: Pull complete c5351b4d6bee: Pull complete 4f946c4dcbe2: Pull complete 0c48c69d4b11: Pull complete dbc71ed1796a: Pull complete 9c6d026ad711: Pull complete 3fced1e5eb8f: Pull complete d8b4853c6e4c: Pull complete 347aad580430: Pull complete f1ecd4740470: Pull complete 185cf7570d6d: Pull complete error pulling image configuration: Get "https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/aa/aa4fdd1dd2113f5db4fdce90472097bf1bd525f29b24bfec2f0552bf269e1657/data?verify=1646742689-hn3OqvQnpX64yYT4iOjfrvWPIiI%3D": EOF


pass-01
截屏2023-03-03 下午5.31.20.png
有的没的先传一下子试试
被拦截(不拦才怪)
截屏2023-03-03 下午5.32.06.png截屏2023-03-03 下午5.31.48.png
绕前端js,抓包改文件名
访问一下
截屏2023-03-03 下午5.32.25.png

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

* * *

pass-02
随手传个png改个名试试
woc?过了
(和pass-01一样)
![截屏2023-03-03 下午5.33.09.png](https://image.3001.net/images/20230303/1677835993_6401bed94522bca1dd8ce.png!small)
随后去网上搜了下其他人的做法
这题其实是对Content-Type:有校验,但可能是因为macos的原因,给php改成png之后自动修改了Content-Type的类型导致这题被pass
这题正经的解法需要更改Content-Typ的类型为image/png后上传
$is_upload = false;
$msg = null;
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.'文件夹不存在,请手工创建!';
    }
}

pass-03
继续随手传个png尝试改名
截屏2023-03-03 下午5.33.52.png

这次不行了
截屏2023-03-03 下午5.34.09.png
选择使用不常用php后缀名绕过
.php|.php5|.php4|.php3|.php2|.php1|.html|.htm|.phtml|.pht|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|.pHp1|等等
截屏2023-03-03 下午5.34.21.png
上传成功
截屏2023-03-03 下午5.34.52.png
但是发现找不到文件
截屏2023-03-03 下午5.35.03.png
扔到repeater看下
截屏2023-03-03 下午5.36.18.png
这里被改名了
因为实在懒得进docker调apache的
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
所以这里可以访问到但是无法执行php5文件
(懒一下)
docker里也确实可见
Last login: Tue Mar 8 21:10:04 on ttys002 chenhuan@MacBook-Pro ~ % docker exec -it c101a2601d4f0666d6a1ba2aefc4f83d33008afc6d2f1ecf075bb16b575fadc5 /bin/sh
> ls
Pass-01 Pass-06 Pass-11 Pass-16 README.md footer.php js Pass-02 Pass-07 Pass-12 Pass-17 common.php head.php menu.php Pass-03 Pass-08 Pass-13 Pass-18 config.php img rmdir.php Pass-04 Pass-09 Pass-14 Pass-19 css include.php upload Pass-05 Pass-10 Pass-15 Pass-20 doc index.php
> cd upload
ls
202203081308421501.php5

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

}


pass-04
继续传一个png
截屏2023-03-03 下午5.40.47.png

php5光荣牺牲

在此之后我试了
.php|.php5|.php4|.php3|.php2|.php1|.html|.htm|.phtml|.pht|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|.pHp1|等等一票后缀
全部gg
最后查了下百度,发现还有一个.hatccess可用
但是需要改一下apache的设置才能被解析成php
继续懒
最后改成.hatccess上传成功
截屏2023-03-03 下午5.41.08.png

$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
老样子传png
截屏2023-03-03 下午5.42.11.png
Content-Disposition: form-data; name="upload_file"; filename="a.pHP"
估计又被改名了截屏2023-03-03 下午5.42.37.png

$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
空格绕过
没啥说的
截屏2023-03-03 下午5.43.19.png

$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 = $_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
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-07
这里讲一个windows的特性
windows中会自动去掉文件末尾中的.
所以这题仅仅需要在a.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_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-08
依旧是windows特性
windows命名文件时,如果命名格式为文件名+"::$DATA",系统会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名
举个例子:"a.php::$DATA" Windows会自动去掉末尾的::$DATA变成"a.php"

所以这题在末尾a.php加上::$DATA即可绕过

$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 = strtolower($file_ext); //转换为小写
        $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-09
代码把能过滤的都过滤了
但是呢
通过构造. . 的文件名
可以绕

$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 = 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-10
pphphp,双写绕过即可

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

}


pass-11
常规%00截断绕过(a.php%00.png)
注意:php版本要小于5.3.4且php.ini的magic_quotes_gpc为OFF状态才可以使用%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类型文件!";
}

}


pass-12
对post的00截断
截屏2023-03-03 下午5.45.05.png


pass-13-16
图片马和文件包含漏洞大联动
没什么绕过的技巧
唯一一个可注意的点,pass-16是一个二次渲染绕过,需要hex找到未被渲染的模块插入webshell截屏2023-03-03 下午5.45.26.png


pass-17
竞争条件

查看源代码发现这玩意先保存后判断文件名
这样的话可以考虑使用竞争条件让文件保存下来

<?php fputs(fopen('a.php','w'),'<?php phpinfo() ?>');?>

写入shell
使用py脚本不断进行访问

import requests
url = "http://localhost:1234/upload/a.php"
while True:
    html = requests.get(url)
    if html.status_code == 200:
        print("OK")
        break

burp的重放模块快速重放payload进行竞争
截屏2023-03-03 下午5.45.52.png


pass-18
也是竞争条件
只不过改成上传图片马了
因为他先检查后缀名


pass-19

考察CVE-2015-2348 move_uploaded_file()以及00截断
https://nvd.nist.gov/vuln/detail/CVE-2015-2348

pass-20
是一个数组传递绕过,文件名后边怼个数组就行了





vx:chenhuan0x00

# 渗透测试 # waf绕过 # 文件上传
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者