我们应该清理$ _FILES ['filename'] ['name']吗?

q09*_*987 10 php

用户将图像上传到服务器后,我们应该进行消毒$_FILES['filename']['name']吗?

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

谢谢

Ali*_*xel 6

绝对!正如@Bob已经提到的那样,覆盖普通文件名太容易了.

还有一些您可能想要涵盖的问题,例如,*nix中不允许Windows中允许的所有字符,反之亦然.文件名也可能包含相对路径,可能会覆盖其他未上载的文件.

这是Upload()我为PHP框架编写的方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

重要的部分是:

  1. array_map('basename', ...),这可以确保该文件不包含任何相对路径.
  2. ph()->Text->Slug(),这确保只.0-9a-zA-Z允许在文件名中,所有其他字符都被下划线替换(_)
  3. md5_file(),如果已存在具有相同名称的另一个文件,则将其添加到文件名中

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

希望这可以帮助!=)

  • 我希望`if(is_dir($ destination)*array_key_exists($ source,$ _FILES)== 1)`是某种内幕笑话...... :-P (3认同)

dec*_*eze 5

文件名是用户提供的任意字符串。通常,永远不要信任用户提供的任意值。

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