解题思路:(绕开前端js检测)
(1):F12 ,直接修改js 允许文件的上传类型 ,
(2):将webshell 文件后缀名改为允许上传的,然后用 burp suite 拦截后修改 文件后缀名 ,
(3):利用 浏览器插件 Noscrip 屏蔽js脚本
操作过程: 1,禁用了js 脚本依旧不能上传,猜测可能是 content-type 检测
解题思路:(Content-type 检测)
(1):将webshell 文件的后缀名改为图片类型 ,再利用 bs 抓包 修改文件后缀
(2):直接上传 webshell 文件 ,利用 bs 修改 Content-type :为 image/gif 绕过
操作过程:修改了webshall 的后缀名,再利用bs 修改成原来的后缀名没有上传成功,猜测服务器端也有文件后缀名检测
查看源代码发现有 文件后缀名的黑名单,以及大小写的过滤
解题思路:(服务端 拓展名检测 之 黑名单后缀名不全)
(1) , 用PHP 的别名进行黑名单绕过,如 php2, php3, php4, php5, phps, pht, phtm, phtml
.
(2), 重写文件解析规则绕过。上传先上传一个名为.htaccess
文件,内容如下:
SetHandler application/x-httpd-php
然后再上传一个 1.jpg 此时1.jpg 就会被当作 PHP来执行
操作过程:查看源代码 发现黑名单几乎过滤了全部的违法后缀名 ,但少过滤了 .htaccess 后缀
解题思路:(拓展名检测 之 绕过黑名单 之 后缀名缺少绕过)
(1),上传一个.htaccess 文件 重写 服务器的文件解析
创建一个.htaccess
文件
内容可以是 : AddType application/x-httpd-php .jpg
,可将jpg
文件解析为php
文件.
或者是 : SetHandler application/x-httpd-php
,可将其他所有文件解析为php
文件.
(2),利用PHP 和 Windows环境的叠加特性,以下符号在正则匹配时的相等性:
双引号" = 点号.
大于符号> = 问号?
小于符号< = 星号*
先把4.php文件后缀改为4.jpg 然后用bs 将文件名改为 4.php:.jpg
,上传成功后会生成4.php
的空文件,大小为0KB.
然后再在bs 中把文件名 改为4.<
或4.<<<
或4.>>>
或4.>><
后再次上传,重写4.php
文件内容,Webshell代码就会写入原来的4.php
空文件中。
操作过程: 查看源代码发现 黑名单里加上了 .htaccess 后缀 ,但是没有 进行大小写 过滤
解题思路:(拓展名检测 之 黑名单绕过 之 大小写绕过)
(1),可以利用 没有进行大小写 进行绕过 ,将1.php 改为 1.phP 上传
(在Linux没有特殊配置的情况下,这种情况只有win可以,因为win会忽略大小写)
(2)也可以用 pass-04 的(2)利用PHP 和 Windows环境的叠加特性,进行绕过
操作过程:查看原第阿玛发现 在 pass-05 的基础上 加上了 大小写 过滤, 但发现 去掉了 收尾去空
查了一下:trim()
函数 : 移除字符串两侧的空白字符或其他预定义字符
.
Win下xx.jpg[空格] 或xx.jpg.
这两类文件都是不允许存在的,若这样命名,windows会默认除去空格或点
解题思路:( 拓展名检测 之 黑名单 之 收尾去空)
(1) 用bs 在1.php 后缀名后面加一个空格 成功绕过
操作过程:查看源代码后 发现没有 删除文件名末尾的点 的过滤
解题思路:(拓展名检测 之 黑名单 收尾去点)
(1),利用windows特性,会自动去掉后缀名中最后的”.” 用bs 在文件名后加 “ .” 成功绕过
操作过程:查看源代码后 发现 黑名单过滤 没有 去字符串 ::$DATA
解题思路:(拓展名检测之 黑名单 之 去字符串 ::$DATA)
(1),NTFS文件系统包括对备用数据流的支持。这不是众所周知的功能,主要包括提供与Macintosh文件系统中的文件的兼容性。备用数据流允许文件包含多个数据流。每个文件至少有一个数据流。在Windows中,此默认数据流称为:$ DATA
。
上传.php::$DATA
绕过。(仅限windows) 上传后 自动保存为 1.php
操作过程:查看源代码 发现 他把之前的漏洞都 补上了 但他 代码本身就有问题 : 之过滤了 一个点 和 一个 空格
还有PATH :
解题思路:(拓展名检测 之 黑名单 之 末尾 点和空格 过滤)
(1) 可以用 bs 将1.php 改为 1.php. . (点+空格+点) 成功绕过
(2)这里发现$_FILES['upload_file']['name']
获取的是文件名中/
后面的字符串,本来还想用move_uploaded_file
会忽略/.
的trick绕过
操作过程:查看源代码 发现 依旧是黑名单过滤 关键过滤就这两句:
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
#当file_name中出现deny_ext中存在的字符串,就把它去掉,但只处理了一次.
解题思路:(拓展名检测 之 黑名单 之 后缀名双写)
(1),可以用双写后缀名 进行绕过 将1.php 改为 1.pphphp 成功绕过
操作过程:查看源代码,发现是白名单过滤
$ext_arr = array('jpg','png','gif');
但是img_path
直接使用点号拼接路径,这里就存在风险.
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
我们可以使用%00截断
来实现绕过.
但这东西有点过气了,因为需要两个条件
如果要完成这一个题目就必须要实现上面的两个条件,但是现在都PHP7了,这东西也就很少见了,满足上面的条件的时候php就是把它当成结束符,后面的数据直接忽略
解题思路:(前台检测 之 白名单 之 img_path 直接用点号拼接)
(1) 用bs 将save_path 和文件名 filename 改为:
save_path=../upload/1.php%00
filename="1.jpg"
网页显示地址
访问地址 : http://localhost/upload-labs/Pass-01/../upload/1.php
这里可本地测试发现通过%00截断,使得无法复制/4620180731010238.jpg" width="250px" />
,即表明截断成功.
此方法没有绕过
操作过程:产看源代码 发现 此题在上题 将GET 换为 POST ,还是利用pass-11 的方法 ,但在url
解码中%00
不会被解析.
但是这里我们可以使用0x00
进行截断.
解题思路:(前台检测 之 白名单 之 img_path 直接拼接 post传参)
操作过程:查看源代码 发现:
代码通过读取上传文件的前两字节判断是否为图片.(漏洞)
$bin = fread($file, 2); //只读2字节
fclose($file);
$strInfo = @unpack("C2chars", $bin);
所以我们可以将图片和一句话木马合并在一起上传.
解题思路:(图片马 之 通过前两个字节判断是否为图片 )
(1)最最最简单的图片马直接一条命令即可生成:生成一个名为 1.png 的图片马
cope 2.jpg/b + 1.php/a 1.png
上传即可,但无法直接利用!
查看upload文件夹 发现 上传的1.png 的后缀名 变成了原来的 .jpg
操作过程:查看源代码 发现:
关键代码 :
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
getimagesize
通过检查图像文件的大小并返回图像的尺寸以及文件类型.
image_type_to_extension
根据指定的图像类型返回对应的后缀名.
解题思路:(图片马 之 使用getimagesize()检查是否为图片文件)
(1)与pass-13 一样直接上传 图片马1.png 成功绕过
查看upload 文件夹 发现 文件的后缀名 变为: .jpeg 原图片为.jpg 都会被改为 .jpeg
操作过程:查看源代码 发现更换了函数:
$image_type = exif_imagetype($filename);
解题思路:(图片马 之 使用exif_imagetype()检查是否为图片文件)
(1)解法同pass-13 可能是环境有问题 上传后直接空白了
操作过程:查看源代码,发现这一关对后缀名和文件类型啥的都进行了很严格的控制,而且在后面还对图片进行了二次编译
解题思路:(二次渲染)
(1)jpg
和png
很麻烦,gif
只需要找到渲染前后没有变化的位置,然后将php
代码写进去,就可以了
jpg 和png 的处理方法 参照https://xz.aliyun.com/t/2657 讲的很细致
操作过程:查看提示,发现是 条件竞争:
条件竞争
条件竞争是指一个系统的运行结果依赖于不受控制的事件的先后顺序。
当这些不受控制的事件并没有按照开发者想要的方式运行时,就可能会出现 bug。
尤其在当前我们的系统中大量对资源进行共享,如果处理不当的话,就会产生条件竞争漏洞。
如果文件检测是先保存后检测,文件不合法再删除的方式进行的,典型的“引狼入室”。
就可以利用条件竞争的方式在木马文件在被删除之前访问它,使他成功的执行
具体的操作过程就是,利用工具,一边不断地快速上传木马文件,一边不断的请求访问上传的木马文件,使一些来不及被删除的木马文件被成功执行
解题思路:(条件竞争)
$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 = '上传出错!';
}
}
可以看到文件先经过保存,然后判断后缀名是否在白名单中,如果不在则删除,此时可以利用条件竞争在保存文件后删除文件前来执行php文件。
先利用burp suite抓一个文件上传的包,右键 Send to Intruder 》添加爆破点 》添加payload,先暂时不开始爆破
我是在一句话后面加了个 爆破点,不影响一句话的执行,至于payload我随便找了个相对较长的字典10000.txt
然后再在浏览器上访问 127.0.0.1/upload-labs/upload/1.php,利用 burpsuite抓包,右键 Send to Intruder 》添加爆破点 》添加payload字典, 字典还用 10000.txt
然后两个爆破 同时点击 Start Attack ,一个上传,一个访问,然后你就会发现有成功访问的包
成功访问到了还没来得及删除的非法文件
操作过程:根据apache的后缀名识别漏洞:从右往左依次识别后缀,遇到不能识别的后缀名便跳过 ,因此可以文件名改为
1.php.7z,然后利用bs 快速发包,
本关对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用burp发送上传图片马的数据包,因为move在rename之前,move操作进行了一次文件保存,然后rename进行了一次更改文件名,由于条件竞争,程序会出现来不及rename的问题,从而上传成功
解题思路:(条件竞争)
(1)利用Apache 的漏洞,将webshell 脚本文件名改为1.php.7z (白名单中 有.7z 这个apache 不能识别的后缀,所以用.7z)
然后利用bs 去不断快速发包,实现条件竞争,进而保留了脚本名,使apache 将其识别为1.php
(2)单纯利用 条件竞争,利用bs 去不断快速发包,实现条件竞争,进而保留了图片马的文件名,成功绕过
操作过程:发现move_uploaded_file()函数中的img_path是由post参数save_name控制的,因此可以在save_name利用00截断绕过. 还有就是move_uploaded_file
底层会调用tsrm_realpath
函数导致,递归删除文件名最后的/.
导致绕过了后缀名检测
解题思路:(0x00截断)
(1), 利用00截断进行绕过,将文件名改为:xx.php【二进制00】.x.jpg
(2)递归删除文件名最后的/.
导致绕过了后缀名检测,在bs中将文件名改为:1.php/. 成功绕过
(3),不知道怎么回事,用大小写就成功绕过了,1.phP
操作过程:而最终的文件名后缀取的是$file[count($file) - 1]
,因此我们可以让$file
为数组。$file[0]
为smi1e.php/
,也就是reset($file)
,然后再令$file[2]
为白名单中的jpg。
此时end($file)
等于jpg,$file[count($file) - 1]
为空。
而 $file_name = reset($file) . '.' . $file[count($file) - 1];
,也就是smi1e.php/.
,最终move_uploaded_file
会忽略掉/.
,最终上传smi1e.php
。
解题思路:(数组 + /. 绕过)