PHP 挺实用主义的,这一点没什么争议。这么多年来它的处境一直有点微妙:大量网站和 Web 应用还靠它撑着,技术圈里聊它的声音却越来越少。隔三差五就有人宣布 PHP 已死,语气像是再过两年这门语言就该退场了。
结果昨天它真火了一把,火的方式谁也没想到。
这次不是哪个框架发布新版本,也不是哪个大厂宣布全面拥抱 PHP,而是 PHP 自己曝出了两个严重的安全漏洞。严重到什么程度?日本首相高市早苗亲自在 X 上呼吁相关组织尽快准备并应用修复补丁,美国国家安全局(NSA)也发了安全提醒,建议暂时无法完成修复的组织考虑把系统下线。
欧洲多个网络安全机构随后联合发出警告,一些政府网站、公共服务和商业平台也采取了紧急维护甚至临时下线。
消息传回国内,又被各种视频号、公众号和某乎某书疯狂传播。
我甚至开始有点不敢刷短剧了,真的很怕刷到下面这种雷霆剧情:
公司:现在已经进入 AI 时代了,所以不需要 Web 系工程师了!
PHP 开发:天要亡我,被炒鱿鱼了,呜呜呜。
国家网络安全局:什么!PHP 暴露出了致命弱点?我们有多少站点使用了 PHP!AI 无法修复吗!
公司:救、救命啊,救救我吧!
没办法,事已至此,把会 PHP 的人全部都叫醒吧!
什么!你!你居然会 PHP!
光是想想就绷不住。
玩笑归玩笑,这次确实不是一次普通的安全更新。
PHP 官方在 10 月 21 日公布了两个严重漏洞,编号分别是 CVE-2026-109618 和 CVE-2026-109619,严重性评分都到了 9.2 分(满分 10 分)。
更麻烦的是,它们可能让攻击者在没登录、不知道账号密码的情况下,直接在服务器上执行代码。
这跟某个页面报错、某个接口返回异常完全不是一回事。攻击成功之后,服务器上运行的程序、能访问到的数据,甚至整个站点的运行状态,都可能被影响。
这两个漏洞到底怎么回事,为什么能让这么多组织如临大敌,AI 又在里面起了什么作用?技术名词先放一边,从两个生活里的例子讲起。
一个因为仓库太忙而出错的管理员
先看 CVE-2026-109618。
它的技术描述里有个词叫 OOM,Out Of Memory,简单说就是内存不够用了。
如果你不是开发者,可能会觉得奇怪:内存不够用不就是程序崩了?最多让网站卡一下、报个错,怎么就成了能攻击服务器的漏洞?
这就得从一个仓库管理员说起。
仓库管理员遇到了一个特别麻烦的订单
想象你经营着一个仓库。平时有人下单,管理员就照订单内容去取货、打包,最后把包裹交给快递员。
为了提高效率,管理员会提前准备一些工具和记录表格:先登记订单信息,再准备货物清单,最后填写发货记录。
正常情况下这套流程跑得很顺。
但有一天,有人送来了一份特别复杂的订单。
这份订单里塞满了各种附加信息,光是整理就要消耗大量纸张、文件夹和工作空间。管理员忙了半天,发现办公用品和工作台空间都快用完了。
于是管理员决定放弃这份订单,停止处理。
问题来了:管理员虽然停下了手上的活,之前创建的一些记录却还没准备完整。
有的表格只填了一半,有的文件夹已经登记进系统,却还没真正准备好。
如果他直接收工,把所有东西收拾干净,自然没事。
可如果结束工作时还按正常订单的流程去检查、整理这些半成品,就可能出大错。
比如系统以为某份表格已经填完,按表格里的内容去操作,结果发现里面的东西根本不存在,甚至误把别的记录当成了自己的。
这种错误一旦发生在管理核心流程的程序里,就不只是订单处理失败了。
PHP 的问题就在这里
PHP 处理 HTTP 请求时也要层层准备。
浏览器发来请求,PHP 不会立刻执行网站的业务代码。它得先接收请求、解析请求头和请求正文、处理表单与文件上传,再为后续执行备好各种内部数据。
这些工作里有相当一部分要分配内存。
正常情况下 PHP 有内存上限,占到上限就该停止处理,避免继续往下耗。
这次漏洞的问题在于:内存耗尽如果发生在某些特殊处理阶段,PHP 可能过早跳出当前流程,却没把那些尚未初始化完成的内部数据处理好。
等请求结束、PHP 开始清理现场,它又可能把这些状态不完整的数据当成正常数据来用。
这就对应了前面仓库里的情况:管理员因为工作台不够用提前结束了订单,收尾时却还按正常订单的标准去检查半成品记录。
那攻击者怎么让 PHP 撞上内存不足?
不一定要传一个离谱的大文件。官方分析提到,某些精心构造的 multipart 请求(常见于表单和文件上传)就能触发问题,比如请求里的附加信息数量过多,或者某些输入结构让 PHP 需要分配比预期更多的内存。
换句话说,看起来不算大的请求,经过 PHP 内部解析后也可能吃掉大量内存。
当然,光让 PHP 内存耗尽还不足以执行任意代码。危险的是它跟内部状态处理的缺陷撞在了一起,给了攻击者继续利用的机会。
内部状态一旦被错误处理,程序就可能出现内存损坏。攻击者在此基础上把执行流程带偏,一个普通请求就有机会变成服务器上的代码执行。
这就是远程代码执行(RCE)。
所以第一个漏洞的重点不是「内存不够用」,而是 PHP 在内存不够用时,异常处理和收尾没处理好,给攻击者留了影响程序执行的口子。
一个没有清理干净的工位
第二个漏洞是 CVE-2026-109619。
第一个漏洞可以说是「事情还没准备好就被迫中断」,第二个则是「上一位员工已经走了,他留下的东西还在被下一位员工使用」。
上一位员工下班了,工位却没收拾干净
还是仓库。
一家仓库有很多员工共用一套工作系统。为省时间,员工不必处理完一单就把系统彻底关掉,同一个员工会连着处理好几单。
每处理完一单,系统清理这单用的资料,准备接下一单。
正常流程是这样:
- 员工 A 接到订单,创建本次订单专用的记录。
- 订单处理完成,系统清理这些记录。
- 员工 B 接到下一个订单,开始使用自己的记录。
这里有个前提:上一单结束后,所有指向旧记录的引用都该清理干净。
但假如员工 A 的订单因为某个错误突然中断,系统销毁了 A 的记录,却忘了删掉公共登记簿里指向这些记录的标记。
这时员工 B 开始处理自己的订单。
在准备好新记录之前,系统先去翻了那本公共登记簿,发现里面还留着 A 的旧标记。
系统以为这份记录还有效,就按旧标记去访问已经被清理的内容。
更麻烦的是,原来存放旧记录的位置可能已经分给了别的用途。按旧地址读出来的东西,早就不是原来的内容。
这份错误的数据要是继续影响程序执行,后果就不好说了。
PHP 里也有这样的「旧标记」
PHP 处理 Web 请求时会用一些内部状态记录当前请求的信息,比如错误处理状态、会话相关状态、对象和扩展的状态。
在某些运行模式下,PHP 处理完一个请求并不会退出整个进程,同一个工作进程会接着处理下一个请求。
所以每个请求结束时,PHP 必须把本次请求专用的数据清理干净,并重置所有可能还指向这些数据的内部状态。
这次的问题出在特定情况下:前一个请求发生致命错误,或者在清理阶段出了别的岔子,导致某些内部状态没被正确重置。
请求占用的内存已经释放了,PHP 内部却还留着指向那片内存的引用。
接着同一个工作进程开始处理下一个请求。正常初始化还没走完,某些操作就可能提前访问这些过期引用。
这就是典型的 Use After Free(释放后使用)。
名字拗口,意思很直白:内存已经放掉了,程序还在用它。
为什么会变成漏洞?因为程序没法保证释放掉的内存保持原样,它可能被重新分配,也可能被别的数据覆盖。程序要是还把这片内存当成原来的数据,就可能读到错误内容,或者执行本不该执行的操作。
再往上利用,这类内存错误就可能发展成远程代码执行。
要说明一点:这不代表下一个访问网站的人就能直接看到上一个用户的全部数据。漏洞涉及的是 PHP 内部状态的生命周期管理,不是把上一个人的 $_POST 或其他变量原封不动地漏给下一个人。
真正的问题是,PHP 对已经失效的内部状态还保留着引用,并且可能在不该用的时候用了它。
两个漏洞到底有什么区别?
把前面的例子摆在一起,就清楚了。
| CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
| 生活中的比喻 | 工作台不够用,管理员提前中断工作,却错误地处理半成品记录 | 上一笔订单已经结束,系统却还保留着指向旧记录的标记 |
| 核心问题 | 内存耗尽时,异常退出和收尾流程没有正确处理内部状态 | 请求结束后,某些内部状态仍然指向已经释放的内存 |
| 关键时机 | 请求处理过程中,特别是内存耗尽等异常发生时 | 前一个请求结束后,到下一个请求正常初始化完成之前的特定阶段 |
| 可能造成的后果 | 内存损坏,并可能进一步发展为远程代码执行 | 释放后使用,并可能进一步发展为远程代码执行 |
表现不同,根子一样:都不是业务逻辑错误,而是 PHP 运行时在内存和请求状态处理上出的问题。
这也是它们影响范围值得重视的原因。
普通的业务漏洞,可能只影响某个页面、某个接口,或者某一种业务操作。
PHP 运行时却在网站业务代码的下层。只要应用跑在受影响的版本和相关条件下,问题就可能出现在业务代码开始执行之前,或者出在多个请求共用的底层流程里。
这并不等于每个 PHP 网站都能被轻易攻破。实际利用还要看运行环境、服务器配置、扩展、请求处理方式这些条件。
可一旦攻击成功,攻击者拿到的是 Web 服务进程权限下的代码执行能力。对一个能连数据库、读配置文件、调其他服务的网站来说,这已经够危险了。
所以官方把两个漏洞都评为严重级别,真不是小题大做。
以前有漏洞,为什么这次这么紧张?
软件漏洞一直都有,PHP 也不是第一次出严重问题。这次连日本首相和美国国家安全局都出来提醒,我觉得原因有两个。
这次捅到的是运行时底层
两个漏洞的后果都很重:攻击者不用登录,靠网络请求就能触发,最终在服务器上执行代码。
同时 PHP 的应用面太广。它不只在开发者自己写的项目里,还藏在各种内容管理系统、电商、博客、论坛和大量历史遗留的业务系统里。
很多网站可能好多年没大改过,但一直在稳定运行。
受影响的是一大片还跑着 PHP 的互联网基础设施,而不是某个小众产品。
对政府、大型企业和云服务商来说,这种漏洞一旦被大规模利用,牵扯的就是用户数据、业务连续性和公共服务。
相关机构会要求尽快修复,实在修不了就考虑先把暴露在公网的服务关掉,原因就在这里。
以前攻一个小网站不划算,现在这笔账在变
以前从发现漏洞到真正用起来,中间隔着挺长一段路。
你得理解目标软件的实现,分析漏洞成因,判断哪些版本中招,再研究怎么让漏洞稳定触发,最后还得处理不同环境下的兼容问题。
这些活儿很吃经验,也吃时间。
大企业和政府机构养得起安全团队,小网站就没这个条件了。
小公司可能没有专职安全人员,网站就放在一台普通云服务器上,PHP 版本几年没动过。
以前攻击者未必愿意为这么一个小站花那么多时间。说得直白点:成本可能比收益还高。
这不代表小网站以前就安全,也不代表没人打它们。自动化扫描、批量利用、撞库这些早就有了,只是门槛和成本不一样。
而 AI 正在改变其中一部分成本。
AI 可能让「补丁发布」变成另一场竞赛的发令枪
这次事件还有个值得留意的地方:AI 不只用来写业务代码,它也开始参与漏洞的发现、分析和修复。
按 Google Cloud 的说明,AI 模型参与了这两个漏洞的发现与验证。也就是说,AI 已经实打实地进到了专业安全研究里。
问题在于,同样的能力也能拿去攻击。
修复补丁本身,也会透露漏洞的线索
修漏洞通常要改原来的代码。
假设某个版本处理不当,开发者在新的版本里调整了异常处理、补上了状态清理,或者改了内存管理的流程。
对普通用户来说,这只是一次安全更新。
对安全研究人员来说,代码改动会暴露原来哪里有问题。
对比修复前后的源码,就能一点点推断:
- 原来的代码在哪些情况下会出错?
- 开发者为什么改这段逻辑?
- 什么样的输入能触发旧版本的问题?
- 哪些环境和配置更容易中招?
这类分析不算新鲜。安全研究者早就会做补丁分析,甚至用它验证修复有没有效。
变化在于,AI 能接手其中一部分繁琐的活。
以前要花很长时间读懂陌生项目的代码、理清函数调用关系,再一步步推出漏洞成因。
现在 AI 可以帮忙读代码、比补丁、总结差异、提测试思路,甚至帮研究者写验证程序。
也别以为随便问 AI 一句就能稳定攻破任意服务器。实际利用仍然需要技术判断、实验验证和对目标环境的理解。
但原本门槛很高的那部分工作,确实可能变得更快、更便宜。
补丁发布之后,防守方和攻击方都能更快行动
在漏洞修好之前,知道细节的人通常不多。开发团队发补丁,是为了让用户尽快修。
补丁一公开,所有人都能开始研究这次改了什么。
安全研究者分析补丁,确认漏洞是不是真的堵上了;管理员升级版本;攻击者也可能反过来推旧版本的问题,琢磨怎么打那些还没更新的系统。
如果攻击者借 AI 把分析和测试的成本压下来,从补丁公开到出现可用攻击方法的时间就会更短。
所以补丁发布,某种意义上也是攻击者集中研究旧版本的起点。
当然也别理解成每次发补丁,所有攻击者立刻就能拿到现成的攻击工具。漏洞复杂度、目标环境、补丁质量、防护措施都会影响结果。
但对那些长期不更新、直接挂在公网上的系统来说,这个变化值得警惕。
安全部门要尽快盘资产、测补丁、安排升级;资源不够的小公司,可能连自己跑了哪些 PHP 版本都说不清。
攻击成本一降,过去因为「太麻烦、不划算」没人搭理的系统,慢慢就会进入攻击者的视野。
PHP 社区之外的人也跟着紧张,原因就在这。各国网络安全机构和大型平台要面对的,是整个互联网基础设施应对这类风险的速度。
以后,及时更新可能比以前更重要
我们过去常听到一种说法:项目只要跑得正常,就别随便升级依赖。
这话不算错。生产环境要控制变更风险,不能新版本一发布就不测试直接上。
但「不要随便升级」不等于「永远不升级」。
安全更新尤其得有明确的处理机制。发现严重漏洞,先尽快确认自己的环境是否受影响,再安排测试和升级,别等网站出事了才处理。
这次 PHP 官方给出的修复版本:
- PHP 8.5:升级到 8.5.12 或更高的适用修复版本
- PHP 8.4:升级到 8.4.27 或更高的适用修复版本
- PHP 8.3:升级到 8.3.36 或更高的适用修复版本
- PHP 8.2:升级到 8.2.35 或更高的适用修复版本
具体版本和适用范围,可以查看 PHP 官方安全公告 以及两个漏洞的 CVE-2026-109618 和 CVE-2026-109619 公告。
如果你还在用 PHP 8.1 或更早的版本,要格外注意:这些版本已经不在上游常规支持范围内。部分操作系统或商业发行版会回移补丁,但不能只看版本号判断有没有修,得去确认对应供应商的安全公告。
升级 PHP 也不是改个命令就完事。用 Docker 的项目要确认镜像更新了、重新构建部署;用 PHP-FPM 的项目要确认跑着的工作进程真的加载了修复后的版本;用托管平台的,要确认它那边的运行时更新了没有。
暂时修不了的,按风险评估做临时隔离、限制公网访问,别指望调某个配置参数就能躲过去。
这些事听着琐碎,但安全问题里真正容易翻车的,往往不是技术有多难,是没人负责确认它到底做完没有。
对开发者来说,这也算观念上的一点变化:升级不再只是为了新功能和性能,也是在维护系统还能安全运行的能力。
不管你用的是 PHP、Go、Java、Python 还是别的语言,都没法保证底层依赖永远不出安全问题。
区别只在于,问题被发现的时候,你有没有能力及时知道、及时修。
最后
回过头看,这次事件倒也不必读成 PHP 要完蛋了。
任何足够复杂、用得足够广的软件,都可能藏着还没被发现的缺陷。两个严重漏洞不代表 PHP 失去了价值,更不代表所有 PHP 网站都会马上被打穿。
但它提醒了一件事:软件安全除了写对代码,还有持续维护和及时更新,以及漏洞公开后尽快动手。
而 AI 的出现,可能让这场攻防跑得更快。
我们当然希望 AI 帮自己更快发现问题、修好问题;但也得承认,同样的工具可能让攻击者把门槛降下来。
以后这样的场面大概会越来越多:一个漏洞公开,一份补丁发布,整个行业抢着确认自己有没有中招。
当然要我说,按互联网的发展速度,估计总有一个缓冲区溢出、IDOR、SQL 注入,或者其他什么东西,终结我们整个网络世界。