upload-labs靶场训练篇(windows版21题)14-21题 upload-labs为文件上传的训练靶场,目前一共有21关,基本涵盖了目前全部的文件上传漏洞。此篇为下篇。
level-14(图片马之文件头检测) 源码: 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 39 40 function getReailFileType ($filename ) { $file = fopen($filename , "rb" ); $bin = fread($file , 2 ); fclose($file ); $strInfo = @unpack("C2chars" , $bin ); $typeCode = intval($strInfo ['chars1' ].$strInfo ['chars2' ]); $fileType = '' ; switch ($typeCode ){ case 255216 : $fileType = 'jpg' ; break ; case 13780 : $fileType = 'png' ; break ; case 7173 : $fileType = 'gif' ; break ; default : $fileType = 'unknown' ; } return $fileType ; } $is_upload = false ;$msg = null ;if (isset ($_POST ['submit' ])){ $temp_file = $_FILES ['upload_file' ]['tmp_name' ]; $file_type = getReailFileType($temp_file ); if ($file_type == 'unknown' ){ $msg = "文件未知,上传失败!" ; }else { $img_path = UPLOAD_PATH."/" .rand(10 , 99 ).date("YmdHis" )."." .$file_type ; if (move_uploaded_file($temp_file ,$img_path )){ $is_upload = true ; } else { $msg = "上传出错!" ; } } }
解答: 图片马
拓展一下如何制作图片马:
思路:上传图片马,制作:copy x.jpg/b + x.php/a xx.jpg
,上传后需要结合文件包含漏洞利用,或者目标服务器支持以php解析.jpg后缀,这里需要注意的是图片马中的一句话能写到中间尽量写到中间,真实环境不容易被发现,可用winhex或bp修改 copy使用注意事项:图片一定要在copy后面,否则创建出来的木马图片有可能无法显示,例如,copy x.php/a + x.gif/b xx.gif
,xx.gif就无法显示。
本题上传图片马后,利用作者留下的include.php来验证。
payload:include.php?file=upload/xx.gif
执行phpinfo();
成功
level-15 源码: 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 function isImage ($filename ) { $types = '.jpeg|.png|.gif' ; if (file_exists($filename )){ $info = getimagesize($filename ); $ext = image_type_to_extension($info [2 ]); if (stripos($types ,$ext )>=0 ){ return $ext ; }else { return false ; } }else { return false ; } } $is_upload = false ;$msg = null ;if (isset ($_POST ['submit' ])){ $temp_file = $_FILES ['upload_file' ]['tmp_name' ]; $res = isImage($temp_file ); if (!$res ){ $msg = "文件未知,上传失败!" ; }else { $img_path = UPLOAD_PATH."/" .rand(10 , 99 ).date("YmdHis" ).$res ; if (move_uploaded_file($temp_file ,$img_path )){ $is_upload = true ; } else { $msg = "上传出错!" ; } } }
解答: 本题检验文件头,采用:GIF89a
来绕过,详细步骤与上题一样。
拓展图片文件头:
1 2 3 JPEG (jpg),文件头hex:FF D8 FF PNG (png),文件头hex:89 50 4E 47 GIF (gif),文件头hex:47 49 46 38(也就是GIF89a)
level-16 源码: 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 function isImage ($filename ) { $image_type = exif_imagetype($filename ); switch ($image_type ) { case IMAGETYPE_GIF: return "gif" ; break ; case IMAGETYPE_JPEG: return "jpg" ; break ; case IMAGETYPE_PNG: return "png" ; break ; default : return false ; break ; } } $is_upload = false ;$msg = null ;if (isset ($_POST ['submit' ])){ $temp_file = $_FILES ['upload_file' ]['tmp_name' ]; $res = isImage($temp_file ); if (!$res ){ $msg = "文件未知,上传失败!" ; }else { $img_path = UPLOAD_PATH."/" .rand(10 , 99 ).date("YmdHis" )."." .$res ; if (move_uploaded_file($temp_file ,$img_path )){ $is_upload = true ; } else { $msg = "上传出错!" ; } } }
解答: 与14和15的方法一样。需要环境:PHP版本大于5.2.10,且开启php_exif扩展
level-17 源码: 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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 $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。具体上传方式会在总结的笔记中详细记录
level-18 源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $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删除文件,我们在他删除之前再次上传,使用条件竞争
发送到爆破,修改一下参数:
no payload 无限次循环
开始攻击。然后以同样的方法访问write_shell.php
。当访问到相应为200后,会自动生成shell.php
。
访问即可。
level-19 源码: 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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 $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 ; } } class MyUpload {...... ...... ...... var $cls_arr_ext_accepted = array ( ".doc" , ".xls" , ".txt" , ".pdf" , ".gif" , ".jpg" , ".zip" , ".rar" , ".7z" ,".ppt" , ".html" , ".xml" , ".tiff" , ".jpeg" , ".png" ); ...... ...... ...... 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 ( $this ->cls_file_exists == 1 ){ $ret = $this ->checkFileExists(); if ( $ret != 1 ){ return $this ->resultUpload( $ret ); } } $ret = $this ->move(); if ( $ret != 1 ){ return $this ->resultUpload( $ret ); } if ( $this ->cls_rename_file == 1 ){ $ret = $this ->renameFile(); if ( $ret != 1 ){ return $this ->resultUpload( $ret ); } } return $this ->resultUpload( "SUCCESS" ); } ...... ...... ...... };
解答: 图片二次渲染,或者利用Apache解析漏洞条件竞争都可。
Apache解析漏洞参考链接:
Apache HTTPD 未知后缀解析漏洞
level-20 源码: 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 $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 . '文件夹不存在,请手工创建!' ; } }
解答: %00截断或者继续解析漏洞。
可控post上去的文件名
直接文件包含也行。
level-21 源码: 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 $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 = "请选择要上传的文件!" ; }
解答: 数组加截断绕过,不详细复现了,给出参考链接和答案。
参考链接: 文件解析漏洞总结
upload-labs—wp(21关)
upload-labs 21关大合集
CTFSHOW文件上传篇