目录
Pass-01-JS绕过
Pass-02 文件类型绕过
Pass-03 黑名单绕过
Pass-04 .htaccess绕过
Pass -05 后缀大小写绕过
Pass-06 空格绕过
Pass-07 点绕过
Pass-08 ::$DATA文件流特性绕过
Pass-9-点+空格+点绕过
Pass-10 双写绕过
Pass-11 %00截断
Pass -12 00截断
Pass-13 图片马
Pass - 14 getimagesize()-图片马
Pass-15-exif_imagetype()-图片马
Pass -16 图片马+二次渲染+文件包含
Pass-17-条件竞争
Pass-18-条件竞争
Pass-19-00截断
Pass -20 / + 数组 绕过
Pass-21 MIME、数组、%00绕过
Pass-01-JS绕过
开启代理抓包,发现没有产生流量,说明是前端js验证
Pass-02 文件类型绕过#解决思路: 1、禁用js脚本 2、直接修改前端代码,允许上传.php文件或者删除οnsubmit="return checkFile()函数
上传一个php文件,返回提示为文件类型不正确
这里猜测应该是对文件类型进行过滤。
#查看源码
$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.'文件夹不存在,请手工创建!';
}
}
#这里是对Content-Type类型的判断。我们进行抓包
#将Content-Type: application/octet-stream改为Content-Type: image/jpeg
上传成功,查看地址,连接蚁剑。
Pass-03 黑名单绕过
上传一个php文件,提示我们过滤了一些后缀名的文件
#解决思路:
上传其他可以解析的后缀名文件进行绕过
如 .phtml .phps .php5 .pht
上传一个php文件,进行抓包,修改后缀名为1.php5,返回数据包,上传成功
并且还可以找到上传文件返回的路径。
#这里的文件名之所以被重名命,是由于源码中对文件名进行了重名命
Pass-04 .htaccess绕过#源码
$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",".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 . '文件夹不存在,请手工创建!';
}
}
观察源码。这里几乎对所有的文件后缀名都进行了黑名单过滤。
Pass -05 后缀大小写绕过#这里会学习一个新的知识点-.htaccess 绕过
.htaccess是一个纯文本文件,它里面存放着Apache服务器配置相关的指令。
.htaccess主要的作用有:URL重写、自定义错误页面、MIME类型配置以及访问权限控制等。主要体现在伪静态的应用、图片防盗链、自定义404错误页面、阻止/允许特定IP/IP段、目录浏览与主页、禁止访问指定文件类型、文件密码保护等。
#简单的说就是:上传.htaccess文件,可以重写文件解析规则绕过
#源码
$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",".ini");
$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 . '文件夹不存在,请手工创建!';
}
}
上传webshell,根据提示,为黑名单绕过,并且限制了.htaccess文件的上传
Pass-06 空格绕过#观察提示发现,没有过滤大小写混合绕过。可以尝试进行大小写绕过
#将上传的1.php文件通过burp抓包修改为1.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",".ini");
$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 . '文件夹不存在,请手工创建!';
}
}
#观察源码的过滤条件发现,这里的条件没有
$file_name = deldot($file_name);//删除文件名末尾的点
#思路
点绕过,在文件名后面加点,进行绕过
返回数据包,上传成功,成功连接蚁剑
Pass-08 ::$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",".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 = 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 . '文件夹不存在,请手工创建!';
}
}
#观察源码的过滤条件发现,这里的条件没有
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
#思路
::$DATA上传绕过(这是什么意思?)
#在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名
例如:"phpinfo.php::$DATA"Windows会自动去掉末尾的::$DATA变成"phpinfo.php"
所有这里我们直接在文件名后面加上::$DATA即可!
返回数据包,上传成功,成功连接蚁剑
Pass-9-点+空格+点绕过#源码
$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",".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 . '文件夹不存在,请手工创建!';
}
}
#观察发现,这里的过滤条件全部都有,我的思路是构造后缀名,抵消掉过滤条件,最后剩下的就是可以上传的文件名。
这里主要看两个过滤条件。
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = trim($file_ext); //首尾去空
通过这两个条件,我们可以先构造1.php . 当上传该后缀文件时,代码会先去掉末尾的点,再去掉末尾的空格,我们上传的文件就变成了1.php 发生存在黑名单绕过,无法上传。
后面观察代码发现了这条语句
$file_ext = strrchr($file_name, '.'); --什么意思呢?
strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。语法:strrchr(string,char)
意思就是查找'.'最后一次出现的位置,并且返回这个位置到结尾的所有字符串,那不就是查看我们的后缀名是什么嘛,比如1.php 通过该语句处理返回的就是.php 与黑名单进行比较。
所有我们现在有思路了,那就是只要让最后返回的东西不在黑名单里面就可以了
构造1.php. . 最终返回1.php. 上传成功,再利用windows特性,会自动去掉后缀名中最后的”.”,最终我们上传的文件就变成了1.php
果然如我们所想,文件最终返回1.php.上传到我们的文件目录中。
再利用windows特性,会自动去掉后缀名中最后的”.”,最终我们上传的文件就变成了1.php
Pass-10 双写绕过
#源码
$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","ini");
$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 . '文件夹不存在,请手工创建!';
}
}
#这里我先上传一个1.php,发现上传成功,查看路径,文件后缀名php没有了,也就是没有了文件类型。
#观察源码,发现了str_ireplace函数
str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。
格式为str_ireplace(find,replace,string,count)
$file_name = str_ireplace($deny_ext,"", $file_name);
这里的意思就是搜索$file_name,与$deny_ext(黑名单),再将$file_name替换为空,即过滤掉文件类型
#思路
双写文件后缀名,绕过str_ireplace函数
成功上传!
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类型文件!";
}
}
#何为00截断
1、0x00截断
0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符。这个可以用在对文件类型名的绕过上
这里主要是对文件的目录/upload/下手,由post方式上传1.jpg ,并且在目录中添加1.php 返回的结果就变为了1.php1.jpg
#原理
系统在对文件名的读取时,如果遇到0x00,就会认为读取已结束。0x表示16进制
0x:16进制表示
00:表示0
0x00:就是代表16进制的0
Pass -12 00截断#思路
1、取后缀名: $file_ext=png 后缀名在白名单中,符合
2、拼接上传路径:$img_path=…/upload/1.php/3220210812084323.png (1.php后面的%00不见了,因为他变成了hex值为00的结束字符,所以看不见)
3、将上传的文件移动到新位置 :move_uploaded_file函数在进行文件移动的时候,在读取$img_path的值的时候,读到1.php的后面时,遇到了hex值为00的结束字符,他会认为$img_path的值读取完毕,这个时候$img_path=…/upload/1.php,最后上传的文件名为1.php,实现了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 = $_POST['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-13 图片马#这里的区别就是save_path采用了Post获得,需要在hex里面去进行修改
#源码
function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只读2字节
fclose($file);
$strInfo = @unpack("C2chars", $bin);
$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 = "上传出错!";
}
}
}
这里通过读文件的前两个字节判断文件的类型。因此直接 上传图片马即可,制作图片马
copy 1.jpg /b + shell.php /a shell.jpg
上传成功后,查看图片地址可以得到上传图片的名字。
这里需要注意的是:直接访问图片并不能把图片当做PHP解析,因此还需要利用文件包含漏洞 。
Pass - 14 getimagesize()-图片马
#源码
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)>=0){
return $ext;
}else{
return false;
}
}else{
return false;
}
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$res = isImage($temp_file);
if(!$res){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
Pass-15-exif_imagetype()-图片马这题是用getimagesize函数判断文件类型,还是可以图片马绕过,方法同pass-13,上传成功后连接蚁剑。
#源码
function isImage($filename){
//需要开启php_exif模块
$image_type = exif_imagetype($filename);
switch ($image_type) {
case IMAGETYPE_GIF:
return "gif";
break;
case IMAGETYPE_JPEG:
return "jpg";
break;
case IMAGETYPE_PNG:
return "png";
break;
default:
return false;
break;
}
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$res = isImage($temp_file);
if(!$res){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
Pass -16 图片马+二次渲染+文件包含这里用到php_exif模块来判断文件类型,用图片马绕过,方法同pass-13
此题麻烦的地方在于找出二次渲染后,图片没有被改变的地方。
请参考如下链接: upload-labs16(二次渲染)_Luckysec的博客-CSDN博客_文件上传二次渲染
Pass-17-条件竞争$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;
if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
}else{
$msg = '上传出错!';
}
}
Pass-18-条件竞争这里是条件竞争,先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可以上传1.php只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可.
//index.php
$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{
require_once("./myupload.php");
$imgFileName =time();
$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
$status_code = $u->upload(UPLOAD_PATH);
switch ($status_code) {
case 1:
$is_upload = true;
$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
break;
case 2:
$msg = '文件已经被上传,但没有重命名。';
break;
case -1:
$msg = '这个文件不能上传到服务器的临时文件存储目录。';
break;
case -2:
$msg = '上传失败,上传目录不可写。';
break;
case -3:
$msg = '上传失败,无法上传该类型文件。';
break;
case -4:
$msg = '上传失败,上传的文件过大。';
break;
case -5:
$msg = '上传失败,服务器已经存在相同名称文件。';
break;
case -6:
$msg = '文件无法上传,文件不能复制到目标目录。';
break;
default:
$msg = '未知错误!';
break;
}
}
//myupload.php
class MyUpload{
......
......
......
var $cls_arr_ext_accepted = array(
".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
".html", ".xml", ".tiff", ".jpeg", ".png" );
......
......
......
/** upload()
**
** Method to upload the file.
** This is the only method to call outside the class.
** @para String name of directory we upload to
** @returns void
**/
function upload( $dir ){
$ret = $this->isUploadedFile();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->setDir( $dir );
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->checkExtension();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->checkSize();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// if flag to check if the file exists is set to 1
if( $this->cls_file_exists == 1 ){
$ret = $this->checkFileExists();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// if we are here, we are ready to move the file to destination
$ret = $this->move();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// check if we need to rename the file
if( $this->cls_rename_file == 1 ){
$ret = $this->renameFile();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// if we are here, everything worked as planned :)
return $this->resultUpload( "SUCCESS" );
}
......
......
......
};
Pass-19-00截断因此也存在条件竞争的问题,不过这题对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,因此可以通过不断上传图片马,由于条件竞争可能来不及重命名,从而上传成功。
$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 = $_POST['save_name'];
$file_ext = pathinfo($file_name,PATHINFO_EXTENSION);
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 -20 / + 数组 绕过发现move_uploaded_file()函数中的img_path是由post参数save_name控制的,因此可以在save_name利用00截断绕过,方法同pass-12
$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
//检查MIME
$allow_type = array('image/jpeg','image/png','image/gif');
if(!in_array($_FILES['upload_file']['type'],$allow_type)){
$msg = "禁止上传该类型文件!";
}else{
//检查文件名
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}
$ext = end($file);
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {
$msg = "禁止上传该后缀文件!";
}else{
$file_name = reset($file) . '.' . $file[count($file) - 1];
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$msg = "文件上传成功!";
$is_upload = true;
} else {
$msg = "文件上传失败!";
}
}
}
}else{
$msg = "请选择要上传的文件!";
}
pathinfo(path,options) 函数以数组的形式返回文件路径的信息。
思路:源码类似与第12、13关只不过是,这关作者是用POST方法来对我们的文件名进行接收,同时拼接到路径上去,那么这就和我们第13关类似,只不过是13关是由POST接收的路径名,而这关只接收了文件名。但是两关所要考察我们的内容应该是一样的
我们首先上传一个php脚本,然后在save_name文件名的后面添加%00(注意要URL解码,或者更改16进制码
)
最后上传成功。
Pass-21 MIME、数组、%00绕过$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
//检查MIME
$allow_type = array('image/jpeg','image/png','image/gif');
if(!in_array($_FILES['upload_file']['type'],$allow_type)){
$msg = "禁止上传该类型文件!";
}else{
//检查文件名
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}
$ext = end($file);
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {
$msg = "禁止上传该后缀文件!";
}else{
$file_name = reset($file) . '.' . $file[count($file) - 1];
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$msg = "文件上传成功!";
$is_upload = true;
} else {
$msg = "文件上传失败!";
}
}
}
}else{
$msg = "请选择要上传的文件!";
}
作者首先检查了我们上传文件的MIME类型,然后定义了允许的上传类型,然后判断我们上传文件的类型,如果我们上传的文件类型在白名单里面,然后判断我们由POST接收的文件名是否为空,如果为空,那么我们上传文件就会保存为原来的文件名,如果不为空,那么我们上传的文件名会保存为,我们POST接收的文件名。然后作者判断了我们的file变量如果不是数组,那么我们将file变量先转换为小写然后再用explode打成数组(以点为分隔符),然后取它的后缀名,并且定义了一个允许上传的后缀名数组,然后判断如果我们取的后缀名在白名单里面,然后取到了我们的文件名,然后进行移动
思路:结合我上面对源码的讲解,其实这关我们需要注意几个点,一个是如果上传的是php文件,那么记得要改MIME类型,这样第一层我们突破了,二我们需要上传一个数组,否则我们只要上传后缀名为php的文件,就会被拦截,所以我们需要抓包更改我们上传的文件为数组,然后在路径那块,运用%00截断
可以参考如下链接:https://blog.csdn.net/m0_46436640/article/details/107809772?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.opensearchhbase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.opensearchhbase#Pass21_MIME00_1489
如果有错误的地方,希望各位指正出来,如果有更好方法,,欢迎大家来一起交流。
目录
Pass-01-JS绕过
Pass-02 文件类型绕过
Pass-03 黑名单绕过
Pass-04 .htaccess绕过
Pass -05 后缀大小写绕过
Pass-06 空格绕过
Pass-07 点绕过
Pass-08 ::$DATA文件流特性绕过
Pass-9-点+空格+点绕过
Pass-10 双写绕过
Pass-11 %00截断
Pass -12 00截断
Pass-13 图片马
Pass - 14 getimagesize()-图片马
Pass-15-exif_imagetype()-图片马
Pass -16 图片马+二次渲染+文件包含
Pass-17-条件竞争
Pass-18-条件竞争
Pass-19-00截断
Pass -20 / + 数组 绕过
Pass-21 MIME、数组、%00绕过
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)