dvwa实战-文件上传

时间:2022-07-22
本文章向大家介绍dvwa实战-文件上传,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

dvwa实战-文件上传

漏洞介绍

文件上传漏洞可以说是危害很大了,因为可以直接通过此漏洞getshell。漏洞原因简单点说就是由于开发人员或者网站运维人员的一些失误导致用户上传的文件可以被服务器当作脚本(可执行文件)解析执行。但是想要成功利用这个漏洞至少需要满足三个条件: A.有效上传点 B.上传文件能够被解析执行 C.上传的文件能够被访问到

low

由于我是搭建在wamp环境下的,所以我试着上传一个php的一句话木马。

这里写图片描述

可以看到我们的一句话成功上传,我们尝试用菜刀连接一下

这里写图片描述

成功连接,看来后台没有做任何过滤。我们来看下源码:

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

?>

看了一下也确实没做什么过滤,文件路径就是DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"再加上文件名。

medium

还是先试试直接上传脚本:

这里写图片描述

根据提示,可以看到只允许上传jpeg或者png的图片。意思就是要我们来绕过这个限制,我们先来想一想开发人员到底是从哪儿限制了我们上传php文件:

1.前端:利用js判断 2.后端: a.判断文件名后缀 b.判断mime类型 c.判断文件内容 现在我们一点点摸索,首先看是否是前端js判断,由于我使用的是chrome浏览器,所以我设置一下禁用js,这样一来页面中的js就不在生效了,但是我上传文件任然不成功,这就说明不是js限制了我的操作。

注:chrome禁用js方法: 设置----->高级------->隐私设置和安全性----->内容设置------>禁用js

如果后台是使用文件名来判断的话,我们这次还真没什么好办法让服务器直接将我们的脚本解析,因为现在我的php版本是5.4,所以以前盛传的文件名%00阶段也不可用了(例如:文件名为1.php%00.jpg,可以绕过后台的文件后缀检查,但是在服务器解析是会解析成1.php,原因是%00截断了后面的字符,但是这个方法我利用其它5.3.29版本的php没有复现出来,可能需要更低版本的php吧,大家可以试一下,欢迎与我交流)。下面就试试绕过看看是不是后台对mime类型进行了判断吧,这个时候需要用到抓包神奇burpsuite,抓包结果:

这里写图片描述

我们手动改一下这个mime类型:

这里写图片描述

成功绕过:

这里写图片描述

菜刀连接:

这里写图片描述

现在我们来看下源码吧:

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

?>

这里写图片描述

红色方框圈起来的地方就是关键,首先获取了文件的类型,保存再$uploaded_type里面,然后再判断这个变量是否符合条件,这个变量实际上就是存储的mime类型

high

同样的,第三题,我们也一点点来试探吧。先直接上传脚本

这里写图片描述

不出所料,不能上传。来吧试试用medium的方法,抓包改mime类型,还是爆出了同样的错误,说明这次不是判断的mime类型了,或者是不止判断了mime类型,我猜想可能是对文件的内容进行了判断。可能必须要内容也是图片才行,一般后台判断一个文件是不是图片都是判断一个文件的前几位数据,好像这个东西叫bom头,具体一点的请读者自行百度一下,我这里说一下利用方法,windows自带了一个合并文件的工具。我们命令行打开,键入如下命令: copy 文件1.jpg/b+文件2.php/a 新文件.jpg

这里写图片描述

这样就会根据两个指定的文件生成一个新文件。我们再看一下生成的文件的内容:

这里写图片描述

可以看到一句话被添加到了我们的文件末尾,现在,我把刚刚生成的图片后缀名改为php,这样就可以绕过后端对文件头的检查,现在我们试试上传

这里写图片描述

还是被拦截了,看来真的不止对文件内容进行了判断。看来带有后缀名的验证,现在还要把后缀名改为jpg或者png,这样一改确实是可以上传了,但是我们访问的时候不能被解析为php了啊,再加上之前说的%00截断不能用,我确实没想到什么好的利用方法。其他人的方法都是配合着文件包含来执行getshell。我也跟着试了一下:

这里写图片描述

怎么说php还是执行了,但是我菜刀连接却不能成功,很奇怪,希望知道的小伙伴分享一下 接下来看看源码,后端到底做了什么:

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

?>

果然是对文件名后缀以及文件内容进行了判断,但是哪个函数进行了文件内容判断呢?好像怎么看都没有啊,实际上getimagesize()这个函数就判断啦。