PHP2Shell:打补丁,还是让 AI 升版本

PHP2Shell:打补丁,还是让 AI 升版本

2026 年 10 月 21 日,PHP 官方发布了一次紧急安全更新。这次更新修复的两个漏洞被评为 CVSS 9.2(满分 10), 攻击者不需要任何账号,只要向网站发一个构造好的请求,就可能在服务器上执行任意代码。安全圈给它起了个代号: PHP2Shell。

这不是某个框架、某个插件的漏洞,而是 PHP 语言引擎本身的问题。也就是说,只要你的服务器上跑着没打补丁的 PHP,你想装多少安全插件都没用。

一、这次到底是什么漏洞

PHP2Shell 是两个漏洞的组合,编号分别是 CVE-2026-109618 和 CVE-2026-109619。它们各自独立成立, 也常被组合成一次攻击。

编号官方描述成因后果
CVE-2026-109618 RCE via OOM corruption(内存耗尽导致的内存破坏) PHP 处理「内存耗尽」时用的是一种跳转机制。如果内存恰好在请求内存还没初始化完的那一刻分配失败, PHP 会留下半成品状态,后面又把它当成有效数据使用 远程代码执行
CVE-2026-109619 RCE via stale global state(全局状态残留) PHP 进程会保留一部分上一个请求的全局状态。如果某个操作在重置它之前就被中断(比如致命错误), 下一个请求可能读到已经释放的内存 远程代码执行

官方在公告里说得很直白:这两个问题都在「内存管理」和「错误处理」里,而这两块是几乎每个请求都会经过的地方。 这正是它们既严重、又难修的原因 —— 动它容易出兼容性问题,也容易影响性能。

二、影响范围:谁中招

先说结论:所有使用 PHP 5.4 及以后版本、且没有打这个补丁的网站,都在影响范围内。

按运行方式看风险高低

不同的部署方式,被利用的难易程度差别很大。这一点很关键,因为它决定你该多着急。

运行方式风险说明
Apache + mod_php最高即使请求初始化失败,它也照样执行收尾流程, 所以攻击可以在任何业务代码运行之前发生,无需登录、无需任何前置条件,用默认配置就能打通
PHP-FPM中高初始化失败时它会直接丢弃这个子进程,挡住了前面那条路; 但源码分析认为正常启动后再触发仍然可能,目前还没有完整的 FPM 攻击演示
FrankenPHP中高行为和 mod_php 类似,推测同样可能存在与业务无关的攻击路径
LiteSpeed (LSAPI)中模型接近 FPM,判断需要配合应用层漏洞才容易打
php-cgi需评估视部署形态而定

换句话说:如果你的站是 Apache + mod_php,请当天处理,不要等。

按版本看修复情况

PHP 分支受影响的版本修复后的版本该分支支撑到
8.5低于 8.5.128.5.122029-12-31
8.4低于 8.4.278.4.272028-12-31
8.3低于 8.3.368.3.362027-12-31
8.2低于 8.2.358.2.352026-12-31(就剩两个月)
8.1 及更早官方不再发布修复版本,只提供了源码补丁已停止支持

注意 8.2 这一行:它今年年底就到寿了。这次能修,但下一次不一定还有。这一点在选升级目标时要想进去。

你的框架干净也没用

因为漏洞在引擎层,所以 WordPress、Drupal、Joomla、MediaWiki、Magento、Laravel、Symfony 这些 本身代码写得再规范,跑的 PHP 没打补丁一样中招。这一点和过去那些框架漏洞完全不同,别按老经验处理。

三、现在被利用了吗

三条公开信息摆在一起,结论很明确:

时间事件
10 月 21 日 07:43 UTCCloudflare 观测到针对性的早期攻击 —— 比官方发布修复版本还早
10 月 21 日 13:30 UTCPHP 发布 8.5.12、8.4.27、8.3.36、8.2.35
10 月 21 日美国 CISA、欧盟 ENISA、CERT-EU 等多国机构同时发布预警
10 月 22 日我国国家网络安全通报中心发布预警
10 月 26 日CISA 把两个编号列入「已遭利用」目录(KEV)

但同时也要说清楚另一面:安全研究机构 Sansec 认为不太可能出现爆发式扫描攻击。 理由是这套攻击需要了解目标服务器的具体情况,不像当年的 Log4Shell 那样一个请求通吃所有机器; 公开的验证代码在默认配置的 PHP 上跑不通,多数还要配合目标应用本身存在文件包含漏洞。

这个判断不影响你要做的事,只影响你有多慌。正确的态度是:不必停服,但必须当天修。 因为已经有人在利用了,而且工具已经公开。

下面把三条路分别讲清楚。先看它们的整体关系:

三条修复路线对比:直接升级、源码打补丁、AI 升版本

四、第一条路:直接升级(唯一完整的修复)

官方公告里有一句原话:升级到包含修复的版本,是唯一完整的缓解措施。 其他所有办法都是打折扣的,包括官方自己给的配置建议。

操作上就三步:

  1. 确认当前版本:命令行执行 php -v,网站环境里看 phpinfo() 或后台的运行环境页
  2. 装到对应分支的最新修复版,然后重启 PHP-FPM 或 Apache
  3. 再查一次 php -v,确认真的换过来了

第三条最容易被跳过。用包管理器升级了,但服务没重启,跑在内存里的还是旧进程 —— 这种「升了等于没升」的情况非常常见。

共享主机用户怎么办

如果你用的是虚拟主机、面板托管,自己管不了 PHP 版本,那就把工单提给服务商, 问清楚一句话:「你们部署的 PHP 是否已包含 CVE-2026-109618 和 CVE-2026-109619 的修复?」 对方答不上来的,就当成没修。

五、第二条路:不能升级时打补丁(只能是临时的)

现实里确实有一批系统升不了:PHP 8.1 及更早的老项目、依赖某个老扩展的遗留系统、被面板或厂商锁死版本的商业软件。 这些怎么办?

官方给了什么

PHP 安全团队为 7.4、8.0、8.1 这三个已经停止支持的分支单独发布了源码补丁。 同时,各大发行版的包维护者把它移植进了旧版本:打完之后版本号还是原来的(比如还是 8.1.34), 只是包的发版号变了。

你的情况该找谁备注
Linux 发行版自建发行版的软件源(Debian/Ubuntu 可关注 deb.sury.org 与 ppa:ondrej/php)升级包但版本号不变,装完重启服务
云托管 / PaaS平台方部分平台已自动给旧版本打了补丁,问一句确认
厂商交付的商业系统厂商别自己改,改动会把维保关系搞复杂
完全自己编译运行只能自己编译见下一节

自己改源码要做什么

最差的情况是:你的 PHP 是自己编译的,版本又老,没人给你提供现成包。这时候只能对照官方的修复提交, 把补丁移植到你的版本上。

但必须提醒一句 —— 这个补丁不是改一行就能完事的。 官方修复 CVE-2026-109618 的做法,是把「内存耗尽」原有的跳转机制整个换掉: 改成在下一个虚拟机安全点触发一次延迟的「软内存耗尽」,另外再设一个更高的阈值,一旦到达就直接硬退出进程。 这动的是内存管理的核心流程,牵涉的文件不止一处。

所以真要做移植,正确的顺序是:

  1. 找到官方针对 7.4 分支的那份补丁(它对旧版本的适配价值最高,很多维护者也是拿它往更低版本移的)
  2. 先在你的版本上试打,把冲突逐个解掉,别一次改完
  3. 改完必须编译 + 跑你自己的业务回归,而不是只看能不能启动
  4. 记清楚这次改了哪些文件、对应哪个提交 —— 下次官方再修漏洞,你得重来一遍

为什么它只能是临时的

问题后果
分支本身已经停止支持这次修好了,下一个漏洞没人管你
你改的是引擎核心代码后续小版本更新会冲突,补丁会不断漂移
没有官方的回归测试覆盖改坏了可能体现为某些请求偶发崩溃,很难排查
维护成本挂在人身上当初改的人走了,这套东西就成了黑盒

结论很简单:打补丁是「今天先活下来」,升级才是「以后不再担这个心」。

六、第三条路:用 AI 把项目升到受支持版本

前面说过,升级到受支持版本是唯一完整的修复。但很多人的真实顾虑不是「不想升」,而是 「升级要改一大堆代码,我改不动」。

这正是 AI 现在能真正帮上忙的地方 —— 不是替你做决定,而是把升级过程中那些又琐碎又费眼力的活接过去: 把所有调用过时写法的地方找出来、逐处改掉、跑一遍看哪里还报错、再改、再跑。

AI 能做什么,不能做什么

能不能
扫描全站代码,列出所有与目标版本不兼容的写法替你判断某项业务逻辑在新版本下应该怎么表现
批量改写语法与废弃 API,并解释每处为什么改凭空补齐你缺失的回归测试用例
根据报错反推出根因,给出修改方案猜出你没告诉它的第三方依赖真实行为
对比官方迁移文档,逐条核对你是否漏改替你做「什么时候切换、切多少流量」的决策

一句话:AI 负责比对和改代码,业务语义和用例覆盖仍然要人来把关。

七、AI 升级 PHP 版本的处理流程

把项目丢给 AI 说一句「帮我升到 PHP 8.3」,大概率得到一堆似是而非的改动。要它真能干活, 关键是按阶段推进,每阶段有明确产出。下面这六步是实打实按顺序走的。

AI 升级 PHP 版本的六步流程:先盘点、建安全网、扫兼容、逐级升、双跑、切换

第一步:先盘点,别急着改

动手之前必须把现状摸清并写成一份清单,这份清单后面要反复回看:

  • 当前 PHP 版本、运行方式(mod_php / FPM / 其他)
  • 框架及其版本、包管理器(Composer)的依赖树
  • 用到的所有 PHP 扩展,逐个确认目标版本上还剩下
  • 当前版本离停止支持还有多久
  • 有没有扩展在目标版本上已被移除或改名

这一阶段最容易翻车的是扩展。语法问题 AI 改得很快,但某个扩展在新版本上没有了, 那就是要换方案的事,不是改代码能解决的。先查清楚,免得改到一半才发现。

第二步:先建安全网,再动代码

这一步经常被跳过,然后就会在第三步后悔。具体做三件事:

动作为什么
代码与数据库完整备份,并真的验证能还原备份过但没试过还原,等于没有备份
把回滚步骤写成可执行的脚本或文档出事时人是要慌的,凭记忆回滚必漏步
整理一套能跑起来的回归用例没有它,你无法判断自己改坏了什么

用例不一定要完整。核心链路、登录、支付、后台的增删改查,能覆盖到这些就足以拦住大部分事故。

第三步:扫描兼容性,拿到改动清单

让 AI 通读代码,产出一份清单,每行包含:文件、行号、问题代码、为什么不兼容、改成什么。 这一份清单是后续所有工作的总账。

扫描要覆盖这四类,缺一类都会在后面返工:

  • 语法层:新版本收紧的写法、废弃的语法、类型声明的强制化
  • 函数层:被废弃、被移除、行为有变化的函数
  • 扩展层:某个扩展消失后,依赖它的函数怎么替代
  • 依赖层:Composer 里的包本身支不支持目标 PHP 版本

最后一条常被忽略:你的框架或依赖包可能根本不支持目标版本。这时候先升框架,再升 PHP, 顺序反了会卡死。

第四步:逐级升,不要一步到位

从 7.4 直接跳到 8.4,报错会一次涌上来几百条,你根本分不清哪条是根因。

正确做法是一次只升一个大版本:7.4 → 8.0 → 8.1 → 8.2 → 8.3, 每一级升完、跑通、提交,再升下一级。每一级只处理这一级的破坏性变更,报错数量可控,出问题也容易定位到是哪次升级引入的。

多花的这些时间,会在你排查问题时十倍地赚回来。

第五步:双版本并行验证

光靠「能启动」不算通过。要同时跑新旧两个版本的环境,把同一套用例各跑一遍,逐项比对结果。

重点看这几类差异:

  • 页面输出是否完全一致(哪怕多了个空格也算差异)
  • 接口返回的字段名、类型、顺序有没有变
  • 数字计算结果有没有微妙漂移(浮点、日期、时区最常见)
  • 日志里的告警和废弃提示有没有新增

这一步 AI 特别合适:把两边的输出丢给它,让它列出差异并判断哪些是预期内的、哪些是真问题。 比人一行行肉眼比对可靠得多。

第六步:灰度切换,盯着指标再全量

不要一次切完。先放一小部分流量,观察错误率、响应时间、PHP 错误日志和慢查询。

稳定一段时间再逐步放量。切换过程中最容易出的事不是直接报错,而是性能下降或 偶发超时 —— 这类问题不会立刻爆,会在全量之后才集中暴露。

让 AI 干活时,话该怎么说

直接给一句「帮我升级 PHP 版本」效果很差。下面这段可以直接改着用:

项目路径是 /path/to/project,当前 PHP 版本 8.1,目标版本 8.3。
请按这四步来做,每一步做完先给我看结果,我确认后再进行下一步:
1. 扫描全项目,列出所有在 8.2 和 8.3 中不兼容的写法,输出成表格:文件、行号、原代码、问题、建议改法
2. 检查 composer.json 里的依赖,逐个确认是否支持 PHP 8.3,列出不支持的
3. 我确认清单后,按文件分批改,每批改完告诉我改了哪些、为什么改
4. 最后给我一份回归测试应该重点覆盖的清单
不要一次改完所有文件,也不要改动我没有确认的部分。

三个要点:先出清单不动手、分批而非一次到底、明确禁止它擅自扩范围。 这三条规定能挡掉绝大多数「AI 改出一堆看不懂的代码」的情况。

八、怎么选:一张表说清

你的情况该走哪条路紧急程度
PHP 8.2 ~ 8.5,装到修复版就能用直接升级当天
PHP 8.2 但马上要停支持了先升级止血,同时规划升到 8.3 或 8.4当天 + 本季度
PHP 8.1 及更早,能编译能改先打官方源码补丁止血,同时启动升级当天 + 一个月内
PHP 8.1 及更早,托管在别人那找服务商要补丁版包,同时催升级方案当天问清
老系统、动不了、也没人维护打补丁 + 前置网关拦截 + 限制入站请求,然后把它列进替换计划当天 + 排期

九、几个容易踩的坑

坑说明
升了但没重启服务包升级了,跑在内存里的还是旧进程。务必重启 FPM 或 Apache 再验证
以为改配置能代替升级官方给了 memory_limit 等配置建议,但明确写了这不是完整缓解。 而且若内存分配在底层失败,那条隐患路径仍然存在
用 RLIMIT_AS 或 RLIMIT_DATA 限内存官方明确说不要用。这两个限制会让内存申请失败,反而正好触发漏洞路径
以为关掉错误显示就安全了CVE-2026-109619 那条与错误报告设置无关。改 error_reporting、加 @、 关掉 display_errors 都不起作用
以为有 WAF 就没事WAF 只能提供部分防护,不能替代升级
只改应用不改环境漏洞在 PHP 引擎,改业务代码一行都没用

十、最后

这次的事情值得记住的,不只是「赶紧升级」这四个字。

它暴露的是一个结构性问题:那些长期停在停止支持版本上的系统,平时看不出任何问题, 一旦出事就没有干净的出路。打补丁是能救命,但你是在给一台已经没人维护的机器手工续命, 每来一次漏洞就要重复一遍,而且每一次都比上一次更难。

所以真正的建议是:今天该打补丁打补丁、该升级升级;同时认真想一下,你的项目打算什么时候离开那个版本。 这件事拖得越久,代价越大 —— 而现在的 AI 工具,确实已经把「改不动」这个理由削弱了很多。

本文信息依据 PHP 官方安全公告(GHSA-w8hw-w9fx-j79w、GHSA-6wmf-4rv5-p3rp)、 PHP 基金会 2026 年 10 月 21 日发布的说明、PHP 官网支持版本页,以及 CISA 于 2026 年 10 月 21 日发布 并于 10 月 26 日更新的预警。具体的修复版本与处置建议,请以官方公告为准。