DVWA-File Upload

0x01 文件上传

File Upload,即文件上传漏洞,通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得可以通过上传webshell获取服务器权限,因此文件上传漏洞带来的危害常常是毁灭性的。

0x02 Low级别

代码如下:
<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // 这段代码是有关文件上传之后的位置的。basename函数返回路径中的文件名部分。如果可选参数suffix为空,则返回的文件名包含后缀名,反之不包含后缀名。
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // 判断是否可以上传。move_uploaded_file函数将上传的文件移动到新位置。
    if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
        // 上传失败
        echo '<pre>Your image was not uploaded.</pre>';
    }
    else {
        // 上传成功,并返回文件路径
        echo "<pre>{$target_path} succesfully uploaded!</pre>";
    }
}

?> 

直接上传一句话木马即可。

上传之后,浏览器访问,看是否上传成功。

上传成功。因为我在一句话木马前面加了GIF89a的。

蚁剑连接一句话:

0x03 Medium级别

代码如下:

<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // 同Low级别
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // 这里是上传的文件的相关信息
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];

    // 判断上传的文件是否是jpeg和png图片且大小小于100000字节
    if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
        ( $uploaded_size < 100000 ) ) {

        // 判断文件是否能够上传
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // 上传失败
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // 上传成功
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // 上传的文件不是图片,返回以下信息给用户
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?> 

medium级别相比于low级别,多了一次验证,验证上传的文件是否是图片。

这里可以使用burp来绕过,当然还有其他的方法。

先将shell.php改为shell.jpg,发送包时用burp进行拦截,并将后缀名重新修改为php。

即可上传成功。

0x04 High级别

代码如下:

<?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // 同以上两个级别
    $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
    $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

    // 文件信息。strrpos函数查找字符串在另一字符串中最后一次出现的位置(区分大小写);substr函数返回字符串的一部分。
    $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);//这句的意思是将文件的后缀名赋给$uploaded_ext
    $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
    $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];

    // 判断是否是图片。strtolower函数将所有字符转换为小写;getimagesize函数用于获取图像的大小及相关信息。
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) ) {

        // 判断能否上传
        if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
            // 不能
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            //
            echo "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // 上传文件不是图片的反馈信息
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?> 

high级别的文件上传可以结合low级别的文件包含进行实验。

上传一个图片马,再用文件包含进行读取即可。

0x05 Impossible级别

代码如下:

 <?php

if( isset( $_POST[ 'Upload' ] ) ) {
    // 检查token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );


    // 文件信息
    $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' ];

    // 将上传的文件进行改名以及确定上传的目录位置。uniqid函数基于以微秒计的当前时间,生成一个唯一的 ID;ini_get函数用于获取一个配置选项的值。sys_get_temp_dir函数用于返回用于临时文件的目录。
    $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;

    // 判断是否为图片
    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 ) ) {

        // 将上传的图片进行重新的编码
        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 );//销毁图像

        // 判断是否可以将文件从临时目录转移到web根目录。rename函数重命名文件或目录;getcwd函数用于获取当前的工作目录;
        if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
            //
            echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
        }
        else {
            // 不能
            echo '<pre>Your image was not uploaded.</pre>';
        }

        // 删除所有的临时文件。file_exists函数用于检查文件或目录是否存在。unlink函数用于删除文件。
        if( file_exists( $temp_file ) )
            unlink( $temp_file );
    }
    else {
        // 上传的文件不符合规则
        echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

// 生成token
generateSessionToken();

?>

0x06 总结

文件上传漏洞防御:
1.上传文件进行重命名(md5值,导致%00截断无法绕过过滤规则)。
2.加入Anti-CSRF token防护CSRF攻击
3.对文件的内容进行严格的检查,让攻击者无法上传含有恶意脚本的文件。
 
 
posted @ 2020-02-28 10:34  Paddling  阅读(483)  评论(0编辑  收藏  举报