upload-labs学习过程
*所有上传的文件在upload目录下
Pass-1
过滤方法 | 绕过方法 |
---|---|
前端JS过滤 | 禁用JS、抓包上传 |
源码分析
function checkFile() {
//判断上传文件类型是否允许上传
if (不是.jpg|.png|.gif后缀) {
return false;
}
}
- 这是在前端进行过滤,如果上传的文件不是
jpg/png/gif
文件,就返回错误
有两种方法绕过
1.禁用JS
禁用方法自行百度
原理:JS被禁用后,前端判断上传文件类型的代码失效
2.抓包上传
先将要上传的文件后缀改为允许上传的类型,再用burpsuite抓包,重新修改后缀即可
Pass-2
过滤方法 | 绕过方法 |
---|---|
MIME白名单过滤 | 抓包修改MIME类型 |
源码分析
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')):
上传文件
else:
报错
本pass在服务端对数据包的MIME进行检查,我们可以抓包修改Content-Type:
字段为image/png
来绕过
Pass-3
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | php3绕过黑名单 |
源码分析
//黑名单
$deny_ext = array('.asp','.aspx','.php','.jsp');
if(所上传的文件后缀不在黑名单):
上传文件
else:
报错
黑名单过滤了php文件,但是我们可以上传php3、phtml类型的文件,还是可以解析成php文件
我上传成功但是没办法打开php3文件,不知道为什么
Pass-4
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | 重写文件解析规则 |
这一关过滤的黑名单有点长,看图
虽然过滤了很多,但是没有过滤 .htaccess
,新建一个.htaccess
的文件,写入以下内容
SetHandler application/x-httpd-php
然后上传,这样该目录的文件都可以解析成php,可以上传.jpg
为后缀的php脚本来绕过检测,到时候会被解析成php
Pass-5
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | .user.ini |
源码分析
$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
,还将文件后缀名转换为小写
.user.ini
先上传一个以
auto_prepend_file=test.gif
为内容的.user.ini
文件,.user.ini
文件里面的意思是:所有的php文件都自动包含test.gif
文件。auto_prepend_file
作用是为了避免多数文件都需要引入一个相同的文件,而反复的 include然后再上传一个内容为
<?php phpinfo();?>
的一句话的脚本,命名为test.gif
因为原来的上传目录里面就已经有了一个
readme.php
的文件,所以我们不是上传了php文件,而是在已存在的PHP文件写入了一句话木马
Pass-6
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | 大小写绕过 |
分析源码
$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); //首尾去空
过滤方法基本和Pass-5相同,但是少了strtolower()
,所以可以利用后缀名大小写绕过
大小写绕过原理:
Windows系统下,对于文件名中的大小写不敏感。例如:test.php和TeSt.PHP是一样的。 Linux系统下,对于文件名中的大小写敏感。例如:test.php和 TesT.php就是不一样的。
我遇到的问题
我是用bp抓包修改大小写,但是访问的时候却500,查了很久也没找到原因,希望有大佬指点一下
Pass-7
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | 空格绕过 |
源码分析
$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
过滤了差不多,但是少了trim()
过滤,它的作用是移除字符串首尾的空格,所以这里可以使用空格绕过
空格绕过原理
在Windows下,对于文件名中空格会被作为空处理,但程序中的检测代码却不能自动删除空格。从而绕过黑名单。
我遇到的问题
bp抓包在文件名最后添加空格,但是却显示上传失败,也找不到原因
Pass-8
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | 点绕过 |
源码分析
$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); //首尾去空
过滤了差不多,但是少了deldot()
过滤,它的作用是移除字符串最后的点,所以这里可以使用点绕过
原理
假如上传的文件名是1.php.
,后端代码过滤时获取的文件后缀名时.
而不是.php.
,这样就会绕过检测
而Windows系统下,文件后缀名最后一个点会被自动去除,这样我们上传的文件到服务区上就变成了1.php
Pass-9
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | 点绕过 |
源码分析
$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); //首尾去空
过滤了差不多,但是忘记过滤::$DATA
,所以这里可以使用::$DATA
绕过,这属于特殊符号绕过
特殊符号绕过原理
在Windows系统下,上传文件名为test.php::$DATA
的文件会在服务器上变为test.php
,因为Windows下文件名中不能有特殊符号
Pass-10
过滤方法 | 绕过方法 |
---|---|
后缀名黑名单过滤 | 点绕过 |
源码分析
$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); //首尾去空
- 发现该过滤的都过滤了,但还是可以利用
deldot()
函数
deldot()
函数只能删掉字符串最后一个点,如果文件名最后有两个点呢?删一个点还剩一个点,然后就跟Pass-8一个样子了
上传1.php..
,deldot()
函数处理后变成1.php.
,后端代码获取文件后缀名时得到的就是.
,这样就绕过了检测