zoukankan      html  css  js  c++  java
  • DVWA-5.4 File Upload(文件上传)-Impossible

    Impossible Level

    查看源码

    <?php
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Check Anti-CSRF token----校验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;//重写文件名(在文件名前面加id再整体md5)
        $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?
       // 校验文件类型及大小
       // 文件名后缀必须为jpg、jpeg、png之一,
       // 并且文件大小必须小于100000B约为97.7KB,
       // 并且文件类型必须为image/jpeg或image/png
       // 并且可以使用getimagesize()返回图像的大小和类型(注意,这个函数本身是不安全的)
    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! $html .= "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>"; } else { // No $html .= '<pre>Your image was not uploaded.</pre>'; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } // Generate Anti-CSRF token generateSessionToken(); ?>

    相关函数介绍

    substr(string,start,length)

    函数返回字符串的一部分

    strrpos(string,find,start)

    函数查找字符串在另一字符串中最后一次出现的位置(区分大小写)

    uniqid()

    函数基于以微秒计的当前时间,生成一个唯一的 ID

    in_get(varname)

    函数返回相应选项的值

    imagecreatefromjpeg ( filename )

    函数返回图片文件的图像标识,失败返回false

    imagejpeg ( image , filename , quality)

    从image图像以filename为文件名创建一个JPEG图像,可选参数quality,范围从 0(最差质量,文件更小)到 100(最佳质量,文件最大)。

    imagedestroy( img )

    函数销毁图像资源

    getimagesize()

    函数用来获取图像的大小和类型

    可以看到,Impossible级别的代码对上传文件进行了重命名(为md5值,导致%00截断无法绕过过滤规则),加入Anti-CSRF token防护CSRF攻击,同时对文件的内容作了严格的检查,导致攻击者无法上传含有恶意脚本的文件。

    扩展

    源码中使用了一个非常不安全的的函数:getimagesize()

    getimagesize()函数会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求的。

    getimagesize()返回结果中有文件大小和文件类型,如果用这个函数来获取类型,从而判断是否是图片的话,会存在问题。因为图片头可以被伪造,我们完全可以通过伪造正确的图片头来绕过它对图片类型的检查。

    这就是图片的十六进制,前几位都是一样的

    按照这样的逻辑,我们就可以去伪造一个假图片,让函数以为我们这就是图片,达到绕过的目的。

    • 方法1 直接伪造头部GIF89A
    • 方法2 CMD:copy /b test.png+munma.php hack.png
    • 方法3 使用GIMP(开源的图片修改软件),通过增加备注,写入执行命令。

    但是,即使我们可以根据上述方法绕过函数getimagesize(),我们也绕不过imagecreatefromjpeg ( filename )、imagejpeg ( image , filename , quality)、imagedestroy( img )等几个函数对我们上传图片的重塑。所以,Impossible等级的代码是比较安全的。

    参考:

    https://www.freebuf.com/articles/web/119467.html

    https://blog.csdn.net/weixin_43915842/article/details/90183305

  • 相关阅读:
    需求规格说明书
    需求规格说明书模板0.2版本
    需求规格说明书模板0.1版本
    万事开头难,团队一起盘!!
    工程开始了!(2019-03-04)
    SpringBoot RESTful API返回统一数据格式还不懂?
    Springboot读取配置文件中的属性
    java本地缓存的使用
    解决github访问不了和慢的问题2021-06-27
    Oracle DDL
  • 原文地址:https://www.cnblogs.com/zhengna/p/12764718.html
Copyright © 2011-2022 走看看