upload-lab与文件上传漏洞(上)

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
<?php
$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
<?php
$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
<?php
$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



完成绕过

0%