若要自己亲自搭建环境,请按照以下配置环境,方可正常运行每个Pass。
配置项 | 配置 | 描述 |
---|---|---|
操作系统 | Window or Linux | 推荐使用Windows,除了Pass-19必须在linux下,其余Pass都可以在Windows上运行 |
PHP版本 | 推荐5.2.17 | 其他版本可能会导致部分Pass无法突破 |
PHP组件 | php_gd2,php_exif | 部分Pass依赖这两个组件 |
中间件 | 设置Apache | 以moudel方式连接 |
$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_ADDR.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格式的图片!"; }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".jpg"; $newimagepath = $UPLOAD_ADDR.$newfilename; imagejpeg($im,$newimagepath); //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = $UPLOAD_ADDR.$newfilename; 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格式的图片!"; }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".png"; $newimagepath = $UPLOAD_ADDR.$newfilename; imagepng($im,$newimagepath); //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = $UPLOAD_ADDR.$newfilename; 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格式的图片!"; }else{ //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".gif"; $newimagepath = $UPLOAD_ADDR.$newfilename; imagegif($im,$newimagepath); //显示二次渲染后的图片(使用用户上传图片生成的新图片) $img_path = $UPLOAD_ADDR.$newfilename; unlink($target_path); $is_upload = true; } } else { $msg = "上传失败!"; } }else{ $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!"; } }
$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_ADDR . '/' . $file_name; if(move_uploaded_file($temp_file, $upload_file)){ // 先移动图片,有条件竞争的前提条件 if(in_array($file_ext,$ext_arr)){ $img_path = $UPLOAD_ADDR . '/'. rand(10, 99).date("YmdHis").".".$file_ext; rename($upload_file, $img_path); unlink($upload_file); $is_upload = true; }else{ $msg = "只允许上传.jpg|.png|.gif类型文件!"; unlink($upload_file); } }else{ $msg = '上传失败!'; } }
首先在burp中不断发送上传webshell的数据包,然后不断在浏览器中访问,发现通过竞争可以访问到。
/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_ADDR); 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的问题,从而上传成功:
$is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists($UPLOAD_ADDR)) { $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)) { $img_path = $UPLOAD_ADDR . '/' .$file_name; if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $img_path)) { $is_upload = true; }else{ $msg = '上传失败!'; } }else{ $msg = '禁止保存为该类型文件!'; } } else { $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!'; } }
_POST['save_name'];中有变量可控 发现move_uploaded_file()函数中的img_path是由post参数save_name控制的,因此可以在save_name利用00截断绕过
本文分享自微信公众号 - HACKWAY(gh_7a5a315cde00),作者:HACKWAY
原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。
原始发表时间:2020-04-18
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句