第十一关:双写绕过
$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 . '文件夹不存在,请手工创建!';
}
}
trim函数 根据我们的测试,它是将指定的字符串移除,那么在这里我们就可以上传.pphphp即可绕过
从这一关开始,就是白名单上传了。前一期已经对白名单进行了解释,在这就不再BB了
$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类型文件!";
}
}
在这里,代码虽然对上传进行了白名单限制,但是这里对上传的文件进行文件名重构,那么我们就可以以用这个重构进行绕过
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
虽然问题找到了,但是%00对PHP版本有要求,
(1)php版本必须小于5.3.4
(2)打开php的配置文件php-ini,将magic_quotes_gpc设置为Off
所有我没办法给大家演示,请大家参考一下,
https://blog.csdn.net/weixin_43571641/article/details/83832578
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
代码和上面差不多,只是这里有一小点变化,GET变为POST
把抓取到的数据包发送到repeater模块,修改如下信息然后点击Hex
找到php+所在位置,按照位置修改+对应的hex为00 如上图所示
注:每一个hex值也就是上面的小方块对应右手边的一个字符。
这题和上面一样都需要php版本小于5.3.4,在这我没办法给大家复习,如果有需要,自行安装其它版本的phpstudy吧
先给大家说一下,文件包含漏洞,以后就不再给大家说了程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数
时,直接调用此文件,无需再次编写,这种调用文件的过程一般被称为文件包含
说白了,就是开发的时候代码写的不够严谨。
这里直接给出了文件包含漏洞,所有我们上传一张图片马即可
我们在同一目录下,存放一句话木马和一张图片
在目录当前运行cmd命令即可
copy 1.jpg/b + 1.php/a 2.jpg
点击下面->文件包含漏洞
访问127.0.0.1/upload-labs/include.php?file=+“图片上传路径”
菜刀连接即可
再这里补充一下文件包含漏洞一些常见操作
1、etc /flag 这里的flag.txt 是自己在upload同级目录下创建的
2、php伪协议(读取php文件)
url?file=php://filter/convert.base64-encode/resource=index.php
得到的结果,base解码即可
参考连接:
https://blog.csdn.net/nzjdsds/article/details/82461043
这两个题都是和第十四关一样的解法,在这就不多说了
$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删除文件,因此可以通过条件竞争的方式在unlink之前,访问webshell。
我们把它转送到Intruder模块
如果效果和我的不一样(才导入过来肯定不一样)记得点击右手边上的Clera
然后我们调整一下Plaloads 意思是啥呢,就是让这个数据包不做变化不断发送同一个包就OK
切记设置上传次数(不要太少)
然后设置线程
点击右上角Start attack跑起来就好
然后我们一直访问可以看见这里没有任何东西(默认提前知道了上传路径)
这就算是成功了 这里没有成功执行php的原因是没有解析,因为源代码是把它当成jpg执行的
所以这里我们结合文件包含试试
附:这里我们其实可以开启两个爆破模块,分别执行俩个操作。第一个是不断上传webshell 另外一个就是访问http://localhost/upload-labs/include.php?file=upload/phpinfo.php
第二个模块肯定是能够返回访问成功的页面
//index.php
$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{
require_once("./myupload.php");
$imgFileName =time();
$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
$status_code = $u->upload(UPLOAD_PATH);
switch ($status_code) {
case 1:
$is_upload = true;
$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
break;
case 2:
$msg = '文件已经被上传,但没有重命名。';
break;
case -1:
$msg = '这个文件不能上传到服务器的临时文件存储目录。';
break;
case -2:
$msg = '上传失败,上传目录不可写。';
break;
case -3:
$msg = '上传失败,无法上传该类型文件。';
break;
case -4:
$msg = '上传失败,上传的文件过大。';
break;
case -5:
$msg = '上传失败,服务器已经存在相同名称文件。';
break;
case -6:
$msg = '文件无法上传,文件不能复制到目标目录。';
break;
default:
$msg = '未知错误!';
break;
}
}
//myupload.php
class MyUpload{
......
......
......
var $cls_arr_ext_accepted = array(
".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
".html", ".xml", ".tiff", ".jpeg", ".png" );
......
......
......
/** upload()
**
** Method to upload the file.
** This is the only method to call outside the class.
** @para String name of directory we upload to
** @returns void
**/
function upload( $dir ){
$ret = $this->isUploadedFile();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->setDir( $dir );
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->checkExtension();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->checkSize();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// if flag to check if the file exists is set to 1
if( $this->cls_file_exists == 1 ){
$ret = $this->checkFileExists();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// if we are here, we are ready to move the file to destination
$ret = $this->move();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// check if we need to rename the file
if( $this->cls_rename_file == 1 ){
$ret = $this->renameFile();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// if we are here, everything worked as planned :)
return $this->resultUpload( "SUCCESS" );
}
......
......
.
分析,本关对文件后缀名做了白名单判断,然后一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名同样存在条件竞争的漏洞。
上传一个图片马,不断利用burp发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename的问题,从而上传成功
由于时间原因我就不再演示,参考第17题的利用方式
$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");
$file_name = $_POST['save_name'];
$file_ext = pathinfo($file_name,PATHINFO_EXTENSION);
if(!in_array($file_ext,$deny_ext)) {
$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 = '禁止保存为该类型文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
从源码中我们可以看到,.use.ini没有在白名单中。在这我偷偷窃喜,可惜当我尝试半天之后我终于发现它并不能成功。关于.uer.ini使用方式和原理请参考
https://xz.aliyun.com/t/6091
也可以去BUUCTF上做做web的CheckIn这个题目
我的方式是简单粗暴
访问一下就OK了 如果不能理解请参考上一篇文章的第八关
$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_name经过reset($file) . '.' . $file[count($file) – 1];处理。
如果上传的是数组的话,会跳过$file = explode('.', strtolower($file));。并且后缀有白名单过滤
而最终的文件名后缀取的是$file[count($file) – 1],因此我们可以让$file为数组。$file[0]为phpinfo.php/,也就是reset($file),然后再令$file[2]为白名单中的jpg。此时end($file)等于jpg,$file[count($file) – 1]为空。而 $file_name = reset($file) . '.' . $file[count($file) – 1];,也就是phpinfo.php/.,最终move_uploaded_file会忽略掉/.,到这里我们就上传成功了
本题参考文章为:https://xz.aliyun.com/t/4029