PHP 安全团队在 10 月 20 日发出预告:10 月 21 日 14:00 UTC 发布紧急补丁,修两个 CVSS v4.0 均为 9.2 分的漏洞,编号 CVE-2026-109618 与 CVE-2026-109619。欧盟 CERT-EU 当天跟进发公告,给出了一句很硬的建议——打不了补丁的,就把暴露在公网的站点先摘下来。澳大利亚 ACSC 也发了同类提示,同时补了一句:目前尚未观察到在野利用。
这条新闻在国内流传时,大多停在「PHP 出大事了」这一层。但真正值得主机吧读者关注的,是三个更具体的问题:漏洞到底出在哪个功能上、你的服务器默认开没开、今晚到底该做什么。这三个问题,本文用本机 PHP 8.3.6 实测 + 公开技术分析逐个回答。
先说结论:这轮漏洞的攻击面是 PHP 的 session.upload_progress 功能,涉及会话文件读写。它默认是开着的。但整条利用链走到最后一步,需要三个条件同时成立——而其中一个条件,在 PHP 默认配置下恰好是不成立的。这一点,很多转发文章都没说清楚。
一、发生了什么:两个 9.2 分,补丁还没发
把时间线拉直,事情是这样的:
- 10 月 20 日 15:20 UTC 前后,Hacker News 上出现帖子,称 PHP 即将披露两个远程代码执行漏洞。帖子随后被删。
- 10 月 20 日当天,PHP 安全团队发布预告,宣布 10 月 21 日 14:00 UTC 发布安全版本,修两个漏洞,均为 CVSS v4.0 9.2 分。
- 10 月 20 日晚,CERT-EU 发布安全公告 2026-018,点名两个 CVE 编号,并指出 9.2 分意味着未授权远程代码执行的可能性。
- 10 月 21 日,Cloudflare CTO Dane Knecht 在 X 上表示「已看到早期攻击出现」,正在更新 WAF 规则作为临时措施,并强调这只是 STOPGAP。
请注意一个细节:PHP 官方的预告里并没有写 CVE 编号,也没写受影响版本。CVE 编号是 CERT-EU 给出的,受影响范围(「PHP 5 起均可能受影响」)是 CERT-EU 引用社交媒体说法得出的,PHP 团队至今没有确认。Tenable 在 FAQ 里也特意提醒:早期有报道说这两个漏洞是 CVSS 10.0 满分,PHP 官方给的是 9.2,以官方为准。
换句话说,现在满天飞的技术细节,绝大多数不是 PHP 官方披露的,而是泄露 + 第三方逆向出来的。这不是说它们不可信——watchTowr 的 CEO 已经确认「漏洞是真的」,并且复现了 CVE-2026-109618——但这些细节在官方公告出来之前,都属于待核对的信息。
二、漏洞在哪:一个「上传进度条」功能
根据 Upwind、Cryptika、Brandefense 等多家安全厂商的公开分析,这两个漏洞都指向 PHP 的 session.upload_progress 功能——也就是网页上传大文件时,那个「已上传 37%」的进度条背后的机制。
它的工作方式是:浏览器上传文件时,PHP 会把进度信息(包括上传的原始文件名)写进当前会话的 session 文件。等上传完成,再把这些键清掉。
问题就出在这里。研究者指出,PHP 的 upload-progress 处理器把用户提供的文件名存进 session 数据时,没有做校验。于是,如果攻击者能控制 session 文件本身,就有可能借应用侧的本地文件包含(LFI)漏洞,把这个 session 文件当成代码执行。这类本地与远程文件包含的检测差异,之前专门写过一篇。
完整的利用链大概是五步:

另外一条被提到的路径是 use-after-free:研究者称「重入 var_destroy 析构函数」可以触发内存错误,并用 AddressSanitizer 确认过。还有一条涉及 PHP-FPM 的序列化状态跨请求残留——顺带一提,反序列化漏洞为什么比 SQL 注入更难用 WAF 防,也是老话题了。这些属于更深层的技术细节,且都还是第三方研究者的说法,PHP 官方未确认。
需要强调:这不是「所有 PHP 网站都能一键 RCE」。Cryptika 的分析特意写了,几条路径都需要额外条件——「需要开启 upload progress 且应用存在本地文件包含缺陷」「需要应用侧 gadget 或本地文件访问权限」。这一点,比「PHP 全员沦陷」的说法要克制得多,也更接近事实。
三、我本机实测:默认开着一道门,也关着一道门
与其看别人的截图,不如直接在自己机器上看。我用的是一台 PHP 8.3.6(NTS)的环境,命令很简单:
php -i | grep upload_progress
输出如下:
session.upload_progress.enabled => Onsession.upload_progress.cleanup => Onsession.upload_progress.name => PHP_SESSION_UPLOAD_PROGRESSsession.upload_progress.prefix => upload_progress_
前两条是重点。第一条说明:这个功能默认就是开的,不需要你在 php.ini 里加任何一行配置。第二条说明:上传结束后会把进度键清掉——但「清掉键」不等于「删掉文件」,那个 session 文件还在磁盘上,可读可写。
接着验证第二个关键点:文件名到底会不会被原样保留。我构造了一条上传进度记录,把文件名填成一段带多级上级目录跳转的相对路径(目标指向网站根目录下的一个 php 文件),写进 session 文件后读回来:

结果很明确:路径穿越序列被完整保留,没有任何转义或校验。这一步坐实了「原始文件名会原样进 session 文件」这个前提。
但接下来的一步,结论反过来了。攻击者要利用这条链,必须能让 PHP 使用「自己指定的 session 文件名」——否则 session 文件名是随机生成的,攻击者根本不知道去包含哪个文件。PHP 里控制这件事的配置叫 session.use_only_cookies。
我分两种情况测了:把 PHPSESSID 塞进 POST 请求体,看 PHP 会不会采纳。
当 use_only_cookies = On(默认值):PHP 拒绝采纳 POST 里的 PHPSESSID,实际 session_id 是系统随机生成的 26 位字符串,例如 8li3iaopvocl4egj0olr24rr5k。攻击者指定的 ID 被完全忽略。
当 use_only_cookies = Off:PHP 采纳了 POST 里的值,session 文件直接按攻击者给的名字落盘,文件名为 sess_attackersessida33b。
这就是那条咽喉。默认配置下,第三环是断的。这也解释了为什么 CERT-EU 说「可能」,而不是「一定」;为什么 Cloudflare 说 WAF 规则只是临时措施而不是万能盾;为什么各家厂商在描述利用条件时都加了限定词。
补一句常识:
use_only_cookies = Off本身就是一个历史遗留的不安全配置,早就该关掉。如果你的 php.ini 里被人改成了 Off,那不只是这个漏洞的问题,会话固定攻击也一并适用。
四、哪些版本有救:一张表看清
补丁还没正式发出时,安全研究者 Kevin Beaumont 已经根据内部信息报出了各分支的修复版本号。多家厂商的整理基本一致:

有一点必须说清:这张表只说明「有没有补丁」,不说明「你的机器是不是暴露」。补丁发布之前,没有任何一个现存版本含修复,也就是说「我的版本很新所以没事」这个判断,在 10 月 21 日 14:00 UTC 之前是不成立的。
另外,如果你用的是发行版打包的 PHP(Debian、Ubuntu、CentOS 的 apt / yum 包),情况有点不一样:发行版通常会把安全补丁回移到旧版本号上。所以你看到 php -v 还是 8.1,不代表没修——得去看发行版自己的安全公告,而不是只看版本号。
至于 PHP 8.1 及更早的版本,情况最尴尬:官方不再提供安全更新,没有补丁可打,只能靠发行版回移(如果发行版还管)或者干脆升级到受支持的分支。这也正是 CERT-EU 那句「打不了就把站点摘下来」针对的人群。
五、CERT-EU 说「下线」,到底什么意思
这条建议在传播中被简化成了「欧盟让网站关站」,听着挺吓人。原文其实更克制,CERT-EU 2026-018 的原话是:
在各机构无法立即打补丁的情况下,应考虑将面向互联网的应用与公共网络隔离,直到补丁可用为止。
注意用词是「隔离」(isolating),不是「关站」。落到实操上,这就是三档选择,按成本从低到高:
- 隔离:把站点从公网入口摘掉,只留内网访问,或者用 WAF / 反向代理挡在前面只放行白名单 IP。适合内部系统、后台面板。
- 下线:整站停掉,页面挂维护通知。适合没法做精细隔离的老系统。
- 硬扛 + 监控:不摘站点,但把上传相关日志、异常 POST 全部盯紧,同时等补丁。风险最高,只在「站点停不起」的情况用。
CERT-EU 同时强调要「立刻盘点所有 PHP 资产」——因为很多机构自己都不知道哪些系统在跑 PHP,尤其是那些「根本没注明底层用 PHP」的第三方软件。Huntress 在博客里那句话说得挺到位:「PHP 无处不在。它默默地支撑着 WordPress、Drupal、Joomla、Magento,支撑着共享主机平台、控制面板,还有一大堆根本不告诉你它跑 PHP 的软件。」
六、你的 WordPress 站点,暴露面在哪
主机吧的读者九成是 WordPress 站,这里单独说。WordPress 本身跑在 PHP 上,所以内核漏洞的影响是普遍存在的;但「存在漏洞」和「能被利用」之间,隔着版本、配置、插件三道墙。
Wordfence 在公告里提了一个特别容易被忽略的点:WordPress 的自动更新只管插件、主题和核心,不管 PHP 本身。很多人看到「自动更新已开启」就放心了,其实 PHP 的版本从来没被动过。Wordfence 的建议也很直接:先搞清楚你的站是谁负责升 PHP 的——是主机商、是运维、还是你自己。
这一点在共享主机上尤其明显。主机商如果用的是 EOL 版本又不肯升级,你除了搬家没有别的办法。所以下面这三步,建议今晚就做一遍:

具体命令都很短,直接抄:
php -v—— 看版本号,或者在网站根目录建一个内容为<?php phpinfo(); ?>的临时文件(看完立刻删)。php -i | grep upload_progress—— 看enabled是不是 On。- 用同一条 grep 命令,把关键字换成
use_only_cookies—— 看是 On 还是 Off。如果是 Off,立刻改成 On 并重启 PHP-FPM。
宝塔面板的用户,路径是「软件商店 → PHP → 设置 → 配置修改」,改完记得点保存并重启,光保存不重启是不生效的——PHP-FPM 读的是启动时的配置。
七、补丁出来之前,可以先做的四件事
补丁在 14:00 UTC 发布。官方公告会发在 php.net 新闻存档,最新版本号也以那里为准。这个时间点前后,有几件事值得提前做掉,而不是等到时候手忙脚乱:
| 动作 | 命令 / 位置 | 说明 |
|---|---|---|
| 关掉 upload progress | php.ini 中设 session.upload_progress.enabled = Off |
这是 Upwind 给出的首选临时缓解。如果你的站不用上传进度条,关掉没有任何副作用 |
| 确认只用 cookie 传 session | session.use_only_cookies = On |
默认就是 On,但要确认没被插件或旧的教程改成 Off |
| WAF 侧加规则 | 在防护面板拦异常 multipart 请求 | Cloudflare 已经在更新规则。注意这会误伤正常文件上传,属于「宁可错杀」的临时手段 |
| 盯日志 | access.log 中的 POST + multipart/form-data | 重点看同一 IP 短时间内对多个 .php 端点的上传请求。ACSC 的原话是「监测应用是否存在恶意活动迹象」 |
关于「关掉 upload progress 有没有副作用」,多说一句:这个功能只影响「上传进度条」,关掉后上传照常工作,只是前端拿不到进度百分比。WordPress 的媒体库上传不依赖它,所以关掉基本无感。这大概是本次事件里性价比最高的一条缓解措施。
至于 WAF 规则,Cloudflare 自己都说得很清楚:「这只是 STOPGAP,PHP 一发布更新就立刻打补丁。」规则怎么调,可以参考WAF 规则调优:从误报走向精准防护。把 WAF 当长期方案是要出事的——攻击者换一个变形,规则就可能失效,而你的 PHP 还是旧的。
八、这次和以往不一样的地方:泄漏先于补丁
正常情况下,安全漏洞的流程是:研究者在保密期内报告 → 厂商修复 → 到日子同时发布补丁和细节。这一次反过来了。
原始计划是 10 月 22 日(周四)在保密期结束时统一披露,并且已经安排了配套的演示视频。但 10 月 20 日下午,有人在 Hacker News 上把消息捅了出来,随后帖子被删,可消息已经散开了。PHP 团队于是把发布提前了一天。
这个顺序颠倒带来了一个很实际的后果:攻击窗口从「补丁发布后」前移到了「消息泄漏后」。按 Sansec 的判断,补丁发布后 15 分钟内就会出现大规模自动化攻击——这是预测,不是实测。但只要想想 PHP 的部署量,这个预测并不过分。
顺带说个反直觉的点:watchTowr 和 Huntress 都说没看到在野利用,ACSC 也说没观察到,CISA 的已知利用漏洞目录里两个 CVE 都没进。也就是说,截至本文写成时,这还是一场「准备战」而不是「抢救战」。这反而是好消息——市场给了你几个小时,去做别人出事之后才想起来做的事。
九、给主机吧读者的一句话
这轮漏洞的新闻标题很吓人:9.2 分、欧盟让下线、PHP 全员受影响。但把技术细节拆开看,它是这样一个故事:
一个没人注意的「上传进度条」功能,默认开着,把用户给的文件名原样存进了会话文件;能不能被利用,取决于你的 use_only_cookies 是不是被人关掉了、你的应用有没有文件包含漏洞。
所以我更想说的是另外两件事。
第一,默认配置是有立场的。这次 PHP 默认把 use_only_cookies 设成 On,恰好挡住了整条链最关键的一环。但这不是设计者预见到了这个漏洞,而是十几年前为了堵会话固定攻击做的决定。你今天之所以没事,很多时候不是因为做对了什么,而是因为某个默认值恰好是对的。而默认值会变,你的环境也会被插件、教程、旧文档一点点改掉。
第二,别等出事才盘资产。CERT-EU 那份公告里最不性感、但最重要的一条是「立刻盘点所有 PHP 资产」。这句话在事发当天说,已经晚了——因为盘点本身就得好几天。真正该做的是平时就有一张表:哪台机器跑什么版本、谁负责升、升级窗口在哪。
补丁 14:00 UTC 发布。今晚之前,先把自己的版本号和那两项配置查清楚,剩下的事,等官方公告出来再动手也不迟。真正会出事的,是那些连自己跑的是哪个 PHP 版本都不知道的站。
