制作文件类型黑名单以保护 PHP 应用程序

信息安全 php 上传文件 文件类型 黑名单
2021-09-04 00:40:22

我在用户可以上传文件的 PHP 系统中工作。

我正在尝试保护系统免受恶意代码的侵害,因此我正在考虑某种类型的文件黑名单,我必须阻止它们上传。

我知道白名单比黑名单好,这是我常用的方法,但在这种情况下,出于多种原因(我无法控制),我需要将文件列入黑名单,但我仍在寻找安全性(如果可能)。

这是我当前的脚本(我正在检查 MIME 类型以获取文件类型):

        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $check= finfo_file($finfo,$file["tmp_name"]);
        finfo_close($finfo);

        $dangerMime = array('application/x-bsh', 'application/x-sh', 'application/x-shar', 'text/x-script.sh');
        if (in_array($check, $dangerMime)) {
            //block upload
        }
        else {
            //allow upload
        }

当前要阻止的 MIME 类型列表是:

  • “应用程序/x-bsh”、“应用程序/x-sh”、“应用程序/x-shar”、“文本/x-script.sh”

我试图阻止任何.sh文件,因为系统在 Apache 下的 CentOS 中运行。还有其他我应该阻止的文件类型吗?

以下是一些重要信息:

服务器是带有 Apache 2.4.6 的 CentOS 7.2。以下是上传目录的权限:

drwxr-xr-x  4 apache apache 4096 Jan  8 12:23 uploads

注意:在这个项目中,我只是作为开发人员,所以我不能更改文件权限。

4个回答

从您的描述中不清楚为什么要完全阻止这些文件。我看到以下可能性:

  • 您想要阻止可能感染服务器本身的文件。不幸的是,这可以是任何东西:shell、perl、python、awk,……当然还有编译的二进制文件。但是要在不使用解释器显式调用它们的情况下执行这些文件,必须设置可执行位,如果文件是从 Web 应用程序内部上传的,则不应如此。至少在 UNIX 系统上是这样,因为在 Windows 上,扩展就足够了,而且还有 PoweShell、JavaScript、Batch 和所有其他文件。尽管如此,某些东西至少必须触发文件的执行,或者在 DLL 和共享库的路径中具有上传目录。
  • 或者您想阻止可能由 Web 服务器本身执行的文件,即从 Web 应用程序内部执行。这些是 PHP、ASP、CGI ... 文件,它们将通过 URL 执行并对用户或服务器造成伤害。当然,如果您的上传目录可以通过 URL 访问,或者如果攻击者设法通过路径遍历攻击或类似攻击来突破上传目录,或者如果攻击者管理一些服务器端代码以包含这些文件(即本地文件包含),则唯一有效攻击)。
  • 或者您想阻止可能包含的文件以向用户提供恶意软件,例如损坏的 PDF 文档、重定向到恶意软件站点的 javascript。在这种情况下,您可能有一个可通过 URL 访问的上传目录,因为您希望用户下载这些文件。不幸的是,对于此类文件,不仅您看到的文件类型很重要,而且调用它们的上下文(即图像、脚本、css、对象...)也很重要,您无法控制这种用法。

...但在这种情况下,出于多种原因,我需要将文件列入黑名单,

由于您显然根本不知道哪些文件可能是危险的,因此这种黑名单永远不会起作用。总会有您错过的文件类型,或者攻击者会将其文件隐藏在其他类型之后,即构造一个polyglot

不要阻止任何特定的 MIME 类型。阻止任何类型的上传文件的执行。一种简单的方法是将上传的文件存储在 Web 根目录之外,并通过脚本提供它们。如果这不可行,请将文件存储在子目录中,并将您的服务器配置为不执行该目录中的任何脚本请记住对可能在服务器上启用的任何脚本语言执行此操作

如果由于各种原因无法修改配置,请检查文件名,并正确执行。PHP 字符串可以包含 NULL 字节,文件名不能,因此如果攻击者上传名为“hack.php\0.jpg”的文件,您可能会将扩展名视为有效的“.jpg”,但它会保存为“hack .php”,让你再次受到攻击。根据白名单检查文件名中的字符。

还有其他我应该阻止的文件类型吗?

没关系,因为finfo_file 可以被绕过,例如参见此处:Encoding Web Shells in PNG IDAT chunksmime_content_type 似乎也不更可靠。

除了 mimetype 检查之外,您还需要检查文件扩展名,因为它更可靠,因为文件名比文件内容复杂得多。

作为深度防御,额外的 mime 类型检查仍然是一个好主意,可以过滤掉简单的攻击。就像你说的那样,白名单是正确的方法,但如果你肯定需要黑名单,我至少会将 PHP mimetypes 添加到阻止列表中:

  • 文本/php
  • 文本/x-php
  • 应用程序/php
  • 应用程序/x-php
  • 应用程序/x-httpd-php
  • 应用程序/x-httpd-php-source

此外,您真的需要在上传目录中执行吗?如果没有,请将其删除以增加安全性。

我建议对所有上传的文件进行短期隔离。您可以在临时监狱中使用本地系统扫描和 AV 工具。这样,您可以添加一个例程来扫描恶意文件并忽略所有不同的文件名称。这停止了​​打地鼠游戏。

这会给应用程序增加一些延迟。

我知道这不是一个编码解决方案,但它解决了黑名单的根本缺陷,并且不会强迫你调整权限——正如你所说的,你没有控制权。

我遇到了一个应用程序,它按照您的建议方式将其列入黑名单。我是在对手控制并以公司资产为食九个月后进行取证分析时发现的。如果这还不是停止列入黑名单的充分理由,那就玩得开心。重击。