PHP 近期披露的 PHP2Shell 相关漏洞值得所有 PHP 服务维护者关注。它并不是常见的应用层 SQL 注入或文件上传漏洞,而是涉及 PHP 请求生命周期、Session 扩展以及底层内存管理的问题。

攻击者在特定条件下,可以通过构造 HTTP 请求触发内存异常,进一步造成内存安全问题,甚至可能发展为远程代码执行(RCE)。

本文重点介绍漏洞原理、影响范围以及生产环境中的修复方案,并补充后续披露的 CVE-2026-115560 风险提醒。

一、漏洞概述

此次 PHP2Shell 相关问题主要涉及两个漏洞:

漏洞编号核心问题风险
CVE-2026-109618OOM(内存耗尽)处理过程中的异常清理问题可能导致内存安全问题
CVE-2026-109619请求级内部状态在内存释放后仍然被使用Use-After-Free(UAF)

两个漏洞都与 PHP 请求处理过程中的内存管理和状态清理有关。

需要注意,漏洞影响的不只是 PHP-FPM。凡是对外提供 Web 请求服务的 PHP 运行环境,都应进行检查,包括:

  • PHP-FPM
  • Apache mod_php
  • php-cgi
  • FrankenPHP
  • LiteSpeed 等 PHP 运行环境

官方修复版本

根据 PHP 官方 2026 年 10 月 21 日发布的安全公告,以下版本包含相关修复:

PHP 分支修复版本
PHP 8.58.5.12
PHP 8.48.4.27
PHP 8.38.3.36
PHP 8.28.2.35

优先建议升级到对应分支的修复版本,或者升级到仍受支持且包含安全补丁的更高版本。

PHP 8.1 及更早版本已不再由 PHP 上游常规维护。如果仍在使用,需要确认发行版或商业供应商是否提供了安全补丁;长期来看,应迁移到受支持的 PHP 版本。

二、漏洞原理

理解这两个漏洞,需要先了解 PHP 的请求生命周期。

2.1 PHP 请求生命周期

PHP 处理一个 HTTP 请求时,大致经历以下过程:

  1. 初始化请求环境。
  2. 执行扩展的请求初始化逻辑。
  3. 解析请求参数和上传数据。
  4. 执行 PHP 应用代码。
  5. 执行请求结束清理逻辑。
  6. 释放请求级内存。

PHP-FPM 通常采用 Worker 进程处理多个请求的方式。

这意味着一个 Worker 处理完请求 A 后,并不一定退出,而是继续处理请求 B。

因此,请求之间的状态清理必须足够严谨。如果前一个请求留下了已经失效的内部状态,就可能影响后续请求。

2.2 Session Upload Progress 是什么

PHP 提供了 Session Upload Progress 功能,用于跟踪文件上传进度。

相关配置:

session.upload_progress.enabled = On

当客户端上传 multipart/form-data 请求时,PHP 可以在请求解析过程中记录上传进度,并将相关状态写入 Session。

问题在于,这个功能涉及请求解析阶段的提前初始化,以及 PHP 内部状态的管理。

在特定异常路径下,初始化和清理过程可能出现不一致。

2.3 CVE-2026-109618:OOM 处理异常

OOM 是 Out Of Memory 的缩写,即内存耗尽。

PHP 在处理请求时,如果遇到内存分配失败,可能进入异常处理和资源清理流程。

CVE-2026-109618 的问题在于:OOM 发生时,请求内部数据可能只完成了部分初始化,但后续清理逻辑仍可能将其当作完整有效的数据处理。

这会破坏正常的内存管理流程,带来内存安全风险。

2.4 CVE-2026-109619:Use-After-Free

CVE-2026-109619 涉及 Use-After-Free,简称 UAF。

UAF 指的是:

  • 一块内存已经被释放;
  • 程序仍然保留指向该内存的引用;
  • 后续代码继续访问这块已经失效的内存。

结合 PHP-FPM 的请求处理机制,可以简化理解为:

  1. 请求 A 触发特定异常路径。
  2. 请求 A 的部分清理流程未按预期完成。
  3. 请求级内存被释放,但部分内部状态仍然残留。
  4. 同一个 Worker 接收请求 B。
  5. 后续代码可能使用已经失效的内部状态。

这就是该漏洞的核心问题。

UAF 在特定情况下可能进一步导致内存破坏、信息泄露,甚至被用于构造远程代码执行攻击。

需要强调的是,这不是简单地关闭某个 PHP 函数就能彻底解决的问题,而是 PHP 底层运行时的安全缺陷。

三、官方修复方案

最可靠的方案是升级 PHP。

如果使用的是 PHP-FPM,需要确认实际运行的 FPM 版本,而不是只检查命令行 PHP 版本。

php -v
php-fpm -v

部分发行版的命令可能带有版本后缀,例如:

php-fpm8.3 -v

升级后,还需要重启 PHP-FPM:

systemctl restart php8.3-fpm

具体服务名称根据发行版和 PHP 版本调整。

3.1 临时关闭 Session Upload Progress

如果暂时无法升级,可以先关闭上传进度功能,降低 CVE-2026-109619 相关风险。

在 PHP-FPM Pool 配置中添加:

php_admin_value[session.upload_progress.enabled] = Off

例如:

; /etc/php/8.3/fpm/pool.d/www.conf

[www]

php_admin_value[session.upload_progress.enabled] = Off

修改后重启 PHP-FPM:

systemctl restart php8.3-fpm

也可以在全局 php.ini 中配置:

session.upload_progress.enabled = Off

需要注意:

  • 应在请求解析之前生效。
  • 不要依赖应用代码中的 ini_set()。
  • 不要依赖 FPM 的 .user.ini 实现这一安全配置。
  • 修改后必须重启相关 Worker,确保配置生效。

Apache mod_php 环境可以使用:

php_admin_flag session.upload_progress.enabled Off

Nginx 本身不执行 PHP,因此需要修改 PHP-FPM 配置,而不是只修改 Nginx 配置。

关闭 Session Upload Progress 只是临时缓解措施,不能代替 PHP 升级。

3.2 限制请求体大小

针对 CVE-2026-109618,PHP 官方还建议限制请求体大小,降低异常请求造成内存压力的风险。

PHP 配置示例:

post_max_size = 32M
upload_max_filesize = 30M

如果业务不需要文件上传,可以设置更低的限制。

同时,应在 Nginx、Apache 或上游代理层限制请求体大小。

Nginx 示例:

server {
    client_max_body_size 32m;
}

请求大小限制应根据实际业务调整,并注意代理层、Web Server 与 PHP 配置之间的一致性。

对于复杂的 multipart 请求,还应考虑限制字段数量、文件数量和请求解析规模。

3.3 谨慎处理 memory_limit

PHP 官方针对 CVE-2026-109618 提供了一个临时缓解思路:

memory_limit = -1

其目的是避免由 PHP 可配置内存限制触发相关异常路径。

但这并不意味着底层内存分配失败不会发生。

更重要的是,关闭 PHP 内存限制可能导致单个请求消耗大量内存,影响整个 Worker 或主机。

因此,不建议在生产环境中无条件设置 memory_limit=-1。

如果确实需要采用这一临时措施,应结合容器或 cgroup 的内存限制、Worker 隔离和监控进行评估,避免将单请求的内存问题扩大为整个服务的可用性问题。

四、CVE-2026-115560:后续风险提醒

除了前面两个漏洞,PHP 官方在 2026 年 10 月 23 日又发布了一个相关安全提示,涉及 CVE-2026-115560。

这是一个独立问题,并不是前两个漏洞的简单延伸。

它与 Session 序列化处理器的动态切换有关。

4.1 触发条件

该问题需要满足特定配置组合:

  1. 应用将 session.serialize_handler 设置为 php_binary 或 php_serialize。
  2. 在调用 session_start() 之前,通过 ini_set() 将序列化处理器切换为 php。
  3. session.upload_progress.enabled 仍然处于开启状态。

也就是说,并不是所有 PHP 应用都会受到这个特定攻击路径的影响。

如果应用没有动态切换 Session 序列化处理器,就不具备上述特定触发条件。

4.2 解决方案

PHP 官方建议,在后续常规修复版本发布之前,关闭 Session Upload Progress:

session.upload_progress.enabled = Off

如果使用 PHP-FPM,建议在 Pool 配置中设置:

php_admin_value[session.upload_progress.enabled] = Off

然后重启 PHP-FPM。

同时,建议检查业务代码中是否存在类似逻辑:

ini_set('session.serialize_handler', 'php');
session_start();

如果确实需要动态切换序列化处理器,应重新评估设计,避免在 Session 启动前进行不必要的处理器切换。

不要仅依赖业务代码调整来替代官方建议的临时配置。

截至本文整理时,PHP 官方公告仍将该问题列为后续常规修复事项,应持续关注 PHP 官方安全公告,并在包含修复的版本发布后及时升级。

五、生产环境安全检查

完成升级和配置调整后,建议对生产环境进行一次全面检查。

5.1 确认 PHP-FPM 实际配置

不要只执行:

php --ini

该命令查看的是 CLI SAPI 使用的配置,不一定与 PHP-FPM 一致。

可以通过对应版本的 FPM 程序查看配置:

php-fpm8.3 -i

具体命令取决于系统环境。

重点确认:

session.upload_progress.enabled = Off

5.2 检查是否存在异常行为

如果服务器在漏洞公开前已经对外提供服务,建议进一步检查:

  • Web 目录是否出现未知 PHP 文件。
  • 是否存在异常系统进程。
  • 是否出现可疑 Cron 或 systemd Timer。
  • 是否存在异常外连和网络连接。
  • Web Server、PHP-FPM 和系统日志中是否存在异常请求。
  • 数据库、云服务及其他重要凭据是否可能泄露。

发现入侵迹象时,不应只删除可疑文件。应进一步分析攻击入口、持久化方式和影响范围,必要时重建主机并轮换相关凭据。

需要注意:没有发现异常日志,并不代表服务器一定没有被入侵。

5.3 Docker 环境

如果 PHP 运行在 Docker 中,需要更新 PHP 基础镜像或应用镜像。

例如:

FROM php:8.3-fpm

应确认实际使用的镜像包含官方修复版本。

更新镜像后执行:

docker compose build --pull
docker compose up -d --force-recreate

仅重启旧容器并不会自动获得新版本 PHP。

六、修复优先级

生产环境建议按照以下顺序处理:

优先级操作目的
P0升级到包含官方修复的 PHP 版本完整修复已披露漏洞
P0关闭 session.upload_progress.enabled临时降低相关风险
P1限制 HTTP 请求体和上传规模降低异常请求造成的资源压力
P1检查 Session 序列化处理器使用方式排查 CVE-2026-115560 特定触发条件
P1检查异常进程、文件和网络连接排查潜在入侵
P2完善 PHP-FPM 监控和日志告警提高异常发现能力

七、总结

此次 PHP2Shell 相关漏洞暴露了 PHP 请求生命周期和内存管理中的安全问题。

其中,CVE-2026-109618 涉及 OOM 异常处理,CVE-2026-109619 涉及 Use-After-Free。后续的 CVE-2026-115560 则提醒开发者关注 Session 序列化处理器动态切换与上传进度功能之间的组合风险。

对于生产环境,建议:

  1. 尽快升级 PHP 到包含官方修复的版本。
  2. 在升级前关闭 session.upload_progress.enabled。
  3. 限制请求体大小,合理配置 PHP 内存和容器资源。
  4. 检查 Session 配置及动态切换序列化处理器的代码。
  5. 对漏洞公开前已经暴露的服务器进行安全排查。

安全漏洞的修复不能只停留在修改配置。对于 PHP 运行时本身的安全问题,及时升级、验证实际运行版本,并完成必要的入侵排查,才是完整的处理方式。

参考资料