【问题标题】:How do I tell if someone's faking a filetype? (PHP)我如何判断某人是否在伪造文件类型? (PHP)
【发布时间】:2010-09-16 03:51:51
【问题描述】:

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

【问题讨论】:

    标签: php upload mime-types file-type


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        顺便说一句,我遇到了一个类似的问题,我必须自己进行类型检查。我的应用程序的前端接口是在 Flash 中完成的。这些文件正在通过 flash 传递给 php 脚本。当我尝试使用 php 进行 MIME 类型检查时,返回的类型总是 application/octetstream,因为它来自 flash。

        我必须实现一个幻数类型范例。我只是创建了一个 xml 文件,其中包含文件类型以及在文件开头找到的一些定义模式。文件到达服务器后,我对 xml 文件进行了一些模式匹配,然后接受或拒绝了该文件。我也没有注意到任何预期的实际性能下降。

        这只是对任何可能在前端使用 Flash 并在上传文件后尝试键入检查文件的人的补充说明。

        【讨论】:

        • 您使用什么方法将文件与您的参考文件进行比较?
        • 在 xml 文件中,我有一个可以在文件中找到魔术字符串的位置的属性。所以我从文件中读取了指定数量的字节并将其转换为十六进制并进行了比较。
        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          如果您只处理图像,则 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 的错误值不是图像。

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

              在 unix 系统上,捕获“文件”命令的输出应该提供足够的信息。

              【讨论】:

                【解决方案8】:

                有点。大多数文件类型都保留了一些字节来标记它们,这样您就不必依赖扩展名。 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

                【讨论】:

                  【解决方案9】:

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

                  【讨论】:

                  • 幻数并不总是在开头。例如,我相信 TGA 将它们放在最后。
                  • 请注意,依靠此检查,恶意用户可以插入魔术字节,然后在同一文件中编写 PHP 代码,以尝试在您的计算机上执行某些代码
                  • 有什么例子可以说明这一点吗?
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-04-09
                  • 2010-09-17
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-09-14
                  • 2011-07-14
                  相关资源
                  最近更新 更多