风炫安全web安全学习第三十六节课-15种上传漏洞讲解(一)

风炫安全web安全学习第三十六节课 15种上传漏洞讲解(一)

文件上传漏洞

0x01 漏洞描述和原理

文件上传漏洞可以说是日常渗透测试用得最多的一个漏洞,因为用它获得服务器权限最快最直接。但是想真正把这个漏洞利用好却不那么容易,其中有很多技巧,也有很多需要掌握的知识。俗话说,知己知彼方能百战不殆,因此想要研究怎么防护漏洞,就要了解怎么去利用。

网站web应用都有一些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型,此时攻击者就可以上传一个webshell到一个web可访问的目录上,并将恶意文件传递给PHP解释器去执行,之后就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理,服务器命令执行等恶意操作。
根据网站使用及可解析的程序脚本不同,此处可以上传的恶意脚本可以是PHP、ASP、JSP文件,也可以是篡改后缀后的这几类脚本。

WebShell 就是以 asp、php、jsp 或者 cgi 等网页文件形式存在的一种命令执行环境,也可以将其称之为 一种网页后门。攻击者在入侵了一个网站后,通常会将这些 asp 或 php 后门文件与网站服务器 web 目录 下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。

上传漏洞分类

0x02 基础知识

php的超级全局变量 $_FILE

$_FILES['file']['name'] 客户端文件名称

$_FILES['file']['type'] 文件的MIME类型

$_FILES['file']['size'] 文件大小 单位字节

$_FILES['file']['tmp_name'] 文件被上传后再服务器端临时文件名,可以在php.ini中指定

要注意的是在文件上传结束后,默认的被储存在临时文件夹中,这时必须把他从临时目录中删除或移动到其他地方,否则,脚本运行完毕后,自动删除临时文件,可以使用copy或者move_uploaded_file两个函数

文件头content-type字段校验(服务端MIME类型检测)

MIME类型格式: 类别/子类别;参数 Content-Type: [type]/[subtype]; parameter

MIME主类别: text:用于标准化地表示的文本信息,文本消息可以是多种字符集和或者多种格式的;

Multipart:用于连接消息体的多个部分构成一个消息,这些部分可以是不同类型的数据;

Application:用于传输应用程序数据或者二进制数据;

Message:用于包装一个E-mail消息;

Image:用于传输静态图片数据;

扫描二维码关注公众号,回复: 12728665 查看本文章

Audio:用于传输音频或者音声数据;

Video:用于传输动态影像数据,可以是与音频编辑在一起的视频数据格式。

0x02 校验方式分类&总结

1、客户端javascript校验(一般只校验后缀名)

2、服务端校验

3、文件头content-type字段校验(image/gif)

4、后缀名黑名单校验

5、文件内容头校验(GIF89a)

6、后缀名白名单校验

7、自定义正则校验

8、WAF设备校验(根据不同的WAF产品而定)

0x03 漏洞利用

此次我们用的靶场是:upload-labs: https://github.com/c0ny1/upload-labs

01利用HTTP PUT方式上传文件

这个漏洞已经过时,几乎不会再出此类漏洞

WebDAV是一种基于 HTTP 1.1协议的通信协议.它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法。使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。当WebDAV开启PUT,MOVE,COPY,DELETE方法时,攻击者就可以向服务器上传危险脚本文件。

此时可以使用OPTIONS探测服务器支持的http方法,如果支持PUT,就进行上传脚本文件,在通过MOVE或COPY方法改名。当开启DELETE时还可以删除文件

02绕过前端验证

<?php
//文件上传漏洞演示脚本之js验证
$uploaddir = 'uploads/';
if (isset($_POST['submit'])) {
    
    
    if (file_exists($uploaddir)) {
    
    
        if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploaddir . '/' . $_FILES['upfile']['name'])) {
    
    
            echo '文件上传成功,保存于:' . $uploaddir . $_FILES['upfile']['name'] . "\n";
        }
    } else {
    
    
        exit($uploaddir . '文件夹不存在,请手工创建!');
    }
    //print_r($_FILES);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=gbk"/>
    <meta http-equiv="content-language" content="zh-CN"/>
    <title>文件上传漏洞演示脚本--JS验证实例</title>
    <script type="text/javascript">
       function checkFile() {
    
    
            var file = document.getElementsByName('upfile')[0].value;
            if (file == null || file == "") {
    
    
                alert("你还没有选择任何文件,不能上传!");
                return false;
            }
            //定义允许上传的文件类型
            var allow_ext = ".jpg|.jpeg|.png|.gif|.bmp|";
            //提取上传文件的类型
            var ext_name = file.substring(file.lastIndexOf("."));
            //alert(ext_name);
            //alert(ext_name + "|");
            //判断上传文件类型是否允许上传
            if (allow_ext.indexOf(ext_name + "|") == -1) {
    
    
                var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" +     ext_name;
                alert(errMsg);
                return false;
            }
        }
    </script>
<body>
<h3>文件上传漏洞演示脚本--JS验证实例</h3>
<form action="" method="post" enctype="multipart/form-data" name="upload" onsubmit="return     checkFile()">
    <input type="hidden" name="MAX_FILE_SIZE" value="204800"/>
    请选择要上传的文件:<input type="file" name="upfile"/>
    <input type="submit" name="submit" value="上传"/>
</form>
</body>
</html>

绕过方式

去掉前端的提交时候的验证checkFile 函数既可

演示地址:Pass-01/index.php

03修改MIME类型绕过上传

MIME type的缩写为**(Multipurpose Internet Mail Extensions)**代表互联网媒体类型(Internet media type),MIME使用一个简单的字符串组成,最初是为了标识邮件Email附件的类型,在html文件中可以使用content-type属性表示,描述了文件类型的互联网标准。

?php
if($_FILE['userfile']['type'] != "image/gif"){
    
     //检测content-type
    echo "sorry,we only allow uploading GIF images";
    exit;
}
else
{
    
    
    echo "Upload success!";
}
?>

以上是一个简单的服务器上传验证代码,只要content-type符合image/gif就允许上传

绕过方式

使用Burp截取上传数据包,修改Content-Type的值,改为image/gif即可成功绕过上传webshell

演示地址:Pass-02/index.php

04后缀名黑名单校验之上传特殊脚本文件后缀突破

使用黑名单,禁止上传.asp,.aspx,.php,.jsp 结尾的文件。

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    
    
    if (file_exists(UPLOAD_PATH)) {
    
    
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空

        if(!in_array($file_ext, $deny_ext)) {
    
    
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
    
    
                 $is_upload = true;
            } else {
    
    
                $msg = '上传出错!';
            }
        } else {
    
    
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
    
    
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

绕过方式

使用特殊文件.php,.phtml、php2、php3、php5、phtml、pht。来突破上传,在特定情况下同样也可以解析

演示地址:Pass-03/index.php
参考
http://blog.evalshell.com/2020/12/20/风炫安全web安全学习第三十六节课-15种上传漏洞讲解/

猜你喜欢

转载自blog.csdn.net/hyj123480/article/details/112252957