PHP 近期披露的 PHP2Shell 相关漏洞值得所有 PHP 服务维护者关注。它并不是常见的应用层 SQL 注入或文件上传漏洞,而是涉及 PHP 请求生命周期、Session 扩展以及底层内存管理的问题。
攻击者在特定条件下,可以通过构造 HTTP 请求触发内存异常,进一步造成内存安全问题,甚至可能发展为远程代码执行(RCE)。
本文重点介绍漏洞原理、影响范围以及生产环境中的修复方案,并补充后续披露的 CVE-2026-115560 风险提醒。
一、漏洞概述
此次 PHP2Shell 相关问题主要涉及两个漏洞:
| 漏洞编号 | 核心问题 | 风险 |
|---|---|---|
| CVE-2026-109618 | OOM(内存耗尽)处理过程中的异常清理问题 | 可能导致内存安全问题 |
| 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.5 | 8.5.12 |
| PHP 8.4 | 8.4.27 |
| PHP 8.3 | 8.3.36 |
| PHP 8.2 | 8.2.35 |
优先建议升级到对应分支的修复版本,或者升级到仍受支持且包含安全补丁的更高版本。
PHP 8.1 及更早版本已不再由 PHP 上游常规维护。如果仍在使用,需要确认发行版或商业供应商是否提供了安全补丁;长期来看,应迁移到受支持的 PHP 版本。
二、漏洞原理
理解这两个漏洞,需要先了解 PHP 的请求生命周期。
2.1 PHP 请求生命周期
PHP 处理一个 HTTP 请求时,大致经历以下过程:
- 初始化请求环境。
- 执行扩展的请求初始化逻辑。
- 解析请求参数和上传数据。
- 执行 PHP 应用代码。
- 执行请求结束清理逻辑。
- 释放请求级内存。
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 的请求处理机制,可以简化理解为:
- 请求 A 触发特定异常路径。
- 请求 A 的部分清理流程未按预期完成。
- 请求级内存被释放,但部分内部状态仍然残留。
- 同一个 Worker 接收请求 B。
- 后续代码可能使用已经失效的内部状态。
这就是该漏洞的核心问题。
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 触发条件
该问题需要满足特定配置组合:
- 应用将
session.serialize_handler设置为php_binary或php_serialize。 - 在调用
session_start()之前,通过ini_set()将序列化处理器切换为php。 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 序列化处理器动态切换与上传进度功能之间的组合风险。
对于生产环境,建议:
- 尽快升级 PHP 到包含官方修复的版本。
- 在升级前关闭
session.upload_progress.enabled。 - 限制请求体大小,合理配置 PHP 内存和容器资源。
- 检查 Session 配置及动态切换序列化处理器的代码。
- 对漏洞公开前已经暴露的服务器进行安全排查。
安全漏洞的修复不能只停留在修改配置。对于 PHP 运行时本身的安全问题,及时升级、验证实际运行版本,并完成必要的入侵排查,才是完整的处理方式。