【问题标题】:Uploading PDF or .doc and security上传 PDF 或 .doc 和安全性
【发布时间】:2011-02-24 23:31:02
【问题描述】:

我有一个脚本可以让用户将文本文件(PDF 或 doc)上传到服务器,然后计划将它们转换为原始文本。但是在文件被转换之前,它是原始格式,这让我担心病毒和各种讨厌的东西。

我需要做些什么来最大程度地降低这些未知文件的风险。如何检查它是否干净,或者它是否是它声称的格式并且它不会使服务器崩溃。

【问题讨论】:

    标签: php security pdf upload doc


    【解决方案1】:

    正如我对 Aerik 的评论,但这确实是问题的答案。

    如果您的 PHP >= 5.3,请使用 finfo_file()。如果您有旧版本的 PHP,您可以使用 mime_content_type()(不太可靠)或从 PECL 加载 Fileinfo 扩展。

    这两个函数都返回文件的 mime 类型(通过查看其中的数据类型)。对于 PDF,它应该是

    text/pdf
    

    对于一个 word 文档,它可能是几件事。一般应该是

    application/msword
    

    如果您的服务器正在运行 *nix,请确保您保存的文件不可执行。更好的是:将它们保存到 Web 服务器无法访问的文件夹中。您仍然可以编写代码来访问这些文件,但请求网页的人根本无法访问它们。

    【讨论】:

    • 您确定mime_get_contents() 存在吗?你的意思是mime_content_type()
    • @alex - 哎呀!你的权利。将它与 file_get_contents 混合。我正在更改我的帖子以修复它。谢谢!
    【解决方案2】:

    如果您曾经在服务器上打开或执行过任何用户上传的文件,那么您应该预料到您的服务器现在已被入侵。

    即使是 JPG 也可以包含可执行的 php。如果您在脚本中以任何方式includerequire 文件,那也可能危及您的服务器。您在网络上偶然发现的图像是这样的...

    header('内容类型:图片/jpeg'); header('Content-Disposition: inline; filename="test.jpg"'); echo file_get_contents('/some_image.jpg'); echo '';

    ...您可以像这样保存并重新托管在自己的服务器上...

    $q = $_GET['q']; // 假装这暂时被清理了 header('内容类型:'.mime_content_type($q)); header('Content-Disposition: inline; filename="'.$_GET['q'].'"'); 包括$q;

    ...将在您的服务器上执行phpinfo()。然后,您的站点用户可以简单地将图像保存到他们的桌面并使用记事本打开它以查看您的服务器设置。简单地将文件转换为另一种格式将丢弃该脚本,并且不应触发任何附加到文件的实际病毒。

    最好在上传时进行病毒搜索。您应该能够对检查器执行内联系统命令并解析其输出以查看是否找到任何内容。无论如何,您的网站用户都应该检查他们下载的文件。

    否则,即使是带有病毒的用户上传的文件只是放在您的服务器上,也不应该对任何东西造成伤害......据我所知。

    【讨论】:

      【解决方案3】:

      嗯 - 恕我直言,您不必担心文档类型或其他问题;如果您使用一个好的转换器来转换为原始文本,那么这个转换器应该在不使服务器崩溃的情况下进行这些检查。

      从您的客户端计算机得知,服务器应始终受到保护以免受病毒和攻击 - 因此在处理新上传的文件之前要对其进行检查。

      我从未见过网络应用程序会自行进行此类检查 - 你有吗?

      【讨论】:

        【解决方案4】:

        如果您正在查看 PDF,除了安装防病毒软件并祈祷它可以恶意捕获已形成的 PDF 之外,您无能为力。

        转换软件通常不是针对的,所以如果你只是转换它并查看文本格式输出,你应该会更安全一些。


        哦,你担心服务器。只是不要执行上传的文件...

        【讨论】:

          【解决方案5】:

          恕我直言,在尝试执行它之前,它只是一个文件。但是,您绝对可以检查(但不要依赖,如下所述)文件扩展名,还可以研究文件格式以查看文件头中是否有任何可以验证的特征字节序列。

          【讨论】:

          • 不,不,不!永远不要依赖文件扩展名来告诉你任何事情。在 PHP > 5.3 中使用 finfo_file() 或在旧版本中使用 mime_content_type()。
          • 抱歉,我不清楚 - 我永远不会依赖文件扩展名,我只是说你当然可以排除任何有错误 扩展名。当然,不信任您找到的匹配扩展,检查可能只是被认为是无用的开销。如果您只想告诉用户“对不起,我只接受文档和 pdf”,这可能很有用。
          【解决方案6】:

          在上传的文件中有 3 种安全方式: 最好:将文件放在另一台最安全的服务器上 更好:将它们放在您的 WWW 文件夹之外,这意味着没有人可以通过 URL 访问它们,您必须使用 readfile() 或 get_content 来读取和显示文件 最后:将文件放入 WWW 并在文件夹中使用 .htaccess 以防止其他人执行文件或放入未知文件 这就是我通过上传文件所做的; 将它们放在网络根目录之外并重命名它们甚至将假名保存在数据库中并通过算法创建文件的真实名称。

          在 web 根目录之外上传文件后,您可以像我在这里一样访问它。这里是文件 caleed getfile.php 的内容:

              <?php
          
              define('DS', DIRECTORY_SEPARATOR);
          //fake name of file
              $uniqueid = $_GET['uniqueid'];
          //file extension
              $ext = $_GET['ext'];
              if (isset($_GET['dir']))
          //check address doenot contain ..
                  $addrss = str_replace('..', '_', $_GET['dir']);
              $baseaddress = '..' . DS . 'foldername outside of web root';
              if ((isset($_GET['uniqueid']) and strlen($uniqueid) === 32) and ( isset($_GET['ext']) and strlen($ext) === 3 )) {
                  $path = $baseaddress . DS . $addrss . DS;
                  $path .= md5($uniqueid . $uniqueid . $uniqueid . $ext.'*#$%^&') .'.'. $ext;
                  if (file_exists($path)) {
              //you can check for all your accessible extension i just use for img
                      switch ($ext) {
                          case 'jpg':
                              $content_type = 'image/jpeg';
                              break;
                          case 'png':
                              $content_type = 'image/png';
                              break;
                          case 'gif':
                              $content_type = 'image/gif';
                              break;
                      }
                      header('Content-type: ' . $content_type . ' ');
                      $file = readfile($path);
                  }
          

          在文件 src 或您需要显示文件的每个位置执行此操作(这是为我的图像):

          <img src="/getfile.php?uniqueid=put fake file name here&amp;ext=put extension here&amp;dir=put rest of file address here" >
          

          希望对您有所帮助。不要犹豫,提出更多问题

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-07-21
            • 2014-03-21
            • 2023-03-24
            • 1970-01-01
            • 2020-06-22
            • 2021-08-03
            • 1970-01-01
            • 2014-04-19
            相关资源
            最近更新 更多