文件上传的前世今生

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

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

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

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

<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. 配置文件里配置安全目录。

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


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

查看所有标签

猜你喜欢:

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

Learning PHP 5

Learning PHP 5

David Sklar / O'Reilly / July, 2004 / $29.95

Learning PHP 5 is the ideal tutorial for graphic designers, bloggers, and other web crafters who want a thorough but non-intimidating way to understand the code that makes web sites dynamic. The book ......一起来看看 《Learning PHP 5》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具