文件上传漏洞练习 upload-labs(11~15)【双写绕过,get%00截断绕过,post 00截断绕过,图片马上传及绕过】
写在前面
下面几道题目与php源码、图片木马有关,如果你对php或者图片木马并不是很熟悉,或者看起来较为吃力,可以点击下方
源码分析链接
会有基础知识和图片马的知识基础,同时在pass-03中有源码分析和对各个函数的讲解。
图片木马在下方pass也会有讲解,也可以看看。
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 . '文件夹不存在,请手工创建!';
}
}
这里的改变是$file_name = str_ireplace($deny_ext,"", $file_name);
这个函数在前面我们已经讲过了,参数分别为:查找值,替换值,待查找目标。
简单来说,就是在你的文件中搜寻是否存在黑名单中的值并且替换为空。
利用双写进行绕过即可。将后缀换为 .pphphp
即可
上传后后缀就变成了php,直接连接即可。
Pass-12
查看源码,变成了白名单。
只能上传图片相关格式。
来看看新源码吧:
$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类型文件!";
}
}
strrpos() 与 strrch() 差不多
用于函数查找字符串在另一字符串中最后一次出现的位置。参数分别为:待查找字符串,查找关键字。
在这里就是取出最后一个后缀。
攻击原理:php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00。
前提:
但需要php版本<5.3.4,并且magic_quotes_gpc关闭。(php.ini中关闭)
并且在后面的保存的时候,文件名是拼接的 但看到$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext
;前面的save_path是用get请求到的,所以你还需要可控路径。
在这里的save_path,我们加上%00来截断后面的rand等等,这样就可以让文件按照我们想要的格式进行储存
在高亮位置写上截断,以php形式保存(注意与后面 HTTP之间有一个空格,否则会失效)
文件本身是写着后门的木马以.jpg后缀上传。
上传成功:
连接时直接使用php后缀即可。
Pass-13
这个题也是00截断的知识点考察,不过这里是以post的形式进行数据发送。
你需要额外知道的是:
POST不会对里面的数据自动解码,需要在Hex中修改。
这里写上‘+’,方便后面修改,+的hex是2b
找到它:
将其修改为00
放包即可
上传成功:
总结:以上两题就是因为存储路径可控造成我们可以自定义存储方式,这样我们上传的.jpg/.png文件就能够重新以php的形式储存。
Pass-14
到这里我们就要使用文件包含了。任务要求也发生了变化:
在开始之前,我们再复习一下图片马,图片马和普通木马的区别在于图片马打开时仍然“像”一张图片,在服务器执行之后就会额外生成恶意代码,本身在前端无法生成。
如果你不使用一句话木马,你也可以使用要求生成一句话木马的脚本
推荐使用格式是fputs、fopen和之前的eval,POST形式。
(由于敏感原因,如果你需要源代码,请自行搜索。)
图片马合成推荐直接使用cmd的copy命令。
整体来说:
1.你需要能够成功上传
2.能够成功在服务器端执行代码
这里使用的图片检测函数为exif_imagetype() 使用的是头部检测方法
补充知识:
1.Png图片文件包括8字节:89 50 4E 47 0D 0A 1A 0A。即为 .PNG。
2.Jpg图片文件包括2字节:FF D8。
3.Gif图片文件包括6字节:47 49 46 38 39|37 61 。即为 GIF89(7)a。
4.Bmp图片文件包括2字节:42 4D。即为 BM。
那么,现在开始吧
利用我们上方的方法制作的图片马将它上传上去,上传完成后,在新标签页打开这个图片
可以看到它被重命名后的名字,随后使用本地文件包含。
在这里进行测试
payload:
include.php?file=upload/3420210320172751.png
注意:上传的图片尽量是小图片,10kb左右最好,否则解析时可能出现莫名其妙的问题。这与apache的特性,配置有关。
在测试页面成功文件包含后,显示出的源代码如下:
是一堆乱码,这也就是说图片解析成功了
最后连接即可
在这里使用的就是头部检测策略,
所以,我们还有个方法,就是把php马用记事本打开,开头加上gif的文件头GIF89a,在把后缀改为gif。这里就不演示了。
Pass15
这里就用的另外一种检测方式,使用的getimagesize(),来看看它的介绍:
也就是说必须是一张“图”,那么和上一个题的解法是一样的,只是不能再从头部修改来绕过了。