前言:文件上传漏洞是很常见的漏洞,也非常有趣,接下来就在DVWA靶场中边学边练。
文件上传漏洞:
文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
具体的原理可以看大师傅的讲解
Smi1e_——文件上传漏洞 学习笔记
文件上传漏洞
low级别
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' ] );
# $_FILES["file"]["name"] - 被上传文件的名称
# $_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称
# basename() 函数返回路径中的文件名部分
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
# move_uploaded_file() 函数将上传的文件移动到新位置
// No
echo 'Your image was not uploaded.
';
}
else {
// Yes!
echo "{$target_path} succesfully uploaded!
";
}
}
?>
通过对源码的分析,我们发现没有任何防护和限制,那就构造一句话木马
进行上传
根据相应的路径进行菜刀连接即可
Medium级别
上传刚才一句话木马试一下,发现
只能上传JPG或者是PNG,那就来查看一下源码
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 'Your image was not uploaded.
';
}
else {
// Yes!
echo "{$target_path} succesfully uploaded!
";
}
}
else {
// Invalid file
echo 'Your image was not uploaded. We can only accept JPEG or PNG images.
';
}
}
?>
通过分析源码,发现只有这一段代码进行了限制
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) )
只能上传jpeg或png的图像,限制了大小,其他没有任何防护,那就可以用
一句话木马图片
一句话木马图片的制作
一、建立一个bat文件,用记事本打开输入cmd
二、将上传的图片和一句话php文件执行以下命令即可
copy 图片1.jpg/b+PHP文件2.php/a 自定义图片名3.jpg
发现一句话确实已经插入图片中
上传成功,用菜刀连接
结果连接不上去,这里我们上传的是一张图片,那对方服务器就认为我们上传的是一张很正常的图,因此只会当做图片来解析,所以图片里的php代码不会被解析了,这里需要了解文件包含漏洞才能将图片进行解析。因为文件包含漏洞也是很好玩的知识,这里就不详细写了,之后单独总结出一篇博客来学习文件包含漏洞
我这里上传的是3.jpg
在url地址栏中输入
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=file://D:\PHPstudy\PHPTutorial\WWW\DVWA\hackable\uploads\3.jpg
发现图片已经被解析了,那么PHP代码也肯定被服务器解析了,用菜刀进行连接
结果还是连不上去,发现有三行警告
警告:无法修改头信息
做到这里实在连不上去,不知道是什么原因,这种方法就暂时先留到这,等找到解决方法了再继续做
除下这种方法还可以用抓包修改文件的type
通过观察这两段代码
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
只是限制了Content-Type,没有限制后缀名,所以这里可以直接抓包修改Content-Type即可
发包,上传成功
访问成功
这里为了方便就不连接菜刀了,将一句话木马改为
phpinfo(); ?>
High级别
查看源码
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 'Your image was not uploaded.
';
}
else {
// Yes!
echo "{$target_path} succesfully uploaded!
";
}
}
else {
// Invalid file
echo 'Your image was not uploaded. We can only accept JPEG or PNG images.
';
}
}
#$_FILES['myFile']['name'] 显示客户端文件的原名称。
#$_FILES['myFile']['type'] 文件的 MIME 类型,例如"image/gif"。
#$_FILES['myFile']['size'] 已上传文件的大小,单位为字节。
#$_FILES['myFile']['tmp_name'] 储存的临时文件名,一般是系统默认。
#$_FILES['myFile']['error'] 该文件上传相关的错误代码。以下为不同代码代表的意思:
#strtolower() 函数把字符串转换为小写
#getimagesize() 函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。
#strrpos() 函数查找字符串在另一字符串中最后一次出现的位置
?>
观察源码发现,代码中增加了一段代码
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
并且修改了这一段代码
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) )
先来解读一下第一段代码,strrpos()函数
查找.
出现在$uploaded_name
的位置然后加1,再利用substr()函数
从变量$uploaded_name
的指定位置截取部分字符串。所以这段代码的作用就是为了截取上传文件的后缀名
第二段代码,strtolower()函数
将无论是大写或小写的后缀名全改为小写,以防大小写绕过
,并且getimagesize() 函数
用于获取图像大小及相关信息,所以这里再用之前的php文件后缀名改为jpg或png就不可行了,不过也可以利用这个函数的漏洞进行绕过,既然对文件的开头内容进行了检测并且通过二进制识别是否为图像,那么就可以利用文件头欺骗,来让getimagesize()函数检测无效。
先了解一下常用图片的文件头标识
通过文件头标识判断图片格式
文件头欺骗
getimagesize() 函数
在这里作用就是检测是否为图像的作用,这里就用最简便的GIF的文件头,在一句话木马前加上GIF的文件头标识
上传
上传成功,说明成功绕过
用文件包含来进行访问
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=file:///D:\phpStudy1\PHPTutorial\WWW\DVWA\hackable\uploads\2.jpg
除此之外那,也可以上传图片马,然后用文件包含进行解析,由于我这里配置的有问题就不再演示了,不过这种方法确实是可行的,看过许多大师傅们都是这样做的
总结:虽然遇到了很多问题,不过也初步了解了文件上传漏洞的原理和一些姿势,接下来通过Upload-labs进行学习。