Php 上传带来的安全威胁

Php 上传带来的安全威胁,php,upload,Php,Upload,我允许用户上传文件到我的服务器。我面临哪些可能的安全威胁?如何消除这些威胁 假设我允许用户从他们的系统或网络上传图像到我的服务器。现在要检查这些图像的大小,我必须将它们存储在我的/tmp文件夹中。这不是很危险吗?我如何将风险降至最低 另外,假设我正在使用wget从用户在我的表单中上传的链接下载图像。我首先必须将这些文件保存在我的服务器中,以检查它们是否确实是图像。另外,如果一个恶作剧者给了我一个URL,我最终下载了一个充满恶意软件的整个网站怎么办?1简单的场景是: 如果您使用的上载接口对允许上载

我允许用户上传文件到我的服务器。我面临哪些可能的安全威胁?如何消除这些威胁

假设我允许用户从他们的系统或网络上传图像到我的服务器。现在要检查这些图像的大小,我必须将它们存储在我的/tmp文件夹中。这不是很危险吗?我如何将风险降至最低


另外,假设我正在使用wget从用户在我的表单中上传的链接下载图像。我首先必须将这些文件保存在我的服务器中,以检查它们是否确实是图像。另外,如果一个恶作剧者给了我一个URL,我最终下载了一个充满恶意软件的整个网站怎么办?

1简单的场景是: 如果您使用的上载接口对允许上载的文件类型没有限制,则攻击者可以上载带有恶意代码的PHP或.NET文件,从而导致服务器受损

参考: 上面的链接讨论了常见的问题

另请参阅: 以下是其中的一些:

将文件上载到服务器时,PHP会将变量$_FILES['uploadedfile']['type']设置为客户端使用的web浏览器提供的mime类型。但是,文件上载表单验证不能仅依赖于此值。恶意用户可以使用脚本或其他允许发送HTTP POST请求的自动应用程序轻松上载文件,从而允许他发送假mime类型

要编译一个包含攻击者可以使用的所有可能扩展的列表几乎是不可能的。例如,如果代码在托管环境中运行,通常此类环境允许使用大量脚本语言,如Perl、Python、Ruby等,并且列表可能是无止境的

恶意用户可以通过上传名为“.htaccess”的文件轻松绕过此类检查,该文件包含一行类似于以下内容的代码:AddType application/x-httpd-php.jpg


首先,要意识到上传文件意味着用户以各种格式向您提供大量数据,并且用户可以完全控制这些数据。这甚至是一个普通形式的文本字段所关心的问题,文件上传是相同的,而且更多。第一条规则是:不要相信任何人

您通过文件上载从用户处获得的信息:

文件数据 文件名 默剧类型 这是文件上传的三个主要组件,没有一个是可信的

不信任$\u FILES['file']['type']中的MIME类型。这是一个完全任意的、用户提供的值

不要在重要的事情上使用文件名。这是一个完全任意的、用户提供的值。您不能信任文件扩展名或名称。不要使用类似“dir/”的命令将文件保存到服务器硬盘$_文件['file']['name']。如果名称为“../../../passwd”,则覆盖其他目录中的文件。始终自己生成一个随机名称以将文件另存为。如果需要,可以将原始文件名作为元数据存储在数据库中

绝不允许任何人或任何东西随意访问该文件。例如,如果攻击者将恶意.php文件上载到您的服务器,而您正将其存储在站点的webroot目录中,则用户只需转到example.com/uploads/malail.php即可执行该文件并在您的服务器上运行任意php代码

永远不要将任意上传的文件公开存储在任何地方,始终将它们存储在只有您的应用程序才能访问它们的地方

仅允许特定进程访问文件。如果应该是图像文件,则只允许读取图像并调整其大小的脚本直接访问该文件。如果此脚本在读取文件时遇到问题,则可能不是图像文件,请将其标记和/或放弃。其他文件类型也是如此。如果该文件应该可以被其他用户下载,那么创建一个脚本来提供该文件供下载,而不做任何其他操作

如果您不知道要处理的文件类型,请自己检测文件的MIME类型和/或尝试让特定进程打开文件,例如,让图像调整进程尝试调整假定图像的大小。这里也要小心,如果该过程中存在漏洞,恶意制作的文件可能会利用该漏洞,从而导致安全漏洞。最常见的此类攻击示例是Adobe的PDF Reader

要解决您的具体问题:

[T] o检查这些图像的大小,我必须将它们存储在我的/tmp文件夹中。这不是很危险吗

不需要。如果您不使用临时文件夹中的数据进行任何操作,那么只将数据存储在临时文件夹中是没有风险的。数据就是数据,不管其内容如何。只有当您试图执行数据,或者某个程序正在解析数据时,如果该程序包含解析缺陷,则恶意数据可能会诱使该程序执行意外操作,这才是有风险的

当然,在磁盘上存放任何类型的恶意数据比没有恶意数据的风险更大 美国数据随处可见。你永远不知道谁会来用它做点什么。因此,您应该验证任何上传的数据,如果未通过验证,则应尽快将其丢弃

如果一个恶作剧者给了我一个url,而我最终下载了一个充满恶意软件的整个网站,该怎么办


具体下载什么取决于你自己。一个URL最多只能产生一个数据块。如果您正在解析该数据,并且正在根据初始blob下载更多url的内容,那么这就是您的问题所在。不要这样做。但即使你这么做了,你也会有一个临时目录,里面满是东西。同样,如果你没有对这些东西做任何危险的事情,这也不危险。

有一些常见的规则来避免文件上传的一般问题:

将上载的文件存储在您的网站根文件夹下,这样当您的应用程序位于/var/www时,用户将无法重写您的应用程序文件并直接访问上载的文件,例如在/var/uploads中。 将经过清理的文件名存储在数据库中,物理文件给出文件名哈希值这也解决了存储重复文件的问题-它们将具有相同的哈希值。 <>为了避免文件系统中存在太多文件/VAL/AppDad文件夹,请考虑将文件存储在文件夹树中: 文件哈希=234wfqwdedqwdcs->将其存储在/var/uploads/23/234wfqwdedqwdcs中

通用规则:/var/上传//

如果您尚未安装nginx,请安装nginx-它像魔术一样提供静态服务,其“X-Accel-Redirect”头将允许您使用自定义脚本首先检查权限的文件


你并没有在这个问题上投入太多的精力,但这是一个非常好的问题,它的核心是非常中肯的。我希望这能成为这个话题的典型问题。为什么人们会投票把它作为离题题来结束呢?这完全是本文的主题,这是每个程序员都需要特别注意的事情!我会尽量说得更具体一些。假设我允许用户从系统或网络上传图像到我的服务器。现在要检查这些图像的大小,我必须将它们存储在我的/tmp文件夹中。这不是很危险吗?我怎样才能最大限度地降低风险?@deceze同意这一点。真的需要进行一次非接近投票来反对CV的花言巧语。@finnw重新开放不是一回事,因为它发生在关闭之后。PHP问题的讨论非常激烈,非接近投票可能会在当时引发更彻底的讨论。在meta上进行了讨论,并被拒绝,理由是不投票结束,实际上就是投了不结束的一票。不过我不同意这个结论。+1读起来很有趣,写得很好,并指出了一些我没有想到的问题。