Security brief · 2026 年 10 月 22 日
PHP2Shell:两个 PHP 核心漏洞的现状与处置
回答四个问题:这两个漏洞是什么,有没有人在攻击,exploit 传开了没有,现在该怎么修、怎么挡。给运维 PHP 站点的人看。
先说结论
PHP 于 2026 年 10 月 21 日修复了两个核心漏洞,统称 PHP2Shell,CVSS v4.0 均为 9.2,可在应用代码运行之前拿到 Web 进程权限1。在野攻击流量已被 Cloudflare 和 watchTowr 确认,但大规模成功入侵没有被证实34。公开 PoC 在流传,PHP 官方发布时检查过这些 PoC,当时没有一个能用,此后的版本不在此结论内2。唯一完整的修法是升级到 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 并重启所有 PHP 进程;WAF 和 php.ini 改动只是临时挡一部分路径。
一、结论与解法
把暴露在公网、未打补丁的 PHP 服务器当成紧急升级任务。下表按 Luca 问的四个问题逐条对应证据。
| 问题 | 证据支持的答案 | 状态 |
|---|---|---|
| 有在野攻击吗 | 有。Cloudflare 看到攻击流量,并观察到攻击者改 payload 绕过其规则;watchTowr 的蜜罐网络也记录到利用尝试34。 | 已确认 |
| exploit 广泛传播了吗 | 公开 PoC 和演示视频在流传。PHP 官方在发布时检查过公开 PoC,当时无一可用;研究者手里有能用的版本2。 | 部分 |
| 大规模成功入侵被证实了吗 | 没有。两家观测方都只报告攻击尝试,没有给出成功入侵生产服务器的数量。 | 未证实 |
| 有完整修法吗 | 有。升级 PHP 并重启所有 worker。配置改动只挡部分路径1。 | 有 |
解法按优先级排三层:第一层升级 PHP,这是唯一的完整修复;第二层在升级前用 WAF 或网络层挡住公网请求;第三层改 php.ini,只能关掉已知的几条路径。第五节展开每一层的具体做法和边界。
二、漏洞细节
两个漏洞都出在 PHP 的内存管理,都在请求解析阶段触发,早于任何应用代码。这意味着登录页、框架的路由守卫、PHP 层的维护页都挡不住它。
2.1 CVE-2026-109618:内存不足时的清理错误
触发条件是一次内存分配失败。PHP 在初始化过程中因为内存不足中途停下,此时内部数据结构只初始化了一半。随后的清理流程仍然按完整结构去处理,于是用到了无效数据。攻击者可以用精心构造的请求让 PHP 在可控的位置耗尽内存。
已确认的攻击路径针对 mod_php(Apache 内嵌模式)。它在应用代码运行之前完成,拿到的是 Web worker 的权限5。
2.2 CVE-2026-109619:跨请求的悬空引用
这是一个 use-after-free。PHP 在上一个请求结束时释放了某块内存,但 worker 进程仍保留着指向它的引用。下一个请求如果走到特定的错误处理、session 或上传进度路径,就会用到这个已释放的引用。研究者证明某些路径可以转成代码执行5。
这个漏洞的利用依赖 worker 复用,所以长期运行的 PHP-FPM 池和 mod_php 都在范围内。
2.3 受影响范围
| 部署方式 | 攻击路径 | 依赖条件 |
|---|---|---|
| mod_php | 已有不依赖应用代码的完整演示 | 无需特定应用行为 |
| PHP-FPM | 已有演示的攻击路径 | 需要合适的应用行为配合 |
| 其他 SAPI | PHP 官方把所有 Web 部署都列为有风险 | 利用条件随配置和构建方式变化 |
除了代码执行,研究还演示了内存泄露:不执行命令,也能读出进程内存里的凭据4。所以“没发现 webshell”不等于没有损失。
- CVSS v4.0
- 9.2 / 9.2(两个漏洞相同)
- 修复版本
- 8.2.35、8.3.36、8.4.27、8.5.12
- 已停止维护的分支
- 7.4、8.0、8.1 有官方最小源码补丁,但不恢复上游支持
- 公布日期
- 2026-10-21
三、在野攻击
两家独立观测方都报告了攻击流量,时间都在修复发布当天或次日。
- Cloudflare 从 03:02 UTC 起对免费和付费 WAF 用户默认开启 PHP2Shell 规则,随后观察到攻击流量,以及攻击者修改 payload 试图绕过规则3。
- watchTowr 发布 FAQ,报告其蜜罐网络记录到利用尝试4。
两份报告的共同边界:它们看到的是攻击尝试,不是入侵结果。Cloudflare 看到的是经过其网络的流量,watchTowr 看到的是蜜罐。都没有给出“多少台生产服务器被拿下”的数字。攻击者改 payload 绕 WAF 这件事本身说明有人在认真投入,不是扫描器顺手扫一下。
四、exploit 传播
这一节要分开两件事:有没有公开代码,和公开代码能不能用。
- 公开 PoC 在流传。PHP 基金会确认 10 月 21 日当天公开 PoC 的流传量明显上升,另有演示视频2。
- 发布时的公开 PoC 没有一个能用。PHP 官方在发布前逐个检查过,结论是当时没有可用的公开 exploit2。这个结论只覆盖发布时刻,之后新出的版本不在内。
- 能用的研究级 exploit 存在。发现漏洞的研究者手里有可用版本,这是 Cloudflare 规则和 PHP 补丁的依据4。
- “对所有部署都可靠的 exploit”没有被证实。利用条件随 PHP 构建、SAPI、应用行为变化,公开代码质量参差。
五、修复与阻止
按三层做。第一层是修,后两层是挡。挡的措施都有边界,列在各自的小节里。
5.1 升级 PHP
- 升级到
8.2.35、8.3.36、8.4.27或8.5.121。 - 用发行版包的,版本号可能不是这几个。发行版常把补丁回移到旧版本号上。以发行版的安全公告为准,确认它同时覆盖两个 CVE。
- 还在跑 7.4、8.0、8.1 的,PHP 提供了最小源码补丁。打了补丁也不恢复上游支持,应当作为迁移前的过渡。
- 升级后重启每一个 PHP 进程:FPM 池、Apache、容器、各个虚拟主机账户。没重启的 worker 仍在跑旧代码。
- 逐站核对实际服务网页的 PHP 版本。命令行
php -v只能证明 CLI 的版本,证明不了 FPM 池、Apache 模块或容器里的版本。
5.2 暂时无法升级时
目标是让请求到不了 PHP。挡在 PHP 前面的措施才有效,挡在 PHP 后面的(应用登录、PHP 写的维护页)无效,因为漏洞在应用代码之前触发。
- 网络层阻断。用反向代理、防火墙白名单或临时下线,把公网请求挡在 PHP 之外。
- 开启 WAF 规则。Cloudflare 自 2026-10-21 03:02 UTC 起对免费和付费 WAF 用户默认开启 PHP2Shell 防护3。要核对两件事:流量确实经过 WAF;源站不能被直接访问。否则攻击者绕过 WAF 直连源站。
- 限制 multipart 请求。应用不需要文件上传的,在代理层直接拒绝 multipart 请求。需要的,限制解码后的请求大小、分段数量、头部数量和嵌套深度。这只挡住一类变体。
5.3 配置级缓解及其边界
PHP 官方给了几条配置改动。每一条都只关掉某一条已知路径,而且必须写在启动配置里并重启所有 worker。在代码里 ini_set() 无效,因为它运行得太晚,请求解析早已完成1。
| 配置项 | 作用 | 代价与边界 |
|---|---|---|
session.upload_progress.enabled=0 | 关闭上传进度路径,堵住 CVE-2026-109619 的一条触发路径 | 只挡这一条路径;依赖上传进度的应用会失去该功能 |
fatal_error_backtraces=0 | 仅 PHP 8.5 需要。关闭致命错误回溯,堵住另一条触发路径 | 只挡这一条路径;排错时少了回溯信息 |
memory_limit=-1 | 去掉 PHP 自身可预测的内存上限失败,降低 CVE-2026-109618 被稳定触发的概率 | 同时去掉了内存保护,拒绝服务风险上升;底层分配失败仍能触发漏洞。必须配合容器或 cgroup 的内存上限和前端请求限制 |
5.4 排查是否已被入侵
升级之前先保全日志:代理、WAF、PHP 和进程日志都留下来。然后按下面的信号查。
- 流量侧:异常的 multipart 请求;大量内存错误;worker 频繁重启;响应里出现超大或畸形的
PHPSESSIDcookie。 - 主机侧:Web 用户名下出现 shell 进程;意外的外连;Web 目录里新出现的 PHP 文件。
这些信号只说明需要进一步查,没有这些信号不能证明安全。怀疑已被入侵的,先隔离主机、保全证据,再从干净的机器上更换所有暴露过的凭据。别忘了 2.3 节提到的内存泄露路径:攻击者可能只读走了凭据,没留下 webshell。
六、再说一遍:按顺序做这五件事
把前面五节压成一个顺序清单。第一条是终点,后面四条是到终点之前的保护。
- 升级到修复版本并重启所有 PHP 进程。逐站核对实际服务的运行时版本。这是唯一完整的修法。
- 升级前先挡在 PHP 外面。网络层限制访问,开 WAF,封死源站直连。
- 配置缓解只当补充。关
session.upload_progress,8.5 关fatal_error_backtraces,memory_limit=-1要配 cgroup 限制。写进启动配置,重启 worker。 - 保全日志并排查入侵信号。重点看 multipart 异常、内存错误、worker 重启、新 PHP 文件、外连。
- 把“攻击尝试已确认,大规模入侵未证实”当成当前状态,不当成安全保证。公开 PoC 在变,Cloudflare 已看到绕过尝试。这个判断的有效期只到 2026-10-22。
七、方法与来源
信息于 2026 年 10 月 22 日(新加坡时间)通过网页检索和直接读取下列官方页面得到。本页没有运行任何 PoC,没有接触任何受害主机,关于 exploit 可用性的判断全部转述自来源。没拿到的信息:成功入侵生产服务器的数量;10 月 21 日之后新出现的公开 PoC 是否可用;各发行版回移补丁的具体版本号。
- PHP,《PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12 Security Releases》,2026-10-21,php.net
- The PHP Foundation,《Today's PHP Security Release and How We're Strengthening PHP Security》,2026-10-21,thephp.foundation
- Cloudflare,《PHP vulnerabilities and WAF protection》,2026-10-21,blog.cloudflare.com
- watchTowr,《PHP CVE-2026-109618 FAQ》,2026-10-22,watchtowr.com
- php/php-src,GitHub 安全公告 GHSA-w8hw-w9fx-j79w,2026-10-21,github.com/php/php-src