CVE-2026-109619(跨请求状态残留 UAF)与 CVE-2026-109618(OOM longjmp 无效状态消费)
| 风险等级 | 发布日期 | 文档版本 | 适用范围 |
|---|
| 严重 Critical | 2026.10.22 | V1.0 | 所有运行受影响 PHP |
1. 漏洞描述
1.1 CVE-2026-109619 跨请求全局状态残留导致释放后使用(UAF)
PHP worker 进程保留的部分全局状态(错误、会话、对象与扩展状态)可能指向某个请求独享的内存。正常流程会在请求内存释放前重置这些状态;但致命错误(解析/编译失败、未捕获 Error、require 失败、最大执行时间超时、OOM 等)可能使操作中断、跳过配对的重置,或关闭阶段的新告警在状态清理后重新写入。请求堆随后被释放,而 worker 的全局字段仍指向它。
利用需要生产者 + 消费者两个请求命中同一 worker:生产者把请求独享状态发布到全局位置;后续请求在正常初始化之前的某个操作读取/释放/分支该悬垂状态(已确认的两类消费者:初始化前的 INI 诊断、会话上传进度处理)。精心构造堆布局可实现完整 RCE。
- 已确认案例 A(PHP 8.5):开启 fatal_error_backtraces 时,致命错误的回溯状态始终错过关闭阶段重置 ——mod_php 已确认 RCE 的基础路径。
- 已确认案例 B:会话上传进度(session upload progress,默认启用,无需应用调用 session_start() )在正常初始化前即可触碰会话/解码器状态 —— mod_php 与 FPM 均已验证 RCE。
1.2 CVE-2026-109618 OOM longjmp 使请求内存处于无效状态
PHP 对内存耗尽(OOM)使用 longjmp() 跳出当前上下文。某些上下文中请求内存在完全初始化前即暂时可达,此时任一分配失败(无需与无效内存相关)都会经 longjmp 提前退出,使请求内存处于无效状态;请求关闭流程随后读取或据此分支。多种 OOM 策略可稳定触发并导致 RCE。
- 无可用地声明 Content-Length 的 multipart 请求可通过 post_max_size 初始检查后持续供给解码数据;
- 单个 multipart part 可含无限多头部,PHP 内部表示的内存开销远大于线上体积,可在 post_max_size 之内耗尽memory_limit;
- 空文件控件不计入 max_file_uploads 但仍生成完整元数据数组,嵌套字段名成倍放大开销。
利用前提
- 先用利用CVE-2026-109618触发OOM
- 再利用CVE-2026-109619实现攻击
- OOM生产者与OOM消费者请求必须命中同一worker。
- 攻击命中前,worker未被回收过。
2. 缓解措施
全局配置 (php.ini)
| 措施 | 针对 | 要点 |
|---|
| memory_limit = -1 | CVE-2026-109618 | 通过避免可预测的OOM路径来阻断击。 |
| max_input_nesting_level = 16 | CVE-2026-109618 | 限制外部输入变量的最大嵌套深度,安全加固。 |
| max_file_uploads = 8 | CVE-2026-109618 | 单次请求中允许同时上传的最大文件数量,安全加固。 |
| post_max_size | CVE-2026-109618 | 限制上传文件的大小,该配置影响在线升级功能,可在需要时临时调整回来。 |
| session.upload_progress.enabled= 0 | CVE-2026-109619 | 阻断已验证的早期会话生产者/消费者。 |
⚠ memory_limit = -1 的把 memory_limit 设为 -1(无限制),并不会改变原本脚本的内存占用行为,页面加载速度、CPU 占用、响应时间都不会因此变快或变慢,但系统失去了对失控脚本的最后一道软性约束,极端情况下可能触发系统级 OOM Killer。
3. 配置示例
php.ini:
Last modified on October 22, 2026