PHP 是世界上最好的语言!

曾经,这是编程界热度最高的梗。
如今,这个梗的含金量还在上升。
要知道,PHP 支撑着互联网上很大一部分网站,政府服务、网上商城、银行、媒体网站都有用到它。也正因为用的人太多,它一出漏洞,波及的就是一大片网站。
10 月 21 日晚上,PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。两个漏洞的评分都是 9.2 分(满分 10 分),被安全圈称为 PHP2Shell。
攻击者不需要登录,只要给你的网站发送特殊构造的请求,就有可能在服务器上执行任意代码!

这次参与发现漏洞的团队里,至少有两家公开表示用上了 AI。按照 PHP 基金会的说法,其中内存超限那个问题,早在 2024 年的一次安全审计中就露出过苗头,只是当时没有找到真正能利用它的方法。直到今年 8 月起,完整的攻击方式才被陆续报告出来。
更要命的是,攻击已经开始了。亚马逊、watchTowr 等安全厂商都监测到了针对这两个漏洞的攻击尝试,亚马逊甚至在官方公布漏洞的 4 天前就抓到过一次。
我团队的同学看到消息之后,第一时间检查了服务器,我也专门写了这篇文章来提醒大家。
下面我先用大白话讲讲这两个漏洞是怎么回事,再说说程序员朋友们应该如何应对。
1、两个漏洞是什么?
要理解这两个漏洞,得先知道 PHP 是怎么处理网页请求的。
你可以把服务器上的 PHP 想象成一家餐厅。每当有用户访问网站,就相当于来了一桌客人,PHP 会派一个服务员来接待,这个服务员就是 PHP 的工作进程。
服务员会给这桌客人分配一张桌子,也就是一块内存。为了防止有人霸占太多位置,每张桌子能用的空间是有上限的。
而且服务员不是一次性的,他接待完一桌、收拾干净之后,会接着接待下一桌。也就是说,同一个工作进程会接连处理很多个请求。

漏洞 1 - 内存超限后没收拾干净
第一个漏洞(CVE-2026-109618)出在内存超出上限的时候。
PHP 的规矩是,一旦某桌用的空间超过上限,服务员就立刻放下手里的活离开,不管当时做到了哪一步。
问题在于,服务员离开的时候可能刚摆台摆到一半,桌上有一块地方还没来得及铺上新桌布,上面还留着之前的东西(也就是这块内存里残留的旧数据)。
随后负责收尾的店员(也就是 PHP 结束请求时的清理流程)过来收拾,以为这桌都已经按流程摆好了,就把这块没准备好的地方也当成正常的东西来处理。
攻击者利用的就是这一点。他先想办法在那块地方留下一张写着指令的纸条(也就是攻击者精心构造的数据),再故意让这桌超出上限。收尾的店员看到纸条,以为是店里正常的安排,就照着上面的指令去做了。

那攻击者怎么让内存超限呢?
他会发送一种特殊构造的表单请求,比如用文件上传那种格式(multipart/form-data)。这种请求在网络上传输时看起来并不大,能通过 PHP 的大小检查,但 PHP 解析它的时候,会占用更多内存。
注意,这跟你的网站有没有上传功能无关。只要请求打到了 PHP 页面上,PHP 都会自动解析这类请求。
更麻烦的是,如果用的是 mod_php(把 PHP 直接装进 Apache 里运行),这一切都发生在 PHP 解析请求内容的阶段,你写的业务代码还没开始运行。
也就是说,这个漏洞出在 PHP 自己身上,跟你的代码写得好不好没有关系,代码写得再规范也拦不住。
漏洞 2 - 上一桌的旧记录没擦掉
第二个漏洞(CVE-2026-109619)出在同一个工作进程接连处理两个请求的时候。前一个请求留下的数据没有清理干净,后一个请求又把这些失效的数据当成有效数据来用了。
这个问题还是用餐厅来类比,会更好理解。
服务员手上有一个记事本(也就是 PHP 的全局状态),记着当前这桌客人的信息,比如坐在哪张桌子、东西放在哪里。按照规矩,一桌客人离开之前,服务员要把记事本上的这一页擦掉。
但如果这桌客人突然出了意外(也就是请求处理时发生了严重错误),被紧急送走了,服务员一着急就忘了擦记事本。可这张桌子已经被收回去,转手分给了别人(也就是这块内存已经被释放,又被重新分配出去了)。
等到下一桌客人坐下,服务员还没来得及翻到新的一页,就照着旧记录去原来那张桌子上拿东西。而这时候桌上摆着的,已经是攻击者提前放好的东西了。

对应到真实的攻击中,攻击者会先发一个请求,让 PHP 发生严重错误,再发一个请求,让同一个工作进程照着旧记录办事。这样一来,他就有机会控制服务器,或者读到内存里残留的其他数据。
官方已经确认了两条攻击路径。一条是 PHP 的上传进度跟踪功能,这个功能默认就是开启的,哪怕你的网站代码里从来没用过它,它也可能被触发。另一条只存在于 PHP 8.5,跟它新增的致命错误回溯功能有关。
按照 PHP 官方的说法,所有处理网页请求的 PHP 都在风险范围内,包括 PHP-FPM、Apache mod_php 这些常见的运行方式,其中 mod_php 的风险最高(PHP-FPM 也不安全)。
这两种运行方式的区别在于 PHP 跟网站服务器的关系。PHP-FPM 是让 PHP 作为一个独立的服务运行,再由 Nginx 这类网站服务器把请求转交给它,宝塔面板用的就是这种方式。mod_php 则是前面提到的,把 PHP 直接装进 Apache 里运行,官方已经验证过,攻击者在这种方式下能赶在业务代码运行之前发起攻击。

目前官方已经发布了修复版本,分别是 8.2.35、8.3.36、8.4.27 和 8.5.12。8.1 及更老的版本官方已经不再维护,只额外给 7.4、8.0、8.1 提供了源码补丁。7.3 及更老的版本连源码补丁都没有,只能迁移到新版本。

官方还特别强调,目前没有任何配置能完全替代升级,升级是唯一安全的选择。
2、如何处理
知道了漏洞的原理和影响范围,接下来就该检查自己的服务器了。
很多同学会用宝塔面板来管理服务器,我自己的部署教程里也经常用它,所以下面主要以宝塔为例来讲。
宝塔面板本身是用 Python 开发的,不是 PHP 程序,所以面板不会因为这次漏洞直接受到影响。但是通过宝塔安装的 PHP 在受影响的范围内,需要你自己处理。
先看看服务器上有没有装 PHP。登录宝塔面板,进入「软件商店」,切换到「已安装」列表,再搜索 PHP,就能看到装了哪些版本。

如果服务器上装了多个 PHP 版本,要逐个检查,别漏掉还在运行的旧版本。
另外,宝塔的软件商店里只能看到通过宝塔装的 PHP。如果你还用 apt 或 yum 命令装过 PHP,在这里是看不到的,要在终端执行 dpkg -l | grep php(Ubuntu、Debian)或者 rpm -qa | grep php(CentOS、RHEL)来查。
确认装了 PHP 之后,就要看你到底用不用得到它,分两种情况来处理。
情况 1 - 用得到 PHP
如果你的网站本身就是用 PHP 开发的,比如 WordPress 搭的博客,那就要尽快升级。
宝塔官方在 10 月 21 日当天就发布了紧急公告,PHP 官方的 4 个修复版本都已经同步上架。对于 7.4、8.0、8.1 这三个 PHP 官方停止维护的版本,宝塔也自己打上补丁,给 Linux 面板重新打包了修复版。

如果你用的是 Windows 版宝塔,8.1 及更早的版本目前还没有修复包,只能先按下文的方法修改配置临时缓解,然后尽快迁移到新版本。
升级方法也不复杂。先备份好网站和配置,然后还是在刚才的「已安装」列表里,点击右上角的「更新软件列表」,再找到网站正在使用的 PHP 版本,点击「更新」就行。
升级完成之后,记得检查一下网站能不能正常访问。
如果你没用宝塔,而是通过系统软件源安装的 PHP,处理方法也差不多,把 PHP 升级到包含补丁的版本,再重启 php-fpm 或者 Apache 就行。
不管用哪种方式升级,都别以为升完就稳了。攻击在漏洞公布之前就已经出现,而且攻击成功之后网站照样能正常访问,你很难察觉。所以如果你的服务器在升级前一直对外开放,最好顺手看看有没有陌生的进程和文件,必要时把数据库密码、API 密钥这些也换一下。(可以让 AI 帮忙检测)
如果暂时没办法升级,可以先修改 PHP 的配置文件 php.ini,做这几项临时缓解:
- 把
session.upload_progress.enabled设置为 0,关闭上传进度跟踪功能 - 如果用的是 PHP 8.5,再把
fatal_error_backtraces也设置为 0 - 把
post_max_size调小一点,网站不需要上传就设成 8M,需要上传就设成 32M,并且让upload_max_filesize小于它,降低漏洞 1 的风险
改完之后要重启 PHP 才能生效。不过这些都只能堵住部分已知的攻击路径,最终还是要升级。
情况 2 - 用不到 PHP
之前我在好几个项目的部署教程里,都推荐大家第一次进入宝塔时安装 LNMP 套件。这个套件除了 Nginx 和 MySQL,还附带了 PHP 和 phpMyAdmin。
可那几个项目都是 Java 后端 + 前端,其实根本用不到 PHP。
那装了但没用到,到底有没有风险呢?
在宝塔里,PHP 安装好之后会作为一个服务一直运行。你创建网站的时候如果选择了 PHP 版本,Nginx 就会把 PHP 请求转交给它处理。phpMyAdmin 本身也是一个 PHP 程序,只要装了它,服务器就在用 PHP。
另外,只要服务器上装了 PHP,也得留个心眼。比如在 Ubuntu 系统上,如果你直接执行 apt install php 命令,系统默认会顺带装上 Apache 和 mod_php,正好是官方认为风险最高的组合。
所以我的建议是,用不到 PHP,就直接卸载。
少装一个软件,就少一个被攻击的入口,下次再出漏洞也不用再排查一遍了。
我们团队的项目用不到 PHP,所以这次就直接卸载了:

注意,卸载之前要先去网站列表里确认一下,没有网站在使用这个 PHP 版本,不然这些网站就访问不了了。phpMyAdmin 依赖 PHP 运行,如果你平时用不到,也可以一起卸载。
最后哔哔
再次强调,这次的两个漏洞藏在 PHP 最底层的内存管理和错误处理里,跟你写的业务代码关系不大,能做的就是尽快升级或者卸载。
用得到 PHP 就升级到修复版本,用不到就直接卸载,千万不要有侥幸心理!(来自一个常年被打的鱼皮提醒)








