点击上方蓝字关注我们
一、环境准备
① 靶场的搭建
-
下载地址:upload-labs -
upload-labs靶场曾有过一次更新,更新新添加了一道Pass-05,有一些以前的教程的题号与这篇教程不符合,请各位自行分辨 -
本篇作者所用到的PHP版本为5.4.45(之前更改设置忘记调回来了,后面用的都是5.2.17,但是5.4.15亲测可用),只有在做部分题目时需要修改 -
Pass16需要打开php.ini中的php_exif模块
注意:更改配置之后记得重启服务器
② 准备webshell
-
测试用webshell
# shell.php → 测试所用的phpinfo
<?php phpinfo(); ?>
-
图片马的制作
准备工作:准备好
.jpg
/.png
/.gif
三种类型的图片,图片大小越小越好,推荐使用截图工具的截图;准备好webshell文件,将图片与文件放到一个目录下
-
在cmd下执行: copy 01.png/b + test.php/a shell.png
[01.png
为图片,大小不宜过大 |test.php
为webshell |shell.png
为生成的图片马文件]
③ 说明
-
Pass14 ~ Pass17的图片马我们将各挑选一种来做演示,不会三种后缀都上传一遍1 -
Pass14 ~ Pass17使用的文件包含漏洞的简单介绍:只要被包含的文件符合php语法,无关该文件的后缀类型,都会当作php代码执行。这就导致了我们可以上传任意类型的webshell,所以我们可以上传图片马作为webshell,不用考虑后缀问题 -
Pass17需要用到的Hex编辑器下载
二、题解
【Pass14 - 利用添加gif图片的文件幻数绕过】
题目:
绕过方法:
-
可以给webshell添加文件幻数(文件开头2个字节)绕过 -
可以上传图片马绕过。
因为Pass15和Pass16我们是使用图片马绕过,这一题我们使用第一种方法尝试,我们以较为简单的gif图为例(有兴趣的朋友们可以去试试其它的文件格式),步骤:在原有webshell代码前添加字符串GIF89a
第一步:上传webshell
可以看到,webshell被自动识别为了gif文件
第二步:利用文件包含漏洞访问图片马
【Pass15 - 利用png图片马绕过】
题目:
绕过方法:
上传图片马绕过
第一步:上传图片马
第二步:使用利用文件包含漏洞访问图片马
【Pass16 - 利用jpg图片马绕过】
题目:别忘记打开php_exif模块
绕过方法:
上传图片马绕过
第一步:上传图片马
第二步:使用利用文件包含漏洞访问图片马
【Pass17 二次渲染绕过】
题目:
# 使用二次渲染过滤
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){<!-
- -->
// 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
$filename = $_FILES['upload_file']['name'];
$filetype = $_FILES['upload_file']['type'];
$tmpname = $_FILES['upload_file']['tmp_name'];
$target_path=UPLOAD_PATH.'/'.basename($filename);
// 获得上传文件的扩展名
$fileext= substr(strrchr($filename,"."),1);
//判断文件后缀与类型,合法才进行上传操作
if(($fileext == "jpg") && ($filetype=="image/jpeg")){<!-
- -->
if(move_uploaded_file($tmpname,$target_path)){<!-
- -->
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path);
if($im == false){<!-
- -->
$msg = "该文件不是jpg格式的图片!";
@unlink($target_path);
}else{<!-
- -->
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".jpg";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagejpeg($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {<!-
- -->
$msg = "上传出错!";
}
}else if(($fileext == "png") && ($filetype=="image/png")){<!-
- -->
if(move_uploaded_file($tmpname,$target_path)){<!-
- -->
//使用上传的图片生成新的图片
$im = imagecreatefrompng($target_path);
if($im == false){<!-
- -->
$msg = "该文件不是png格式的图片!";
@unlink($target_path);
}else{<!-
- -->
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".png";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagepng($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {<!-
- -->
$msg = "上传出错!";
}
}else if(($fileext == "gif") && ($filetype=="image/gif")){<!-
- -->
if(move_uploaded_file($tmpname,$target_path)){<!-
- -->
//使用上传的图片生成新的图片
$im = imagecreatefromgif($target_path);
if($im == false){<!-
- -->
$msg = "该文件不是gif格式的图片!";
@unlink($target_path);
}else{<!-
- -->
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".gif";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagegif($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {<!-
- -->
$msg = "上传出错!";
}
}else{<!-
- -->
$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
}
}
绕过方法:
这里作者使用文章中介绍的GIF绕过方法进行打靶,其它方法比较麻烦,想玩玩的朋友们可以自行尝试
第一步:上传一个gif图片马,上传之后,将网站回显的图片下载下来进行比较发现少了一堆的数据,很不幸,写入的webshell被删了 第二步:找一个数据没有被更改的地方插入webshell代码
如果显示不为gif图片,则需要重新挑选一个位置插入webshell
第三步:上传图片马,并测试是否成功
【Pass18 条件竞争绕过文件删除】
题目:绕过方法:
根据题目可知,此操作是先将文件移动至目录,再判定是否符合上传规范,若不符合则删除文件。我们可以利用php代码生成新的webshell文件,再利用条件竞争在上传的文件未被删除之前访问它,则可以添加webshell文件至服务器
第一步:制作创建webshell的代码
若上传一句话木马,需要特别注意引号的问题:写入数据的时候需要使用单引号包裹,因为使用双引号会解析里面的$变量
<?php
fputs(fopen('shell.php','w'), '<?php phpinfo(); ?>');
?>
第二步:利用Burp的爆破模块制造条件竞争访问创建webshell的代码
-
抓取上传文件的包,并通过爆破模块进行持续无字典爆破 -
由源码可知,上传的文件不会被重命名。我们可以访问该文件(可以任意上传一个图片,找到保存的位置),并抓包,然后爆破模块进行持续无字典爆破 访问文件的爆破模块出现长度不同的返回包即可停止爆破,查看包的内容
由返回包可知访问成功
第三步:访问创建的webshell代码
【Pass19 apache的后缀名识别漏洞 + 条件竞争绕过重命名】
题目:绕过方法:
绕过白名单过滤:利用apache的后缀名识别漏洞 —— 从右往左依次识别后缀,遇到不能识别的后缀名便跳过 ,因此可以文件名改为
create.php.7z
(.7z
这个后缀apache不能识别)
绕过重命名(因为重命名会把shell.php
重命名为其它的字符串,导致后缀名识别漏洞不可用):利用条件竞争绕过
只需要对添加了.7z
后缀的文件进行条件竞争绕过即可,步骤与Pass18一致,这里就不做演示
【Pass20 ./
绕过黑名单检测】
题目:
绕过方法:
就是一个很简单的一个绕过黑名单检测,不明白为什么会放到Pass20来。只需要修改POST传参中的
save_name
参数即可,点绕过、大小写绕过啥的都可以
为了弄清楚这一题的考点,我去看了其它的靶场教程,发现是考
move_uploaded_file()
会忽略掉文件末尾的/.
,也就是将save_name
的参数改为shell.php/.
,亲测有效,应该是黑名单检测补充的一个新方法,这种方法没有系统的限制
【Pass21 /.
绕过白名单检测】
题目:
$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{<!-
- -->
//检查文件名
# 如果save_name存在则使用save_name的数据,否则使用upload_file的数据
$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的第一个元素与位于数组长度-1的元素拼接组成保存用的文件名
$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 = "请选择要上传的文件!";
}
绕过方法:
由代码审计可得,是通过读取数组的最后一个元素来进行后缀名白名单检测,通过位于数组长度-1的元素拼接文件名作为保存所用的文件数据。我们只需要让数组的最后一个元素符合条件,让数组长度-1的元素为空即可完成绕过
第一步:修改webshell的文件类型为白名单内的文件类型 第二步:修改请求包,将save_name空出来,不填入数据
Note:这一题的save_name参数最好要加上在结尾加上/
,利用/.
绕过,而不要单纯的使用.
绕过,因为.
绕过只适用于Windows系统
第三步:访问上传的文件
以下为注释内容 条件竞争:多个线程或进程在读写一个共享数据时结果依赖于它们执行的相对时间
参考资料
[1]upload-labs:https://github.com/c0ny1/upload-labs
原文始发于微信公众号(网络安全自修室):打靶归来-详解upload-labs靶场(下)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论