一、环境准备
① - 靶场的搭建
- 下载地址:upload-labs
- upload-labs靶场曾有过一次更新,更新新添加了一道Pass-05,有一些以前的教程的题号与这篇教程不符合,请各位自行分辨
- 本篇作者所用到的PHP版本为5.4.45(之前更改设置忘记调回来了,后面用的都是5.2.17,但是5.4.15亲测可用),只有在做部分题目时需要修改
- Pass16需要打开php.ini中的php_exif模块
注意:更改配置之后记得重启服务器
② - 准备webshell
- 测试用webshell
<?php phpinfo(); ?>
- 图片马的制作
- 准备工作:准备好
.jpg / .png / .gif 三种类型的图片,图片大小越小越好,推荐使用截图工具的截图;准备好webshell文件,将图片与文件放到一个目录下 - 在cmd下执行:
copy 01.png/b + test.php/a shell.png [01.png 为图片,大小不宜过大 | test.php 为webshell | shell.png 为生成的图片马文件]
③ - 说明
- Pass1 ~ Pass13 见打靶归来 - 详解upload-labs靶场(上)
- 确认webshell上传成功的演示在上篇做了说明,这里就不再赘述
- Pass14 ~ Pass17的图片马我们将各挑选一种来做演示,不会三种后缀都上传一遍
- Pass14 ~ Pass17使用的文件包含漏洞的简单介绍:只要被包含的文件符合php语法,无关该文件的后缀类型,都会当作php代码执行。这就导致了我们可以上传任意类型的webshell,所以我们可以上传图片马作为webshell,不用考虑后缀问题
- Pass17需要用到的Hex编辑器下载 —— 网盘链接 【提取码:8888】
二、题解
【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
第三步:上传图片马,并测试是否成功 作者用到的Hex编辑器的下载链接在文章开头有介绍
【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'])){
$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 = "请选择要上传的文件!";
}
绕过方法:
由代码审计可得,是通过读取数组的最后一个元素来进行后缀名白名单检测,通过位于数组长度-1的元素拼接文件名作为保存所用的文件数据。我们只需要让数组的最后一个元素符合条件,让数组长度-1的元素为空即可完成绕过
第一步:修改webshell的文件类型为白名单内的文件类型 第二步:修改请求包,将save_name[1]空出来,不填入数据
Note:这一题的save_name参数最好要加上在结尾加上/ ,利用/. 绕过,而不要单纯的使用. 绕过,因为. 绕过只适用于Windows系统 第三步:访问上传的文件
|