2008-10-08 91 views
12

我正在编程一些东西,允许用户将文档和图片存储在网络服务器上,稍后进行存储和检索。当用户将文件上传到我的服务器时,PHP会告诉我它基于扩展名的文件类型。但是,恐怕用户可以将zip文件重命名为somezipfile.png并存储它,从而在我的服务器上保留一个zip文件。有没有合理的方法来打开上传的文件,并“检查”,看看它是否真的是所说的文件类型?如何判断某人伪造文件类型? (PHP)

回答

18

Magic number。如果你可以读取二进制文件的前几个字节,你可以知道它是什么类型的文件。

+0

幻数并不总是在开始。例如,TGA最终会让他们走到最后,我相信。 – 2008-10-08 23:02:12

+0

请注意,通过依赖此检查,恶意用户可以插入魔术字节,然后在同一个文件中写入PHP代码,以尝试在您的机器上执行一些代码。 – Jorre 2012-12-04 13:53:03

4

排序大多数文件类型都有一些字节保留用于标记它们,以便您不必依赖扩展名。该网站http://wotsit.org是一个很好的资源,为特定类型找出这个。

如果你在unix系统上,我相信文件命令不依赖于扩展名,所以如果你不想写字节检查代码,你可以掏出它。

对于PNG(http://www.w3.org/TR/PNG-Rationale.html

前八个字节的PNG文件的总是包含下列值:

(十进制)137 80 78 71 13 10 26 10

(十六进制)89 50 4E 47 0D 0A 0A 1A

(ASCII C表示法)\ 211 PNG \ r \ n \ 032 \ n

2

许多文件类型在文件的开头都有“magic numbers”来标识它们,您可以从文件的前面读取一些字节,并将它们与已知幻数的列表进行比较。

1

在unix系统上,从'file'命令捕获输出应该提供足够的信息。

8

查看FileInfo PHP的PECL扩展,它可以为您执行MIME魔术查找。

2

如果只处理图像,然后和getimagesize()应该从一个假的区分有效的图像。

$ php -r 'var_dump(getimagesize("b&n.jpg"));' 
array(7) { 
    [0]=> 
    int(200) 
    [1]=> 
    int(200) 
    [2]=> 
    int(2) 
    [3]=> 
    string(24) "width="200" height="200"" 
    ["bits"]=> 
    int(8) 
    ["channels"]=> 
    int(3) 
    ["mime"]=> 
    string(10) "image/jpeg" 
} 

$ php -r 'var_dump(getimagesize("/etc/passwd"));' 
bool(false) 

来自getimagesize的错误值不是图像。

1

作为一个侧面说明,我遇到了类似的问题,我不得不做我自己的类型检查。我的应用程序的前端界面是在Flash中完成的。这些文件正在通过闪存传递给一个PHP脚本。当我尝试使用php进行MIME类型检查时,总是返回的是application/octetstream,因为它来自flash。我不得不实现一个魔术数字类型范例。我只是简单地创建了一个xml文件,它保存了文件类型以及在文件开头的一些定义模式。一旦文件到达服务器,我做了一些与xml文件匹配的模式,然后接受或拒绝该文件。我没有注意到我期望的任何实际性能下降。

这只是一个小贴士,任何人都可能使用闪存作为有前端,并尝试键入检查文件一旦上传。

1

除了识别文件类型之外,您可能还想留意其他文件已嵌入或附加到其中的文件。不幸的是,这需要对文件内容进行更深入的分析,而不仅仅是使用“幻数”。

例如,http://quantumrook.wordpress.com/2007/06/06/hide-a-rar-file-in-a-jpg-file/(数据隐藏的这种特殊类型可以很容易地工作围绕通过加载和重新保存到一个新文件的实际图像数据的..别人会更加困难。)

相关问题