DVWA--全等级文件上传(File Uplode)
File Uplode:文件上传漏洞可以说是危害很大了,因为可以直接通过此漏洞getshell。漏洞原因简单点说就是由于开发人员或者网站运维人员的一些失误导致用户上传的文件可以被服务器当作脚本(可执行文件)解析执行。Apache、Tomcat、Nginx等都曝出过文件上传漏洞。
但是想要成功利用这个漏洞至少需要满足三个条件:
A.有效上传点
B.上传文件能够被解析执行
C.上传的文件能够被访问到
Low
源代码:
1 <?php 2 3 if( isset( $_POST[ 'Upload' ] ) ) { 4 // Where are we going to be writing to? 5 $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; 6 $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); 7 8 // Can we move the file to the upload folder? 9 if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { 10 // No 11 $html .= '<pre>Your image was not uploaded.</pre>'; 12 } 13 else { 14 // Yes! 15 $html .= "<pre>{$target_path} succesfully uploaded!</pre>"; 16 } 17 } 18 19 ?>
通过上面的源码我们可以发现,服务器对上传文件的类型、内容没有做任何的检查、过滤,存在明显的文件上传漏洞,生成上传路径后,服务器会检查是否上传成功并返回相应提示信息,那么我们来进行文件上传就如鱼得水了。此外,我在这里再介绍一下basename(path,suffix)
函数返回路径中的文件名部分,如果可选参数suffix为空,则返回的文件名包含后缀名,反之不包含后缀名。
接下来我们就来上传可执行,已知路径的木马文件,进行文件的上传,来一番操作 。
开始我们新建一个含有木马的文档muma.txt:
之后就是上传文件:
上传文件成功后我们就可以利用我们伟大的中国菜刀来获取webshell权限了,打开软件,在地址处填写刚刚上传文件的路径,口令是你文档中写入的。然后菜刀就会通过向服务器发送包含gxy参数的post请求,在服务器上执行任意命令,获取webshell权限。然后我们就可以随意处理文件了。http://192.168.24.140/hackable/uploads/muma.php
Medium
源码:
1 <?php 2 3 if( isset( $_POST[ 'Upload' ] ) ) { 4 // Where are we going to be writing to? 5 $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; 6 $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); 7 8 // File information 9 $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; 10 $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ]; 11 $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; 12 13 // Is it an image? 14 if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) && 15 ( $uploaded_size < 100000 ) ) { 16 17 // Can we move the file to the upload folder? 18 if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { 19 // No 20 $html .= '<pre>Your image was not uploaded.</pre>'; 21 } 22 else { 23 // Yes! 24 $html .= "<pre>{$target_path} succesfully uploaded!</pre>"; 25 } 26 } 27 else { 28 // Invalid file 29 $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; 30 } 31 } 32 33 ?>
Medium级别的代码对上传文件的类型、大小做了限制,要求文件类型必须是jpeg或者png,大小不能超过100000B(约为97.6KB)
这个就有些不愉快了!
这里总结了三种方法:
方法一:文件包含+文件上传
还是先写一句木马 ,将文档类型变为png,即muma.png
之后上传,显示成功
打开中国菜刀,进行地址的、口令的添加,可是却出了问题,因为中国菜刀的原理是向上传文件发送包含参数的post请求,通过控制参数来执行不同的命令,而这里服务器将木马文件解析成了图片文件,因此向其发送post请求时,服务器只会返回这个“图片”文件,并不会执行相应命令。这里我们就要想到上一节的文件包含了这里可以借助Medium级别的文件包含漏洞来获取webshell权限,打开中国菜刀,右键添加,在地址栏中输入 http://192.168.24.140/vulnerabilities/fi/?page=hthttp://tp://192.168.24.140/hackable/uploads/muma.png ,口令选择我们填入木马文件的指令,脚本语言选择php,可以成功了!
方法二:进行抓包并修改文件类型:
我们上传muma.png文件,然后用抓包软件进行抓包:
可以看到文件类型为image/png,尝试修改filename为muma.php,修改完毕后,点击Forward:
接下来看到上传成功,然后还是打开中国菜刀,获取权限:
方法三:截断(只限定老版本)方法四就是直接抓包改动截断的,更有参考价值:
在php版本小于5.3.4的服务器中,当Magic_quote_gpc选项为off时,我们可以在文件名使用%00截断,把上传文件命名:muma.php%00.png,其实就相当于php文件,但是却可以蒙混过去。之后还是用中国菜刀。
方法四:将木马文件格式改为muma.php.jpeg,进行上传。抓包截断
将2e改为00:
我们看见文件已经进来了:接下来就是中国菜刀出手了。
High
查看代码
1 <?php 2 3 if( isset( $_POST[ 'Upload' ] ) ) { 4 // Where are we going to be writing to? 5 $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; 6 $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); 7 8 // File information 9 $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; 10 $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); 11 $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; 12 $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; 13 14 // Is it an image? 15 if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) && 16 ( $uploaded_size < 100000 ) && 17 getimagesize( $uploaded_tmp ) ) { 18 19 // Can we move the file to the upload folder? 20 if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) { 21 // No 22 $html .= '<pre>Your image was not uploaded.</pre>'; 23 } 24 else { 25 // Yes! 26 $html .= "<pre>{$target_path} succesfully uploaded!</pre>"; 27 } 28 } 29 else { 30 // Invalid file 31 $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; 32 } 33 } 34 35 ?>
strrpos(string,find,start)
函数返回字符串find在另一字符串string中最后一次出现的位置,如果没有找到字符串则返回false,可选参数start规定在何处开始搜索。
substr(string,start,length)
返回string字符中从start开始的字符串,length参数可选,表示返回字符的长度
getimagesize(string filename)
函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错。
可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是”*.jpg”、”*.jpeg” 、”*.png”之一。同时,getimagesize()函数更是限制了上传文件的文件头必须为图像类型。
@1、我们需要将上传文件的文件头伪装成图片,首先在命令行的模式下利用copy命令将一句话木马文件1.php与正常的图片文件1.jpg合到一起 输入 copy 1.jpg/b+1.php/a 3.jpg
@2、也可以在文件头部加上了jpg格式的 GIF89(本人没有试验) 。
再用文件包含进行地址的输入:http://127.0.0.1/vulnerabilities/fi/?page=file:///D:/PhpStudy/WWW/hackable/uploads/1.jpg
我们打开含有木马的图片,会发现一句话木马被写在了最后
然后我们试着将生成的木马图片文件3.jpg上传,上传成功。
接下来就可以连接菜刀。
Impossible
查看代码
1 <?php 2 3 if( isset( $_POST[ 'Upload' ] ) ) { 4 // Check Anti-CSRF token 5 checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 6 7 8 // File information 9 $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; 10 $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); 11 $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; 12 $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ]; 13 $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; 14 15 // Where are we going to be writing to? 16 $target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/'; 17 //$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-'; 18 $target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; 19 $temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) ); 20 $temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; 21 22 // Is it an image? 23 if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) && 24 ( $uploaded_size < 100000 ) && 25 ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) && 26 getimagesize( $uploaded_tmp ) ) { 27 28 // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD) 29 if( $uploaded_type == 'image/jpeg' ) { 30 $img = imagecreatefromjpeg( $uploaded_tmp ); 31 imagejpeg( $img, $temp_file, 100); 32 } 33 else { 34 $img = imagecreatefrompng( $uploaded_tmp ); 35 imagepng( $img, $temp_file, 9); 36 } 37 imagedestroy( $img ); 38 39 // Can we move the file to the web root from the temp folder? 40 if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) { 41 // Yes! 42 $html .= "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>"; 43 } 44 else { 45 // No 46 $html .= '<pre>Your image was not uploaded.</pre>'; 47 } 48 49 // Delete any temp files 50 if( file_exists( $temp_file ) ) 51 unlink( $temp_file ); 52 } 53 else { 54 // Invalid file 55 $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; 56 } 57 } 58 59 // Generate Anti-CSRF token 60 generateSessionToken(); 61 62 ?>
in_get(varname)
函数返回相应选项的值
imagecreatefromjpeg ( filename )
函数返回图片文件的图像标识,失败返回false
imagejpeg ( image , filename , quality)
从image图像以filename为文件名创建一个JPEG图像,可选参数quality,范围从0(最差质量,文件更小)到100(最佳质量,文件最大)。
imagedestroy( img )
函数销毁图像资源
可以看到,Impossible级别的代码对上传文件进行了重命名(为md5值,导致%00截断无法绕过过滤规则),加入Anti-CSRF token防护CSRF攻击,同时对文件的内容作了严格的检查,导致攻击者无法上传含有恶意脚本的文件。