【问题标题】:Should we sanitize $_FILES['filename']['name']?我们应该清理 $_FILES['filename']['name'] 吗?
【发布时间】:2010-08-03 04:44:26
【问题描述】:

用户上传图片到服务器后,我们应该清理$_FILES['filename']['name']吗?

我会检查文件大小/文件类型等。但我不检查其他事情。是否存在潜在的安全漏洞?

谢谢

【问题讨论】:

  • 我会说你可能想要命名它而不是让你的用户来命名它,例如,如果你将它保存到数据库名称文件 id 或给它自己的 md5 作为 name 。 ..这也取决于你如何做,但我完全会给它一个 md5 或校验和文件或类似的东西。

标签: php


【解决方案1】:

绝对!正如@Bob 已经提到的,普通文件名太容易被覆盖。

您可能还想讨论一些问题,例如,并非 Windows 中允许的所有字符都在 *nix 中允许,反之亦然。文件名还可能包含相对路径,并可能覆盖其他未上传的文件。

这是我为phunction PHP framework写的Upload()方法:

function Upload($source, $destination, $chmod = null)
{
    $result = array();
    $destination = self::Path($destination);

    if ((is_dir($destination) === true) && (array_key_exists($source, $_FILES) === true))
    {
        if (count($_FILES[$source], COUNT_RECURSIVE) == 5)
        {
            foreach ($_FILES[$source] as $key => $value)
            {
                $_FILES[$source][$key] = array($value);
            }
        }

        foreach (array_map('basename', $_FILES[$source]['name']) as $key => $value)
        {
            $result[$value] = false;

            if ($_FILES[$source]['error'][$key] == UPLOAD_ERR_OK)
            {
                $file = ph()->Text->Slug($value, '_', '.');

                if (file_exists($destination . $file) === true)
                {
                    $file = substr_replace($file, '_' . md5_file($_FILES[$source]['tmp_name'][$key]), strrpos($value, '.'), 0);
                }

                if (move_uploaded_file($_FILES[$source]['tmp_name'][$key], $destination . $file) === true)
                {
                    if (self::Chmod($destination . $file, $chmod) === true)
                    {
                        $result[$value] = $destination . $file;
                    }
                }
            }
        }
    }

    return $result;
}

重要的部分是:

  1. array_map('basename', ...),这样可以确保文件不包含任何相对路径。
  2. ph()->Text->Slug(),这确保文件名中只允许使用 .0-9a-zA-Z,所有其他字符都替换为下划线 (_)
  3. md5_file(),这是添加到文件名iff另一个同名文件已经存在

我更喜欢使用用户提供的名称,因为搜索引擎可以使用它来提供更好的结果,但如果这对您不重要,简单的 microtime(true)md5_file() 可以简化一些事情。

希望这会有所帮助! =)

【讨论】:

  • 我希望if (is_dir($destination) * array_key_exists($source, $_FILES) == 1) 是某种内部笑话... :-P
  • 布尔乘法是一种有效的方法,但我不禁想到如果这是 VB 会发生什么,其中 FALSE 为 -1。无论哪种方式,这种事情都令人害怕。
  • @Marc “有效方法”如“它碰巧有效”?我只看到一个轻微的代码混淆案例,与&& 相比没有优势。
【解决方案2】:

文件名是用户提供的任意字符串。作为一般规则,永远不要相信任意用户提供的值。

您不应该使用用户提供的文件名作为在服务器上保存文件的名称,始终创建您自己的文件名。您可能唯一想做的就是将其保存为元数据以供参考。输出元数据时,请采取通常的预防措施,如卫生和逃生。

【讨论】:

    【解决方案3】:

    您还需要检查重复名称。多人上传名为“mycat.jpg”的图像太容易了,如果上传到同一个文件夹会覆盖以前上传的同名文件。您可以通过在文件名中放置一个唯一的 id 来做到这一点(正如 Prix 建议的那样)。还要验证文件类型不仅以图像扩展名结尾,而且是实际图像;您不希望您的服务器充当随机文件的盲主机。

    【讨论】:

      猜你喜欢
      • 2010-11-18
      • 1970-01-01
      • 2019-10-27
      • 2010-09-15
      • 2016-01-28
      • 1970-01-01
      • 2013-12-25
      • 2012-05-10
      • 1970-01-01
      相关资源
      最近更新 更多