10 月 21 日,PHP 官方发了一组紧急安全版本。名字叫 PHP2Shell,两个编号:CVE-2026-109618 和 CVE-2026-109619,PHP 安全团队给的评分都是 CVSS v4.0 9.2。

这条我一开始没当回事——安全圈每周都有"9.9 分严重漏洞"。看了两眼才坐直:洞在 PHP 引擎本身,不是某个插件、某个框架、某个面板;无需登录,一个特制的 multipart POST 请求就能打;影响面从 PHP 5.4 起步。公开的利用代码已经流出来了,安全厂商的判断是"发布后十几分钟内就会出现大规模扫描"。

对绝大多数人来说,这就意味着:今天要做的不是"研究一下",是"查版本、升级"。

这两个洞到底坏在哪

编号类型说明
CVE-2026-109618RCE内存不足(OOM)的处理路径被破坏,可被诱导执行任意代码
CVE-2026-109619RCE全局状态残留,跨请求的数据没被清干净,被拼成可利用的状态

两个都是未认证远程代码执行,也就是直接拿 shell。不需要账号,不需要诱导管理员点链接,不需要任何交互。

特别说一句 109619 那条:在 PHP-FPM 模式下,它能顺着 session.upload_progress 这条路打进去——而这个特性默认是开着的。很多人做加固盯的是 disable_functions、是上传目录权限,却从没看过这个开关。

影响范围:先对版本号

公开口径是 PHP 5.4 及以上均可能受影响。不止新站——一批跑着老版本的存量业务也在射程里。

官方给出的修复版本:

分支修复版本
8.58.5.12
8.48.4.27
8.38.3.36
8.28.2.35

8.1 及以下要分清楚说(这块最容易被传错):

  • 官方对 8.1 及以下不再发正式版本;
  • 但安全团队额外维护了 7.4 / 8.0 / 8.1 的源码 backport 分支,会自己编译的可以跟;
  • 部分发行版和 LTS 厂商也会 backport,值得去对应厂商的安全公告里确认一下;
  • 7.3 及以下确实没有任何官方或 backport 来源——只能升级,或者做临时缓解。

风险大小还跟 Server API 有关:mod_php(Apache 处理器模式)风险最高,FPM 相对低一些但不是安全区,php-cgi 也一并按暴露处理。所以别因为自己是 FPM 就放心。

第一步:确认自己跑的是哪个版本

php -v

这里有个老坑:命令行看到的 PHP 版本,不一定等于网站实际用的版本。宝塔、cPanel、多版本共存的机器上,nginx / Apache 挂的往往是另一个 php-fpm。稳妥的办法是看 web 真正在用的那个:

ps aux | grep -E 'php-fpm|php-cgi' | grep -v grep

或者直接问网站自己(临时放个探测文件,看完立刻删):

echo '<?php echo PHP_VERSION;' > /www/wwwroot/你的站点/v.php
curl -s https://你的域名/v.php; echo
rm -f /www/wwwroot/你的站点/v.php

顺手看一眼 phpinfo() 里的 Server API 那一行,确认是 mod_php 还是 FPM。

第二步:升级

Debian / Ubuntu:

sudo apt update
sudo apt install --only-upgrade php8.3-fpm php8.3-cli
php -v && sudo systemctl restart php8.3-fpm

把 8.3 换成你在用的分支;用 ondrej PPA 的话先确认源里已经出了新版本。

RHEL / CentOS / Rocky:注意 Remi 源在发布当天并不保证同步更新,官方建议优先用发行版自身的包或源码编译。硬跑 dnf --enablerepo=remi-php83 update php 很可能白跑一趟,先看发行版公告。

sudo dnf update php
sudo systemctl restart php-fpm

宝塔面板:软件商店 → 对应 PHP 版本 → 升级。升级前先把自编译扩展记下来(redis、swoole 之类),升完确认扩展还在,不然站点直接 502。

源码编译:拉对应 tag 重编。注意 php(CLI)和 php-fpm 是两个二进制,两个都要换。

容器或托管环境升不了:找服务商要一份书面确认——他们的 PHP 什么时候打上补丁。

第三步:升完必须验证

php -v | head -1
systemctl status php8.3-fpm --no-pager | head -5
curl -sI https://你的域名 | head -1

三行分别是:版本到位、fpm 真的重启过(看启动时间)、站点还在跑。升级 PHP 最容易翻车的从来不是升级本身,而是扩展丢失和兼容问题。先拿一个站点验证,再全量推——尤其是跑着老框架的站。

升不了,怎么办

现实里很多业务卡在老版本上,程序升不动、框架不兼容。这种时候能做的是按官方口径做临时缓解,把攻击面收窄。

一句话讲清楚:缓解不是修复。它能挡掉批量扫描和现成的 exp,挡不住定向攻击。具体改哪几处、每条配置写在哪、怎么确认生效,值得单独写一篇——这里先不铺开。

小结

  • PHP2Shell = CVE-2026-109618 + CVE-2026-109619,CVSS 9.2,未认证 RCE
  • 影响 PHP 5.4+,修复版本 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12
  • 8.1 及以下没有正式版本,但有 7.4 / 8.0 / 8.1 的源码 backport;7.3 及以下什么都没有
  • mod_php 风险最高,FPM 也不是安全区
  • 升完三验证:版本、fpm 重启、站点可用

跟上周那个 Nginx 面板一晚上爆七个洞 有点像:都不是"写错了代码",而是基础设施层的东西你没盯着,它就在那儿等着。区别是这个洞在引擎里,覆盖面更大、窗口期更短。

今天顺手查一遍版本号,比下周在访问日志里看到一堆可疑 POST 强。平时要管一批机器的话,用七亿批量远程管理工具一条命令并行跑几十台 php -v,比一台台登上去快得多——真懒,也比不查强。