跳转到内容

PHP2Shell:我们如何关闭并验证了两个严重的 PHP 漏洞

事件与状态  ·   ·   ·  8 分钟 阅读时间

简要概述
  • 2026 年 10 月 21 日,PHP 项目修复了两个严重漏洞,即 CVE-2026-109618 和 CVE-2026-109619,合称“PHP2Shell”。两者都允许远程执行代码,CVSS 4.0 评分均为 9.2。
  • 早在当天上午,也就是补丁发布前数小时,我们就已关闭了已知攻击所利用的功能。在发布前不久,我们又出于预防将 PHP 整体下线。
  • 每个系统只有在确认运行的是已修补版本之后才重新上线。Plesk 面板一直保持关闭,直到 Plesk 在 10 月 22 日上午提供了自己的更新。
  • 我们没有发现攻击痕迹。对于“更新并不足够”的说法,我们自己做了验证,没有一条得到证实。

PHP 中的漏洞影响的不是某一个应用,而是几乎所有应用:WordPress、Nextcloud、商城、论坛、网页邮箱。因此我们反应很快。本文介绍我们在何时做了什么,以及我们自己验证了什么。

这两个漏洞是什么

两个错误都藏在 PHP 的核心中,涉及两次请求之间的这段时间。一个 PHP-FPM 进程会依次处理许多请求,在两次请求之间,它必须把自己的状态彻底清理干净。

  • CVE-2026-109618(RCE via OOM corruption):PHP 内存耗尽时,会通过一次跳转中止当前请求。在某些位置,这会留下处于半完成状态的内存,而之后的清理过程仍然会读取它。根据 PHP 项目的安全公告,这可以被有针对性地触发,并一直发展到代码执行。
  • CVE-2026-109619(RCE via stale global state):全局指针会在短时间内指向某个请求的内存。如果它们没有被干净地重置,下一个请求就会读取已经释放的内存。这里 PHP 项目的公告同样将代码执行描述为后果。

示意图:未打补丁时,一个精心构造的请求会把 PHP 进程推到内存极限,残留数据留在内存中,下一个请求因此执行了外来代码。打补丁后,PHP 会彻底清理残留数据,下一个请求得到正常的响应。

两个漏洞均已在 PHP 8.2.35、8.3.36、8.4.27 和 8.5.12 中修复(PHP 8 更新日志)。核心修复的标题是 “Avoid state corruption via bailout”。CVE 条目:CVE-2026-109618 和 CVE-2026-109619。

带具体时间的处理流程

PHP 项目在 10 月 20 日宣布,次日将发布针对两个严重漏洞的安全版本,计划在德国时间 16:00 发布。事先没有给出任何细节。我们利用了这段时间。

时间(MESZ)发生了什么
10月21日,07:30 起第一项防护措施:关闭 session.upload_progress,先是在我们的网站上,然后逐步推及虚拟主机、Nextcloud 和邮件服务器。
10月21日,14:00 前针对虚拟主机中已知的攻击途径设置并测试了防火墙规则。已有的更新全部装完。
10月21日,15:36PHP 发布已修补的版本,比预告的时间更早。
10月21日,15:37我们出于预防将各系统上的 PHP 下线。原计划是 15:45。根据经验,补丁一发布,大规模扫描就会立刻开始。
10月21日,16:03我们的网站恢复运行,使用已修补的 PHP。
10月21日,16:22–16:46邮件服务器、虚拟主机、Nextcloud 以及大部分应用重新上线,每一个都是在检查过运行中的版本之后才恢复的。
10月21日,约 17:45其余几乎所有应用在重新构建镜像后恢复上线。
10月22日,01:56Plesk 提供 18.0.81.4 版本,其中面板的 PHP 已修补。
10月22日,06:36经过我们自己的检查,我们重新开启 Plesk 面板。

对大多数服务来说,这意味着半小时到一小时的中断。我们是有意接受这一点的:按照我们的规则,没有确认已修补 PHP 的系统不会重新上线。

我们做了什么

发布之后,我们更新了由我们负责的所有 PHP 安装:Plesk 和 KeyHelp 下的虚拟主机、Nextcloud 实例、邮件服务器的网页邮箱、我们自己的网站以及内部应用。Plesk 仍附带的较旧 PHP 版本 7.4、8.0 和 8.1 也收到了相应的更新。

仅仅更新对我们来说还不够。因此还额外设置了三层防护:

  1. session.upload_progress 在所有地方都已关闭并被锁定。公开描述的攻击链利用这个功能把数据写入会话。我们在整个服务器范围内关闭了它,并通过 php_admin_flag 固定下来,使 .user.ini 或域名设置都无法再将其重新开启。
  2. PHP 进程会定期更新。借助 pm.max_requests = 500,每个进程最迟在处理 500 个请求后就会结束。滞留在请求之间的状态也就不会无限期地存活。
  3. Web 应用防火墙拦截攻击途径。我们自己的 ModSecurity 规则会拒绝携带 PHP_SESSION_UPLOAD_PROGRESS 字段的请求,包括使用伪装 Content-Type 的变体。

四层防护示意图:1. 防火墙拦截带有 PHP_SESSION_UPLOAD_PROGRESS 的请求,2. upload_progress 已关闭并被锁定,3. 已修补的 PHP 在请求之间清理状态,4. PHP 进程在 500 个请求后更新。攻击会在第 1 层失败,试图绕过的尝试会在第 2 层失败。

此外还有一套监控,每十分钟检查一次 PHP 崩溃、由 Web PHP 进程启动的 shell,以及重新开启 upload_progress 的配置。

Plesk 面板为什么下线

Plesk 的管理界面运行的不是网站使用的 PHP,而是它自己内置的、固定的 PHP 版本。在我们这里,10 月 21 日那是 PHP 8.4.25,也就是未修补的,upload_progress 处于开启状态,而且可以从外部访问。这个 PHP 无法自行替换。

因此我们关闭了面板,直到 Plesk 提供更新。更新随 Plesk 18.0.81.4 在 10 月 22 日上午到来。重新开启之前,我们检查了面板确实运行在 PHP 8.4.27 上,并且在那里也额外关闭了 upload_progress。在此期间网站本身运行正常,只是无法登录面板。

我们自己验证了什么

早在 10 月 21 日晚上,社交网络和 GitHub 上就流传着各种说法,称更新没有用,或者已经有了绕过方式。我们没有依赖其中任何一条,而是逐一亲自验证。

  • 看运行中的版本,而不是软件包列表:已安装的版本并不能说明一个正在运行的进程实际执行的是什么。我们直接查询了每个 PHP 池,看它报告的版本是什么,以及 upload_progress 是否已关闭。结果发现,比如在某个系统上,网站的 PHP 是最新的,而命令行的 PHP 却不是。
  • 修复本身:我们比对了已发布的版本是否确实包含核心修复。受影响的源文件在全部四个发布分支中都以相同方式打了补丁。
  • 自建实验室测试:在已修补的 PHP 8.4.27 上,如果 upload_progress 处于开启状态,攻击者选定的文件名会出现在会话文件中。功能关闭后,根本不会生成会话文件。已知的攻击链恰恰缺少这一步。

未经证实的说法

  • 补丁之后的“残余攻击链”:多个公开仓库展示了针对已修补 PHP 的所谓攻击。我们读了代码。这些攻击链每一条都至少需要满足以下之一:开启 upload_progress、仍是未修补的版本(如 8.4.26),或者应用本身存在额外的漏洞,例如不安全的 unserialize()。对我们的配置,其中任何一条都不起作用。
  • 一个“补充改进”补丁:PHP 仓库中的一个 Pull Request 声称对两个漏洞提供额外加固。它在当天晚上就被关闭,没有被合并。另一个更早的、关于会话处理的提议仍处于开放状态,但在 upload_progress 关闭的情况下无关紧要。
  • 利用代码压缩包:有些地方提供“可用”的利用代码供下载,未加密,来源可疑。对于这种规模的漏洞,这类压缩包本身往往就带有恶意软件。我们没有下载它们,也没有在我们的服务器上运行任何来路不明的利用代码。

攻击痕迹

我们按照已知的特征搜索了访问日志、错误日志和防火墙日志。找到的是扫描。例如在 10 月 21 日 16:22,一个自称是 PHP2Shell 扫描器的扫描器向我们的虚拟主机发送了一个精心构造的请求。防火墙拦截了它,而它背后的 PHP 此时已经修补。我们没有发现成功利用的迹象。

还有哪些问题未解决

新版本 8.4.27 和 8.5.12 带来了它们自己的一个错误:在某些情况下,SimpleXML 扩展可能会崩溃(GH-24488)。修复正在进行中。我们这里目前还没有出现这个崩溃。我们的监控会留意此事,后续版本一发布我们就会装上。

这对你意味着什么

虚拟主机、Nextcloud 和邮件:你无需做任何事。更新和加固都已完成。有一个例外:如果你的应用通过 session.upload_progress 使用上传进度条,它现在不再显示进度。上传本身仍然正常工作。

自己的 vServer 或 Root 服务器:这里需要你自己负责。请检查正在运行的 PHP-FPM 服务,而不是只看命令行里的 php -v。至少需要 8.2.35、8.3.36、8.4.27 或 8.5.12。之后请重启 PHP-FPM,并设置 session.upload_progress.enabled = Off。运行 Plesk 或其他自带 PHP 的面板的用户,另外还需要面板厂商提供的更新。

关于你的服务器的问题,我们很乐意通过我们的工单系统解答。

常见问题

什么是 PHP2Shell?
PHP2Shell 是 PHP 中两个严重漏洞的名称,即 CVE-2026-109618 和 CVE-2026-109619。两者的成因都是 PHP 在两次请求之间没有完全清理自己的状态。攻击者可以利用这一点远程执行代码。两者的 CVSS 4.0 评分均为 9.2。
哪些 PHP 版本修复了这些漏洞?
PHP 8.2.35、8.3.36、8.4.27 和 8.5.12,均于 2026 年 10 月 21 日发布。决定性的是正在运行的 PHP-FPM 服务所报告的版本。更新之后必须重启该服务。
作为虚拟主机客户,我需要做什么吗?
不需要。我们已更新虚拟主机中的所有 PHP 版本,并额外关闭了 session.upload_progress。只有依赖该功能的上传进度条不再显示进度。上传本身仍然正常工作。
为什么 Plesk 面板曾一度无法访问?
Plesk 界面运行在它自己的 PHP 版本上,只有 Plesk 才能更新它。当时它还没有修补。因此我们关闭了面板,直到 Plesk 在 10 月 22 日上午提供更新。在此期间网站运行正常,只是无法登录面板。
有系统受到攻击吗?
我们没有发现成功利用的迹象。日志中出现了扫描。防火墙拦截了它们,而且它们背后的 PHP 当时已经更新。
更新并不足够,这种说法是真的吗?
我们自己验证了流传的各种说法。每一个所谓的绕过方式都要求开启 session.upload_progress、使用未修补的 PHP 版本,或者应用中存在额外的漏洞。在使用最新 PHP 且关闭 upload_progress 的情况下,其中任何一条都不起作用。
Prepaid-Host.com 本身即为服务器、虚拟主机与域名服务商,在此报道的正是自己所处的市场。我们如何处理这一点,见利益披露说明。