半个互联网连夜关站:PHP 爆出 9.2 分核弹漏洞,攻击量已破数百万次

10 月 22 日上午 9 点 25 分,Cloudflare CEO Matthew Prince 在 X 上发了一组数字,看得我头皮发麻:

关于 #php2shell 的一些统计数据。在它被公开宣布前的 10 小时内,在 @Cloudflare 网络上我们看到了数千次利用它的尝试。宣布后 45 分钟内,这一数字激增至数万次,2 小时内达到数十万次,现在已达数百万次。

数小时前还是”理论上的严重漏洞”,数小时后就是数百万人次的实弹射击。这不是一次普通的安全更新,这是 PHP 诞生三十多年来最接近”全球性事故”的一次。

如果你手上管着任何一台跑 PHP 的服务器——WordPress、Typecho、Discuz、Laravel、宝塔面板、群晖里的 Web Station——请先停下手上的事,看完第一节,然后去升级。

先把结论放在前面

  • 漏洞名:PHP2Shell,两个 CVE:CVE-2026-109618、CVE-2026-109619
  • 评级:CVSS 9.2(满分 10),无需账号、无需登录,一个 HTTP 请求就能触发
  • 影响:PHP 5.4 到 8.5 的所有版本,覆盖全球约 70% 的网站
  • 修复版本:PHP 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35(2026 年 10 月 21 日 14:00 UTC 发布)
  • 现状:PoC 已公开,全网扫描器在跑,Cloudflare 侧的攻击量已到百万级;NSA、FBI、CISA 同时发警告,德国、法国、荷兰、比利时、芬兰、捷克、日本都有政府站点临时下线

一句话:这不是”有空再修”的漏洞,是”现在不修就可能已经晚了”的漏洞。

一个请求就能拿到 shell,问题出在 PHP 自己身上

PHP2Shell 这个名字很直白:PHP to shell。

两个漏洞都出在 PHP 内核处理 HTTP 请求的内存管理上,跟你的代码写得好不好、插件是不是最新版,没有关系。PHP 官方说得很清楚:

  • CVE-2026-109618(内存耗尽型破坏):服务器内存吃紧时,PHP 会中断当前请求,但内部数据结构只初始化了一半。请求清理阶段会把这堆”半成品”当成合法数据来用,攻击者可以顺着这条路径劫持执行流。PHP 官方特别点名:mod_php 模式下风险最高,因为未认证的请求可以在任何应用代码执行之前就触发攻击。
  • CVE-2026-109619(跨请求的过期全局状态):一个致命错误打断请求后,PHP 仍然持有已经被释放的内存的引用。下一个落到同一个 worker 上的请求,会在正常初始化重置它之前用到这份”僵尸状态”,形成 use-after-free——可以读内存,也可以执行代码。

第二个尤其阴险。它意味着同一个 PHP 进程处理的上一个用户的请求,可能把数据漏给下一个用户。泄露的东西包括数据库密码、Session Token、API Key、TLS 证书私钥。Wiz 的演示里,攻击者甚至不需要拿到 RCE,光靠读内存就能把敏感信息捞走——这种攻击比 RCE 更难被”检测恶意进程”的工具发现。

Wiz 说这两个漏洞”是 PHP 历史上最严重的漏洞之一,也堪称软件史上最严重的漏洞之一”。它们的根子可以追溯到几十年前,但一直被认为”理论上存在、实际上不可利用”,直到 AI 把这条利用链拼了出来。

时间线:从”预告”到”破禁”,只用了一天

这件事最值得记录的不是漏洞本身,而是它崩坏的披露过程。

  • 8 月 11 日:Calif(参与 OpenAI “Patch the Planet” 项目)报告第一个漏洞
  • 8 月 24 日:Wiz 报告第二个漏洞。三家机构都承认,AI 模型在找洞过程中做了大量工作
  • 10 月 20 日 15:00 UTC:两个 CVE 编号开始在论坛和社交媒体上流传,还带着错误的发布时间和评分
  • 10 月 20 日:PHP 官方被迫提前一天发预警,把原定周四的发布改到周三;同一天,Calif “误发”了一段 PoC 演示视频
  • 10 月 21 日 03:02 UTC:Cloudflare 的 WAF 规则上线,免费版和付费版默认开启。这比官方披露早了大约 9 小时
  • 10 月 21 日 07:41 UTC:Chainguard 提前发布含修复的镜像,比协调披露时间早 6 个多小时
  • 10 月 21 日 14:00 UTC:PHP 正式发布 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35
  • 10 月 22 日:多国政府站点下线,NSA/FBI/CISA 联合警告

PHP 基金会在事后博客里直接点名 Chainguard”单方面撕毁禁运”——所有分发商都提前拿到了补丁,Chainguard 抢先构建了含修复的镜像,等于让攻击者可以对着二进制做 diff,在其他人还在等官方发布的时候就把洞看明白了。Chainguard CEO Dan Lorenc 的回应是”我们没泄露”,理由是禁运规则没写清楚,而且他们自己也用 AI 独立发现了同样的漏洞。

这场口水战谁对谁错,留给律师。对运维来说只有一句话:你的修复窗口,被别人的抢跑压缩到了几个小时。

攻击量为什么涨得这么疯

Prince 给的那条曲线,本质上是一条”武器化速度”曲线:

时间点Cloudflare 观测到的利用次数
公开宣布前 10 小时数千次
宣布后 45 分钟数万次
宣布后 2 小时数十万次
现在数百万次

三个推手:

  1. PoC 是现成的。Calif 误发的视频、随后流传的利用代码,让脚本小子的门槛降到”复制粘贴”。
  2. 目标太好找。Shodan、FOFA 上一筛就是几百万个暴露的 PHP 服务,Unit 42 统计有 2260 万个 互联网暴露实例可能受影响。
  3. AI 在攻防两端同时加速。找洞用 AI,写变种 payload 也用 AI。Cloudflare 说他们观察到攻击者在根据 WAF 规则反复变形 payload,试图绕过检测。

所以这次不是”某个插件爆雷,等作者更新”的节奏,而是”全网的扫描器已经把你的域名放进队列”的节奏。

现在该做什么:按顺序来

第一步:查你到底是什么版本

别信面板首页那行字,要查真正跑在 FPM 里的二进制:

# CLI 版本(不一定等于网站用的版本)
php -v
php-fpm -v

# 找到站点实际使用的 socket / 进程
ps aux | grep php-fpm
ls -l /proc/$(pgrep -f 'php-fpm: master' | head -1)/exe

WordPress 用户可以在站点根目录临时放一个 info.php:

<?php phpinfo(); ?>

访问后看 PHP Version,看完立刻删掉。更稳妥的方式是看面板里的 PHP 版本,或者用 wp --info(WP-CLI)。

对比一下:

分支受影响版本修复版本
8.5< 8.5.128.5.12
8.4< 8.4.278.4.27
8.3< 8.3.368.3.36
8.2< 8.2.358.2.35
8.1 及更早全部官方已停止支持,仅有源码级 backport

第二步:升级,然后重启

# Debian / Ubuntu(Ondrej PPA 或发行版源)
sudo apt update
sudo apt install --only-upgrade 'php8.4-*'
sudo systemctl restart php8.4-fpm

# RHEL / Alma / Rocky
sudo dnf update 'php*'

# Docker:拉新镜像重建,别只 restart
docker pull php:8.4-fpm
docker compose up -d --force-recreate php

几个坑:

  • 只 apt upgrade 不重启 FPM,等于没修。老进程还在内存里跑着旧代码。
  • CLI 升级了不代表 FPM 升级了。很多机器 CLI 是 8.4、网站跑的是 8.2,两个都要看。
  • remi 源这次没有当天更新。PHP 官方专门提醒用 rpms.remirepo.net 的人切换到发行版包或自己编译。宝塔编译安装的 PHP 要等面板推新版本,如果面板还没跟上,临时方案是切到系统源里的新版 PHP,或者先做下一节的缓解。
  • WordPress 后台的自动更新修不了这个洞。它更新的是 WP 核心和插件,不是 PHP 运行时。托管主机用户请直接开工单,把这条 CVE 编号甩给客服。

第三步:补不上?先按官方清单收紧

PHP 官方说得很直白:”没有任何完整的缓解措施,升级是唯一安全的选择。”下面这些只能减少特定攻击路径的成功率,不能让你变安全:

; php.ini 或 FPM pool 配置(php_admin_value)
memory_limit = -1
post_max_size = 32M
session.upload_progress.enabled = 0
display_errors = 0
fatal_error_backtraces = 0

注意两点:

  • memory_limit = -1 是把内存耗尽的风险转交给操作系统,必须配合 cgroup v2 的 memory.max 做兜底,否则一个请求就能把整台机器拖垮。不要用 RLIMIT_AS / RLIMIT_DATA 代替,那会触发同一条脆弱路径。
  • session.upload_progress.enabled = 0 必须写在 FPM pool 或 php.ini 里,ini_set() 和 .user.ini 不生效——它们在请求解析之后才执行。

改完一样要重启 worker。不重启,配置只是躺在文件里。

第四步:当作”可能已经被打过”来排查

这一点很多人会跳过。因为这个漏洞能读进程内存,即使没有 RCE,凭据也可能已经泄露。

# 1. 一周内被改过的 PHP 文件
find /var/www -name '*.php' -mtime -7 -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort -r | head -50

# 2. 可疑的大 POST / multipart 请求
grep -E 'POST .*(multipart|upload_progress)' /var/log/nginx/access.log | tail -50

# 3. WordPress 完整性
wp core verify-checksums
wp plugin list --status=active
wp user list --role=administrator

然后换掉所有能换的密钥:数据库密码、wp-config.php 里的 salts、对象存储 AK/SK、支付和短信接口的 Key、SSH 密钥。如果服务器上还跑着别的站点,一并按”已失陷”处理。

最后检查 /tmp、/dev/shm、wp-content/uploads 里有没有陌生的可执行文件,以及 crontab -l 和 /etc/cron.d 里有没有陌生任务。

几个必须纠正的误解

“我装了 Wordfence / 云 WAF,没事。” WAF 是创可贴,不是手术。Cloudflare 自己都说,请客户”在打补丁的同时保持 WAF 开启”。而且这次攻击在披露前就已经开始,WAF 规则是抢在披露前 9 小时上线的——你能被保护,是运气好,不是理所当然。

“我用的是最新版 WordPress。” WordPress 版本和 PHP 版本是两回事。WP 再新,底下的 PHP 是 8.1,照样中招。

“PHP 7.4 早就停止支持了,应该没人打。” 恰恰相反,老版本没有官方补丁,是这次最危险的一批。PHP 官方给了 7.4/8.0/8.1 的最小源码 backport,但需要你自己编译;发行版和 LTS 厂商也可能有回移补丁,值得先查一下。

“我的网站小,没人会盯上。” 这次的攻击是全网无差别扫描,不是定向打击。攻击者要的是”能用的服务器”,不是”有价值的服务器”——你的机器可以拿去发垃圾邮件、当代理、挖矿。

写在最后

过去我们习惯了”漏洞公布→等厂商→下周打补丁”的节奏。PHP2Shell 把这个节奏压到了小时级:漏洞细节提前泄露,补丁镜像提前发布,PoC 视频误发,AI 让写利用代码的成本趋近于零。

这次 AI 帮防守方抢到了几个小时的先手——Wiz 和 OpenAI 用它找洞,Cloudflare 用它写规则,PHP 基金会用它验证修复。但同一个工具在攻击者手里,效率是一样的。

对个人站长来说,能做的其实很朴素:把 PHP 版本管理当成日常,而不是事故。 订阅 php.net 的安全公告,给服务器开自动安全更新,别把 PHP 8.1 用到 2028 年。

毕竟下一次,未必还有 9 小时的提前量。


参考来源:PHP 官方安全公告(2026-10-21)、Cloudflare 博客《Cloudflare deploys protections against php2shell vulnerability》、Wiz Research、The Hacker News、BleepingComputer、The Register、Al Jazeera、Unit 42、CISA 公告。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

奇客罗方公众号 奇客罗方小程序 奇客罗方客服 ITGeeker Telegram

网站由ITGeeker技术奇客开发并管理;隶属于GeekerCloud奇客罗方智能科技
Site designed and developed by ITGeekerwhich is a sub-website of GeekerCloud
网站地图 | 沪ICP备2021031434号-4