【问题标题】:PHP file verificationPHP文件验证
【发布时间】:2012-03-05 16:35:27
【问题描述】:

我正在为自己编写一个多文件上传功能。

问题是我要上传 .psd、.cdr、.indd、.cad 等文件。

我可以轻松检查文件是否为合法图像,但是否有类似的方法可以验证上述文件扩展名。

编辑问题不在于检查文件是否具有 psd、cdr 等扩展名。我需要能够验证文件是否是合法的 PSD 或 CDR 文件。

【问题讨论】:

  • 对于 etc. 文件来说,这是最简单的——因为它是未定义的,所以没有什么要检查的。但老实说,您需要对每种格式进行验证。可能存在一些,先做一个研究。如果您将稍后发现的内容作为答案列出,将会很高兴。另见How to check file types of uploaded files in PHP?
  • 可以检查 psd 文件,因为它们有点 XML 结构。对于 etc 文件,我的意思是可能出现的其他设计软件文件扩展名,但前 4 个是最重要的
  • 我会从两个方面来解决这个问题:首先找出文件规范是否公开可用以及存在哪些文件格式版本。维基百科不是一个太糟糕的起点。第二方面是搜索这些文件的库。对于更流行的格式,我假设一些可能已经存在于 PHP 中。否则,如果您在 linux 上运行,我也会寻找系统库。

标签: php validation file-upload


【解决方案1】:

我真的不知道可以为您提供如此准确信​​息的 php 命令。以上都是基于可以被欺骗的文件扩展名。

如果你的 web 服务器运行在 *nix 系统上,你可以使用系统命令file

system("file $filePath");

这是可靠的,因为文件查找文件内容的头部(文件扩展名不会改变结果)。此命令特定于二进制文件。文本文件,比如sql,都是ascii。

如果您认为这是一种解决方案,请查看手册页并检查 file 的选项。

【讨论】:

    【解决方案2】:

    是和不是。

    从文件名中提取扩展名是一个简单的字符串操作。
    针对预定义扩展数组测试提取的扩展也不是一门火箭科学。

    但是,在某些情况下,此类验证可能会危及您的网站安全。
    如果您使用的是 Apache 网络服务器,它有一个非常特殊的习惯,即在多个文件中查找文件扩展名。
    比如说,文件名image.php.cad 将由 Apache 使用默认设置作为 PHP 脚本执行。

    为避免这种危险,要么根本不使用 Apache,而是在整个文件名中搜索 .php,或者以这种方式配置您的 PHP

    <FilesMatch \.php$>
      SetHandler php5-script
    </FilesMatch> 
    

    (由http://verens.com/2008/10/13/security-hole-for-files-with-a-dot-at-the-end/ 提供)

    【讨论】:

    • 感谢您提供了一些有关 apache 工作原理的方便信息。但我已经这样配置了。
    【解决方案3】:

    使用FileInfo 功能获取接收文件的真实mimetype:

    http://www.php.net/manual/en/intro.fileinfo.php

    不要相信上传文件的扩展名,这是浏览器发送的数据,很容易伪造。假设输入文件没有名称,没有扩展名。

    【讨论】:

    • 看起来mime-type是要走的路,即使它可以被伪造,也没有办法运行坏脚本,至少我不知道。
    • @Skatebail - 如果您担心通过上传程序进行某种脚本注入,您可以将上传的文件从您的 docroot 中取出,或者通过 .htaccess 阻止任何直接文件访问子目录。我个人让用户通过另一个脚本下载此类文件(作为您可能希望防止的一些文件,例如盗链、公共访问等)。
    【解决方案4】:

    你可以使用函数pathinfo

    if ( pathinfo($_FILES['fileinput']['name'], PATHINFO_EXTENSION) == 'psd' ) {
        // do something...
    }
    

    要检查 mime 类型,请尝试使用 http://ru.php.net/manual/en/function.finfo-file.php

    【讨论】:

      【解决方案5】:
      function endsWith($haystack, $needle)
      {
          $length = strlen($needle);
          $start  = $length * -1; //negative
          return (substr($haystack, $start) === $needle);
      }
      
      if(!endWith($_FILES['file1']['name'],".psd") || !endWith(..)...){
         //Error! file extension not correct
      }else{
          //correct!
      }
      

      【讨论】:

      • 这个函数根本不会验证任何东西,我可以轻松地编写一个 php shell 并将其重命名为 psd。您还应该检查文件名中的多个“点”。不过,感谢您的宝贵时间,我真的很感激。
      • 明白了!您要检查所选文件是否真的是具有该扩展名的文件。 RAW WAY:您应该打开一些具有相同扩展名的文件并检查该文件是否具有与其他相同的标题。通过这种方式,您可以使用 fopen 打开文件并获取标题(fgets),以便您真正检查文件是否正确。对你想要允许的所有扩展文件重复什么操作:)
      猜你喜欢
      • 2012-02-03
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-13
      • 2021-06-11
      • 2017-03-26
      相关资源
      最近更新 更多