💡 2026 年 10 月 21 日,PHP 官方发了一条标题毫不客气的通告:《Critical remote code execution vulnerabilities, update now》,然后用四个小版本------8.5.12、8.4.27、8.3.36、8.2.35------修掉两个未认证远程代码执行漏洞。
真正让我决定写这一篇的,是通告里另外两句话。第一句是风险面:所有对外提供 Web 请求的 PHP 安装都在影响范围内,PHP-FPM、Apache mod_php、php-cgi、FrankenPHP、LiteSpeed 一个不落。第二句更硬:没有任何完整缓解措施,升级是唯一安全选择。
这两句话合起来的意思其实挺吓人的------它意味着你不需要用 WordPress,不需要有上传接口,没有反序列化点,模板层写得再干净,只要服务器上那个 PHP 在解析请求,你就在这一次的影响面里。而国内安全厂商给这件事起的代号 PHP2Shell,也确实是按这个传播的。
所以这一篇我想把这件事摊开讲一讲:两条 CVE 到底在哪个环节把解释器打穿、为什么我们熟悉的那套应用层防护这次一律不起作用、披露日之前攻击就已经开始的这十天是怎么发生的,以及一个后端负责人现在应该按什么顺序去排查自己那堆 PHP。
1. 先把层级说清楚:这次被打穿的不是网站代码
PHP2Shell 不是「PHP 站被 getshell」这类事件的统称,它是这次两个具体 CVE 的外部代号。这个名字在 PHP 官方通告和 NVD 条目里都不存在,两边全程只用编号。我先把这个层级关系画出来,因为后面所有的判断都建立在它上面。
| 编号 | 官方命名 | 触发位置 | CVSS v4.0 |
|---|---|---|---|
| CVE-2026-109618 | RCE via OOM corruption | 同一个请求内:内存分配失败后,请求清理流程读到半初始化的内存 | 9.2 Critical |
| CVE-2026-109619 | RCE via stale global state | 跨请求:全局状态指向已被释放的上一个请求内存 | 9.2 Critical |
两条的向量完全相同:AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N。网络可达、不需要任何账号、不需要用户点任何东西;攻击复杂度写的是 High,但这恰恰是我最想提醒后端同学的地方------CVSS 里的 AC:H 描述的是「打穿一次有多难」,不是「被打的这个面有多窄」。
Q1:和我以前理解的 PHP 被 getshell,区别到底在哪?
以前那套路径,漏洞主体是你的代码或者你装的组件 。上传点没校验后缀、反序列化用了用户可控输入、模板引擎把用户字符串当模板编译、ThinkPHP 那个 filter 参数、Laravel 忘了关 debug------共同前提是「应用层存在一个可达的缺陷」。
text
老路: 攻击者 --> Web 服务器 --> PHP 解释请求 --> 你的代码有缺陷 --> 落地文件 --> getshell
↑ 漏洞在这里,补代码/升级框架就能堵
这次: 攻击者 --> Web 服务器 --> PHP 解释请求 --> 解释器自己就崩坏了 --> RCE
↑ 漏洞在这里,你的代码还没开始执行
差别就在这一格。官方对 mod_php 的描述是逐字可查的:未认证请求可以在任何应用代码执行之前触发攻击 。也就是说,请求还没交到你写的第一个 index.php 手里,解释器内部的内存状态已经被破坏完了。
Q2:那我把 WordPress、ThinkPHP 升到最新版有用吗?
没用,至少这次没有。CMS 和框架的最新版只修自己层的洞;这两条 CVE 在解释器层。我反而觉得「应用是最新版」这次会变成一种误导性的安全感------国内测绘里 WordPress 那 310 万个独立 IP,Censys 的调查显示超过 70% 跑的仍是过期 PHP 版本。框架新不新,和 PHP 是不是 8.2.35,是两个完全独立的变量。
Q3:为什么 mod_php 被单独点名成最高风险?
这里有个很具体的工程原因。PHP 处理致命错误的方式是用 longjmp() 跳出当前调用栈、直接放弃这个请求,它不做栈展开 ,所以析构和中间清理逻辑一概不执行。正常情况下这没什么,反正进程状态接下来要重置。但 mod_php 是嵌在 Apache 进程里的,请求启动失败之后,Apache 侧仍然会无条件执行 request shutdown------于是清理流程就去读那份没人收拾过的、半初始化的内存,并按它分支。
FPM 的 worker 是独立的、生命周期由自己管,路径不完全一样;但官方明确写了 FPM 同样在服务范围内,只是「已验证的利用路径」这条在 mod_php 上最顺。我自己的读法是:不要拿「我们用的是 FPM 不是 mod_php」当降级理由,官方那句 "all PHP installations serving web requests" 已经把降级空间堵掉了。
2. 披露日不是最早利用日:10-17 到 10-27 这十天
这一节是整件事里我认为对做运维和应急的人最有价值的部分。它跟漏洞机理关系不大,跟「你的响应窗口有多长」关系很大。

时刻全部 UTC,来源是各机构自己的公开观测:
| 时刻 | 发生了什么 | 来源 |
|---|---|---|
| 10-17 | 蜜罐捕获到最早一次利用尝试,来自商业化匿名网络 | AWS MadPot / GTIG |
| 10-20 | 官方发布《Upcoming Critical PHP Security Release》预告条目 | PHP 官网 |
| 10-20 下午 | 预告帖出现在 Hacker News,直接给出两个 CVE 号 | 奇安信整理 |
| 10-21 02:00 | 最早的公开 PoC 出现;02:00--08:00 多个来源连续尝试 | AWS |
| 10-21 03:02 | WAF 拦截规则给全部套餐(含免费版)默认上线 | Cloudflare |
| 10-21 07:41 | 含修复的容器镜像提前 6 个多小时发布,被 PHP 基金会公开批评 | Chainguard |
| 10-21 13:30--13:52 | 四个修复版本正式发布 | PHP 官网 |
| 10-21 14:00 | 禁运窗口实际解除 | AWS |
| 10-26 | 两个 CVE 被列入 KEV,整改期限 10-29 | CISA |
| 10-27 | 首个经取证确认的成功 RCE 证据公开 | BleepingComputer 等 |
三个数字值得单独拿出来看。
第一个是 4 天。 最早捕获到的利用尝试在 10-17,公开披露在 10-21。这不是「披露后攻击者反应很快」,这是攻击者在披露之前就已经在打 。所以 AWS 给安全负责人的第一条工作假设修正我完全同意:调查起点要设在最早已知利用时间,不是披露日。如果你的应急流程是「以 CVE 发布日期为 T0 起算 SLA」,这次事件的 T0 得往前挪四天。
第二个是 11 小时。 从 02:00 第一个公开 PoC 出现,到 13:30 补丁落地,中间有超过十一个小时,互联网上已经有可用攻击代码、而修复版本还没发布。这段时间里 WAF 在 03:02 就把规则铺到了全部套餐,Chainguard 在 07:41 提前发了镜像------两家都是在做正确的事,但 PHP 基金会公开批评了抢跑。这个矛盾本身没有标准答案,我倾向于认为:禁运期缩短到几乎不起作用时,「先出防护」和「先出补丁」的次序问题就会反复出现,团队要提前想好自己的立场。
第三个是 10 天。 10-27 才出现第一个经公开取证确认的成功 RCE。这件事的口径分歧我必须并列写清楚,不然就是在替某一方背书:
| 立场 | 说法 | 来源 |
|---|---|---|
| 已在野 | 规模化利用;broadly exploited in the wild | Hadrian、AWS |
| 未成功 | 迄今无人成功,但不指望这种状态能持续多久 | watchTowr |
| 仅探测 | 以探测性攻击为主,无确凿失陷证据 | Patchstack、Huntress |
| 官方认定积极利用 | 列入 KEV(10-26),整改期限 10-29 | CISA |
我的读法是:扫描、探测与利用尝试在 10-21 当天就已规模化,而「成功」这个词在 10-22 之前没有任何人拿到公开取证证据 。两者不矛盾,只是各家对「成功」的门槛不一样。而 10-27 那个案例本身也被明确限定了条件------证据证实链条在单工作进程的 mod_php 环境中可行,那个环境被刻意设置成对攻击者有利;不能外推到多 worker、不同 PHP 构建或不同应用环境。
顺带记一条我核对时踩到的坑:有厂商文章把受影响版本写成「PHP 8.4.x < 8.4.26」,而官方边界是 < 8.4.27。8.4.26 是被成功利用的那个实验环境的版本,不是修复分界,别抄错。
3. 两条 CVE 分别怎么触发
机理部分我只写到「能判断影响面、能设计检测」的深度,不写可复制的请求构造。官方与 NVD 的描述是逐字公开的,我直接引关键的半句。

CVE-2026-109618:请求内存还没初始化完,就先被"发布"出去
NVD 逐字描述里最关键的是这两句:PHP 用 longjmp() 处理 OOM 以跳出当前上下文、放弃处理这个请求;某些上下文没有正确考虑这种情况,会在执行下一次分配之前把请求内存留在未初始化状态;随后的请求清理流程可能读取或按这份内存分支。
攻击侧要做的,是稳定地制造出这个 OOM。这里就有个特别值得后端同学警惕的细节:制造 OOM 不需要真的发一个巨大的包。国内一线流量里被反复观测到的一类请求,是利用 multipart 解析路径上的几个校验缺口去触发分配失败------没有可用 Content-Length 时绕过 post_max_size 的初检、空文件控件不计入 max_file_uploads,几 MB 的请求就能把默认内存上限耗掉。也就是说,「我们上传目录都禁了、也不接受大请求体」这类直觉判断在这次不成立。
官方在默认配置下完成了完整的 RCE 验证,并且明确写了攻击发生在任何应用代码执行之前。
CVE-2026-109619:全局状态指向的内存,其实属于上一个请求
NVD 逐字:PHP 有各种临时指向请求内存的全局状态;某些场景下这些状态没有被正确重置,或者重置后又被重新填充;之后的请求可能在完全初始化之前读取或按这份陈旧状态分支。
这就是典型的释放后重用。worker 是复用的,A 请求留下的指针指向已经归还的内存,B 请求进来先用了它。官方确认了两条「消费者」路径:初始化前的 INI 诊断,以及默认开启的 session.upload_progress。PHP 8.5 的 fatal_error_backtraces 是最强的一个案例------它会把回溯信息留在跨请求可见的地方。
这里要补一条很多人漏掉的后续:10-23 官方又发了一条 Informational advisory ,把 upload-progress 这条路径单独编成了 CVE-2026-115560。它的触发前提相当苛刻:配置里把 session.serialize_handler 设成 php_binary 或 php_serialize,然后在 session_start() 之前用 ini_set() 在运行时切回 php,同时 upload progress 还开着。官方原话把它称作 "an unlikely RCE vector",按常规发布周期处理,不发紧急补丁。所以如果你查到自己代码里有运行时切序列化 handler 的写法,这条也要一起排;从不切 handler 的应用可以继续开着这个特性。
Q:不实现 RCE 是不是就没损失?
这是我觉得这次最容易被低估的一面。上面那条 upload-progress 路径还有一个副作用:指针悬垂之后,后续的 multipart 请求会让 PHP 把回收堆里的内容 URL 编码进 PHPSESSID 响应 Cookie 返回去。
在 10-27 那个被确认成功的案例里,解码后的 Cookie 转储达到 800 KiB,攻击者按公开利用代码中的偏移量从中提取出一个函数地址,再用进后续载荷------泄露直接充当了绕过地址随机化的那一步。而同一个 worker 处理过的密码、会话令牌、API 密钥、TLS 私钥,理论上都可能出现在那堆内存里。这个暴露面的形状,和十年前的 Heartbleed 是同一种。
所以「我只是被扫、没有被拿下 webshell」不等于没有数据外泄。这一条对排查的影响非常大,下一节展开。
4. 为什么我们熟悉的那套防护这次一律不起作用
这一节我原本想写成「缓解措施清单」,但更值得说清楚的是「为什么无效」,因为官方给的三条临时缓解本身也承认不是完整方案。

Q:为什么关错误显示、关 display_errors 没用?
因为漏洞读的是内存状态 ,不是错误输出。官方在这点上是直接否定的语气:用 error_reporting、display_errors 或 @ 把诊断信息藏起来,does not help。状态在「决定是否要报告这个错误」之前就已经被访问了。
Q:disable_functions、open_basedir 呢?
管不到。这两个是脚本层的限制,缺陷在解释器的内存管理和错误处理里。顺便把它们的既有边界也记一下,免得当成保险箱:disable_functions 在官方文档里自带警告级说明------这个机制可以被绕过 ,它只能算纵深防御的一层;open_basedir 的路径判定按真实路径走,符号链接会被解析,所以「用软链逃出 web 目录」不是可行绕过,但它同样挡不住这次的利用。
Q:那我挂「维护模式」总可以吧?
不行,至少应用层的维护模式不行。PHP 在应用代码去检查那个维护标志之前,就已经把请求解析完了。要下线就得在 Web 服务器层停掉 PHP------不是应用返回一个 503 页面。
Q:官方给的缓解措施到底是什么,能挡多少?
| 措施 | 阻断哪条 | 官方写明的局限 |
|---|---|---|
memory_limit = -1 |
109618 的可预测 OOM 触发点 | 必须用应用无法覆盖的方式设置(FPM pool 或 Apache php_admin_value),并确认没有 pool/目录/应用把有限值改回去;要配合 cgroup/容器内存上限,否则从「可预测 OOM」变成「整机可用性风险」 |
post_max_size 设小 |
109618 的请求体侧 | 不需要上传的应用设 8M ,需要上传的设 32M ,并保持 upload_max_filesize 低于它。注意默认值本来就是 8M------这条缓解的实际含义是「别把它调大」 |
关闭 session.upload_progress.enabled |
109619 已确认路径之一 | 必须写在 php.ini/FPM pool/服务器配置里(要在请求解析前生效 ),不能靠 ini_set(),也不能靠 FPM 的 .user.ini;且要重启所有 worker |
fatal_error_backtraces = 0 |
109619 在 8.5 上的最强案例 | 仅 PHP 8.5;只阻断已确认的 fatal backtrace 这一条路径 |
| Web 服务器/代理层限流 | 109618 的触发面 | 官方要求限制覆盖到没有可用 Content-Length 的请求:解码后的请求体大小、输入字段数、multipart 分片数、头部数量、嵌套深度都要设 |
| 容器/cgroup 限制 | 兜底可用性 | 最好只杀掉受影响的 worker。官方特别警告:不要 用 RLIMIT_AS 或 RLIMIT_DATA 替代,因为它们本身就会造成可被利用的分配失败 |
六条里我唯一觉得可以放心执行的是「关掉 upload_progress + 用 php_admin_value 设 memory_limit」这一组,其余每一条都在把风险从一处挪到另一处。这也是为什么官方在四个分支的发布条目里各自重复了同一句话:There are no complete mitigations, updating is the only safe choice.
Q:WAF 虚拟补丁呢?云厂商都在宣传这个。
这里存在一个明确的口径矛盾,我按官方优先来记。Cloudflare 在 03:02 就把规则铺到全部套餐,这件事本身值得做,也确实会挡掉大量自动化尝试;但部分厂商文档把「WAF 可拦截/虚拟补丁」写成了主叙事,而 PHP 官方的措辞是「没有完整缓解措施」。我的判断是:WAF 当第一道减速带来用,不要当修复来记账。特别是这次还有一条对排查非常不利的实测------成功利用可以返回标准 HTTP 200,worker 不崩溃、应用日志无异常。
说到日志,国内一线流量侧的侧写里有四条规则回测结论,我觉得比任何检测规则本身都值得抄进排查手册:
- 靠
upload_progress标记做检测,能命中全部攻击流量,但单独用没有判别力------正常上传业务也带这个字段; - 针对「超长 urlencoded 字段名」的检测思路,零命中;
- 响应侧 OOM 回显检测,精度高但召回低;
- 不要把
<?php当必要条件------这次的请求里根本没有 PHP 标签。
这四条合起来说的是一件事:这次的流量形态和「找 webshell 上传」不是一回事,拿老模板去筛新流量会大面积漏。
5. 排查:先确认你跑的是哪个 PHP,再看日志
这一节按我自己会执行的顺序写。顺序很重要,因为最常见的失败不是没升级,而是升了但进程还是旧的。
5.1 第一步:清点,而且要按「实际在跑的版本」清点
text
php -v 只告诉你 CLI 版本,不代表线上那个 FPM/Apache 在用的版本
php-fpm -v 以这个实际输出为准
发行版包名 backport 常常不改版本号,必须查 changelog 里的 CVE 标记
容器镜像 基础镜像 tag 没变 ≠ 里面的 PHP 没变
阿里云侧的修复包已经把主流分支都覆盖了(Alinux 2 的 5.4.16 系列、Alinux 3 的 7.4.33 系列、Alinux 4 的 8.3.36 与 Ubuntu 24.04 的 8.3.6 系列都有对应 Errata),但这里有个坑必须说清:第三方仓库、容器镜像和自编译的 PHP 不会被发行版自动修复。官方原话是 Linux 发行版和 LTS 厂商提前拿到了补丁,所以「去问你的厂商」,而不是「等 apt update」。
5.2 第二步:升级之后必须做的事
| 动作 | 为什么必须 | 常见漏法 |
|---|---|---|
| 重启 Apache、PHP-FPM 及所有常驻 worker | mod_php/FPM 是常驻进程,只换二进制不杀进程,内存里跑的还是旧代码 | 只 apt upgrade,不重启;systemd 里托管的额外 pool 没重启 |
| 重建镜像,而不是重启容器 | 容器重启用的是同一个只读层,里面还是旧 PHP | 只 kubectl rollout restart,基础镜像没换 |
| K8s 滚动重启所有 Pod | 同上 | 只重启了 Deployment,StatefulSet/CronJob 漏掉 |
用 php-fpm -v 与 changelog 双确认 |
发行版 backport 不改版本号 | 看到包版本没变就判定「没修」,或看到版本号变了就判定「修好了」 |
5.3 第三步:往回看日志,起点放在最早利用时间
调查起点要回到 10-17,不是 10-21。要筛的形态(这几条是从官方缓解措施和公开检测特征反推的检索方向,属于本文结论,不是官方规则):
text
带 session.upload_progress 相关字段的请求 ← 109619 的已确认路径
异常大的 Content-Length,或者干脆没有 Content-Length
multipart 分片数/输入字段数/头部数异常偏高的请求
PHPSESSID 响应 Cookie 体积异常(正常是几十字节量级)
应用层返回 200、但 worker 之后行为异常的请求 ← 最不像攻击的那一类
最后一条最贵也最容易漏。国内那份流量侧写里,几百条捕获到的攻击流量按 payload 形态分成六类(探测型、填充型、数组洪泛型、gadget 链型、文件名序列化型、PHP 标签验证型),最活跃的单源在 4 小时内发了四百多次请求,还有专门用来试探 memory_limit 的固定长度填充体。这些数字都出自厂商口径、不是一手官方统计,量级可以参考,不要当基准。
进程侧的判据可以借 CISA 那句话当检测描述:监控 PHP worker 进程启动 shell 或下载工具的行为 。worker 起了 sh、curl、wget,或者在 web 目录之外落了文件,无论 HTTP 状态码是什么,都值得当场查。
5.4 我自己在 EOL 分支上,怎么办
这是这次最尴尬的一群。官方口径是「PHP 8.1 及更老版本不再由 PHP 项目更新」,考虑到严重程度,安全团队为 7.4/8.0/8.1 提供了 minimal source-backports------注意是源码级最小回填,不是发行版包,也不是承诺维护。
| 情况 | 我会怎么做 |
|---|---|
| 8.2/8.3/8.4/8.5 | 直接升小版本,重启,重建镜像。这是唯一有完整官方支持的路径 |
| 8.1 及更老,能升 | 这次一起把大版本升上去。8.1 的 EOL 是 2025-12-31,8.0 是 2023-11-26,7.4 是 2022-11-28,早就在只修不保证的状态 |
| 8.1 及更老,暂时不能升 | 取官方 source-backport 自行构建,或找有商业 LTS 的发行版;同时把上面的缓解组合 + Web 服务器层限流一起上,并把这台机器按「已暴露」来处置 |
| 完全无法触达的遗留系统 | 按 NSA 与 CERT-EU 的口径处理:无法立即更新的,把互联网暴露的应用与公共网络隔离,必要时直接下线 |
这里给一个量级参考,别混着用:一家测绘方统计到约 438 万 个暴露的 PHP 服务(约 189 万 台主机),其中约 79% 可识别版本运行在已无官方支持的分支,折算下来约 141 万 台等不到官方补丁、只有约 53 万 台能靠升小版本直接修;另一家的口径是全球 PHP 主机超过 510 万台 、其中约 380 万台 至少有一个端口开放。两组数字的统计对象和判据完全不同,不能相加也不能互相印证,只能各自说明「EOL 占比很高」这一件事。W3Techs 的公开统计是 PHP 用在 69.2% 已知服务端语言的网站上,其中 PHP 7 还有 26.5%、PHP 5 还有 7.6%------这就是为什么这次的影响面没法靠「让我们 CMS 升级」收口。
6. 横向对照:PHP 生态的四条老路,这次站在哪
把这次放进历史里看,能更清楚地知道它新在哪。下面四条老路至今仍在被扫,我按「漏洞主体在哪一层」来分。
| 层 | 代表编号 | 触发前提 | KEV 在野记录 |
|---|---|---|---|
| php-cgi 参数注入 | CVE-2012-1823 | CGI 模式下查询串缺少 = 时把命令行选项当参数吃 |
2022-03-25 列入 |
| ↑ 的补丁绕过 | CVE-2024-4577 | Windows + Apache + PHP-CGI + 特定代码页,四前提缺一不可 | 2024-06-12 列入,勒索软件已知使用 |
| FPM 配置 | CVE-2019-11043 | 某些 FPM 配置下写越界进 FCGI 协议数据 | 2022-03-25 列入,勒索软件已知使用 |
| 组件与 vendor 暴露 | CVE-2016-10033(PHPMailer)、CVE-2017-9841(PHPUnit eval-stdin.php)、CVE-2009-1151(phpMyAdmin setup 写配置文件) |
依赖版本过旧//vendor 目录可外网访问 |
三条都在 KEV;PHPMailer 那条是 2025-07-07 才列入 |
| 框架/CMS | ThinkPHP CVE-2018-20062 与 CVE-2019-9082、Laravel CVE-2021-3129(debug 模式)、Drupal CVE-2018-7600、WordPress File Manager CVE-2020-25213 | 框架版本区间 + 特定配置(debug 未关、插件过旧、REST 开启) | 五条全部在 KEV |
| 解释器自身 | CVE-2026-109618/109619 | 只要 PHP 在服务 Web 请求 | 2026-10-26 列入,期限 10-29 |
表里最锋利的一条是 PHPMailer 那个 2016 年的洞,2025 年 7 月才被官方认定「已知积极利用」 。老洞不会过期,只会因为没人再讨论而变成默认配置。ThinkPHP 那条 s=index/\think\app/invokefunction&function=call_user_func_array 到今天仍然是很多 WAF 和访问日志里的探针特征串------国内那 57 万条 ThinkPHP 测绘记录,和这次要排的 PHP 版本,是同一批资产的两个属性。
而这次的新意就一句话:前五行都需要你先有一个缺陷,第六行不需要。
Q:这次为什么武器化这么快?
AWS 的判断我认为是当前最实用的解释:AI 辅助分析让「补丁 diff → 可用 EXP」变得极其廉价,更多攻击者能在技术细节公开后数小时甚至数分钟内完成武器化。对照上一次同级别的 PHP 核心 RCE(CVE-2024-4577),从披露到被僵尸网络大规模扫描大约 24 小时;这次是补丁落地与首次攻击几乎零间隔,而且利用尝试在披露前 4 天就已经出现。
比较讽刺的一条背景是:PHP 核心开发者早在 2024 年的一次审计中就见过这个 OOM 问题的迹象 ,当时因为没有可行利用路径、修复方案取舍困难而搁置。这条不是我替谁开脱,而是它精确对应了 AWS 的第三条建议------投入不依赖具体 CVE 签名的检测能力。因为「已知有隐患但没编号」的窗口,比「有编号但没补丁」的窗口更长。
还有一条行业侧的连锁反应值得记:官方在 10-20 就发了预告条目,日本首相官邸在 10-21 东京时间 21:55 发出当晚处理的紧急请求,荷兰众议院、国家网络安全中心、DigiD、MijnOverheid 主动转只读或下线,niconico、pixiv、宝可梦相关服务把维护窗口提前。这些关停全部是预防性的,各机构都声明未发现入侵迹象------它衡量的是这个依赖面的谨慎程度,不是失陷数量。但一个由官方预告 + 提前泄露 + 蜜罐捕获共同构成的「补丁未至、攻击先行」样本,值 141 万台等不到补丁的主机认真看一遍。
最后总结
- 如果你只跑 Java/Go/Node,这次和你无关------但请把「依赖里有没有 PHP」加进资产清点,因为很多 CMS、老后台、内部工具是顺手挂的。
- 如果你是 PHP 站点的负责人:
升级 → 重启所有常驻 worker → 重建镜像 → 用php-fpm -v和 changelog 双确认,这四步少一步都等于没做。 - 如果你管的是 8.1 及更老的分支:这次不要再单独讨论了,把它当成一次大版本升级的立项理由。
- 如果你做检测:这次的流量形态和找 webshell 上传不是一类,
upload_progress标记单独用无判别力、<?php不是必要条件、成功利用可以返回 200。三条叠起来意味着老模板会大面积漏。 - 如果你是架构或者安全负责人,我个人更关注的是 AWS 那三条工作假设的修正:关键漏洞的补丁与缓解时间线以小时计,7 天/30 天 SLA 的预设已经失效;调查起点设在最早已知利用而不是披露日;检测能力要能不依赖具体 CVE 签名。
- 一句话结论:这次真正要改的不是某个配置项,而是「应用是最新版所以安全」这个默认假设。
参考资料 & 致谢
- PHP 官网 - 安全公告与发版存档(2026-10-21《Critical remote code execution vulnerabilities, update now》;四个 Released 条目里的 "There are no complete mitigations";2026-10-20 预告条目;2026-10-23 Informational advisory 的 CVE-2026-115560 触发前提;2026-10-26 Windows 构建重建)
- GitHub 仓库 php / php-src 安全公告 GHSA-w8hw-w9fx-j79w、GHSA-6wmf-4rv5-p3rp(CVSS v4.0 向量、机理原文、缓解原文与局限、Credits)
- NVD - CVE-2026-109618 / CVE-2026-109619 条目(两条 RCE 描述逐字,均发布于 2026-10-21)
- CISA - Known Exploited Vulnerabilities Catalog(catalogVersion 2026.10.29;两条 CVE 的 DateAdded 10-26 与 DueDate 10-29、CWE 清单、requiredAction 引用 BOD 26-04 与 Forensics Triage Requirements;PHP 生态共 10 条历史条目的收录日期)
- CISA - Alert《Critical Vulnerabilities in PHP Require Immediate Patching》(2026-10-21;PHP worker 启动 shell 或下载工具的监控语、SIGMA 规则)
- AWS Security Blog - Amazon Threat Intelligence identifies PHP2Shell exploitation prior to public disclosure in MadPot(10-17 最早捕获、02:00--08:00 多攻击者、六个 IP IoC、AI 辅助武器化判断、三条工作假设修正)
- 安全内参(奇安信威胁情报中心)- 补丁未至,攻击先行:PHP2Shell 在野攻击全记录(2026-10-22;泄露过程、攻防时间线、机理细节、天眼流量侧写与四条规则回测、全球下线清单、加固与排查)
- 安全内参 - 首次!PHP2Shell 漏洞已被成功利用,实现远程命令执行(2026-10-27;8.4.26 + mod_php 确认 RCE、800 KiB Cookie 转储、限定条件)
- 阿里云文档 - PHP2Shell 漏洞影响范围与修复建议(Alinux 修复包与 Errata;第三方源、容器、自编译不自动修复)
- Cloudflare 博客 - PHP 漏洞 WAF 防护(03:02 UTC 默认上线、载荷变异观测)
- watchTowr - CVE-2026-109618 FAQ(禁运期确认与复现、「迄今无人成功」口径)
- Tenable - Blog「php2shell (CVE-2026-109618, CVE-2026-109619)」(2026-10-21;外部代号最早出处之一、CVSS v4.0 9.2、引 Amazon GTIG 的 10-17 观测)
- PHP 官网 - Manual(ini.core、configuration.file、security.cgi-bin、security.filesystem、features.file-upload:php.ini 指令语义与 INI_* 模式逐条)
- PHP 官网 - Supported Versions 与 Unsupported Branches(两年 active + 两年 security-only 策略;8.1 EOL 2025-12-31 等日期表)
- W3Techs - 页面 pl-php(PHP 服务端语言占比 69.2% 与主版本分布,页面日期 2026-10-30)
- CNCERT - 漏洞公告(2026-10-22,关联 CNVD-2026-41674、CNVD-2026-41675)
- GreyNoise - 博客(2025-03-07,CVE-2024-4577 在 2025 年 1 月有 1,089 个独立 IP 尝试利用)
- imagetragick 站点(研究者页)- 首页(CVE-2016-3714 在野与 policy.xml 关闭危险 coder 的缓解口径)
- Corelight GitHub - php2shell-detect;Neo23x0 GitHub - process-watcher(开源检测项目)