Upload-labs文件上传靶场通关---{更新第16关中}
upload-labs是一个使用php语言编写的、专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共21关,每一关都包含着不同上传方式。
以下是Upload-labs文件上传靶场中包含的文件上传漏洞类型:
注:Upload-labs文件上传靶场的搭建方法请查阅另一篇Blog:基于Ubuntu20.04搭建Upload-labs文件上传靶场。以下通关过程中,为了避免其它因素干扰,大部分关卡采用了upload-labs作者推荐的windows版傻瓜式集成包,个别关卡采用Ubuntu+phpstudy环境。
Pass-01 前端JS限制
首先制作一个一句话木马文件。本次通关中为快速验证靶场通关结果,以phpinfo()函数替代恶意函数。
即输入<?php phpinfo();?>
重命名为phpinfo.php
访问Upload-labs文件上传靶场的Pass-01,选择phpinfo.php文件
点击上传,发现上传失败,提示文件类型非法
将phpinfo.php文件后缀名更改为.jpg,再次上传
抓包修改文件名后缀,将.jpg改为.php,点击Forward
继续点击Forward,注意观察上传请求的路径信息
访问/upload/phpinfo.php,显示如下信息说明已执行了文件中已定义的phpinfo()函数,上传成功。
查看源代码
为了便于理解和上手操作,第1关文件上传流程记录得较为详细。后续将进行简化。
Pass-02 MIME绕过
选择phpinfo.php文件,上传失败,提示如下:
上传phpinfo.php文件,抓包将Content-Type: application/octet-stream
改为
Content-Type: image/jpeg
或
Content-Type: image/png
或
Content-Type: image/gif
此时可成功访问/upload/phpinfo.php。
查看源代码:
Pass-03 特殊后缀绕过黑名单
选择phpinfo.php文件,上传失败,提示如下:
上传phpinfo.php文件,抓包将文件名后缀更改为.phtml
或 .php3
均可。
继续点击Forward,注意观察请求路径中的文件名已重新命名。
此时可成功访问 http://192.168.3.21/upload/202307301634081208.php3,
但是访问原文件名 http://192.168.3.21/upload/phpinfo.php 失败。
查看源代码:
注:本次通关环境为windows版phpstudy、PHP5.2.17,并且Apache httpd.conf中的 AddType application/x-httpd-php .php .php3 .phtml .php5
配置生效。
Pass-04 .htaccess绕过黑名单 {“待更新”}
选择phpinfo.php文件,上传失败,提示如下:
使用上一关Pass-03的篡改文件名后缀为.phtml
或 .php3
的方法也提示失败。
.htaccess {“待更新”}。。。
查看源代码:
Pass-05 大写绕过黑名单
选择phpinfo.php文件,上传失败,提示如下:
将phpinfo.php文件重命名为phpinfo.phP,直接上传,访问成功。
查看源代码:
Pass-06 加空格绕过黑名单
选择phpinfo.php文件,上传失败,提示如下:
抓包在phpinfo.php文件后面加一个空格,直接上传,访问成功。
查看源代码:
Pass-07 加.绕过黑名单
选择phpinfo.php文件,上传失败,提示如下:
抓包在phpinfo.php文件后面添加一个.
不加空格,点击Forward上传。
此次后台未对文件名进行变更,访问 /load/phpinfo.php 或 /load/phpinfo.php. 均可成功。
查看源代码:
Pass-08 加::$DATA
绕过黑名单
选择phpinfo.php文件,上传失败,提示如下:
抓包在phpinfo.php文件后面添加::$DATA
,点击Forward上传。
访问 /upload/202308011129144699.php::$data
显示Fobidden,
访问 /upload/202308011129144699.php
成功。
查看源代码:
Pass-09 加. .
绕过黑名单
选择phpinfo.php文件,上传失败,提示如下:
抓包在phpinfo.php文件后面添加点空格点. .
,点击Forward上传。
访问成功:
查看源代码:
Pass-10 双后缀绕过黑名单
选择phpinfo.php文件,点击上传,未提示失败,但是无法访问。显示如下:
抓包将文件phpinfo.php
的后缀.php
改为.pphphp
点击Forward上传。
此时文件名后缀已经成功绕过,但是文件名中的php也去掉了,最终的文件名为info.php
访问 /upload/info.php
成功
查看源代码:
Pass-11 00截断
选择phpinfo.php文件,上传失败,提示如下:
抓包在第一行的save_path=../upload/
后面添加phpinfo.php%00
Content-Disposition处的form-data; name="upload_file"; filename="phpinfo.jpg"
文件名保持不变,点击Forward上传。
访问/upload/phpinfo.php
成功。
查看源代码:
注:利用00截断的前提条件
php版本小于5.3.4 php的magic_quotes_gpc为OFF状态
Pass-12 00截断
选择phpinfo.php文件,上传失败,提示如下:
抓包在../upload/
处添加phpinfo.php%00,
点击上传后访问失败。
接下来,抓包在../upload/
处添加phpinfo.php=
在Hex视图中找到=
对应的3d
并将其改为00
,点击Forward上传,访问成功。
查看源代码:
Pass-13 图片马 unpack()
首先试试能否上传一句话:选择phpinfo.php文件,上传失败,提示如下:
现在打开cmd窗口,使用copy命令copy OIP-C.jpg/b + phpinfo.php/a picma.jpg
制作.jpg后缀的图片马:
选择刚刚制作好的picma.jpg文件,上传成功。然后右键点击图片,选择“在新标签页中打开图片”,复制图片路径/upload/5220230802121409.jpg
备用。
回到主界面,点击超链接文件包含漏洞,跳转到/include.php
页面。
在include.php
后面添加?file=./
拼接图片路径upload/5220230802121409.jpg
,访问成功。
以下采用另一种姿势、上传.gif后缀的图片马。
将phpinfo.php重命名为phpinfo.gif,点击上传,抓包,在文件内容前添加GIF89A,点击Forward,上传成功。
接下来的步骤和利用.jpg后缀的图片马一样,可成功访问。
查看源代码:
Pass-14 图片马 getimagesize()
使用Pass-13的.jpg .gif
后缀的两种马均可通关。
查看源代码:
Pass-15 图片马 exif_imagetype()
使用Pass-13的.gif
图片马可通关。
查看源代码:
注:本关需开启php_exif功能。
Pass-16 二次渲染
{“待更新”}
查看源代码:
$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的图片文件!"; } }
Pass-17
{“待更新”}
查看源代码:
Pass-18
{“待更新”}
查看源代码:
//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" ); } ...... ...... ...... };
Pass-19
{“待更新”}
查看源代码:
$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 . '文件夹不存在,请手工创建!'; } }
Pass-20
{“待更新”}
查看源代码:
$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 = "请选择要上传的文件!"; }
Pass-21
{“待更新”}
查看源代码:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 全面指南,95% 的人都不知道的9个技巧(建议收藏)
· 自定义Ollama安装路径
· 本地部署DeepSeek
· 快速入门 DeepSeek-R1 大模型
· DeepSeekV3+Roo Code,智能编码好助手