PHP2Shell 披露 AI 发现的 PHP 严重执行漏洞
PHP2Shell 称 AI 发现了 PHP 中的严重远程代码执行漏洞,并引发较多社区讨论。输入未提供受影响版本、触发条件或修复状态。
完整中文译文
PHP 应用没有写错业务代码,也可能遭遇未认证远程代码执行。Wiz Research 披露的 PHP2Shell 指向 PHP 引擎自身:请求因内存不足而异常结束后,部分内部状态没有清理干净,后续请求或其他 worker 可能继续使用这些失效状态,造成内存泄露或代码执行。
这次研究值得程序员关注,还因为 AI 参与了复杂漏洞的发现、利用适配和补丁验证。不过,「已经演示成功」和「所有部署都能轻易攻破」之间仍有距离,原文中的影响范围和效率判断需要分开看。
PHP 请求结束了,为什么危险还会留下
PHP 通常由持续运行的工作进程(worker)处理多个请求。一次请求结束,请求使用的内存可以被释放,但进程还会接着处理下一次请求。
问题出在异常退出路径。按作者描述,PHP 在处理致命错误,尤其是内存不足错误时,可能已经销毁请求堆,却没有清除某些全局指针。后续请求访问这些指针,就会把已经释放、甚至已被其他数据占用的内存,当成原来的对象使用。这类问题叫释放后使用(use-after-free)。
请求失败,不等于进程已经恢复到可以安全接待下一次请求的状态。
原文称,受影响版本可追溯到 PHP 5.4,近十年的每个 PHP 版本至少受其中一种问题影响。研究披露了四种可利用实例,归入两个 CVE,最高严重性达到 CVSS 9.2。但提供的材料没有列出 CVE 编号、完整版本矩阵和修复版本号,不能据此直接完成资产核对。
Wiz 将多个问题组合成 php2shell 脚本,在测试当时的 wordpress:latest、drupal:latest、joomla:latest 容器镜像上,演示了未认证远程代码执行(RCE)。他们也单独验证了进程内存泄露,不必先拿到代码执行能力,就可能读到密码、认证令牌、API keys 和证书。
这里的边界是 PHP 引擎。WordPress、Drupal、Joomla 是演示对象,不能把它理解成这三个 CMS 各自出了业务漏洞。作者称,即使只有「Hello World」的应用也可能受影响;但具体能否利用,仍取决于版本、配置和运行状态。
四种漏洞,都指向异常清理留下的旧状态
四种问题的共同点,是内部状态的生命周期出了错。不过,跨请求和跨 worker 的传播方式并不相同。
第一种是上传进度反序列化器的释放后使用。Session 模块在处理上传进度时,可以提前解码会话数据,并把属于当前请求的管理状态存入 BG(unserialize)。如果内存分配失败打断流程,请求内存被释放,全局状态却仍然可见。作者将这个内存破坏能力与内存泄露结合,降低地址不确定性,在三个 CMS 上完成了 RCE 演示。
第二种是远程进程内存泄露。PHP 在请求启动阶段解析 RFC1867 multipart 请求,此时正常模块初始化尚未完成。上传进度处理可能提前设置会话标识 PS(id),内存不足又可能让它在清理不完整时退出。
后续请求沿用这个失效指针时,PHP 会把错误位置上的内容当成 zend_string,经过 URL 编码后写入 PHPSESSID 响应 Cookie。作者强调,即使应用没有调用 session_start(),这条路径也可能存在。因此,检查业务里有没有使用 Session,无法排除这个引擎问题。
第三种涉及致命错误回溯。EG(last_fatal_error_backtrace) 保存最近一次致命错误的调用回溯。如果请求堆被销毁后,这个值仍指向旧内存,下次请求早期产生诊断信息时,就可能在状态重新初始化之前访问它。作者利用这一原语,在 Drupal 上演示了未认证 RCE。
第四种是 OPcache 类型混淆。OPcache 把编译后的 PHP 结构保存在共享内存中。执行 zend_accel_script_persist() 时,进程本地的 CG(map_ptr_last) 会先推进,相关共享状态稍后才更新。两步之间发生内存分配失败,就可能留下不一致的槽位记录。其他 worker 再利用槽位时,旧元数据可能把一种对象解释成另一种对象,最终破坏共享状态。作者据此完成了 WordPress RCE 链。
原文还提到其他变体,并称 PHP 团队的补丁从共同根因修复这些问题。这是作者对修复范围的结论;材料没有展开补丁代码,读者无法仅凭这篇文章独立验证其覆盖程度。
AI 改变的是把漏洞做成可用攻击的成本
发现一个悬空指针,和把它变成稳定的远程攻击,中间还有大量工作。
不同 PHP 版本、配置和应用行为,会改变内存分配与复用方式。一条攻击链在某个部署上成功,换一个目标可能就失败,需要重新分析、测试和调试。原文对 AI 作用最具体的描述,正是让这个适配循环更容易推进。
研究使用了 Wiz Atlas、Gemini 4 Argon 和 GPT-5.6 Sol。作者特别提到,Gemini 4 Argon 参与了漏洞发现、利用开发、攻击检测和补丁验证。他们称,借助模型与测试调试工具,可以在数小时内开发并适配多个应用的利用;又称一名研究员用一周完成了过去可能需要顶尖团队数月的工作。
这些是作者报告的成果和效率判断。原文没有给出模型独立完成的比例、人工干预次数、失败成本,也没有同任务的人类团队对照实验,不能据此计算通用提效倍数。
披露时间线则比较明确:2026 年 8 月 19 日发现首个漏洞,8 月 20 日确认 Drupal 未认证 RCE,8 月 21 日确认 WordPress 未认证 RCE,8 月 24 日报告给 PHP 安全团队。9 月 21 日 PHP 确认报告并开始协调修复,10 月 21 日修复版本可用,同时公开披露。
期间,Wiz 与 PHP 团队、Calif、OpenAI,以及多家云厂商和基础设施服务商合作,准备检测与缓解措施。对这种跨应用的运行时漏洞,修好代码只是其中一步,把修复送到大量独立管理的服务器上同样困难。
我的判断
我认同文章最有价值的提醒:利用链复杂,不能继续被当成可靠的安全缓冲。 如果模型能持续读取失败信息、辅助定位问题并调整方案,过去难以规模化的适配工作,就可能变得更便宜。
但文章把 PHP2Shell 与 2014 年 Heartbleed、2021 年 Log4Shell 并列,甚至称其属于软件史上最严重的漏洞之列,这仍是作者的评价。所给材料没有提供真实受害规模、在野利用情况或覆盖不同配置的成功率,尚不足以支撑同等级的历史判断。
「PHP 支撑全球 70% 网站」也不能直接推导出「70% 的互联网都可被这条攻击链攻破」。技术使用占比、受影响版本占比和实际可利用比例,是三个不同的问题,原文没有完整拆开。
与常见的静态分析、模糊测试(fuzzing)相比,这篇文章展示了模型辅助分析和反复调试的价值,却没有提供对照数据。它能说明 AI 在这次研究中有用,不能证明 AI 已经可以普遍替代传统工具或安全研究员。
对一般团队而言,更应该吸收的是异常路径的审查方法。请求初始化到一半失败、状态写入到一半退出、局部状态与共享状态更新不同步,这些地方往往比正常业务流程更值得追问。
能拿来做什么
-
如果你维护 WordPress、Drupal、Joomla,或前端项目背后的 PHP 服务,应把排查范围落到 PHP 运行时和实际容器版本。
latest是可变标签,原文又没有给出修复版本号,不能用「刚拉过镜像」作为修复凭据;应用依赖升级也不能代替 PHP 安全更新。 -
如果你负责网关或服务排障,可以结合原文给出的信号调查:异常 multipart 请求之后出现内存限制错误、重复 HTTP 500、异常大或畸形的
PHPSESSID响应 Cookie,以及无法解释的 PHP worker 频繁退出重建。这些信号只能辅助调查,作者明确将 PHP 安全更新视为完整修复手段。其产品侧另提到,Sensor1.0.12768可启用内置响应策略。 -
在 Node 或日常 AI 编程审查中,可以借用这次研究的问题清单:初始化中途失败后,全局缓存、对象引用和共享状态是否仍然有效?这只是审查思路的迁移,不代表 Node 存在相同漏洞。让模型逐条追踪异常退出路径,并用测试或调试结果验证判断,比只让它浏览正常流程更有针对性。