0

0

全网最全upload-labs通关攻略(建议收藏)

絕刀狂花

絕刀狂花

发布时间:2025-09-27 08:13:27

|

1104人浏览过

|

来源于php中文网

原创

upload-labs是一个帮你总结所有上传漏洞类型的靶场,学习上传漏洞原理,复现上传漏洞必备靶场环境,玩起来吧!项目地址:https://github.com/c0ny1/upload-labs

环境要求

若要自己亲自搭建环境,请按照以下配置环境,方可正常运行每个Pass。

配置项

配置

描述

操作系统

Window or Linux

推荐使用Windows,除了Pass-19必须在linux下,其余Pass都可以在Windows上运行

PHP版本

推荐5.2.17

其他版本可能会导致部分Pass无法突破

PHP组件

php_gd2,php_exif

部分Pass依赖这两个组件

中间件

设置Apache

以moudel方式连接

第一关思路发现随意上传php木马,发现前端报错,响应速度超快,且数据包未达到服务器,猜测前端js验证
全网最全upload-labs通关攻略(建议收藏)
源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">function checkFile() {    var file = document.getElementsByName('upload_file')[0].value;    if (file == null || file == "") {        alert("请选择要上传的文件!");        return false;    }    //定义允许上传的文件类型    var allow_ext = ".jpg|.png|.gif";    //提取上传文件的类型    var ext_name = file.substring(file.lastIndexOf("."));    //判断上传文件类型是否允许上传    if (allow_ext.indexOf(ext_name + "|") == -1) {        var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;        alert(errMsg);        return false;    }}</code>
逻辑大致是识别上传文件的后缀名 并查看是否是jpg、png、gif中的一个,否则不允许上传bypass

1.修改前端不使用该checkfile函数

全网最全upload-labs通关攻略(建议收藏)
直接可上传php文件成功第二关思路发现上传php显示文件类型不正确
全网最全upload-labs通关攻略(建议收藏)
抓包查看文件类型字段,猜测会判断Content-Type字段源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$is_upload = false;$msg = null;if (isset($_POST['submit'])) {    if (file_exists(UPLOAD_PATH)) {        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {            $temp_file = $_FILES['upload_file']['tmp_name'];            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']                        if (move_uploaded_file($temp_file, $img_path)) {                $is_upload = true;            } else {                $msg = '上传出错!';            }        } else {            $msg = '文件类型不正确,请重新上传!';        }    } else {        $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';    }}</code>
逻辑大致是识别上传文件的类型 并查看是否是image/jpge、image/png、image/gif中的一个,否则不允许上传$_FILES全局变量

$_FILES'myFile'

标书对比王
标书对比王

标书对比王是一款标书查重工具,支持多份投标文件两两相互比对,重复内容高亮标记,可快速定位重复内容原文所在位置,并可导出比对报告。

下载

上传文件的原名称

$_FILES'myFile'

文件的 MIME 类型

$_FILES'myFile'

已上传文件的大小,单位为字节

$_FILES'myFile'

文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定

$_FILES'myFile'

和该文件上传相关的错误代码

bypass

直接抓包改Content-Type为image/png,上传成功

全网最全upload-labs通关攻略(建议收藏)
第三关思路发现直接上传php脚本显示提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!
全网最全upload-labs通关攻略(建议收藏)
猜测设置了后缀名黑名单源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$is_upload = false;$msg = null;if (isset($_POST['submit'])) {    if (file_exists(UPLOAD_PATH)) {        $deny_ext = array('.asp','.aspx','.php','.jsp');        $file_name = trim($_FILES['upload_file']['name']);        $file_name = deldot($file_name);//删除文件名末尾的点        $file_ext = strrchr($file_name, '.'); // 截取'.'后的后缀名        $file_ext = strtolower($file_ext); //转换为小写        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA        $file_ext = trim($file_ext); //收尾去空        if(!in_array($file_ext, $deny_ext)) {            $temp_file = $_FILES['upload_file']['tmp_name'];            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;// 随机命名            if (move_uploaded_file($temp_file,$img_path)) {                 $is_upload = true;            } else {                $msg = '上传出错!';            }        } else {            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';        }    } else {        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';    }}</code>
逻辑大致是识别上传文件的类型 并查看是否是'.asp','.aspx','.php','.jsp'中的一个,否则不允许上传bypass尝试使用和php一样解析效果的后缀名,如php3、php4、php5、phtml等后缀名
全网最全upload-labs通关攻略(建议收藏)
上传成功,并成功解析
全网最全upload-labs通关攻略(建议收藏)
第四关思路发现直接上传php脚本显示提示:此文件不允许上传!需抓包验证检验的参数源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$is_upload = false;$msg = null;if (isset($_POST['submit'])) {    if (file_exists(UPLOAD_PATH)) {        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini");        $file_name = trim($_FILES['upload_file']['name']);        $file_name = deldot($file_name);//删除文件名末尾的点        $file_ext = strrchr($file_name, '.');        $file_ext = strtolower($file_ext); //转换为小写        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA        $file_ext = trim($file_ext); //收尾去空        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 . '文件夹不存在,请手工创建!';    }}</code>
逻辑大致大致和上一关类似,只是增加了黑名单量,识别上传文件的类型 并查看是否是黑名单量中的一个,否则不允许上传,可见大小写都包括了,常见的一些后缀也包括了,通过查看资料发现.htaccess后缀文件并未在这个黑名单中,可以进行利用。bypass上传一个.htaccess文件内容如下,意思为所有文件都用php来解析代码语言:javascript代码运行次数:0运行复制
<code class="javascript">AddType application/x-httpd-php .png或者<FilesMatch "文件名">SetHandler application/x-httpd-php</FilesMatch></code>
上传一个图片马hacker.png直接访问该图片地址,均成功!第五关思路发现和上一关类似源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");        $file_name = trim($_FILES['upload_file']['name']);        $file_name = deldot($file_name);//删除文件名末尾的点        $file_ext = strrchr($file_name, '.');        $file_ext = strtolower($file_ext); //转换为小写        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA        $file_ext = trim($file_ext); //首尾去空                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 . '文件夹不存在,请手工创建!';    }}</code>
逻辑大致大致和上一关类似,只是增加了.htaccess黑名单量,识别上传文件的类型 并查看是否是黑名单量中的一个,否则不允许上传,细看大小写过滤并不全,可以混合大小写进行利用。bypass上传shell.PhP上传成功第六关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");        $file_name = trim($_FILES['upload_file']['name']);        $file_name = deldot($file_name);//删除文件名末尾的点        $file_ext = strrchr($file_name, '.');        $file_ext = strtolower($file_ext); //转换为小写        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA                if (!in_array($file_ext, $deny_ext)) {            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {                $img_path = $UPLOAD_ADDR . '/' . $file_name;                $is_upload = true;            }        } else {            $msg = '此文件不允许上传';        }    } else {        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';    }}</code>
PHP _FILES 是一个预定义的数组,用来获取通过 POST 方法上传文件的相关信息。如果为单个文件上传,那么 FILES 为二维数组;如果为多个文件上传,那么 代码语言:javascript代码运行次数:0运行复制
<code class="javascript">Array(    [userfile] => Array    (        [name] => Screen Shot 2016-05-12 at 18.13.24.png        [type] => image/png        [tmp_name] => /private/var/tmp/phplVHp3W        [error] => 0        [size] => 344925    ))</code>
是后缀名黑名单,少了这段代码file_ext = trim(file_ext); //首尾去空bypass

可以进行空格绕过,直接抓包修改文件名,再文件名末尾添加空格,成功上传

全网最全upload-labs通关攻略(建议收藏)
直接可上传php文件成功第七关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");        $file_name = trim($_FILES['upload_file']['name']);        $file_ext = strrchr($file_name, '.');        $file_ext = strtolower($file_ext); //转换为小写        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA        $file_ext = trim($file_ext); //首尾去空                if (!in_array($file_ext, $deny_ext)) {            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {                $img_path = $UPLOAD_ADDR . '/' . $file_name;                $is_upload = true;            }        } else {            $msg = '此文件不允许上传';        }    } else {        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';    }}</code>
没有对后缀名进行去”.”处理,strrchr(file_name, '.')只是截取.后面的后缀名。利用windows特性,会自动去掉后缀名中最后的”.”,可在后缀名中加”.”绕过。少了代码file_name = deldot(bypass

查看源码还是黑名单没有对后缀名进行去.操作利用Windows特性会自动去掉后缀名中最后的.可在后缀名中加 . 绕过

全网最全upload-labs通关攻略(建议收藏)
第八关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");        $file_name = trim($_FILES['upload_file']['name']);        $file_name = deldot($file_name);//删除文件名末尾的点        $file_ext = strrchr($file_name, '.');        $file_ext = strtolower($file_ext); //转换为小写        $file_ext = trim($file_ext); //首尾去空                if (!in_array($file_ext, $deny_ext)) {            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {                $img_path = $UPLOAD_ADDR . '/' . $file_name;                $is_upload = true;            }        } else {            $msg = '此文件不允许上传';        }    } else {        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';    }}</code>
逻辑大致是识别上传文件的类型 并查看是否是'.asp','.aspx','.php','.jsp'中的一个,否则不允许上传,少了代码file_ext = str_ireplace('::DATA', '', file_ext);//去除字符串::DATAbypassNTFS文件系统包括对备用数据流的支持,主要包括提供与Macintosh文件系统中的文件的兼容性。备用数据流允许文件包含多个数据流。每个文件至少有一个数据流。在Windows中,此默认数据流称为: DATA。上传.php::DATA绕过。(仅限windows)第九关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript"> $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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");        $file_name = trim($_FILES['upload_file']['name']);        $file_name = deldot($file_name);//删除文件名末尾的点        $file_ext = strrchr($file_name, '.');        $file_ext = strtolower($file_ext); //转换为小写        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA        $file_ext = trim($file_ext); //首尾去空                if (!in_array($file_ext, $deny_ext)) {            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {                $img_path = $UPLOAD_ADDR . '/' . $file_name;                $is_upload = true;            }        } else {            $msg = '此文件不允许上传';        }    } else {        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';    }}</code>
查看源码,这里只过滤了一次,所以直接构造 .php. . 绕过bypass

直接构造点加空格加点 .php. . 绕过

全网最全upload-labs通关攻略(建议收藏)

可通过https://localhost/upload-labs/upload/shell1.php访问mm

第十关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");        $file_name = trim($_FILES['upload_file']['name']);        $file_name = str_ireplace($deny_ext,"", $file_name);        if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name)) {            $img_path = $UPLOAD_ADDR . '/' .$file_name;            $is_upload = true;        }    } else {        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';    }}</code>
file_name = str_ireplace(deny_ext,"", bypass

1.双写绕过

全网最全upload-labs通关攻略(建议收藏)
第十一关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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类型文件!";    }}</code>
strrpos() 函数查找字符串在另一字符串中最后一次出现的位置是后缀名白名单,截取后缀名并随机命名拼接bypass

$_GET['save_path'] 有传入参数可控,可以使用%00截断

全网最全upload-labs通关攻略(建议收藏)
第十二关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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 = $_POST['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类型文件!";    }}</code>
与前一关类似,只是变成了POST提交bypass

%00截断进行拼接

全网最全upload-labs通关攻略(建议收藏)
第十三关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">function getReailFileType($filename){    $file = fopen($filename, "rb");    $bin = fread($file, 2); //只读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_ADDR."/".rand(10, 99).date("YmdHis").".".$file_type;        if(move_uploaded_file($temp_file,$img_path)){            $is_upload = true;        }        else{            $msg = "上传失败";        }    }}</code>
会读取文件头和文件类型,已提示传入图片mmbypass

制作图片mm上传

全网最全upload-labs通关攻略(建议收藏)

结合文件包含进行解析

第十四关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript"> 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)){            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_ADDR."/".rand(10, 99).date("YmdHis").$res;        if(move_uploaded_file($temp_file,$img_path)){            $is_upload = true;        }        else{            $msg = "上传失败";        }    }}</code>

这里用getimagesize获取文件类型

bypass

还是直接就可以利用图片马就可进行绕过

第十五关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">function isImage($filename){    //需要开启php_exif模块    $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_ADDR."/".rand(10, 99).date("YmdHis").".".$res;        if(move_uploaded_file($temp_file,$img_path)){            $is_upload = true;        }        else{            $msg = "上传失败";        }    }}</code>

这里用到php_exif模块来判断文件类型

bypass

还是直接就可以利用图片马就可进行绕过

第十六关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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的图片文件!";    }}</code>
本关综合判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染bypass
全网最全upload-labs通关攻略(建议收藏)
第十七关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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 = '上传失败!';    }}</code>
这里先将文件上传到服务器,然后通过rename修改名称,再通过unlink删除文件,因此可以通过条件竞争的方式在unlink之前,访问webshellbypass

首先在burp中不断发送上传webshell的数据包,然后不断在浏览器中访问,发现通过竞争可以访问到。

第十八关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">/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.phpclass 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" );    }.................. };</code>
需要上传一个图片mm本关对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等bypass

将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用burp发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename的问题,从而上传成功:

第十九关源码解读代码语言:javascript代码运行次数:0运行复制
<code class="javascript">$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 . '文件夹不存在,请手工创建!';    }}</code>
file_name = _POST['save_name'];中有变量可控发现move_uploaded_file()函数中的img_path是由post参数save_name控制的,因此可以在save_name利用00截断绕过:

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

182

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

225

2025.12.18

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

89

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

106

2025.09.18

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

738

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

219

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1561

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

649

2023.11.24

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

23

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.1万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号