PHP 紧急安全公告解读:两个 9.2 分 RCE 漏洞,所有 PHP 站点请立即升级
目录
- 一句话先说结论
- 漏洞概览:两个 CVE 都是什么
- 影响范围:你中招了吗
- 漏洞原理:为什么"未授权"就能 RCE
- 修复方案:升级到哪个版本
- 来不及升级怎么办:临时缓解措施
- 给开发者与运维的几点反思
- 结尾:安全是流水线,不是一次性事件
1. 一句话先说结论
如果你运行的是 PHP 8.5/8.4/8.3/8.2 任何分支,且对外提供 Web 服务,请在今天之内升级到对应修复版本:8.5.12 / 8.4.27 / 8.3.36 / 8.2.35。 没有完整缓解措施,升级是唯一安全选择。
2. 漏洞概览:两个 CVE 都是什么
| 项目 | CVE-2026-109618 | CVE-2026-109619 |
|---|---|---|
| 评分 | CVSS v4.0 9.2(Critical) | CVSS v4.0 9.2(Critical) |
| 类型 | RCE via OOM corruption | RCE via stale global state |
| GHSA | GHSA-w8hw-w9fx-j79w | GHSA-6wmf-4rv5-p3rp |
| 触发前提 | 未授权请求即可 | 同一 worker 处理的后续请求 |
| 根因 | OOM 处理中断时请求数据仅部分初始化 | 请求私有状态在内存释放后仍被复用 |
两个漏洞都是未授权远程代码执行——攻击者不需要登录、不需要任何应用层凭证,发一个构造好的 HTTP 请求就可能触发。这是安全等级里最严重的一类。
3. 影响范围:你中招了吗
官方明确列出的受影响部署形态:
- PHP-FPM(最常见,Nginx + FPM 架构)
- Apache with mod_php(风险最高,已有公开可复现的攻击 PoC,未授权请求可在应用代码运行前触发)
- php-cgi
- FrankenPHP
- LiteSpeed
也就是说,只要你的 PHP 在对外接 HTTP 请求,就受影响。CLI 脚本不直接受影响,但只要同一套 PHP 二进制被用于 Web 服务,就必须升级。
最容易忽视的场景:那台"只跑了个内部小工具""只是个测试服"的机器——它们往往 PHP 版本最旧、补丁最不及时,反而最危险。
4. 漏洞原理:为什么"未授权"就能 RCE
两个漏洞都指向同一个根因类型:PHP 内部请求生命周期的"清理—复用"边界出了问题。
CVE-2026-109618(OOM corruption)
当内存耗尽(OOM)发生在请求初始化的中间时刻,PHP 可能被中断在"内部请求数据只初始化了一半"的状态。随后请求清理逻辑会把这部分未完整初始化的数据当作有效数据来处理,攻击者借此让"本不该被信任的内存内容"进入执行路径,最终达成 RCE。
CVE-2026-109619(stale global state)
某些"请求私有"的内部状态,在它的底层内存被释放之后,指针仍然存活。如果同一个 worker 紧接着处理下一个请求,在新请求正常初始化重置这块状态之前,就可能复用了上一个请求遗留的脏状态。攻击者精心构造两个连续请求,就能让第二个请求"踩到"第一个请求留下的可控数据。
这两个漏洞共同的设计教训:在长期运行的 worker 模型里,"请求边界"必须是一道绝对干净的墙。任何"上一个请求的东西漏到下一个请求"的路径,都是 RCE 的温床。这和当年 HTTP/2 流复用、TLS 状态复用的漏洞是同一类问题——复用是性能的好朋友,却是安全的天然敌人。
5. 修复方案:升级到哪个版本
按你当前分支对号入座:
| 当前分支 | 升级到 |
|---|---|
| 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 官方不再维护,需联系发行版看是否有 backport,或升级到受支持分支 |
几点提醒:
- Linux 发行版/LTS 厂商已提前收到补丁,优先用你的包管理器升级(
apt、yum、dnf等),而不是自己编译; - PHP 8.2 将于 2026-12-31 EOL,借此机会直接规划升到 8.3 或更高;
- PHP 7.4 / 8.0 / 8.1 官方提供了最小源码 backport,仅帮助从源码构建或无 LTS 厂商可用的用户,不构成正式支持分支。
6. 来不及升级怎么办:临时缓解措施
官方反复强调:以下措施只能降低暴露面,不能算作完整修复,升级仍是唯一安全选择。
针对 CVE-2026-109618(OOM)
memory_limit = -1,且用php_admin_value(FPM pool 或 Apache 配置)设置,避免被应用覆盖;同时检查没有任何 pool/目录/应用级配置把有限值改回来;- 调小
post_max_size(无需上传设 8M,需上传设 32M),并保持upload_max_filesize < post_max_size; - 在 Web 服务器/反代层限制解码后请求体大小、字段数、multipart part 数、header 数、嵌套深度,且要覆盖没有可用 Content-Length 的请求;
- 用容器或 cgroup 限制做可用性边界,不要用
RLIMIT_AS/RLIMIT_DATA,它们反而会触发漏洞路径的分配失败。
针对 CVE-2026-109619(stale state)
session.upload_progress.enabled = 0并重启所有 worker,用php.ini/ FPM pool / 服务器配置在请求解析前生效,不要依赖ini_set()或.user.ini;- PHP 8.5 上额外设
fatal_error_backtraces = 0并重启 worker; - 移除会在初始化前发出诊断的非法/废弃配置项(用
error_reporting/display_errors/@隐藏没用); - 修复攻击者可触达的 fatal error 和执行超时,包括回调、上传/导入处理与清理中的失败。
一个常被忽视的动作:改完 ini 必须重启所有 worker。FPM 平滑 reload 不一定会重置已存在的 worker 内存状态,这次尤其要彻底重启。
7. 给开发者与运维的几点反思
反思一:把"升级 PHP"做成可一键执行的事。 这次从公告到补丁只隔一天,但很多团队光"找到所有机器上的 PHP 版本"就要半天。把版本巡检和升级做成脚本/流水线,关键时刻能省下最宝贵的时间。
反思二:mod_php 风险常被低估。 公告特别点名 mod_php 风险最高、已有 PoC。如果还在用 mod_php,建议借此机会迁到 PHP-FPM——不仅更安全,资源隔离也更干净。
反思三:临时缓解不是"修复完成"。 这次官方明确说"没有完整缓解"。把 memory_limit=-1 设上就当处理完了,是最危险的心态——缓解措施会让人误以为安全,从而推迟真正的升级。
反思四:EOL 分支要主动淘汰。 PHP 8.1 及更早已经拿不到官方补丁了。还在跑老版本的同学,这次真的没有"再拖一拖"的余地。
8. 结尾:安全是流水线,不是一次性事件
这次 PHP 漏洞给我最直接的感受是:严重漏洞从公告到全网扫描往往只有几小时。能不能在几小时内完成"看到公告 → 定位受影响资产 → 升级 → 验证",靠的不是当天加班,而是平时的自动化程度。
如果你今天只能做一件事,那就先把这台机器上的 PHP 升到修复版本。剩下的反思——版本巡检自动化、mod_php 迁移、EOL 淘汰计划——可以慢慢做,但升级这件事,没有"明天再说"。
行动清单:① 升级 PHP 到修复版本 → ② 彻底重启所有 worker → ③ 验证服务正常 → ④ 排查是否还有 EOL 分支 → ⑤ 把"PHP 版本巡检"加进运维常规项。
- 点赞
- 收藏
- 关注作者
评论(0)