php fileinfo是否足以阻止上传恶意文件?

时间:2010-04-01 15:25:43

标签: php security

嘿伙计们,我已经搜索了一下,并没有真正找到专业类型的响应如何获得安全的文件上传功能,所以我想得到一些专家在这个网站上的意见。我目前允许上传mp3和图像,虽然我对防止我的网站上的xss和注入攻击非常有信心,但我并不熟悉fileupload安全性。我基本上只使用php fileinfo并检查文件类型的接受文件类型数组。对于图像,有getimagesize功能和一些额外的检查。至于存储它们,我只在我的目录中有一个文件夹,因为我希望用户能够使用这些文件。如果有人能给我一些提示,我会非常感激。

6 个答案:

答案 0 :(得分:7)

在接受可共享的文件时,我通常会调用ClamAV。使用PHP,可以使用php-clamav轻松完成。

您要做的最后一件事是在全球传播恶意软件:)

如果可以,请在上传文件后在后台执行此操作,但必须先将其公开。这个类的一个怪癖是它可以将整个整个 ClamAV病毒定义数据库加载到内存中,如果PHP按照常规方式在Apache下运行,那几乎肯定会发臭(想想订单)每个实例+120 MB的内存)。

使用类似beanstalkd的内容来扫描上传内容,然后更新您的数据库以使其公开是解决此问题的一种非常好的方法。


我之所以提到这一点,只是因为其他答案没有,我绝不打算将其作为完整的解决方案。看到这里发布的其他答案,这是你应该完成的一步。始终,始终,始终清理您的输入,确保它是预期的类型等(我是否提到您应该阅读其他答案?)

答案 1 :(得分:4)

“恶意”文件不是伤害您的服务器的唯一方法(如果您的网站出现故障,则会伤害您的用户)


例如,损害服务器的可能性是上传很多非常小的文件:

  • 它不会占用磁盘上的所有空间,
  • 但可以使用所有可用的inodes ...

...当没有剩余的免费inode时,就不可能再创建任何文件了;这显然是坏事。


之后,还存在以下问题:

  • 版权
  • 对您或您的用户不熟悉的内容(裸体?)

为此,您对技术解决方案的了解并不多 - 但“提醒主持人”功能非常有用; - )

答案 2 :(得分:2)

不,因为这很容易被欺骗。有an article描述了如何通过上传1x1“jpg文件”以及如何防止服务器来攻击服务器。好读。

答案 3 :(得分:2)

从“文件类型”开始($ _FILES ['userfile'] ['type'])完全没有意义。这是HTTP post请求中的变量,可以是攻击者想要的 ANY VALUE 。尽快删除此检查。

getimagesize()是验证图像是否真实的绝佳方法。声音文件可能有点棘手,您可以在命令行上调用file /tmp/temp_uploaded_file

到目前为止,上传文件中最重要的部分是文件的扩展名。如果文件是.php,那么你就是被黑了。情况变得更糟,Apache可以配置为忽略第一个文件扩展名,如果它不能识别它,然后使用下一个扩展名,所以这个文件将被执行一个普通的.php文件:backdoor.php.junk。默认情况下,应禁用此功能,但几年前默认启用它。

必须使用文件扩展名白名单。所以你想强制使用像jpg,jpeg,gif,png,mp3这样的文件,否则拒绝它。

答案 4 :(得分:1)

要做的第一件事是通过服务器配置禁用该目录中任何服务器端代码(例如PHP)的执行。为MIME类型(或文件扩展名设置白名单,因为您的服务器首先使用它们来计算mime类型)并且仅允许媒体文件(不是HTML或任何内容)将保护您免受XSS注入。结合文件类型检查的那些应该是足够的 - 我唯一可以想到的可能是通过那些利用图像/音频解码器的东西,以及发现那些你需要接近病毒扫描程序的东西。

答案 5 :(得分:0)

如果exiv2无法移除元数据,那么它可能是恶意的,或者至少以某种方式被破坏。在unix系统上安装以下必需的exiv2。不幸的是,如果文件包含恶意shell代码,这可能会很危险。不确定exiv2对抗shell漏洞是多么坚固,所以请谨慎使用。我还没有使用它,但我已经考虑过使用它了。

function isFileMalicious($file)
{
    try{
        $out = [];
        @exec('exiv2 rm '.escapeshellarg($file).' 2>&1',$out);
        if(!empty($out)){
            return false;
        }
    }
    catch(exception $e)
    {
        return false;
    }
    return true;
}