本文转载自微信公众号「表哥带我」
原文标题:PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相
内容版权归原作者及原公众号所有,转载仅为传播资讯;若有侵权请联系管理员删除。
2026 年 10 月 21 日,PHP 发了四个安全版本:8.5.12、8.4.27、8.3.36、8.2.35。
![图片[1]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/c12267455520261024122639.jpg)
图 1:PHP 官方归档中的 2026 年 10 月 21 日公告。来源:PHP News Archive,截图时间 2026-10-22 10:28 CST。
修的是两个未认证远程代码执行漏洞。PHP 安全团队给它们的命名分别是:
-
CVE-2026-109618:RCE via OOM corruption
-
CVE-2026-109619:RCE via stale global state
社区后来把它们合称为 PHP2SHELL。两个漏洞的官方 CVSS v4.0 向量一样:
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
基础评分 9.2,Critical,可远程,无需授权,造成RCE,但利用复杂度高,还需要额外的攻击前置条件。对下游关联系统,官方没有确认直接影响。
一时间舆论甚嚣尘上,但它既非真正的“核弹”,也非无用的“玩具”——这两个洞的实际判断从两个角度来说:①一旦打中,后果有多重;②打中的难度有多大。
版本和影响面
漏洞与修复版本
![图片[2]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/a6bff0dd9a20261024122640.png)
PHP 8.1 及更早分支已经 EOL,所以官方 advisory 的修复版本表只覆盖上面四个受支持分支。
PS: Debian、Ubuntu、RHEL、AlmaLinux、Rocky Linux 以及各类 LTS 厂商经常保留上游版本号,只回填安全补丁。现场得看包 changelog、厂商公告或构建时间。PHP 8.3.x 不能直接判安全,旧版本号也不能直接判有问题。
哪些 PHP 运行时暴露
PHP 官方和 CERT-EU 的口径都很直接:所有对外提供 Web 服务的 PHP 运行时,都该纳入排查。mod_php、PHP-FPM、php-cgi、FrankenPHP、LiteSpeed 这些 SAPI 都在范围内。
风险最高的是 Apache mod_php。php_request_startup() 失败以后,mod_php 仍可能进入 request shutdown。
FPM 得分开看。请求启动失败时,FPM 通常会终止异常 child,所以官方没有给出和 mod_php 完全相同的、应用无关的启动阶段利用链。源码分析仍把 FPM 算在受影响面里:应用执行阶段触发的 OOM,仍可能走到错误清理路径。
109619 的 session upload progress 链已经在 FPM 上验证过。它通常要求前一个请求在正常启动后执行到某个合适的应用操作,再触发 fatal error。这个条件比 mod_php 的启动阶段链多一步,不能拿一句“FPM 已验证”省略。
受影响的也不只是网站。网关、NAS、防火墙管理口、虚拟化管理面板、打印设备、工控 appliance,以及把 PHP 打进镜像的商用产品,只要运行时旧,都该按“可能未认证 RCE”处理。
9.2 和 9.8 怎么来的
PHP 安全团队给的是 CVSS v4.0 9.2。NVD 同时给了自己的 CVSS 3.1:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
NVD 3.1 评分是 9.8。两个分数的评价模型不同,复杂度判断也不同。它们描述的还是同一组漏洞。内部工单可以优先采用 PHP 官方 v4.0 向量,风险说明里保留 NVD 3.1 分数,免得业务方看到 9.2 就把它当成普通高危。
![图片[3]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/b2aa1881e720261024122642.jpg)
图 2:CVE-2026-109618 的 NVD API 返回。CVSS v4.0 为 9.2,CVSS v3.1 为 9.8。来源:NVD REST API。NVD 详情页在当前网络下无法稳定渲染,图中数据按官方 API 原响应本地格式化。
![图片[4]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/ce8a86c67b20261024122643.jpg)
图 3:CVE-2026-109619 的 NVD API 返回。CVSS v4.0 为 9.2,CVSS v3.1 为 9.8。来源:NVD REST API。
把 v4.0 向量拆开看,扣分项其实就那几个:
![图片[5]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/6ed56729a420261024122644.png)
AC:H 和 AT:P 不能略过。网上出现完整 RCE 利用,不等于每个请求都能成功。worker 调度、堆布局、PHP 构建、扩展、SAPI、配置和前端限制,都会改变成功率。
两个漏洞到底坏在哪
CVE-2026-109618:OOM 会直接跳出去
PHP 旧路径处理内存耗尽时,会调用 longjmp() 一类 bailout 机制,从 allocator 的错误现场直接跳回请求边界。
正常异常退栈会逐层执行清理逻辑。longjmp() 不会。
![图片[6]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/221908027420261024122645.jpg)
图 4:CVE-2026-109618 官方 advisory 页面,标题为 RCE via OOM corruption。来源:GHSA-w8hw-w9fx-j79w。
请求启动阶段很敏感。PHP 正在解析 multipart/form-data,$_POST、$_FILES、数组键、文件元数据和 session upload progress 等结构正在逐步建立。此时某块 request memory 可能已经挂到内部结构中,但还没有完成初始化。
如果这时发生一次 OOM,即使失败的那次分配和这块半初始化内存没有直接关系,执行流也会被提前拽走。状态链大概是这样:
|
multipart 解析 |
在 mod_php 上,request startup 失败以后,request shutdown 仍可能继续跑。攻击者可以用 HTTP 请求控制 OOM 前的堆布局,让 shutdown 去消费伪造的 zval、HashTable 或其他内部结构。最后落到函数指针,命令也就执行了。
补丁改了什么
核心提交是:
|
3584a98bda0f2c0d367255b046798b0d3a221a19 |
![图片[7]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/94bca3378620261024122647.jpg)
图 5:官方补丁提交 3584a98,提交说明同时列出两个 GHSA。来源:php-src commit 3584a98。
提交说明直接写了它同时修复两个 advisory。改动集中在 OOM 退出语义,没法靠某一个 multipart 分支里的 NULL 判断解释:
-
软 OOM 改为 delayed OOM。allocator 不再立刻 longjmp(),而是记录 pending 状态,在下一个 VM safe point 正常处理。
-
如果内存继续增长到更高的 hard limit,则使用 _exit() 终止进程,避免再回到不确定的 shutdown 状态。
-
请求解析中的关键分配改为 fallible 路径,允许上层停止解析并正常清理。
-
只保留 multipart 真正需要的 Content-Disposition 和 Content-Type,重复 header 不再全部长期保留。
-
request shutdown 清理 PG(http_globals)、last error、module activation 等可能在 startup 失败后仍被访问的状态。
-
新增加 php_basic_early_rinit(),在请求早期重新初始化此前可能被前置流程使用的序列化、反序列化和 URL scanner 状态。
改动铺得这么大,是因为它同时碰到 Zend Memory Manager、VM 中断点、request lifecycle、multipart parser 和 session 全局状态。每个位置都牵着请求生命周期的另一端。
CVE-2026-109619:上一条请求留下的指针
109619 的入口在 worker 的全局位置。那里缓存了一个 request-owned memory 的地址。请求结束后,这块内存会释放,worker 进程却还在,地址也留在原处。下一条请求只要在正常初始化覆盖它之前碰到这段状态,就可能出现 use-after-free。
![图片[8]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/1d71368f5320261024122648.jpg)
图 6:CVE-2026-109619 官方 advisory 页面,标题为 RCE via stale global state。来源:GHSA-6wmf-4rv5-p3rp。
PHP-FPM 和 Apache prefork 都会让长期存活的 worker 连续处理多个请求。一个请求结束后,request heap 会被释放,worker 进程不会退出。正常情况下,RINIT、RSHUTDOWN 和模块 lifecycle 会把全局引用逐个清空。异常路径可能断掉这条清理链。
官方把它拆成 producer 和 consumer:
|
请求 A(producer) |
成功利用至少要同时满足五件事:
-
攻击者可达的 producer。
-
reset 被跳过,或者 reset 之后又被 shutdown 诊断重新填回。
-
worker 不退出,request heap 被释放。
-
后续请求命中同一个 worker。
-
正常初始化前存在 consumer。
真打起来,卡在哪
首先,这两个漏洞都是未授权的RCE。
Wiz 的披露材料把影响演示到了 WordPress、Drupal 和 Joomla 的容器镜像上。
![图片[9]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/451dcdb75320261024122650.jpg)
图 7:Wiz Research 展示的已确认影响,包括未认证内存泄露和预认证 RCE。来源:PHP2Shell: AI uncovers critical RCE vulnerabilities affecting 70% of the Internet。
但他的原文中提到:①攻击者可以远程利用,某些情况下“fairly easily”。②完整利用要串联多个缺陷,还得以目标为样本反复调整堆布局。
所以入口可以很容易,终点不一定容易——未认证和无需交互降低了尝试成本,堆布局、二进制适配和 worker 调度又把成功门槛抬了上去。
CVE-2026-109618
109618 的确认利用已经通过 HTTP 打到 Apache mod_php。官方写的是默认 PHP 输入限制、默认内存限制,以及正常的多 worker prefork 配置。
但,“能打到那条路径”和“每个站都能稳定拿到命令执行”是两码事。官方明确说,可移植性和可靠性取决于 PHP 构建、扩展、前端行为和 allocator 布局。所以 109618 在互联网可达的旧版 mod_php 上建议按照真实 RCE 风险处理。
而对于FPM,官方没有给出 109618 的完整利用。请求启动失败时,FPM 通常会终止 child,刚好把 mod_php 那条“startup 失败后继续 shutdown”的路截短。源码分析仍认为,应用执行阶段触发的 OOM 可能进入错误清理路径,但这和前面的 startup 链不是同一个实战入口。
FrankenPHP 在源码行为上更像 mod_php,被官方列为可能受影响;LSAPI 更像 FPM,但官方没有验证完整利用。看到 FPM 就写“安全”不对,看到 PHP 就写“都能一把打”也不对。
CVE-2026-109619
109619 则更看运气。
完整条件至少包括:
-
请求 A 能触发 producer,并制造 fatal error、OOM、超时或清理阶段的诊断。
-
该请求结束时,匹配的 reset 没有执行,或者 reset 之后又被诊断信息填回。
-
request heap 被释放,worker 继续存活。
-
请求 B 命中同一个 worker。
-
正常初始化之前,有 consumer 读取、释放、分支或调用悬空状态。
在现实场景中,显然攻击者不能直接指定 worker,此时,请求 A 和请求 B 可能被不同 child 接走。worker 越多,尝试次数越多,但 A/B 落回同一个进程也需要调度配合。
官方确认了两条比较实用的 consumer。PHP 8.5 的 fatal_error_backtraces 开启时,可以把 fatal backtrace 留在 worker 全局状态里,下一条请求在早期产生诊断时碰到它;另一条是 session.upload_progress,它默认开启,不需要业务调用 session_start(),可以在普通 session 初始化之前进入 session 和 decoder 状态。
mod_php 可以在 multipart startup 阶段同时完成 producer 和 interruption,所以业务代码可以完全不参与。FPM 在 startup 失败时会杀掉 child;已确认的 FPM session 链要在应用正常启动后执行到合适操作,再触发 fatal error,最后由后续请求的 upload progress 消费。
![图片[10]-PHP2SHELL:真正的核弹还是虚假的“核弹”——关于网传核弹级 PHP 漏洞,剥开噱头看真相-阻击者联盟](https://blog.h-acker.cn/wp-content/uploads/2026/10/c25618263520261024122652.jpg)
图 8:Wiz Research 对利用构造、堆布局适配和重复调试的描述。来源同上。
排查和修补方式
确认资产和补丁状态
优先级从高到低:
-
互联网可达的 Apache mod_php。
-
多租户 PHP-FPM pool、共享 session 存储、统一登录入口。
-
文件上传、工单附件、头像、导入功能明显的应用。
-
容器镜像、Helm chart、基础镜像和 CI/CD 中的 PHP runtime。
-
网关、NAS、管理面板、虚拟化平台和厂商 appliance。
检查命令至少包括:
|
php -v upload_max_filesize|max_input_vars|max_input_nesting _level|max_file_uploads|max_multipart_body_parts| session.upload_progress|fatal_error_backtraces’ apache2ctl -M | grep php |
php -v 只能当一个入口。容器还要看镜像 digest、构建时间、包 changelog,以及实际运行进程加载的 libphp.so/php-fpm 路径。
打补丁
目标版本:
|
PHP 8.5.12 |
发行版提供的等价安全包也可以。
落地时,需要注意:
-
更新包以后必须滚动重启或重建所有 worker、Apache child 和容器。
-
多阶段构建镜像要确认最终镜像里的 runtime 被更新,builder 更新不算。
-
FPM master 不会因为替换磁盘上的 .so 自动加载新代码,必须 reload/restart。
缓解措施
以下措施都替代不了补丁,但可以应急。
1、所有 SAPI
-
在反向代理、API Gateway、Ingress 和 WAF 上限制解码后的请求体大小。
-
对 multipart 限制 part 数、单 part header 数、单 header 长度、字段嵌套深度和文件控件数量。
-
明确处理 chunked request、缺失 Content-Length、伪造或冲突的 Content-Length。
-
如果业务不需要 multipart,直接在 PHP 之前拒绝 multipart/form-data。
-
把前端限制和 PHP 自身 post_max_size、max_input_vars、max_input_nesting_level、max_file_uploads、max_multipart_body_parts 同时收紧。
-
让每个 worker 或小型 worker 组有独立 cgroup 内存边界,避免一个容器杀 master 和所有 child。
-
不要把 RLIMIT_AS、RLIMIT_DATA 当成修复手段。底层 mmap() 失败同样可能触发旧版 longjmp() 路径。
2、针对 109618
-
无法升级时,官方给出的首要配置缓解是启动级设置并强制执行 memory_limit=-1。
-
检查 FPM pool、Apache php_admin_value、.user.ini、控制面板和框架启动脚本,确认没有重新恢复有限值。
-
memory_limit=-1 仍不是完整修复。物理内存、cgroup、mmap() 或其他底层分配失败,仍可能触发漏洞路径。
-
如果不使用上传,优先在前端阻断 multipart。必须上传时,把 post_max_size 保持在业务真正需要的范围内,并让 upload_max_filesize 更低。
-
对无文件上传业务,可先把 post_max_size 压到接近普通表单大小。有上传业务时,避免继续沿用 100M、512M 这类省事配置。
3、针对 109619
-
在启动配置中设置 session.upload_progress.enabled=0,然后重启全部 worker。
-
不要依赖 ini_set()、.user.ini、运行时路由或管理后台开关。这些设置可能晚于漏洞触发点。
-
PHP 8.5 额外设置 fatal_error_backtraces=0,阻断已确认的 fatal backtrace producer。
-
清理会在请求早期产生 warning、notice、deprecation 的无效 INI、过时配置和扩展参数。
-
修复攻击者可达的 fatal error、解析错误、未捕获异常和 Maximum execution time exceeded 路径。
-
性能允许时,把 pm.max_requests=1 作为缩小跨请求利用窗口的减害措施。它会显著增加进程创建成本,也可能掩盖其他问题。
关闭 session.upload_progress 只阻断已确认的 session consumer。它不会修复 109618,也覆盖不了 109619 的其他 extension 或 error state。
4、添加日志告警规则
建议把下面这些 PHP 日志模式加入临时告警:
|
Allowed memory size of .* exhausted |
除此之外,还可以关注:
-
Apache/FPM child 异常退出、SIGABRT、segfault、频繁 respawn。
-
同一客户端在短时间内发送超大 multipart、超多 part、超长 header 或大量 upload progress 字段。
-
max_input_vars warning 与后续 OOM 连续出现。
-
Set-Cookie: PHPSESSID 异常变长、包含不可打印字符或二进制样式内容。
-
FPM pool 在低业务量时快速耗尽。
-
新出现的 www-data、apache、nginx、php-fpm 子进程、cron、systemd timer 或文件写入。
WAF 只能做补偿控制。实际利用可能只使用结构合法、内容看起来像普通表单的 HTTP 请求。单靠一个 multipart 特征签名,不能说明请求安全。
5、对于应急响应
-
隔离对应实例和共享存储,保留内存、进程树、网络连接、日志和容器层。
-
轮换 worker 可读的所有数据库、对象存储、API、CI/CD 和第三方服务凭据。
-
检查 /tmp、上传目录、session 目录、webroot、cron、systemd、SSH authorized_keys、容器挂载和 Kubernetes service account。
-
检查 worker 到内网管理口、Redis、数据库和云元数据服务的异常连接。
-
不要只删除一个可疑文件就恢复服务。完整 RCE 通常伴随凭据获取和持久化。
参考来源
-
PHP 官方发布归档,用于核对 2026 年 10 月 21 日、四个修复版本和风险口径:https://www.php.net/archive/2026.php
-
CVE-2026-109618 官方 advisory,用于核对 RCE via OOM corruption、影响版本和补丁版本:https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
-
CVE-2026-109619 官方 advisory,用于核对 RCE via stale global state、producer/consumer 条件和补丁版本:https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
-
官方补丁提交 3584a98bda0f2c0d367255b046798b0d3a221a19,提交说明同时引用两个 GHSA:https://github.com/php/php-src/commit/3584a98bda0f2c0d367255b046798b0d3a221a19
-
NVD CVE-2026-109618 详情页:https://nvd.nist.gov/vuln/detail/CVE-2026-109618
-
NVD CVE-2026-109619 详情页:https://nvd.nist.gov/vuln/detail/CVE-2026-109619
-
NVD REST API,CVE-2026-109618 原始响应:https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-109618
-
NVD REST API,CVE-2026-109619 原始响应:https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-109619
-
CERT-EU / NCSC-NL 运营信息和缓解建议:https://github.com/NCSC-NL/php2shell
-
Wiz Research 披露材料,用于核对已演示影响、利用构造过程和目标适配成本:https://www.wiz.io/blog/php2shell-php-rce
-
oss-security CVE-2026-109618 公告:http://www.openwall.com/lists/oss-security/2026/10/21/6
-
oss-security CVE-2026-109619 公告:http://www.openwall.com/lists/oss-security/2026/10/21/7
你对这个事件怎么看?对于漏洞修复,你有什么建议?欢迎在评论区分享。
— 阅读原文请访问微信公众号「表哥带我」 · 原文链接 —














暂无评论内容