upload-lab针对在CTF中常见的20种文件上传漏洞进行总结
现在将一一讲解一下20种绕过方法
先放上黑盒测试情况下的思路图:
0x01 (1)本地js绕过
第一题使用JavaScript脚本进行过滤,我们可以通过浏览器中禁用JavaScript脚本施行绕过
或者通过burp抓包,上传一句话木马图,抓包,然后修改filename实现绕过。
0x02 各种后缀的绕过
(2)MIME类型检查
观察源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$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.'文件夹不存在,请手工创建!';
}
}
这里是对content type进行检查,然后有两种方法实现绕过
(1)上传木马图,修改其filename的后缀为php。
(2)上传一句话木马,然后修改其content type 为 image/jpeg 。
(3)php类型绕过
可以尝试将filename的后缀名.php修改为.php5,.php3,.phtml
同样地使用burp抓包进行绕过。
不过这里要修改apache的httpd.conf文件1
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
不然会出现apache无法解析其他版本的php文件
(4)上传.htaccess文件绕过
根据提示:
然后发现.htaccess文件未被过滤,所以编写.htaccess文件,这里的yjh.jpg是我们的木马图1
2
3<FilesMatch "yjh.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
然后上传.htaccess文件,以及yjh.jpg
输入url:127.0.0.1/upload-lab/upload/yjh.jpg。
然后在我们打开这个文件时,将以php的形式打开,然后连接菜刀,获得shell
(5)对大小写的绕过
观察源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$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 = 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 . '文件夹不存在,请手工创建!';
}
}
发现这里对于大小写没有过滤,所以burp抓包修改其filename的后缀名.php为.PhP。如此,完成绕过。
(6)空格绕过
这一关的源码和第五关的源码差了1
$file_ext = trim($file_ext); //首尾去空
所以我们在后缀名后加上空格,实现绕过。
绕过完成
(7)点号绕过
观察源码,发现这一关与第六关相比,少了如下代码:1
$file_name = deldot($file_name);//删除文件名末尾的点
所以使用点号绕过,后缀名.php修改问.php.
(8)::$DATA绕过
1 | $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA |
所以一样的套路,后缀名由.php修改为.php::$DATA
(9)点号绕过2
关键代码:1
2
3
4
5
6
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");
$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); //首尾去空
由于这段代码中的1
$file_name = deldot($file_name);//删除文件名末尾的点
并不是递归删点,所以这里点号仅被删除了一次,然后我们可以通过双写点号实现绕过,修改”.php”为”.php. .”
(10)双写后缀名绕过
关键代码:
$file_name = str_ireplace($deny_ext,"", $file_name);
这说明这里的后缀名在过滤时也仅过滤了一次而已,所以我们修改”.php”为”.pphphp”实现绕过
(11)%00截断
%00截断-get型
观察源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$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类型文件!";
}
}
可以发现,这里已经使用白名单过滤
我们尝试抓包
可见save_path可控,于是构造save_path=../upload/shell.php%00
修改filename=”shell.jpg”
实现绕过
%00截断-post型
由于post无法对%00自动解码,所以我们使用burp的decorder模块修改hex20为00
完成绕过