前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DVWA靶机之文件上传漏洞通关笔记

DVWA靶机之文件上传漏洞通关笔记

作者头像
Power7089
发布2019-07-25 15:53:18
1.5K0
发布2019-07-25 15:53:18
举报

简介

文件上传漏洞通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传漏洞带来的危害常常是毁灭性的。

环境搭建

关于docker的安装:

https://www.docker.com/

通过Docker一键搭建 docker run --rm -it -p 80:80 vulnerables/web-dvwa 搭建完成后,访问http://localhost即可进入

测试工具

  • Burp Suite Community Edition
  • Firefox Browser

文件上传操作流程(本段内容来自参考资料2)

前端提交

在前端上传文件的form表单中,<form>标签的属性值enctype属性会规定发送到服务器之前对表单的数据进行何种编码 它的常见值如下:

代码语言:javascript
复制
application/x-www-form-urlencoded: 在发送前编码所有字符(默认)

multipart/form-data: 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。

text/plain: 空格转换为 "+" 加号,但不对特殊字符编码。
后端处理

PHP会用$_FILES数组接收参数 $_FILES的内容为:

代码语言:javascript
复制
[name] => feng.jpeg     文件的名称
[type] => image/jpeg     文件的MIME类型
[tmp_name] => C:\Users\Administrator\AppData\Local\Temp\php2007.tmp  文件的临时位置
[error] => 0       文件的错误信息  0 ok      1234 error
[size] => 2859    文件的大小,单位:byte 1M=1024KB 1KB=128Byte

文件上传漏洞的利用条件

  1. 能够成功上传木马文件
  2. 上传文件必须能够被执行
  3. 上传文件的路径必须可知

Security Level: low

源代码:
代码语言:javascript
复制
<?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
        $html .= '<pre>Your image was not uploaded.</pre>';
    }
    else {
        // Yes!
        $html .= "<pre>{$target_path} succesfully uploaded!</pre>";
    }
}

?>
源代码分析:

代码流程

文件上传文件后,文件直接保存,保存路径为hackable/uploads/,文件上传成功后,返回succesfully。 函数basename():返回路径中的文件名部分 函数

move_uploaded_file ( string $filename , string $destination ):将文件移动到指定地址

防御措施:无

测试方法:

本关没有任何保护措施,上传成功后会返回文件路径地址,可直接上传恶意脚本文件进行攻击


Security Level: Medium

源代码:
代码语言:javascript
复制
<?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
            $html .= '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            $html .= "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?>
源代码分析:

代码流程

当有提交上传文件时,后端先用变量从$_POST['uploaded']取出文件路径、文件名、文件类型、文件大小;然后对文件MIME类型进行判断,如果文件类型为image/jpeg或者image/png并且文件大小小于100000byte,则将临时文件移动到指定目录,上传成功,则回显文件路径

防御措施

  • MIME类型白名单过滤检测
  • 上传文件大小限制
测试方法:

上传我们准备好的恶意脚本文件,通过Burp Suite抓包拦截

Content-Type的值修改为image/png,即可绕过检测,成功上传,访问该文件即可执行恶意脚本


Security Level: High

源代码:
代码语言:javascript
复制
<?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
            $html .= '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            $html .= "<pre>{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        // Invalid file
        $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
    }
}

?>
源代码分析:

代码流程

当有提交上传文件时,后端先用变量从$_POST['uploaded']取出文件路径、文件名、文件扩展名、文件大小,临时文件名称;然后进行判断,如果文件扩展名为jpgpngjpeg,且文件大小小于100000byte,并且能获取到图像信息,则将临时文件移动到指定目录,上传成功,则回显文件路径 函数strtolower():将所有字母转换为小写 函数getimagesize():获取图像信息

防御措施

  • 大小写统一
  • 基于白名单的扩展名过滤
  • 上传的文件大小限制
  • 图像信息检测
文件头知识补充(本段内容来自参考资料2)

常见的图片格式的文件头标识如下:

代码语言:javascript
复制
JPEG/JPG - 文件头标识 (2 bytes): FF D8 (SOI) (JPEG 文件标识) - 文件结束标识 (2 bytes): FF D9 (EOI) 

PNG - 文件头标识 (8 bytes)   89 50 4E 47 0D 0A 1A 0A

GIF - 文件头标识 (6 bytes)   47 49 46 38 39(37) 61 |GIF89(7)a

文件头欺骗:伪造文件头,使文件头标识一样,其它部分我们修改为一句话木马,也就成了我们常说的图片一句话。

测试方法:

思路

绕过扩展名检测和getimagesize()图像信息检测,通过制作图片马可以绕过图像信息检测,通过00截断可以绕过扩展名检测(适用于 php 小于 5.3.4 版本),通常图片马需要配合文件包含才能发挥作用

制作图片马

(windows的copy命令) 准备好恶意脚本文件(x.php)和图片文件(y.png),在cmd下执行如下命令

代码语言:javascript
复制
copy y.png/b+x.php/a z.png

即可生成图片马

%00截断上传

由于我搭建的环境是PHP7.2,%00截断在此不适用

文件上传+文件包含组合利用: 通过我们刚刚上传的图片一句话木马,借助High Security Level的文件包含漏洞来进行组合利用:

代码语言:javascript
复制
http://your-dvwa-ip/vulnerabilities/fi/?page=file:///var/www/dvwa/hackable/uploads/c.jpg

访问如上地址即可成功执行我们的恶意脚本(这里用phpinfo()代替)


Security Level: impossible

源代码:
代码语言:javascript
复制
<?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!
            $html .= "<pre><a href='${target_path}${target_file}'>${target_file}</ 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();

?>
源代码分析:

代码流程

当有提交上传文件时,后端先用变量从$_POST['uploaded']取出文件路径、文件名、文件扩展名、文件大小,临时文件名称;通过uniqid()生成唯一的ID拼接文件名进行md5加密再拼接上扩展名形成新的文件名,对临时文件也进行此操作,如果扩展名为jpg,jpeg,png且文件大小小于100000byte,且MIME类型为image/png或者image/jpeg并且能取得图像信息,则重新生成图像进行上传

代码语言:javascript
复制
函数uniqid():基于以微秒计的当前时间,生成一个唯一的 ID。
函数ini_get():函数返回相应选项的值
函数sys_get_temp_dir(): 返回用于临时文件的目录
函数imagecreatefromjpeg(filename):函数返回图片文件的图像标识,失败返回false
函数imagejpeg(image,filename,quality):从image图像以filename为文件名创建一个JPEG图像,可选参数quality,范围从 0(最差质量,文件更小)到 100(最佳质量,文件最大)。
函数imagedestroy():函数销毁图像资源
函数rename():重命名文件或目录
函数getcwd():获取当前工作目录

防御措施

  • 重命名文件名并进行md5加密,%00截断失效
  • 基于白名单的扩展名,MIME类型检测
  • 服务器文件内容检测
  • 文件大小限制
  • 加入Anti-CSRF token 防护 CSRF攻击
测试方法:

无解

代码语言:javascript
复制
##  参考资料:
1. DVWA_File Upload 文件上传:https://www.cnblogs.com/huangming-zzz/p/9900435.html
2. DVWA File Upload 通关教程:http://www.storysec.com/dvwa-file-upload.html
3. 《DVWA漏洞测试平台分析》
4. 通过文件头标识判断图片格式:http://www.cnblogs.com/Wendy_Yu/archive/2011/12/27/2303118.html
5. windows中copy命令详解:https://www.cnblogs.com/andr01la/p/5146422.html
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小白帽学习之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
    • 环境搭建
      • 测试工具
        • 文件上传操作流程(本段内容来自参考资料2)
          • 文件上传漏洞的利用条件
            • Security Level: low
              • Security Level: Medium
                • Security Level: High
                  • Security Level: impossible
                  相关产品与服务
                  容器镜像服务
                  容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档