PHP 紧急修复两项严重 RCE 漏洞,8.2 至 8.5 用户应立即升级 ​

2026 年 10 月 21 日,PHP 官方发布紧急安全公告,并同时推出 PHP 8.5.12、8.4.27、8.3.36 和 8.2.35,修复两项可能导致**未经身份验证的远程代码执行(RCE)**的漏洞。

这两项漏洞的 CVSS v4.0 评分均为 9.2,严重级别为 Critical。已验证的代码执行以 Web 工作进程的权限运行,并不意味着直接获得 root 权限;但应用凭据、业务数据和服务可用性仍可能受到严重影响。官方明确强调,没有能够完整替代补丁的配置缓解方案,部署包含完整补丁的版本才是完整修复。

对于正在维护 PHP 网站、API 服务或容器镜像的团队,当前最重要的事情是确认实际承载 Web 请求的 PHP 版本,并尽快部署已包含修复的版本。此次风险来自 PHP 自身的内存处理和请求生命周期。已验证的 mod_php 启动阶段利用无需先利用业务代码漏洞;其他路径是否可达,仍取决于具体应用、扩展和配置。

哪些环境需要升级 ​

官方安全公告 将所有承载 Web 请求的 PHP 安装列为需要关注的对象,包括 PHP-FPM、Apache mod_php、php-cgi、FrankenPHP 和 LiteSpeed。

各受支持分支本次的修复版本如下:

PHP 分支本次修复版本升级建议
PHP 8.58.5.12升级至此版本或后续包含修复的版本
PHP 8.48.4.27升级至此版本或后续包含修复的版本
PHP 8.38.3.36升级至此版本或后续包含修复的版本
PHP 8.28.2.35立即修复,同时安排后续版本迁移

如果使用发行版或 LTS 厂商维护的软件包,应以厂商安全公告和补丁状态为准。厂商可能回移补丁,不能只比较上游版本号就断言软件包是否已经修复。PHP 官方表示,发行版和 LTS 厂商已提前收到补丁。

PHP 8.1 及更早版本已经不再获得 PHP 项目的常规更新。鉴于此次漏洞的严重程度,安全团队额外提供了 PHP 7.4、8.0 和 8.1 的最小源码回移补丁,供自行编译或无法获得 LTS 支持的用户使用。这不代表这些分支恢复了常规维护;长期运行的服务仍应迁移到受支持版本。

另外,PHP 8.2 将于 2026 年 12 月 31 日结束官方支持。升级到 8.2.35 解决的是本次漏洞,后续迁移也需要进入计划。

第一项漏洞让内存耗尽变成代码执行风险 ​

CVE-2026-109618,RCE via OOM corruption,对应公告为 GHSA-w8hw-w9fx-j79w。

通常看到“内存耗尽”,容易先想到请求报错或者进程崩溃。这次的问题在于,PHP 处理内存耗尽的方式可能打断尚未完成的内部初始化流程。

漏洞版本会通过 longjmp() 退出当前执行上下文。在某些时刻,请求内部数据已经能够被其他代码访问,却还没有初始化完成。如果此时发生内存分配失败,PHP 可能直接跳出当前流程,将这些数据留在无效状态。随后,请求清理过程又把它们当作正常数据读取或处理,进而形成内存破坏和代码执行风险。

因此,危险不只是“请求用掉了很多内存”,而是内存耗尽发生在什么阶段,以及清理代码接下来会访问什么状态。触发失败的分配操作,甚至不必与那块无效内存直接相关。

技术公告指出,multipart 请求解析中的一些情况会放大风险:请求可能没有可用的声明长度,内部生成的请求元数据可能远大于网络上传输的数据,嵌套字段和上传相关元数据也会增加内存消耗。这说明仅仅认为“请求体已经限制得很小”,并不足以证明安全。

官方已经在 Apache mod_php 上验证了完整的 HTTP 远程代码执行,使用的是默认 PHP 输入与内存限制,以及常见的多工作进程 prefork 配置。尤其值得注意的是,相关攻击可以在业务代码执行之前发生,应用层的登录检查或框架中间件还来不及运行。

对 PHP-FPM,需要区分具体路径:FPM 会在请求启动失败时终止子进程,因此阻断了公告中这条启动阶段的利用流程;但启动成功后,仍可能出现类似的异常退出与无效状态清理问题。就这第一项漏洞而言,公告依据源码分析判断 FPM 存在风险,尚未展示完整的 FPM 利用。

补丁调整了 OOM 处理方式:在下一个虚拟机安全点处理延迟的软 OOM;若内存消耗触及更高阈值,则通过 _exit() 立即终止进程。这样可以避免清理过程继续处理未完成初始化的数据,同时保留 PHP 正常限制内存消耗的能力。

第二项漏洞让上一次请求的失效状态影响下一次请求 ​

CVE-2026-109619,RCE via stale global state,对应公告为 GHSA-6wmf-4rv5-p3rp。

PHP 工作进程会复用,但每次请求都有自己的内存。有些内部全局状态保留在工作进程中,却指向单次请求持有的内存,例如错误、会话、对象或扩展相关状态。这些引用必须在请求内存释放前正确重置。

此次漏洞的核心,是部分状态可能在内存已经释放后仍然存在。后续请求如果在正常初始化完成前访问这些状态,就可能触发释放后使用(use-after-free)。

可以把这一过程理解为五个阶段:

  1. 某次请求执行操作,把请求级状态写入工作进程能够持续访问的位置。
  2. 致命错误等中断导致状态未被清理,或者后续清理阶段的诊断信息又重新写入状态。
  3. 请求结束,相关内存被释放,但工作进程仍保留指向它的引用。
  4. 同一个工作进程接收到下一次请求。
  5. 正常初始化重置状态之前,某个操作先读取或处理了旧引用。

这里的触发因素并不限于内存耗尽。解析或编译失败、未捕获错误、require 失败、执行超时,以及清理阶段产生的非致命诊断信息,都可能参与相关状态生命周期。

公告确认了两类重要路径:

已确认路径关键条件与影响
PHP 8.5 致命错误回溯fatal_error_backtraces 开启时,回溯状态可能遗留到下次请求;后续初始化前的诊断操作访问失效状态,已在 mod_php 上确认 RCE
会话上传进度生命周期会话上传进度可能在正常初始化前访问会话或解码器状态;相关 RCE 已在 mod_php 和 FPM 上验证,FPM 路径依赖合适的应用操作

没有显式调用 session_start(),并不能排除会话路径的风险。 公告指出,会话上传进度默认开启,可以在普通会话初始化之前触发相关处理。

攻击中的前后请求需要落到同一个工作进程。增加工作进程数量、采用一般性的工作进程轮换,可能降低单次尝试的成功率,但不能视为完整修复。

这也解释了为什么不能简单地认为“使用 Nginx + PHP-FPM 就没事”。第一项漏洞中尚未展示完整 FPM 利用,不等于第二项漏洞没有经过验证;两项公告需要一起看。

关闭错误显示并不能防住这次攻击 ​

第二项漏洞有一条容易误解的路径:初始化之前应用无效或已弃用的配置,可能产生 warning、notice 或 deprecation,并在这个过程中访问遗留状态。

问题发生在 PHP 决定是否报告、显示或记录这条诊断信息之前。因此,关闭 display_errors、降低 error_reporting、关闭 log_errors,或者用 @ 隐藏错误,都不能修复这条路径。

对于 FPM,公告特别区分了配置生效时机。前端通过 PHP_VALUE / PHP_ADMIN_VALUE 传入、且在请求初始化前产生诊断的配置,可能成为相关入口;FPM 池配置在工作进程启动时应用,.user.ini 则在正常初始化之后应用,不构成同样的早期配置消费路径。

不过,没有这条配置路径,也不能排除会话上传进度或其他应用、扩展相关路径。日志中没有异常记录,同样不能作为安全证明。

无法立即升级时,只能降低部分风险 ​

官方给出了应急配置建议,但同时反复强调:这些措施只能阻断特定路径,不能让未打补丁的安装变得安全。 应急配置的作用是争取升级时间。

内存相关缓解要同时考虑可用性 ​

针对 CVE-2026-109618,官方建议在暂时无法升级时,以管理员配置强制设置 memory_limit=-1,并确认池、目录或应用配置不会重新设置有限的 PHP 内存上限。修改后需要重启所有 PHP 工作进程。

这一建议看起来与通常的资源保护原则相反,但有明确原因:它移除了攻击者可以利用的、可控的 PHP 请求内存限制失败点。它不会阻止底层内存分配失败,也不是完整修复。

同时,解除 PHP 自身的请求内存限制会带来资源耗尽风险,因此必须配合请求限制和外部资源边界。官方建议包括:

  • 不需要文件上传的应用,将 post_max_size 设为 8M;需要上传时,公告给出的建议值为 32M,并保持 upload_max_filesize 小于 post_max_size。
  • 在 Web 服务器或代理层限制解码后的请求体大小、输入字段数量、multipart 分段数量、头部数量和嵌套深度;这些限制也应覆盖没有可用 Content-Length 的请求。
  • 不使用 multipart 表单的应用,可以在前端阻止这类请求进入 PHP。
  • 使用容器或 cgroup 提供可用性边界,并尽可能让资源超限只终止受影响的工作进程;如果限制作用于整个容器或进程组,也可能一起终止主进程和其他工作进程。

不要用 RLIMIT_AS 或 RLIMIT_DATA 替代上述措施。 技术公告指出,它们可能直接造成底层内存分配失败,重新触及存在漏洞的处理路径。容器或 cgroup 限制也不保证彻底避免分配失败,仍不能替代补丁。

会话和回溯配置必须在请求解析前生效 ​

针对 CVE-2026-109619,公告建议关闭会话上传进度;PHP 8.5 还可以关闭致命错误回溯。以适用环境的启动配置为例:

ini
; 所有受影响分支:阻断已确认的早期会话相关路径
session.upload_progress.enabled=0

; 仅 PHP 8.5:阻断已确认的致命错误回溯路径
fatal_error_backtraces=0

这些配置必须通过 php.ini、FPM 池或合适的服务器配置,在请求解析之前生效,并重启所有工作进程。不要依赖业务代码中的 ini_set(),也不要依赖 FPM 的 .user.ini 来关闭这条早期会话路径。

此外,应清理请求初始化前会触发诊断的无效或已弃用配置,修复攻击者能够触达的致命错误和执行超时,尤其关注上传、导入、回调和清理流程。只修复正常页面访问时能看到的错误,并不能覆盖所有相关路径。

升级时要确认真正处理请求的运行时已经更新 ​

源码及 Windows 下载入口可见 PHP 官方下载页面。使用操作系统软件包、托管运行时或容器镜像的环境,则应跟进对应供应方的修复公告。

官方还在 10 月 21 日公告中特别说明,志愿者维护的 rpms.remirepo.net 当天不会提供更新,并建议相关用户改用发行版软件包或自行编译,以便及时应用补丁。这是当天的仓库供应情况;实际操作时,应核对该仓库后续更新状态。

部署时可以先检查命令行环境:

bash
php -v
php --ini

但这两条命令只说明 CLI 的版本和配置,不能证明 FPM、Apache 模块或容器中的 PHP 已经更新。多版本共存、不同服务使用不同镜像或独立安装目录时,尤其需要分别核对。

实际升级至少应完成以下步骤:

  1. 盘点对外处理请求的 PHP 服务、版本、软件包来源和镜像,而不只检查开发机或 CLI。
  2. 安装上述修复版本,或确认发行版、LTS 厂商的软件包已经包含对应 CVE 的补丁。
  3. 重建并部署使用旧 PHP 的容器镜像,重启或完整滚动替换工作进程,确保没有旧实例继续接收请求。
  4. 在实际 Web 运行环境确认版本和配置,检查关键业务路径及错误日志;不要把公开暴露 phpinfo() 页面作为长期验证方式。

此次公告已经给出了明确的修复版本,也说明了配置缓解的局限。对于生产环境,处置重点应落在完成升级、替换旧工作进程、验证实际运行版本这三个环节,而不是在关闭几个配置项之后结束处理。

官方资料 ​

本作品采用《CC 协议》,转载必须注明作者和本文链接