web服务器端文件内容检测及绕过_优品建站

web服务器端文件内容检测及绕过

  这类检测方法相对于上述检测方法来说更为严格。它通过检测文件内容来判断上传文件是否合法。但由于防护手段严格,允许的内容也就更加单一,这里针对图片上传功能进行防护分析。
1.文件内容检测防护思路
  对文件内容的检测主要有以下三种方法。
  ● 通过检测上传文件的文件头来判断当前文件格式。
  ● 调用API或函数对文件进行加载测试,常见的是图像二次渲染。
  ● 检测上传文件是否为图像文件内容。
  在上传漏洞的防护过程中,在文件上传时检测内容是一项非常有效的防护措施。防护手段可包含检测文件的文件头及内容图像格式是否合法(参考第一、三种防护方法),或者在显示过程中调用函数进行二次渲染,导致木马等非图像代码由于无法渲染成像素而被丢弃,从而达到防护的效果(参考第二种防护方法)。但需注意的是,针对图像二次渲染会给服务器带来额外的性能开销。因此需要根据业务防护需求来寻找性能开销与安全要求之间的平衡点。
2.文件内容检测防护代码
  本节将详细介绍文件内容检测的三种方法。
  (1)文件头判断
  读取文件开头部分的数个字节,判断文件头与文件类型是否匹配。通常情况下,通过判断前10个字节基本上就能判断出一个文件的真实类型。
  在HTML上传表单中,先获取文件名,并对文件后缀名根据原有规则进行匹配。如果确认是合法文件名,则认为可信,即进入后续流程。此种方法完全为服务器端信息判断,在此过程中,客户提交的信息无法修改,因此防护效果要明显优于MIME类型验证机制。
  如下是基于上传文件的文件头判断防护代码,其中array均为常见文件格式的文件头。

        function getTypeList()
        {
                return array(array("FFD8FFE0", "jpg"),
                array("89504E47", "png"),
                array("47494638", "gif"),
                array("49492A00", "tif"),
                array("424D", "bmp"),
                array("41433130", "dwg"),
                array("38425053", "psd"),
                array("7B5C727466", "rtf"),
                array("3C3F786D6C", "xml"),
                array("68746D6C3E", "html"),
                array("44656C69766572792D646174", "eml"),
                array("CFAD12FEC5FD746F", "dbx"),
                array("2142444E", "pst"),
                array("D0CF11E0", "xls/doc"),
                array("5374616E64617264204A", "mdb"),
                array("FF575043", "wpd"),
                array("252150532D41646F6265", "eps/ps"),
                array("255044462D312E", "pdf"),
                array("E3828596", "pwl"),
                array("504B0304", "zip"),
                array("52617221", "rar"),
                array("57415645", "wav"),
                array("41564920", "avi"),
                array("2E7261FD", "ram"),
                array("2E524D46", "rm"),
                array("000001BA", "mpg"),
                array("000001B3", "mpg"),
                array("6D6F6F76", "mov"),
                array("3026B2758E66CF11", "asf"),
                array("4D546864", "mid"));
        }
        function checkFileType($fileName){
                $file = @fopen($fileName, "rb");
                $bin = fread($file, 5); //只读5字节
                fclose($fi le);
                $typelist=getTypeList();
                foreach ($typelist as $v)
                {
                    $blen=strlen(pack("H*", $v[0])); //得到文件头标记字节数
                    $tbin=substr($bin,0, intval($blen)); ///需要比较文件头长度
                    if(strtolower($v[0])==strtolower(array_shift(unpack("H*", $tbin))))
                    {
                        return $v[1];
                    }
                }
                    return 'error';
            }
            $upfi le=$_FILES["upfi le"];
            $name=$upfi le["name"];
            $type=$upfi le["type"];
            $size=$upfi le["size"];
            $tmp_name=$upfi le["tmp_name"];
                $distination = '/var/www/html/upload_04/file/'.$name;
                echo checkFileType($upfile['tmp_name']);
            move_uploaded_fi le($upfi le['tmp_name'], $distination);
(2)文件加载检测中的图像二次渲染
  关键函数imagecreatefromjpeg从jpeg生成新的图片(类似的还有imagecreatefromgif、imagecreatefrompng等),这样就导致在二次渲染过程中,插入的木马无法渲染成像素,因此在渲染过程中被丢弃,进而使木马执行失效。
防护关键代码如下:

        function newimage($nw, $nh, $source, $stype, $dest)
        {
            $size = getimagesize($source);
            $w = $size[0];
            $h = $size[1];
            switch($stype)
            {
                case 'gif':
                $simg = imagecreatefromgif($source);
                break;
                case 'jpg':
                $simg = imagecreatefromjpeg($source);
                break;
                case 'png':
                $simg = imagecreatefrompng($source);
                break;
            }
            $dimg = imagecreatetruecolor($nw, $nh);
            $wm = $w/$nw;
            $hm = $h/$nh;
            $h_height = $nh/2;
            $w_height = $nw/2;
            if($w > $h)
            {//图像宽度大于高度的情况
                $adjusted_width = $w / $hm;
                $half_width = $adjusted_width / 2;
                $int_width = $half_width - $w_height;
        imagecopyresampled($dimg, $simg, -$int_width,0,0,0, $adjusted_width, $nh, $w, $h); //
重采样拷贝部分图像并调整大小
            }
            elseif(($w < $h) || ($w == $h))
            {
                $adjusted_height = $h / $wm;
                $half_height = $adjusted_height / 2;
                $int_height = $half_height - $h_height;
        imagecopyresampled($dimg, $simg,0, -$int_height,0,0, $nw, $adjusted_height, $w, $h);
            }
            else
            {
                imagecopyresampled($dimg, $simg,0,0,0,0, $nw, $nh, $w, $h);
            }
                imagejpeg($dimg, $dest,100); //输出新生成的图像到指定位置
        }
(3)图像内容检测
  可利用PHP中的getimagesize()函数实现。getimagesize()函数可获取目标图片(GIF、JPEG及PNG)的高度和宽度的像素值,再与本地获取到的图片信息进行比对,如果相同,则进行保存,不同,则放弃代码执行。防护代码如下:

        $file_name = $_FILES['upfile']['tmp_name'];
        print_r(getimagesize($fi le_name));
        $allow_ext = array('image/png', 'image/gif', 'image/jpeg', 'image/bmp');
        $img_arr = getimagesize($file_name);
        $file_ext = $img_arr['mime'];
        if (in_array($file_ext, $allow_ext)) {
        if  (move_uploaded_file($_FILES['upfile']['tmp_name'],  $uploaddir  .  '/'  .  $_
    FILES['upfi le']['name']))
        {
        echo ’文件上传成功,保存于:' . $uploaddir . $_FILES['upfile']['name'] . "\n";
        }
3.文件内容检测绕过方式
  针对文件内容的检测方式,只有在文件开头添加所允许文件类型对应的文件头,方可绕过现有防护措施。下面介绍一些常用手段。
(1)文件头检测
  修改文件头,对前20字节进行替换,后面再插入一句话木马,即可实现对文件内容检测的绕过。使用时先在要上传的文件的所有内容前添加GIF89a, Web系统可判断当前文件为gif类型。需要注意的是,在实际中仅使用这种方法很多时候不能成功,因为上传功能还检测了后缀名\MIME等。因此若仅仅是针对文件内容检测,可采用这种方法进行尝试。如图5-13所示。

图5-13 单独文件头检测绕过效果
  图5-13就是添加GIF89a但没有修改文件后缀名而进行的上传测试,可看到其中针对上传文件的类型及文件名均未防护。
(2)文件二次渲染(极难)
  1)基于数据二义性,即让数据既是图像数据也包含一句话木马。
  2)对文件加载器进行溢出攻击。
  这里需要注意的是,如果仅仅对.php文件添加上述文件头,并不一定会控制MIME的生成值。因为在不同浏览器下,针对文件生成MIME时会有不同的情况。IE浏览器默认会根据文件头确定MIME值。但是Chrome、Firefox则仍以后缀名方式进行判断,这点需注意。

  • Linux服务器的管理和维护建议
    下面这些服务器操作规范和建议初学者可能不容易看懂,但是这些经验之谈对服务器的管理和维护都非常重要。
  • 如何将Node.js部署到服务器
    在开发完Node.js的项目之后,需要将项目部署到服务器上才能让别人来访问。上线部署的事情一般都由运维人员来操作,但是作为开发人员还是需要知道一些基本的部署知识的。
  • 服务器的进程、线程和协程
    “多进程多线程”是“单进程多线程”和“多进程单线程”的组合体,其原理并没有差异,所以接下来只讨论“单进程多线程”和“多进程单线程”两种编程模型,对比“多进程”和“多线程”的关键差异。
  • 配置Linux网络时间服务器
    配置Linux异构网络下的NTP服务器,NTP服务的配置文件。
  • 企业Samba服务器实用案例
    企业Samba服务器实用案例:1.企业环境及需求,2.需求分析,3.解决方案。
  • 服务器运维必会知识:利用U盘安装Linux系统
    光盘介质没有U盘携带方便,有的服务器为节省成本甚至没有安装光驱,所以很多管理员习惯做一个U盘的安装盘,随身携带以备不时之需。如果使用U盘作为安装介质,那么U盘需要进行一定的配置,本文我们来学习一下如何使用U盘安装Linux。
  • nginx服务器必会知识点:nginx.conf文件的结构
    我们可以归纳出nginx.conf文件的基本结构为:(“#”后边的内容是笔者添加的注释内容,它们的含义在后文中会给出)。
  • 服务器缓冲I/O和直接I/O
    表4-1列出了缓冲I/O与直接I/O对应的API接口列表,缓冲I/O是C语言提供的库函数,均以f打头;直接I/O是Linux的系统API,但因为操作系统的API也是用C语言编写的,所以导致开发者往往无法区分这两类I/O,但在原理上实际差异很大。
  • mysql_connect函数:打开MySQL服务器的非持久连接
    该函数将打开一个非持久的到MySQL服务器的连接。如果函数执行成功,将返回一个MySQL服务器的连接标识符,执行失败则返回FALSE。
  • RHEL6.0服务器系统的基本配置
    RHEL6.0服务器系统的基本配置:设置一个系统管理员账号;yum配置。
  • 网站制作 服务

    免费网站制作报价,免费优化,1对1服务,个性化定制服务

    pc和wap网站制作

    多年建站经验,上千个成功案例,
    为您提供一站式服务

    网站维护改版

    大厂经验工程师对现有网站进行
    改版,修复,维护。

    小程序制作

    微信小程序,支付宝小程序,
    百度小程序

    响应式网页设计

    响应式网页设计可以与多种设备兼容,
    如智能手机,平板电脑和PC