今天(10 月 21 日)14:00 UTC,PHP 官方发布了两个 CVSS v4.0 评分 9.2 的安全补丁。
但这不是一次正常的协同披露。原定 10 月 22 日的发布计划,因为信息在补丁可用前就被泄露,被迫提前了一天。而安全公司 Sansec 的判断更激进:补丁发布后约 15 分钟,大规模攻击就会开始。
这个数字背后逻辑很简单:利用代码(代号 php2shell)早就在那了,只是被道德约束压着;一旦官方公告确认影响范围,武器化成本趋近于零。
这篇文章拆四件事:泄露是怎么发生的、漏洞大概率在哪、为什么这次特别麻烦、以及你现在该做什么。
一、时间线:一次被打破的 embargo
协同披露(coordinated disclosure)的核心价值,是让发行版和托管商在公告发布的同一时刻就能分发补丁。这个缓冲一旦消失,就会出现一个无补丁的裸奔窗口。
这次事件的时间线:
| 时间(UTC) | 事件 |
|---|---|
| 10-20 之前 | 漏洞处于 embargo,原定 10-22 协同披露,发行版已拿到补丁 |
| 10-20 晨 | Hacker News 出现 "Tell HN" 帖,引用"可靠消息源"称有影响 PHP 5+ 的 RCE,发帖者自认没证据 |
| 10-20 | 帖子被 HN 下线,但截图已在 X / Mastodon 扩散,Kevin Beaumont 等人转发 |
| 10-20 | 研究员 Kirill Firsov 放出演示视频,攻击链命名 php2shell,署名 LCFR 与 Calif.io |
| 10-20 | watchTowr 确认漏洞真实,复现了 CVE-2026-109618 |
| 10-20 | PHP 安全团队发预警,补丁提前到 10-21 14:00 UTC |
| 10-20 | CERT-EU 发布公告 2026-018 |
| 10-21 | 补丁落地:PHP 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 |
PHP 官方公告原文写得很克制:
我们保留在漏洞细节公开、或出现野外利用证据时提前发布的权利。
这句话在 10-20 就兑现了。
二、漏洞大概率在哪:session upload progress 的 UAF
先说清楚:截至本文写作,PHP 官方尚未公布 root cause。以下是社区分析(奇安信、上海交大网络信息中心等)的技术假设,最终以官方公告为准。
2.1 攻击面:php_session_rfc1867_callback
分析指向 session upload progress 功能的处理路径,核心函数 php_session_rfc1867_callback(位于 ext/session/session.c)。
这个功能是 PHP 5.4 引入的,用于让前端显示上传进度条。它的工作机制有三个特点,叠加起来很危险:
- 客户端在
multipart/form-data请求里带上PHP_SESSION_UPLOAD_PROGRESS字段,PHP 在解析 multipart 请求体的过程中(不是处理完之后)就开始写 session 数据; - 进度更新发生在应用脚本执行之前——也就是 RINIT 之后、你的代码运行之前;
- 该功能由
session.upload_progress.enabled控制,php.ini 默认值是 On。
默认开启 + 不需要应用写任何代码 + 解析请求时就触发 —— 这三个条件意味着,大量"从没用过进度条"的部署也在攻击面里。
2.2 机理:生命周期错位导致的 UAF
php_session_rfc1867_callback 在 multipart 解析过程中会触发多次 session 状态切换(save/open/close 与引用计数操作)。在特定请求顺序和状态组合下:
- 某些 session 相关内存对象(session 结构、上传进度元数据)在后续处理到达前被提前释放;
- 随后的进度更新逻辑仍持有已释放对象的引用,再次访问形成 Use-After-Free;
- 观测特征:release 构建下表现为 PHP 工作进程崩溃(FPM master 重启,看起来像"上传失败");debug/ASAN 构建下能看到明显的引用计数异常。
奇安信把成因映射到 CWE-94(代码注入) 与 CWE-787(越界写入)。这个组合的读法是:底层是 UAF 类内存破坏,越界写是 UAF 被利用后的典型效果,顶层表现才是任意代码执行。
UAF 能否稳定利用,取决于堆布局可控性。而在 session upload progress 场景下,攻击者通过控制请求体大小、multipart 分片、并发连接,可以相当程度地操控堆分配序列(heap grooming)——这正是历史上大量 PHP UAF 能被稳定武器化的原因。
2.3 为什么有 2 个 CVE
目前无法确认 CVE-2026-109618 与 CVE-2026-109619 的确切对应关系。合理推测是:同一回调路径上的两个独立缺陷(比如 open handler 和 update handler 各一处),或者触达同一 UAF 的两条不同路径。
一个旁证:php2shell 演示视频引用的受影响版本从 PHP 5.4.0 起,而 5.4.0 恰好就是 session upload progress 引入的版本。时间线上完全自洽。
2.4 触发条件
CERT-EU 说漏洞可能允许无需认证的远程代码执行。这与攻击面分析一致——触发只依赖 HTTP 请求本身,不依赖业务逻辑或登录态。
需要满足:
- 能向目标 PHP 服务发 HTTP 请求(即公网可达);
- PHP 版本受影响,且
session.upload_progress.enabled未关闭(默认开启); - 若配置过
session.upload_progress.prefix/name,字段名需匹配(默认配置下都能满足)。
但请注意:这些是从攻击面推导的推断。在官方公告出来前,不能因为"我的配置不符合"就断定安全。
三、为什么这次特别麻烦
3.1 补丁真空:EOL 分支没得打
| PHP 分支 | 当前版本(2026-09-24) | 修复版本 | 状态 |
|---|---|---|---|
| 8.5.x | 8.5.11 | 8.5.12 | 安全支持中 |
| 8.4.x | 8.4.26 | 8.4.27 | 安全支持中 |
| 8.3.x | 8.3.35 | 8.3.36 | 安全支持中 |
| 8.2.x | 8.2.34 | 8.2.35 | 仅安全修复 |
| 8.1 及更早 | 8.1.33(2025-12-31 EOL) | 无补丁 | 已 EOL |
| 7.x / 5.x | — | 无补丁 | 已 EOL |
三个要点:
- "影响 PHP 5+ 所有版本"来自泄露信息(php2shell banner 和 HN 帖),PHP 官方从未证实。但结合疑似触发点在 5.4 引入的功能上,这个范围有技术合理性。
- 官方补丁只覆盖受支持的 8.x 分支。PHP 5/7/8.0/8.1 处于补丁真空——EOL 系统如果公网可达,唯一安全选项是迁移或隔离。
- 用 apt/yum 装的 php-fpm 别自己编译。发行版通常会给旧分支做 backport,应盯 Debian/Ubuntu/RHEL 的 DSA/USN/RHSA,而不是 php.net 的版本号。
3.2 补丁的"物理位置"很麻烦
PHP 是 WordPress(全球约 40% 网站底层)、Drupal、Joomla、Magento、Laravel、MediaWiki 以及绝大多数共享主机的运行时。有非官方估计称互联网上直接暴露的 PHP 主机约 130 万台量级。
但比主机数量更麻烦的是补丁要打在哪:
- 应用层漏洞(某个 WordPress 插件 RCE):升级插件即可,影响面限于用这个插件的人;
- PHP 核心漏洞:修复点在服务器 / 容器 / 镜像层面。
这意味着 WordPress 站长常用的"一键更新插件"完全无济于事。你必须触达:每一个 FPM 容器、每一个主机镜像、每一台内嵌 PHP 的第三方设备(NAS、负载均衡器、备份一体机里都可能藏着一份 PHP)。
Huntress 特别提醒要排查厂商软件内嵌的 PHP —— 这类资产通常没有版本管理责任人,恰恰最容易漏。
四、现在该做什么
立刻(补丁前 / 无法立即升级时)
① 关闭 session upload progress(当前最有效的临时措施)
绝大多数业务根本不用上传进度条。在你的 php.ini、.user.ini 或 .htaccess 里:
session.upload_progress.enabled = Off
然后重载 FPM:
systemctl reload php8.3-fpm # Debian/Ubuntu
# 或
systemctl reload php-fpm # RHEL/CentOS
这条切断的是已验证的攻击路径,但不能替代补丁。
② 网关层拦截
在 WAF / 反向代理层,保护那些本来就不需要文件上传的端点。可以拦截请求体含 PHP_SESSION_UPLOAD_PROGRESS 的请求。代价是会误伤真正用进度条的业务,需评估。
③ 隔离 EOL 分支
PHP 8.1 及更早版本立即下线公网暴露面,改走 VPN / IP 白名单,直到完成迁移。
④ 保留并监控日志,重点看:
- PHP-FPM worker 异常退出(segfault)、Web 崩溃——UAF 利用失败的典型痕迹是大量 worker 无故重启;
- PHP 进程派生的异常子进程、异常文件写入(WebShell 落盘特征);
- 高频、畸形、含
PHP_SESSION_UPLOAD_PROGRESS的 multipart 访问记录。
补丁发布后(T+0 ~ T+1h)
- 只认 php.net 官方公告的受影响版本与修复版本,不信第三方转述
- 按资产清单灰度推送,优先公网暴露面
- 发行版用户盯 DSA/USN/RHSA;自编译用户从 php.net 拉源码
- 升级后验证
php -v实际生效 —— FPM reload ≠ restart,注意 opcache 和长连接 worker
后续(T+1h ~ T+7d)
- 基于上面的特征做日志狩猎,排查 10-20 以来的可疑 multipart 流量
- 关注 CISA KEV 目录的后续确认,修正技术假设
- EOL 分支制定迁移时间表,别把"临时隔离"变成永久状态
五、几点想法
Embargo 机制比想象中脆弱。 这次泄露源头只是一篇"无法定位原文"的报告,加一条自认没证据的 HN 帖。信息一旦进入口头传播链,embargo 就名存实亡。PHP 团队选择提前一天发补丁而不是硬扛原时间表,是正确的危机处理——披露纪律已被打破时,缩短裸奔窗口比维护流程仪式更重要。
"准备型公告"正在成为新范式。 在补丁还用不了的时候提前 48 小时发"prepare now",这在 PHP 历史上很少见。但它承认了一个现实:从公告到武器化的时间已经从数周压缩到分钟级,防御方唯一能准备的时机在公告之前。
EOL 长尾的清算时刻。 每次这种事件都在给"还能跑就行"的系统记账。8.1 及以下无补丁可打,运营方被迫在漏洞窗口和业务连续性之间选——而这个选择本该在版本 EOL 那天就做完。
信源纪律。 这次网上流传的 CVSS 10.0(官方是 9.2)、"所有版本受影响"(实际只有受支持分支有补丁),落差再次说明:以官方公告为准,对泄露信息保持"合理怀疑 + 按最坏情况准备"的双重姿态。
参考来源
- PHP 官方公告:Upcoming Critical PHP Security Release(php.net,2026-10-20)
- Tenable:php2shell (CVE-2026-109618, CVE-2026-109619) Critical PHP RCE FAQ
- Huntress:Rapid Response: php2shell, Leaked Critical PHP Vulnerabilities
- Beazley Security Labs:BSL-A1233 Advisory
- CERT-EU Advisory 2026-018
- 奇安信安全内参:PHP 远程代码执行漏洞安全风险通告
- 上海交通大学网络信息中心:关于 PHP Core 存在远程代码执行漏洞的风险预警
- Sansec:PHP2Shell Is Coming: Your Patch Window Is 15 Minutes
⚠️ 免责声明:本文成文于补丁发布当日,其中 session upload progress / UAF 部分来自社区分析,尚未经 PHP 官方确认,请在官方公告发布后核验修正。文中配置与命令仅供自有系统防御性使用,请勿用于未授权测试。任何因滥用造成的问题由使用者自负。
如发现漏洞,请通过官方渠道(security@php.net)报告。
浙公网安备 33010602011771号