我使用PHP语言进行文件上传,并想知道我使用的以下方法是否安全?
我使用简单的文件上传方法, 我从$ _FILES ['userfile'] ['type']检查文件名 然后,如果它有一个允许的文件扩展名,我上传一个随机数的文件。 就像它是abc.zip一样,它可能会变成8w43x9d.zip。
请告诉我:这是一个非常糟糕的文件上传方法吗?
答案 0 :(得分:2)
随机生成的安全文件名绝对是件好事。但是,如果您允许文件扩展名通过webroot,您仍然需要确保扩展名不会导致服务器出现任何问题,例如.php
(好的,应该禁用PHP处理)用于上传目录的Web服务器,但仍然)。如果您在Windows服务器上也存在问题,其中尾随点和空格会混淆文件系统;确保将扩展名锁定为一些“已知良好”值。
不幸的是,根本不能依赖['type']
属性。有些浏览器不会填充内容类型,其他浏览器会输入错误的类型,因为他们的操作系统设置得很糟糕(一个臭名昭着的无用的是Windows上的IE默认调用JPEG image/pjpeg
),有些人会说application/octet-stream
甚至text/plain
。
即使['name']
属性也不可靠;除了说谎或混淆值的浏览器之外,给定类型总是有可能在该特定机器上具有意外的文件扩展名。或者,对于Mac和Linux客户端,完全有可能上传的文件根本没有扩展名(或者甚至可能具有操作系统认为的类型的错误扩展名)。
所以是的,这有点乱。虽然从Content-Type提交或文件扩展名中嗅探类型可能有助于猜测文件应该是什么默认类型,但它完全不可靠,因此提供手动方法来选择文件类型是一件好事。或者,如果您将上传的文件作为附件提供(例如,通过PHP脚本设置Content-Disposition: attachment
),您通常只需调用所有application/octet-stream
并让用户在保存时将其排序它
如果您不是附件,则可能存在安全问题。 IE会很高兴地嗅到你为<html>
标签提供的许多文件类型,并将这些文件视为HTML,即使你告诉它它们是其他的东西。然后它可以在浏览器中内联显示它们,并让它们将脚本注入您的安全上下文。如果您的安全上下文中有任何重要内容,例如用户帐户和Cookie,则这是跨站点脚本安全漏洞。解决方法的变通方法是作为附件和/或服务于不在主站点安全上下文中的不同主机名(通常使用子域)。
允许您不完全信任的用户将文件上传到您的服务器实际上是比PHP教程中的简单示例代码让您相信的任务要困难得多。 : - (
答案 1 :(得分:1)
来自PHP Manual:
$ _ FILES [ 'userfile的'] [ '类型']
文件的mime类型,如果浏览器提供此信息。一个例子是“image / gif”。但是,在PHP方面没有检查这个mime类型,因此不会将其值视为理所当然。
我不相信用户或用户的浏览器发送给我的任何内容。
如果您正在尝试学习,我会查看现有的安全来源,例如来自PEAR的HTTP_Upload。您甚至可以考虑使用Beta版本。
答案 2 :(得分:0)
除上述帖子外,我们依赖于FileInfo或SplFileInfo,到目前为止,它已被证明是满足我们需求的最佳选择。
答案 3 :(得分:0)