你写的 PHP 代码,这次真的救不了你

PHP2Shell · 应急研判 · 2026-10-21

你写的 PHP 代码,这次真的救不了你

补丁发布前的最后几个小时,我把 3 份一手公告和 8 家安全厂商的分析读完了。全网转的那张预警图,有三句话必须改。

现在是 10 月 21 日下午。

距离 PHP 官方那批紧急补丁落地,还有不到 5 小时。

我盯着 php.net 的公告页看了很久。那份 10 月 20 日 19:33 UTC 发布的预告里,几乎没有技术细节,只有一句话在干火警的活:
"We reserve the right to release earlier should details of either vulnerability become public, or should evidence of active exploitation appear in the wild."
(如果漏洞细节公开,或在野出现实际利用证据,我们保留提前发布的权利。)

一份没有细节的公告,一个提前两天的"请准备"提醒,两个 CVSS v4.0 都打 9.2 的 RCE 🔥

这件事不寻常。PHP 官方很少这么说话。

然后,今天早上我的群里开始刷一张图------某服务商的"最高级别安全预警",红字、加粗、感叹号。我逐条对了下去:八成是对的,三成是错的,而那三成,恰好是你今晚做决策要看的那三成。

这篇不贩卖焦虑。我们把已确认的、没确认的、被误传的摊在桌上,然后给你三件今晚真的能做的事。

先自我介绍一下:这个号叫 TaonyDaily,我在这儿写后端那些真会踩的坑------Go、PHP、架构,偶尔 AI。平时不这么赶稿,今晚是例外。
一、先把"事实"和"传闻"分开

这次事件最特殊的地方在于:漏洞是真的,但最早那批细节是泄露的。

时间线是这样的:

时间(北京时间) 发生了什么
10/20 晚 Hacker News 出现一个帖子,声称两个 PHP RCE 漏洞 CVSS 10.0、影响 PHP 5 起、原定 10/22 披露。帖子随后被删除,发帖人自己承认"no evidence beyond 'source: trust me, bro'"
10/21 凌晨 PHP 官方发布预告:10/21 14:00 UTC 发补丁,两个漏洞 CVSS v4.0 9.2,不公布细节
同一时段 watchTowr 在 X 上确认漏洞真实,已复现其中一个(CVE-2026-109618),但拒绝在补丁前披露技术细节
10/21 Sansec 表示:预计补丁发布后 15 分钟内,大规模攻击开始
今晚 22:00 补丁计划发布(届时才会公布受影响版本、修复版本、root cause)

现在把这三种信息分栏:
✅ 已确认(PHP 官方 / watchTowr / CERT-EU)

• 两个 PHP 核心 RCE,CVSS v4.0 9.2

• 补丁时间:10/21 14:00 UTC(北京时间 22:00)

• 只给 8.2 / 8.3 / 8.4 / 8.5 发补丁,8.1 及更早不会有官方补丁

• 截至 10/21 无确认的在野利用,也不在 CISA KEV 目录
⚠️ 未经官方确认(来自泄露资料与研究机构)

• 影响范围"PHP 5.4 起所有版本"------来自泄露工具的 banner 自述,watchTowr FAQ 明确写了"未获官方确认"

• root cause 在 session.upload_progress 上传进度处理

• 是否所有 SAPI(mod_php / FPM / CGI)都能触发

• 预期修复版本号 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35(目前是猜的)

• 受影响主机数 130 万(研究者估算,未证实)
❌ 被当成事实传播

• "CVSS 10.0"------那是泄露帖的数字,官方是 9.2

• "所有版本全中,一个都跑不掉"

• "自动化利用工具已全网泄露"(见第四节,这条要辩证看)

• "唯一办法就是升级,其他都无效"

看懂了这三栏,你就知道那张预警图哪里在坑人:
它把"泄露帖的营销数字"当成了官方结论,把"未经确认的影响范围"写成了"PHP 5.4 及以上所有版本",然后用这个被放大的范围,制造了一个更大的恐慌。

恐慌不解决问题。范围会变,时间不会。
二、这次为什么不一样:漏洞在你的代码开始跑之前

我们习惯了这种剧本:WordPress 插件出洞 → 打插件补丁 → 收工。

这次不是。

长亭安全应急响应中心的复现结论值得逐字看:他们在 PHP 8.5.11(NTS)+ Apache 2.4.68(mod_php) 环境上,3/3 稳定触发 SIGSEGV;release 构建表现为进程崩溃,debug/ASAN 构建能看到引用计数异常。

技术上,目前指向的路径是:

• PHP 的 session 上传进度 机制(session.upload_progress,默认开启);

• 在处理 multipart/form-data 请求时,会触发多次会话状态切换;

• 在特定请求顺序下,内存对象被提前释放,随后在上传进度更新时被再次访问 → UAF(释放后重用);

• 研究者 J4ck3LSyN 的分析把它定位在 ext/session/session.c 的 php_session_rfc1867_callback(),并认为第二个漏洞在 multipart 解析器里;

• GMO Flatt Security 独立分析也指向同一个功能模块,并说明这是该功能的内存破坏问题。

注意这个细节:PHP 在读你的上传请求时,就已经在处理这些逻辑了。

而 WordPress、Laravel、ThinkPHP 的入口文件,还没开始执行。

这意味着三件事:

  1. 🚫 你在中间件里写的鉴权、你在控制器里写的参数校验、你在业务层做的签名验证------在这个漏洞面前,一行都不会被执行。

  2. 🚫 你装的应用层安全插件、你在 PHP 代码里实现的"防注入/防上传"逻辑------同理,来不及跑。

  3. ⚠️ 但"攻击面在应用代码之前"不等于"你只能干等补丁"。这是那张预警图最大的误导,下面细说。

一个细节特别值得注意:泄露视频里,命令执行回显的身份是 www-data(uid=33),环境是 Ubuntu 26.04 + PHP 8.5.4 + Apache prefork/mod_php。

www-data 意味着什么,做运维的都懂。它意味着你的 wp-config.php、你的 .env、你的数据库密码文件,全都在这个权限的射程之内。
三、"无法在代码层防御"≠"你什么都做不了"

那张图里最要命的一句话是:
"防御的唯一有效方式是在服务器基础设施层面直接更新 PHP 版本。"前半句对,后半句错。

准确的说法是:代码层防不住,但配置层能挡住已经公开的攻击路径。

区别在哪?看这张表:

层 有没有用 说明
业务代码(中间件、控制器、校验) ❌ 无效 执行顺序在漏洞触发点之后
PHP 应用内防护插件 ❌ 无效 同上,插件本身也是 PHP 代码
php.ini 配置开关 ✅ 有效(有条件) 直接关掉漏洞所在的代码路径,在请求解析阶段就生效
网关 / WAF 规则 ✅ 部分有效 能挡住已公开 PoC 的请求特征,但只是减速带
升级 PHP 运行时 ✅ 根治 唯一完整解

那个"成本近乎为零"的开关

复制代码
session.upload_progress.enabled = Off

为什么它有用?因为这个功能默认开启,而绝大多数业务根本不用它。不用上传进度条的项目,关掉它没有任何副作用------代价只是"如果你有基于它的上传进度条,进度条会失效"。

但这里有几个坑,很多人今晚会踩:
坑 1:ini_set() 无效。

PHP 在读取上传数据时就处理这个逻辑,早于你的代码执行,所以运行时 ini_set() 改不了它(会返回 false)。必须改配置文件,然后重载服务。
坑 2:改错文件。

Debian/Ubuntu 上要改的是 FPM 或 Apache 那份 php.ini,不是 CLI 的那份 。改完 php -v 看着正常,其实网站一点没变。
坑 3:只改了一个 pool。

多 pool 部署时,要用 php_admin_flag[session.upload_progress.enabled] = off 逐个 pool 设,或者放进 conf.d/ 统一覆盖。

按环境对号入座:
PHP-FPM(推荐)
生效方式:conf.d/ 放 99-php2shell.ini,写 session.upload_progress.enabled = Off,reload FPM

实测反馈:✅ 生效
PHP-FPM 单 pool
生效方式:pool 文件里 php_admin_flag[session.upload_progress.enabled] = off

实测反馈:✅ 生效
共享主机(FPM/CGI)
生效方式:站点根目录 .user.ini(注意 user_ini.cache_ttl 默认 300 秒才生效)

实测反馈:✅ 生效
Apache + mod_php
生效方式:vhost 里 php_admin_flag session.upload_progress.enabled off

实测反馈:⚠️ 用 vhost,不要依赖 .htaccess 的 php_flag
官方 Docker 镜像
生效方式:conf.d/ 挂载 ini 文件后重新构建/重启容器

实测反馈:⚠️ 必须重建镜像

顺手查一遍你现在是什么状态(没有任何输出 = 功能开着):

复制代码
grep -rnE 'session\.upload_progress\.(enabled|name)' \
  /etc/php/ /etc/php.ini /etc/php.d/ /etc/php-fpm.d/ /usr/local/etc/php/ 2>/dev/null

第二层:给 WAF 加一条规则

已公开的 PoC 请求,基本都带那个默认字段名 PHP_SESSION_UPLOAD_PROGRESS。所以一条 ModSecurity 规则就能拦:

复制代码
SecRule ARGS_POST_NAMES "@streq PHP_SESSION_UPLOAD_PROGRESS" \
  "id:1026109618,phase:2,deny,status:403,log,t:none,\
  msg:'PHP session upload progress field (interim, PHP CVE-2026-109618/109619)'"

前提:SecRequestBodyAccess On。有分析者实测过------带该字段的上传返回 403、PHP 没写入任何东西,正常上传和页面访问仍是 200。

但请记住这句话:WAF 是减速带,不是刹车片。 内存破坏类漏洞,特征规则天生容易漏;而且在官方细节公开前,安全厂商的虚拟补丁本质上是"盲写"。等真规则出来,还是要打补丁。
一个必须说清楚的边界

session.upload_progress 这条线索,目前只是研究者的分析,官方尚未确认。

更要命的是:J4ck3LSyN 自己的说法是,关掉这个开关只能挡住两个漏洞中的一个(另一个在 multipart 解析器里)。

所以正确的姿势是:
关开关,是为了在补丁到达前的这几个小时里,把"已知的那条路"堵上;
打补丁,是为了把"所有路"堵上。
前者是买时间,后者才是解决问题。
四、按你的版本,分三档处置

先看清楚你站在哪儿:

分支 当前版本 官方支持状态 今晚能不能拿到补丁
8.5 8.5.11 主动支持至 2027-12-31 ✅ 能
8.4 8.4.26 主动支持至 2026-12-31 ✅ 能
8.3 8.3.35 仅安全修复至 2027-12-31 ✅ 能
8.2 8.2.34 仅安全修复至 2026-12-31 ✅ 能
8.1 / 8.0 / 7.x / 5.x --- 已 EOL ❌ 不会有

数字很难看:安全公司 Mallory 对 Shodan 的统计显示,10 月 20 日有约 884,000 台 对外暴露的主机,HTTP banner 报告自己跑的是 PHP 8.1 或更早------占所有上报 PHP 版本主机(约 150 万台)的 59%。另有约 74 万台报了 PHP 但没说版本。

也就是说:一半以上的 PHP 网站,今晚等不到自己的补丁。
第一档:你在 8.2 -- 8.5

今晚 22:00 前做完三件事:

  1. 点名:谁负责这台机器上的 PHP?不是"运维组",是一个人。

  2. 清点 :别只看主站。容器镜像、/opt、/usr/local、/srv 里藏着的 PHP、cPanel/Plesk 自带的多版本、第三方设备内嵌的运行时,全都要列。

  3. 备份 + 回滚方案:网站文件 + 数据库,今晚之前做完。补丁翻车是真实存在的风险。

复制代码
# 主版本
php -v
# 实际在跑的 SAPI
ps aux | grep -E "php-fpm|php-cgi|apache2|httpd" | grep -v grep
# 藏在非标准路径的 PHP
find /opt /usr/local /srv -xdev -type f \( -name 'php' -o -name 'php-fpm*' -o -name 'php-cgi*' \) -perm -u+x 2>/dev/null

补丁落地后:升级 → 重启 FPM 和 Web 服务器 → 用真实请求验证版本真的变了(不要只看文件替换成功,php -v 和 phpinfo() 都过一遍)→ 如果走发行版包或托管平台,去问供应商的回溯补丁到位没有。
第二档:你在 8.0 / 8.1

官方不会救你。三选一:

  1. 迁到 8.3/8.4/8.5(正确但慢);

  2. 找发行版或主机商的回溯补丁(快,但要看运气);

  3. 今晚就做网络隔离:下线非必要系统、套 VPN、上白名单。CERT-EU 的原话是"考虑在补丁可用前,把对外应用从公网隔离"。

同时把第三节那个开关务必关掉------这是你唯一的缓冲垫。
第三档:你在 5.x / 7.x

说难听点:这不是"今晚"的问题,是"这三年"的问题。

一个 7.4 的项目能活到 2026 年,通常不是因为技术选型,而是因为没人敢动它。但今晚之后,它可能从"技术债"变成"安全事故"。

今晚能做的:断网/白名单 + 关开关 + 有人盯着日志。明天该做的:排迁移。
如果你是共享主机 / 面板用户

你控制不了宿主机的 PHP 版本。你要做的是发工单,问三个问题:

  1. 你们什么时候升级到含修复的版本?

  2. 我的站点实际跑的是哪个 PHP 版本?

  3. .user.ini 能不能生效?

别等公告。今晚就问。
五、打完补丁才是真正的开始

这是最容易被跳过、也最容易出事的一步。

原因很简单:漏洞细节在补丁发布前就泄露了,补丁一发布,diff 就是说明书。 攻击者不需要猜,直接看代码改动反推触发条件。历史参照很扎心:2024 年 6 月 CVE-2024-4577(PHP CGI 模式漏洞)公开后,Akamai 在 24 小时内 就观测到蜜罐被扫。而这次,Sansec 给的预期是 15 分钟。

补丁和攻击之间,几乎没有窗口。

所以在升级完 PHP 之后,按"假定失陷"做四件事:

  1. 看 PHP 有没有生出不该生的孩子

正常的 php-fpm 不该启动 shell、不该起 curl/wget/nc、不该跑 python。Huntress 的建议很具体:监控 php-fpm / php-cgi / httpd / apache2 派生的子进程,重点看命令行里有没有 /dev/tcp/、mkfifo、fsockopen,以及 whoami、id、uname -a 这类侦察命令。轻量方案可以用 Florian Roth 的 process-watcher(它只记录,不拦截)。
2. 找 webshell

复制代码
# 10/20 之后被动过的 PHP 文件
find /var/www -type f -name '*.php' -newermt '2026-10-20' 2>/dev/null
# 常见 webshell 特征
grep -rlE 'eval\(|base64_decode\(|assert\(|system\(|passthru\(|shell_exec\(' /var/www 2>/dev/null

重点看上传目录、缓存目录、uploads/、tmp/。
3. 翻日志找探测痕迹

查访问日志里带 PHP_SESSION_UPLOAD_PROGRESS 的 multipart 请求、异常的 POST 频率、以及 PHP worker 的异常退出/崩溃记录(长亭那条复现路径,在 release 构建上就是直接 SIGSEGV,崩溃日志本身就是入侵信号)。
4. 换凭据

如果某台机器在补丁前就对外暴露、且你无法证明它是干净的,那就按已失陷处理:轮换数据库密码、API Key、.env 里的所有密钥。

这四步做完,今晚基本就稳了。像这种"照着抄就行"的清单,我平时会发在 TaonyDaily 上------比起转发预警图,我更愿意给你能直接跑的命令。
写在最后

这次事件里,我最想让你记住的不是 CVSS 9.2。

是那个数字:15 分钟。

过去二十年,我们的补丁节奏建立在一个假设上------从"漏洞公开"到"大规模利用",中间有几周。所以我们可以周二扫描、按 SLA 打补丁、月度汇报。

现在这个假设塌了。厂商的期望是 15 分钟,脚本小子的自动化是 2 到 6 小时逆向 diff。
你的流程,是按 15 分钟设计的吗?

如果不是,那今晚真正该修的,可能不只是那台服务器。

还有一件事,也想留给你:

今天早上那张预警图,把"CVSS 10.0"、"PHP 5.4 起全部受影响"、"唯一办法只能升级"混在一起发出去,三个小时内传遍了十几个群。它说的核心事实没错,但它用三个被放大的数字,换来了一次转发。

下次再看到这种图,先问三个问题:

  1. 这个数字,是官方的还是泄露的?

  2. 这个范围,是确认的还是工具自己写的?

  3. 这个"唯一办法",是不是在替某个产品铺路?

预警本身,也需要被预警。

至于今晚------22:00,php.net。别刷群,刷官网。

如果这篇帮你在今晚少踩一个坑,转给那个还在机房加班的运维朋友。他大概正对着那张预警图发愁。
关注 TaonyDaily,把「预警」变成「预案」

• 事件类:一手结论 + 可复制命令,比群里的预警图快一步,也准一点

• 技术类:Go / PHP / 架构实战,讲清"为什么这么设计",不搬运文档

• 工具类:文中这些脚本、配置、检查清单,验证过才发

点文章上方蓝字「TaonyDaily」→ 关注。不日更,但每篇都值得存。

参考来源

1PHP 官方公告《Upcoming Critical PHP Security Release》,2026-10-20

https://www.php.net/archive/2026.php#2026-10-20-1

用于:补丁时间、CVSS 9.2、保留提前发布权、"细节随发布公布"

2watchTowr FAQ: php CVE-2026-109618

https://watchtowr.com/intelligence/php-cve-2026-109618-faq/

用于:漏洞真实性、已复现 109618、"影响范围未获确认"、在野利用状态

3Ars Technica《PHP warns it plans to release 2 emergency patches imminently》,2026-10

用于:泄露帖内容与删除、Sansec"15 分钟"判断、演示覆盖的应用清单、130 万主机估算

4Huntress《Rapid Response: php2shell, Leaked Critical PHP Vulnerabilities》

https://www.huntress.com/blog/php2shell-leaked-critical-php-vulnerabilities

用于:子进程监控清单、webshell 排查思路、PoC 状态说明

5CERT-EU Security Advisory 2026-018(Critical Vulnerabilities in PHP)

用于:未认证 RCE 定性、隔离建议

6长亭安全应急响应中心漏洞通告(2026-10-21)

用于:PHP 8.5.11 + Apache 2.4.68 复现 3/3 SIGSEGV、UAF 成因分析、临时缓解建议

7上海交通大学网络信息中心《关于 PHP Core 存在远程代码执行漏洞的风险预警》

https://net.sjtu.edu.cn/info/1016/7818.htm

用于:缓解措施、PHP_SESSION_UPLOAD_PROGRESS 拦截思路

8GMO Flatt Security 分析(经 IT-Connect 2026-10-21 转述)

https://www.it-connect.tech/php-zero-day-alert-two-critical-flaws-leak-early-emergency-patch-due-october-21

用于:session 扩展内存破坏判断、视频日志中的 www-data/Ubuntu 26.04/PHP 8.5.4 环境、各环境配置方法

9J4ck3LSyN 技术分析(经 lilting.ch 汇总)

https://lilting.ch/en/articles/php2shell-session-upload-progress-uaf

用于:php_session_rfc1867_callback() 定位、第二个漏洞在 multipart 解析器、缓解只覆盖其一

10PenTestIT《PHP CVE-2026-109618 and CVE-2026-109619: What We Know about php2shell》

https://pentestit.com/php-cve-2026-109618-and-cve-2026-109619-what-we-know-about-php2shell

用于:ini_set() 无效、各环境配置生效实测、ModSecurity 规则与实测结果、PoC 已带该字段

11Mallory 基于 Shodan 的暴露面统计(经 techno.express 2026-10-21 转述)

用于:884,000 台 ≤PHP 8.1、59%、150 万台、74 万台未报版本

12SecureLayer7《PHP RCE CVE-2026-109618 & 109619: What To Do Now》

https://blog.securelayer7.net/php-rce-cve-2026-109618-109619

用于:WAF 定位为减速带、补丁后"假定失陷"排查清单、CVE-2024-4577 对比

130dayNews《PHP Issues Emergency Patches for Two Critical RCEs》,2026-10-21

用于:补丁仅覆盖 8.2--8.5、CISA KEV 状态、泄露帖 CVSS 10.0 的来源
说明事项

• 本文所有事实性陈述均标注来源。凡属"未经官方确认"的信息(尤其受影响版本范围、root cause 归属、预期修复版本号),文中已明确标注,不作为结论使用。

• 关于"PoC 是否已公开",公开信息存在冲突:Huntress 表示未见到公开利用代码,另有分析者称 PoC 已可获取。本文按"应视为已公开"的最坏情况给出处置建议。

• 本文所述技术细节以 2026 年 10 月 21 日补丁发布前可查的公开信息为准。补丁于 22:00 发布后,受影响版本、修复版本与 root cause 均应以 php.net 官方公告为准,本文相关表述需随之更新。

• 文中命令与配置建议需按自身环境验证后执行,涉及生产环境变更请先备份并准备回滚方案。

本文信息以 2026 年 10 月 21 日补丁发布前的公开信息为准。补丁发布后,受影响版本、修复版本与技术细节以 php.net 官方公告为准。