如何辨别某人伪造文件类型? (PHP)

时间:2008-10-08 22:51:54

标签: php upload mime-types file-type

我正在编写一些东西,允许用户在网络服务器上存储文档和图片,以便以后存储和检索。当用户将文件上传到我的服务器时,PHP会根据扩展名告诉我它是什么文件类型。但是,我担心用户可以将zip文件重命名为somezipfile.png并存储它,从而在我的服务器上保留一个zip文件。有没有合理的方法来打开上传的文件并“检查”以查看它是否真的属于所述文件类型?

9 个答案:

答案 0 :(得分:18)

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

答案 1 :(得分:8)

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

答案 2 :(得分:4)

排序。大多数文件类型都保留了一些字节用于标记它们,因此您不必依赖扩展名。网站http://wotsit.org是查找特定类型的最佳资源。

如果您使用的是unix系统,我相信file命令不依赖于扩展名,因此如果您不想编写字节检查代码,可以使用它。

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

PNG文件的前八个字节始终包含以下值:

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

(十六进制)89 50 4e 47 0d 0a 1a 0a

(ASCII C表示法)\ 211 P N G \ r \ n \ 032 \ n

答案 3 :(得分:2)

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

答案 4 :(得分: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的错误值不是图像。

答案 5 :(得分:1)

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

答案 6 :(得分:1)

有关如何在PHP中快速完成此操作的确切答案,请查看以下问题:How do I find the mime-type of a file with php?

答案 7 :(得分:1)

作为旁注,我遇到了类似的问题,我不得不进行自己的类型检查。我的应用程序的前端界面是在flash中完成的。这些文件正在通过flash传递给php脚本。当我尝试使用php进行MIME类型检查时,总是返回的类型是application / octetstream,因为它来自flash。

我必须实现一个神奇的数字类型范例。我只是创建了一个xml文件,其中包含文件类型以及在文件开头找到的一些定义模式。一旦文件到达服务器,我做了一些与xml文件匹配的模式,然后接受或拒绝该文件。我没有注意到任何真正的性能下降,这是我所期待的。

对于任何可能正在使用flash作为前端并尝试在上传文件后键入内容的人,这只是一个附注。

答案 8 :(得分:1)

除了识别文件类型之外,您可能还需要注意嵌入或附加了其他文件的文件。遗憾的是,这需要对文件内容进行更深入的分析,而不仅仅是使用“魔术数字”。

例如,http://quantumrook.wordpress.com/2007/06/06/hide-a-rar-file-in-a-jpg-file/(这种特殊类型的数据隐藏可以通过加载并将实际图像数据重新载入新文件来轻松解决。其他的将更加困难。)