你的位置:面向PHP >> 资讯 >> PHP开发 >> 经验交流 >> 详细内容 在线投稿

PHP检测上传文件的类型

热度92票  浏览36次 【共0条评论】【我要评论 时间:2010年1月20日 16:57
文章信息

来源:转载

最烂的方法就是通过$_FILES[...]['type']来检测上传文件的类型,因为只需简单修改文件扩展名就可以伪造它。面向PHP;O+o8}/G1l3?J,RNro
面向PHP:]J'_p \)c
另一个相对安全点的方法是通过文件头两个字节的内容来判断上传文件的类型,例子代码如下:面向PHP NDMf"X#dj*j
面向PHP6O+Ht8OS
01 $handle = fopen($_FILES[...]['tmp_name'], 'rb');面向PHPs@? X o"v K i-DG1x
02 $content = fread($handle, 2);面向PHP ug9sp2aS4A
03 fclose($handle);面向PHPF*|#G'xeHeK
04面向PHP)L-~%f `Y&B_
05 $info = unpack('c2chars', $content);
HRc#A2?r;]0 06
o K&D0@K?^q0 07 if (empty($info['chars1']) || empty($info['chars2'])) {面向PHPC,R.Tq U(K(X!m#u
08     exit('Error!');
RV U#kMVY~0 09 }
8j p1\3|2t&Y X&X%C1a0 10
#O4j,Q{8E4?n _ d0 11 if ($info['chars1'] < 0) {面向PHP/g\~^VAU-Gi;V
12     $info['chars1'] += 256;面向PHPk8V5`\$B*v KT7V
13 }
_q&A[%L6k)W0 14 if ($info['chars2'] < 0) {面向PHPJ7dz&k c
15     $info['chars2'] += 256;
;H\+py.d#vy'L2m9?0 16 }面向PHP-Z4r ~jTJ+U
17
&[6n+P9r(RDT0 18 $code = $info['chars1'] . $info['chars2'];

Qu#~ c(F6H7qk0
eN hNl*E4Z.x0 注:网上搜索的大多数相关的程序没有做256的相关操作,这是我通过试验数据自己意淫的TDD结果,不肯定是否一定正确,读者自己斟酌。面向PHPr `]%_Y(w/y3I

6k-i-n2Q)G{.P0 通过switch判断$code变量,就可以对应到文件类型,常见的图片类型结果大致如下:
#aT5Q:QY4Jny}(j;P,L0
uvj7dH0 GIF:7173面向PHP\3?MUS0A7M
JPG:255216
0O gAf8Eu9d1W{0 PNG:13780

@7p&j/} N|$Y?0 面向PHP J#xM4yj
当然也可以判断其他的文件类型,自己做做试验就知道数值大小了。但此方法也不是一定安全的,因为前两个字节的内容也是可以伪造的,所以最好还要限制一下文件的扩展名,以防意外的解析,比如说,你创建一个名为foobar.php的文件,内容如下:面向PHP-LiZ9l}] @*?

2j/wjU I\ m6F?S0 GIF面向PHPatQM?!qOMu
<?php eval(...); ?>
] HU9yR'I0 面向PHPw*n1m8yY DGV-T f U
当你使用前两个字节去检测文件类型的时候,就会得出GIF:7173的结果,由于扩展名是.php,那么此文件就被php引擎解析了,如此一来就给了黑客 一个web shell,安全也就无从谈起了。所以说限制文件扩展名非常重要,切记!至于已经如何限制这类伪装,最简单的方法是在用shell命令过滤一遍:面向PHPmz0P%\7Mk(Sq

Q`z"jM2C0 strings /path/to/image/file | grep -i "<?php"面向PHPd3AiD5F^;u8L"m
面向PHP G[`9N;}-a
如此一来,维护一个用于grep的敏感关键字列表似乎也很必要。如果想更安全点,还应该把图片服务器独立出来,不装php,只解析静态文件。
v'O}7I2HSb9Va'R8mc0 面向PHP6]5FC.qe-GwS&x
补充:如果仅仅是判断图片的话,还有一个更简单方法,那就是getimagesize,这个方法虽然从名字上看是用来取得图片大小的,但结果里包含了图片类型,另外,虽然这个方法在文档里被归纳在GD部分,但是即便没有安装GD,也是可用的,不过和前面一样,也要注意限制文件扩展名。
TAG: PHP php 文件 检测 类型
顶:8 踩:7
对本文中的事件或人物打分:
当前平均分:-0.63 (27次打分)
对本篇资讯内容的质量打分:
当前平均分:-0.93 (27次打分)
【已经有23人表态】
5票
感动
4票
路过
1票
高兴
1票
难过
3票
搞笑
4票
愤怒
3票
无聊
2票
同情
上一篇 下一篇
发表评论

网友评论仅供网友表达个人看法,并不表明本网同意其观点或证实其描述。

查看全部回复【已有0位网友发表了看法】