dvwa文件上传通关及代码分析

文章目录

low等级

查看源码:

<?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' ] );

    // Can we move the file to the upload folder?
    if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
        // No
        echo '<pre>Your image was not uploaded.</pre>';
    }
    else {
        // Yes!
        echo "<pre>{$target_path} succesfully uploaded!</pre>";
    }
}

?> 

对上传的文件没有任何过滤,上传一个具有一句话木马的php文件:

上传成功,并且返回成功的地址:

medium等级

做代码审计:

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

?>

发现它是接收了一个http头部,并用post方法传参,并在

if(($uploaded_type == "image/jpeg" || $uploaded_type == "image/png") && ($uploaded_size < 100000))

限制了接收文件的类型,即只接收jpeg、png格式的图片,并限制了上传文件的大小不能超过100k。

我们继续上传有一句话木马的php文件,然后用bp抓包,修改文件的类型字段为image/png:

点击放包后可以看到上传文件成功:

high等级

查看源码:

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

在代码中有

 $uploaded_ext  = substr( $uploaded_name, strrpos($uploaded_name, '.') + 1);

strrpos(string,find,start) 函数返回字符串 find 在另一字符串 string 中最后一次出现的位置,如果没有找到字符串则返回 false,可选参数 start 规定在何处开始搜索。

getimagesize( $uploaded_tmp)通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头则报错

这段代码在medium的基础上增加了读取文件头,判断文件幻数来更严格地判断文件的类型,提高了过滤的强度。

接下来我们准备一张图片和包含一句话木马的php文件:

用下面的命令将它们合并成一个新的图片:

copy dvwa_email.jpg/b + 1.php/a  2.jpg

然后直接上传,网页提示上传成功:

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();

?>

发现这段代码包含了high等级的过滤策略,会检查图片文件的头部,用幻数来更严格地判断文件的类型,不仅如此,它还在

if( $uploaded_type == 'image/jpeg' ) {
            $img = imagecreatefromjpeg( $uploaded_tmp );
            imagejpeg( $img, $temp_file, 100);
        }
        else {
            $img = imagecreatefrompng( $uploaded_tmp );
            imagepng( $img, $temp_file, 9);
        }

中用imagecreatefromjpeg( $uploaded_tmp )函数对上传的图片进行二次渲染,相当于直接生成一个外观相同的新图片文件,这样一来,如果图片中存在恶意代码,就会被过滤,这中方式更严密地防范了漏洞,导致攻击者无法上传木马文件。

相关推荐
Henry_He1 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗1 小时前
Android笔试面试题AI答之Android基础(1)
android
qq_397562312 小时前
android studio更改应用图片,和应用名字。
android·ide·android studio
峥嵘life2 小时前
Android Studio版本升级那些事
android·ide·android studio
新手上路狂踩坑2 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
TroubleMaker5 小时前
OkHttp源码学习之retryOnConnectionFailure属性
android·java·okhttp
叶羽西7 小时前
Android Studio IDE环境配置
android·ide·android studio
发飙的蜗牛'7 小时前
23种设计模式
android·java·设计模式
花追雨16 小时前
Android -- 双屏异显之方法一
android·双屏异显
小趴菜822716 小时前
安卓 自定义矢量图片控件 - 支持属性修改矢量图路径颜色
android