(这个没删就是还没做完 ; ω ; )
目录
Pass-01 前端绕过
关卡分析
绕过:Burpsuite抓包修改或页面禁用js
Pass-02 服务器端检测–IMME类型
关卡分析
Content-type
绕过:抓包修改文件的content-type
Pass-03 黑名单绕过
关卡分析
绕过:尝试使用其他后缀名上传
Pass-04 .htaccess文件
关卡分析
.htaccess文件
绕过:.htaccess文件绕过
Pass-05 user.ini绕过和加点/加空格绕过
关卡分析
.user.ini
绕过:使用burpsuite抓包修改文件后缀为.php. .或.user.ini文件绕过
Pass-06 大小写绕过
关卡分析
绕过:改变后缀名的大小写
Pass-7 空格绕过
关卡分析
绕过:抓包添加空格绕过
Pass-8 . 绕过
关卡分析
绕过:抓包加.绕过
Pass-9 ::$DATA 特殊符号绕过
关卡分析
::$DATA
绕过:抓包添加::$DATA
Pass-10 . .点 空格 点绕过
关卡分析
绕过:抓包加点加空格
Pass-11 双写绕过
关卡分析
绕过:抓包双写后缀
Pass-12 %00阶段(GET型)
关卡分析
%00截断
绕过:抓包修改上传路径,通过%00截断后续的代码
Pass-13 0x00截断(POST型)
关卡分析
绕过:抓包修改上传路径后send,修改文件名后面的code值为00(即文件名后面的为'\0')
Pass-14 图片马文件包含
使用的靶场::c0ny1/upload-labs: 一个想帮你总结所有类型的上传漏洞的靶场https://github.com/c0ny1/upload-labs
使用的小皮面板进行的搭建 php版本:5.3 nginx1.15.11
Pass-01 前端绕过
关卡分析
尝试直接上传.php文件时会发现网页提示智能上传规定内的文件类型,且上传时尝试使用burp suite进行抓包会发现没有抓到数据包
即在上传时,数据包还没有经过客户端发给后端就被拦截掉了,说明上传验证是在前端进行的,且查看页面源代码也可以看到:
绕过:Burpsuite抓包修改或页面禁用js
Burpsuite抓包修改
将准备的.php文件后缀改成不会被拦截的.jpg形式,通过Burpsuite进行抓包
在这里将文件后缀的.jpg改成.php然后进行发送
关闭抓包后回到网页可以发现上传成功:
选择在另外新页面打开图片可以发现php文件已经成功上传:
页面禁用js
在设置里面选择禁用js然后直接上传php文件
php文件能够直接上传并打开
Pass-02 服务器端检测–IMME类型
关卡分析
和第一关一样,首先打开抓包直接上传php文件,这时会发现能够抓到数据包,说明不再是前端验证
这里尝试上传一张图片,能够正常上传:
查看抓取的数据包:
两个包中的content-type有区别:
文件源码:
$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的值进行过滤,当值为:image/jpeg、image/png、image/gif 这种时能够上传成功
Content-type
Content-Type在HTTP协议消息头中,使用Content-Type来表示请求和响应中的媒体类型信息
绕过:抓包修改文件的content-type
上传php文件抓包将content-type改为图片的类型然后发送
这里可以看到文件已经上传成功
Pass-03 黑名单绕过
关卡分析
上传一个php文件,可以看到提示,本关不允许上传 .asp, .aspx, .php, .jsp文件,是一个黑名单绕过的关卡
网站源代
$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 . '文件夹不存在,请手工创建!';}
}
源代码对array('.asp','.aspx','.php','.jsp')内的文件类型进行小写,去除特殊字符以及收尾去空等处理,我们可以尝试选择一些不在黑名单内的后缀代替.php后缀进行上传,例如:
.php3:早期PHP 3版本使用的后缀,现已不常见。.php4:早期PHP 4版本使用的后缀,现已不常见。.php5:早期PHP 5版本使用的后缀,现已不常见。.phtml:常用于包含HTML和PHP混合代码的文件。.phps:用于显示PHP源代码的文件,通常不执行。.php7:早期PHP 7版本使用的后缀,现已不常见。.inc:常用于包含文件,但需注意安全性问题,因为.inc文件可能被直接访问。(以上来自deepseek搜索)
绕过:尝试使用其他后缀名上传
(因为版本原因受限,这里可以用较低版本的apache/php)
Pass-04 .htaccess文件
关卡分析
这一关和上一关类似,相比上一关增加了许多禁止后缀,但是没有禁止上传.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 . '文件夹不存在,请手工创建!';}
}
.htaccess文件
分布式配置文件,指在特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。在Apache 服务器中,优先级较高,可以覆盖主要配置文件httpd-conf文件。
绕过:.htaccess文件绕过
先上传.htaccess文件,将.jpg和.txt文件作为 PHP 脚本处理,而不是作为普通文件。
AddType application/x-httpd-php .jpg .txt
之后可以将php文件后缀改为.jpg或txt,在与.htaccess文件同一上传目录下,该文件会被当作php文件处理
Pass-05 user.ini绕过和加点/加空格绕过
关卡分析
网页源代码
$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 . '文件夹不存在,请手工创建!';}
}
这里将.htaccess也过滤了,但是.user.ini文件没有,我们可以上传user.ini文件进行绕过
.user.ini
.user.ini 和 .htaccess 一样是对当前目录的所以php文件的配置设置,即写了.user.ini和它同目录的文件会优先使用.user.ini中设置的配置属性
其次,这关的路径变量拼接方式为:
$img_path = UPLOAD_PATH.'/'.$file_name;
且它对文件的末尾点只限制了一次
$file_name = deldot($file_name);//删除文件名末尾的点
我们可以尝试上传文件后缀为.php. .这样子的文件
绕过:使用burpsuite抓包修改文件后缀为.php. .或.user.ini文件绕过
抓包该文件后缀绕过
抓包后将文件名修改为.php. .后发送,这样就能够绕过上传成功了
.user.ini文件绕过(暂略)
Pass-06 大小写绕过
关卡分析
$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 . '文件夹不存在,请手工创建!';}
}
相比上面的网页,虽然增加了禁止文件类型以及去空去点,但是少了 $file_ext = strtolower($file_ext); 转换为小写的操作因此可以用后缀名大写的方式进行绕过
绕过:改变后缀名的大小写
Pass-7 空格绕过
关卡分析
$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 = $_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);//去除字符串::$DATAif (!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 = trim($file_ext); 首尾去空去空格的操作,不过因为在windows,以及代码上传中后缀会忽略空格,因此需要通过抓包添加空格
绕过:抓包添加空格绕过
Pass-8 . 绕过
关卡分析
$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-9 ::$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
::$DATA(只适用于Windows系统)在Windows的时候如果文件名"+::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名绕过,比如上传的文件名为info.php::$DATA会在服务器上重新生成一个test.php的文件,其中内容和所上传文件内容相同,并被解析。
绕过:抓包添加::$DATA
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",".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 . '文件夹不存在,请手工创建!';}
}
类似第五关可以通过. .的方式绕过
绕过:抓包加点加空格
Pass-11 双写绕过
关卡分析
$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 . '文件夹不存在,请手工创建!';}
}
与前面的有些许不同,代码在进行去空格和去转义字符后,将后缀存入$temp_file与黑名单进行move_uploaded_file这样移除的操作,例如:直接上传一个php文件
文件能够上传成功,但是打开时已经没有文件后缀了
这种情况我们可以考虑双写文件后缀进行绕过,即使其删除一次后恢复正常的文件后缀进行绕过上传
绕过:抓包双写后缀
Pass-12 %00阶段(GET型)
关卡分析
$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类型文件,但是我们的上传路径是可控的(通过GET方式传参)
%00截断
当编译时读取到0x00这样的空字符会认为是结束符,后面的内容都将不在读取,而在在url编码中使用%00作为字符串的结束标识符(表示数字‘0’是%20)
【注意:只有数据包中必须含有上传路径的情况下才可以用,攻击者可以通过修改path的值来构造paylod;但是,文件名的情况下,是不能让%00截断生效的,因为只是文件名可控,即使通过00截断`test.php%00.txt`,但是此时经过服务器处理后,文件名仍然为`test.php`,不能通过对后缀的检测】
绕过:抓包修改上传路径,通过%00截断后续的代码
上传成功后可以直接通过地址栏去找到上传的文件打开
【%00截断只适用于php5.2及以前的版本】
Pass-13 0x00截断(POST型)
关卡分析
$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类型文件!";}
}
这里和上一关区别只是一个为POST一个为GET方法,在GET请求中会对输入的内容进行URL解码。但POST请求有不同,因为在上传表单中存在一个enctype的属性,而且在enctype=”multipart/form-data”这里,是不会对表单中的数据进行解码的,需要我们将POST中的%00解码后传入。)
绕过:抓包修改上传路径后send,修改文件名后面的code值为00(即文件名后面的为'\0')
同上面一样,能够成功上传上去后可以通过地址栏直接输入文件路径打开
【也是只适用于php5.2及以前的版本】
Pass-14 图片马文件包含
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 = "上传出错!";}}
}