21

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

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

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

4

4 回答 4

34

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

您通过文件上传从用户那里得到什么:

  • 文件数据
  • 一个文件名
  • MIME 类型

这是文件上传的三个主要组成部分,没有一个是可信的。

  1. 不要相信$_FILES['file']['type']. 这是一个完全任意的、用户提供的值。

  2. 不要将文件名用于任何重要的事情。这是一个完全任意的、用户提供的值。通常,您不能信任文件扩展名或名称。不要使用类似'dir/' . $_FILES['file']['name']. 如果名称是'../../../passwd',则您正在覆盖其他目录中的文件。始终自己生成一个随机名称以将文件另存为。如果您愿意,您可以将原始文件名作为元数据存储在数据库中。

  3. 永远不要让任何人或任何东西任意访问该文件。例如,如果攻击者将malicious.php文件上传到您的服务器,并且您将其存储在站点的 webroot 目录中,则用户可以简单地example.com/uploads/malicious.php执行该文件并在您的服务器上运行任意 PHP 代码。

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

    • 只允许特定进程访问文件。如果它应该是图像文件,则只允许读取图像并调整它们大小的脚本直接访问该文件。如果此脚本在读取文件时出现问题,则可能不是图像文件,标记它和/或丢弃它。其他文件类型也是如此。如果该文件应该可供其他用户下载,请创建一个脚本来提供该文件以供下载,并且不对其进行任何其他操作。

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


要解决您的具体问题:

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

不会。如果您不对这些数据进行任何操作,那么仅将数据存储在临时文件夹中的文件中是没有风险的。数据只是数据,无论其内容如何。如果您尝试执行数据,或者如果程序正在解析数据,如果程序包含解析缺陷,则可能会被恶意数据诱使做出意想不到的事情,这才是有风险的。

当然,在磁盘上存放任何类型的恶意数据比在任何地方都没有恶意数据风险更大。你永远不知道谁会来和它一起做点什么。所以你应该验证任何上传的数据,如果它没有通过验证,请尽快丢弃它。

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

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

于 2012-06-16T07:16:49.000 回答
5

一个简单的场景是:如果您使用的上传接口对允许上传的文件类型没有限制,那么攻击者可以上传带有恶意代码的 PHP 或 .NET 文件,这可能会导致服务器受损。

参考: http ://www.acunetix.com/websitesecurity/upload-forms-threat.htm 以上链接讨论了常见问题

另请参阅: http: //php.net/manual/en/features.file-upload.php

于 2012-06-16T06:31:08.577 回答
3

这里是其中的一些:

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

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

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

于 2012-06-16T06:32:38.553 回答
3

有一些通用规则可以避免文件上传的一般问题:

  • 将上传的文件存储在您的网站根文件夹之外 - 因此用户将无法重写您的应用程序文件并直接访问上传的文件(例如/var/uploads而您的应用程序位于/var/www中)。
  • 将清理过的文件名存储在数据库中,物理文件给出文件哈希值的名称(这也解决了存储文件重复的问题 - 它们将具有相等的哈希值)。
  • 为了避免在 /var/uploads 文件夹中有太多文件时文件系统出现问题,请考虑将文件存储在文件夹树中,如下所示:

    file hash = 234wffqwdedqwdcs-> 将其存储在/var/uploads/23/234wffqwdedqwdcs

    通则: /var/uploads/<first 2 hash letters>/<hash>

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

于 2012-06-16T08:00:38.507 回答