文件上传的前世今生

栏目: JSP · 发布时间: 5年前

内容简介:从开始到现在,文件上传其实都是一项正常功能。其最大的好处就是方便了文件类型信息的交互与传递,大大减轻了现代办公压力。但是,它也有一个悖端,那就是,如果是不怀好意的人上传了不应该上传的内容,就会造成结果的不可预料。这样,就衍生成了一个严重的安全威胁。所以,我们要对文件上传内容进行过滤。先来看一下什么是上传表单得到的结果为

从开始到现在,文件上传其实都是一项正常功能。其最大的好处就是方便了文件类型信息的交互与传递,大大减轻了现代办公压力。但是,它也有一个悖端,那就是,如果是不怀好意的人上传了不应该上传的内容,就会造成结果的不可预料。这样,就衍生成了一个严重的安全威胁。所以,我们要对文件上传内容进行过滤。

先来看一下什么是上传表单

<form action="up.php" enctype="multipart/form-data" method="post">Add File: <input name="file" type="file" value="" />
 <input type="submit" value="Submit" /></form> 
 
 <?php if(isset($_POST)) { foreach($_FILES as $k=>$v) {
 foreach ($v as $k=>$v)
 {
                   echo '<pre>';
           echo $k.'----'.$v;
           echo '</pre>';
 }
 }
 
 }

得到的结果为

name—-aserasfsadfdf.txt

type—-text/plain

tmp_name—-D:\test\tmp\phpA677.tmp

error—-0

size—-377

依次分别为包含后缀的文件名,文件类型,上传时产生的临时文件名,文件上传状态,文件大小。但是,这只是把上传文件打印出来,还没有真正实现上传,要想实现上传,还得用到一个函数 move_uploaded_file , 说到上传,不得不还要说2种文件上传判断方式

1. 黑名单判断。

2. 白名单判断。

黑名单判断就相当于如果恶意ext在array中,那么返回false,但是这样存在一个问题,恶意不可能包含所有文件类型,所以这里只要传任意一个在array中不存在的文件类型,就会直接导致验证被绕过,比如说,我在array中的是 cer,aspx,jsp,jspx。 此时如果上传前没有对大小写进行转换,那么,传一个.ASPX, 验证将会被绕过。所以,更多的时候,上传采用的验证类型一般是以白名单为主,那么什么是白名单呢? 认识的可以传,不认识的统统不可以。

黑名单判断实例


  

可以看到, 表面上对后缀进行了过滤,事实上稍微改变一下大小写,或者传一个array中不存在的类型,该方式就被绕过了。这也是很多网站被入侵的一个原因。所以更多时候使用白名单,在说白名单之前,黑名单真的是一定可被绕过吗? 答案肯定是不一定的。这个可以后面再说, 先再来看一下白名单。


  

使用非array中文件类型上传,大写后缀均会上传失败, 原因是使用大写文件上传时,遇到strtolower均会被转换成小写,大写被破功,非array中的话,因为只有在array中搜索到了ext才会返回true, 没有搜索到就根本不会进入上传执行流程。 这里有个题外话,曾经有人问过我上传漏洞怎么补,我答:array一个ext数组不在数组中不让它传啊。 结果对方说,你这不是还是黑名单吗?希望阁下看到我的文章后能够明白。 其实如果想再安全点, 还可以加上对 $_FILES[‘file’][‘type’]的判断,如果是多类型文件上传,根据文件类型的不同再做出不同的判断,比如遇到图像后使用内置图像压缩函数对图像进行压缩等。 前面说到了黑名单绕过的疑问,这里重提一下,黑名单真是那么一无是处吗? 可以看一下

$dirname = $_SERVER['DOCUMENT_ROOT'].'/uploads/';

从这里能看的出来, 上传后的路径是根据当前绝对路径和带后缀的文件名拼接而来的,所以这里如果对文件进行重命名,只要文件名在控制范围,无论黑名单怎么写,都不太可能造成意外结果。但这只是强词夺理,原因是白名单也一样。

比如

move_uploaded_file($_FILES['file']['tmp_name'],$dirname.'.'.md5(time('Y-m-d',round(0,9999999))))

无论怎么传,后缀都是随机数, 正常的情况下随机数不会被解析。再保险一点,filename可以只取文件名不取后缀。但是这样依然是存在问题的。 如果没有采用绝对路径,依然存在绕过的可能。 所以还是要对文件类型进行验证的。再一个,采用array判断方式也是存在问题的,前面说过,它存在意外返回true的可能,所以保险点的做法还是采用$ext == ‘JPG’ 进行比对。比如

strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png"

但是,如果服务端软件出现了漏洞,该验证依然会被打破,这也是为什么没有绝对安全的原因。综上所述,处理文件上传一般采用以下几种组合办法。

1. 前端判断,后端校验(JSON一样要确认)。

2. 上传目录去除解析或者上传到一个专用的子域。

3. 配置文件里配置安全目录。

还有一个要注意的是,很多人可能记起了过滤要采用白名单,但是他们把白名单过滤写到了前端,我想说的是,这样做是错误的,因为客户端内容是可以修改的。没有检查逻辑和错别字。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程真好玩

编程真好玩

[英] 乔恩·伍德科克 / 余宙华 / 南海出版公司 / 2017-8-1 / 88.00元

在美国,编程已进入幼儿园和中小学课堂,是备受欢迎的课程之一。 在英国,编程被列入国家教学大纲,成为6~15岁孩子的必修课。 在芬兰,编程理念融入了小学的各门课程,孩子们可以随时随地学编程。 编程已经成为世界的通用语言,和听、说、读、写、算一样,是孩子必须掌握的技能。 Scratch是美国麻省理工学院设计开发的可视化少儿编程工具,全球1500多万孩子正在学习使用。它把枯燥乏味......一起来看看 《编程真好玩》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具