技术
PHP2Shell:漏洞属实,流传的细节有多处不对
· 据 PHP 官网、PHP 基金会

2026 年 10 月 21 日,PHP 发布紧急更新,修复两个可以在未登录的情况下远程执行命令的漏洞,合称 PHP2Shell。漏洞本身是真的。10 月 20 日先流出去的说法里,严重分数、影响版本、临时开关和原因都有错。
事件经过
- 10 月 20 日约 15:00 UTC,两个编号 CVE-2026-109618、CVE-2026-109619 开始在论坛和社交平台流传。附带的发布时间和严重分数都不对,当时没有技术细节。PHP 基金会事后写明,分数被写成 10.0,实际是 9.2。
- 同日 19:30 UTC,PHP 提前发出预告,并把发布时间从 10 月 22 日 14:00 UTC 改到 10 月 21 日 14:00 UTC。发行版还在打包,立刻公开会让很多人没有现成的升级包。
- 预告之后,报告方之一 Calif 误发了一段演示视频,随后删除。复制件仍在流传,各种演示代码跟着多起来。PHP 安全团队在正式发布时检查过这些代码,没有确认其中有能用的。
- 10 月 21 日 07:41 UTC,Chainguard 在约定时间之前公开了已经打上补丁的容器镜像。PHP 基金会认为这破坏了事先约定,别人可以先研究补丁,而多数用户还在等正式包。
- 10 月 21 日 14:00 UTC,PHP 8.5.12、8.4.27、8.3.36、8.2.35 发布。
同一天还有两句不能并成一句的话。美国 CISA 在通报里说,截至发文时尚未观察到被利用。Cloudflare 则说已经看到攻击尝试。看见尝试,不等于已经确认打穿。
官方回应
PHP 官网和 PHP 基金会的说明是:
- CVE-2026-109618:请求在内存用尽的时机不对时,PHP 可能留下只初始化了一半的内部数据,随后又把它当成有效数据。
- CVE-2026-109619:请求在错误的位置发生致命错误后,内部状态可能还指着上一轮请求已经释放的内存,同一个工作进程处理的下一个请求会用到它。
- 对外提供网页的安装都在范围内,包括 PHP-FPM、Apache 的 mod_php、php-cgi、FrankenPHP 和 LiteSpeed。官方认为风险最高的是 mod_php,并说已经演示:一个未登录的请求可以在应用代码运行之前触发。
- 严重分数是 9.2,不是流传的 10.0。
PHP 安全团队成员 Alexandre Daubois 在 10 月 21 日核对了流传说法。工具横幅写「从 PHP 5.4 起」,还有人把从未发布的 PHP 6 也算进去。官方补丁清单只列 8.2 到 8.5。另一句反复出现的建议是关掉 session.upload_progress.enabled。这项只写在 CVE-2026-109619 里,而且只覆盖它已经确认的会话路径;CVE-2026-109618 的说明没有这一项。把两个洞说成同一个上传进度缺陷,是把两件事折成一件。
应对措施
完整的办法是升级。先看本机版本:
php -v对照关系:
8.5 → 8.5.12
8.4 → 8.4.27
8.3 → 8.3.36
8.2 → 8.2.35Linux 发行版和长期支持厂商提前拿到了补丁,用系统自己的软件源升级,不要凭文章猜包名。PHP 8.1 及更早的版本,PHP 项目本身不再发更新;部分发行版会移植修复。官方另外提供了 7.4、8.0、8.1 的最小源码补丁,给从源码构建、又没有厂商包的人。暂时升不了的,CISA 的建议是先把面向公网的 PHP 服务下线,直到补丁装上并确认生效。
下面是 PHP 官网写明的临时措施。改在 php.ini,或写进应用改不掉的 FPM、Apache 配置里。ini_set() 和 .user.ini 不算。改完要重启全部工作进程。这些只缩小一部分路径,不能代替升级。
; CVE-2026-109619:只挡住已确认的会话路径
session.upload_progress.enabled = 0
; 仅 PHP 8.5:只挡住已确认的 fatal backtrace 路径
fatal_error_backtraces = 0
; CVE-2026-109618:去掉可被这次请求触发的内存上限
; 应用不能再把上限改回去。底层分配失败仍可能走到旧路径
memory_limit = -1官方还提醒,不要用 RLIMIT_AS 或 RLIMIT_DATA 来顶替上面的内存上限,这两种限制本身就可能造成那次有问题的分配失败。
依据:PHP 官网安全公告,PHP 基金会 10 月 21 日说明,Alexandre Daubois 对传言的核对,CISA 10 月 21 日警报。
点评
这件事该信的是「要马上升级」,不该信的是泄露截图里的分数、版本名单和那一句「关一项设置就安全了」。漏洞是真的,严重程度也够高,但把两个不同的洞收成一个原因,再拿一个从未发布的 PHP 6 来凑影响范围,只会让人修错地方。
临时配置只能挡住官方已经点名的一部分路径。对外还在跑 PHP 的机器,以 php.net 上的版本号为准,升到 8.5.12、8.4.27、8.3.36 或 8.2.35。8.1 及更早已经不在 PHP 项目的更新范围内,要么找发行版的移植包,要么换到仍在维护的版本。升不了,就先把面向公网的服务停掉。
Cloudflare 看到了攻击尝试,CISA 在发通报时还没有确认被利用,这两句可以同时成立。转发时不要把「有人在试」写成「已经打穿」。