PHP被曝两个严重RCE漏洞:深度解析与防护指南

jipa233 发布于 5 小时前 最后更新于 5 小时前 2226 字 26 次阅读 技术分享


【AD🪧】关注我的TG频道@jipa233,获取一些实用新闻以及搞笑内容!

10月21日,PHP官方发布紧急安全公告,披露了两个严重程度高达CVSS 9.2的远程代码执行(RCE)漏洞,影响范围涵盖自PHP 5.4起的所有历史与现代版本,包括PHP 5.x、7.x、8.0至8.5等分支,且攻击在业务框架代码执行前即可触发。

影响范围:所有用于处理Web请求的PHP安装都可能受影响,包括PHP-FPM、Apache mod_php、php-cgi、FrankenPHP和LiteSpeed。官方认为mod_php风险最高,已有利用验证表明,攻击者无需身份验证,就能在应用代码运行前通过请求触发攻击。

那么这个漏洞究竟有多么严重呢?

日本、欧洲等全球多个国家/大洲的各大政府、银行、娱乐等旗下所属网站连夜关站:

甚至日本首相高市早苗都发X催打补丁:

听上去天都要塌了。

一、被忽视多年的「小问题」

最早是在2020年,有人给PHP报了个小问题。看着没什么攻击性,像是记下来、以后顺手处理就行。2024年,PHP基金会组织了多年来第一次外部安全审计,审计人员也注意到了这个隐患,只是当时没人找到利用它攻击服务器的办法。

真正要动手修,事情却卡住了。几种优化方案各有取舍,懂PHP内核的人不多,最后还得全票通过才能拍板。意见迟迟凑不齐,修复断断续续拖了几个月。基金会后来复盘时说:「这次拖延是结构性的失败。」

今年 8 月,几家安全团队各自借助AI模型,把这个旧问题变成了能实际利用的漏洞,陆续报给PHP官方,OpenAI团队也在其中。第一份报告在8月11日提交。之后各方一直保密,PHP安全团队悄悄修补,大家约好同一天公开。从上报到补丁公开,过了71天。

原定公开日前两天,消息还是漏了。一位网友在技术论坛发帖:「据可靠消息源,PHP要出大事,信我。」公开节奏被打乱,PHP官方只好把补丁提前一天发布。

二、本次漏洞详情:PHP2Shell

不同于特定业务代码或第三方插件层面的缺陷,PHP2Shell直接存在于PHP核心运行时(Runtime)的底层内存与错误恢复逻辑中。攻击者可以将这两个漏洞组合利用(Chaining),在无需任何身份认证(Pre-auth)的前提下向目标服务器发送特定构造的HTTP请求,直接实现远程代码执行(RCE):

CVE-2026-109618:OOM(内存耗尽)导致的远程代码执行
当 PHP 在处理请求过程中发生内存耗尽(Out-of-Memory)错误时,会调用 longjmp() 跳出当前上下文并中止请求。但在特定路径(如处理 RFC 1867 multipart/form-data 表单文件上传及进度追踪)中,代码未能妥善处理该异常跳转,导致内部请求数据结构在仅完成部分初始化时被中断,随后的请求清理流程会将未初始化的内存误判为有效数据指针。
简而言之:内存耗尽时,PHP 可能在请求内部数据尚未初始化完整前中断处理。后续清理流程若把这些无效数据当成有效数据处理,就可能触发漏洞。

CVE-2026-109619:陈旧全局状态导致的远程代码执行
在通过 longjmp() 处理致命错误恢复时,请求所拥有的内部状态指针(例如 ext/session 中用于追踪上传进度的缓存 zval 指针)在其底层 HashTable 内存被释放后依然残留。当同一个常驻 Worker 进程(如 PHP-FPM、LSPHP)继续处理下一个请求时,会在正常初始化重置前访问或复用该已释放的悬垂指针,从而触发堆内存释放后重用(Heap Use-After-Free)并达成任意代码执行。
简而言之:某个请求使用的内部状态可能在其占用的内存释放后仍被保留下来。同一个 worker 处理后续请求时,如果在正常初始化并重置状态前使用了这份旧状态,就可能触发漏洞。

三、修复方法:升级PHP版本至最新

最安全有效的办法是升级到已经更新补丁后的版本,升级前记得先备份:

分支修复版本
PHP 8.5.x8.5.12
PHP 8.4.x8.4.27
PHP 8.3.x8.3.36
PHP 8.2.x8.2.35

PHP官方还放出了7.4、8.0、8.1的最小源码补丁,但最安全的办法还是升级到仍在维护的版本。

PHP更新完,记得重启PHP和常驻的PHP进程,让新版本真正跑起来。用Docker官方PHP镜像的,拉取新镜像后还要重新构建应用镜像,再重建容器。

四、临时缓解方法

如果你的网站运行的环境受限,无法升级到最新版本,也有临时缓解的方法,但只能缩小部分攻击路径,不等于完全修复。

①将网站接入Cloudflare

对的,我们的Cloudflare大善人早在官方发布修复补丁前就为所有WAF用户(包括免费版)默认启用了针对php2shell两个高危漏洞的防护:https://blog.cloudflare.com/php-vulnerabilities-waf-protection

同时提醒,不要只依赖Cloudflare,而忽视源站自身防护:

  • 源站IP可被绕过:如果源站80/443端口直接对公网0.0.0.0/0开放,攻击者可通过历史DNS记录、证书透明度日志(CT Logs)或全网扫描发现源站IP,并在请求头中伪造Host: 你的域名直连源站,从而完全绕过Cloudflare WAF。
  • Docker端口映射可绕过防火墙:在Linux主机上使用Docker映射端口(如-p 80:80)时,Docker会将规则写入iptables的FORWARD/DOCKER-USER链,默认绕过宿主机ufw等防火墙的INPUT规则。

②PHP官方临时缓解方案

CVE-2026-109618:OOM 内存耗尽导致的远程代码执行

  • 将memory_limit设为-1,并尽量通过应用无法覆盖的方式配置,例如FPM pool中的php_admin_value或Apache配置。检查其他pool、目录或应用配置没有重新设置有限值。这样可以避免由PHP内存上限触发的OOM,但底层内存分配仍可能失败并进入漏洞路径。
  • 调低post_max_size:不需要文件上传的应用可设为8M;需要上传的应用可设为32M。同时确保upload_max_filesize小于post_max_size。
  • 可在 Web 服务器或代理层限制解码后的请求体大小、输入字段数量、multipart 分段数、请求头数量和嵌套深度。即使请求没有可用的Content-Length,这些限制也必须生效。
  • 可用容器或cgroup作为资源边界,最好配置为只终止受影响的worker。不要用RLIMIT_AS或RLIMIT_DATA替代,它们可能引发漏洞相关的内存分配失败。

CVE-2026-109619:陈旧全局状态导致的远程代码执行

  • 将session.upload_progress.enabled设为0,并重启所有worker。配置应通过php.ini、FPM pool或服务器配置,在请求解析前生效。不要依赖ini_set()或FPM.user.ini。这只能阻断已确认的session攻击路径,其他变体仍可能存在。
  • PHP 8.5还可将fatal_error_backtraces设为0,并重启所有worker。这只针对已确认的fatal backtrace路径。
  • 移除那些按请求生效、会在初始化前触发诊断信息的无效或已弃用设置。用error_reporting、display_errors或@隐藏诊断信息并不能缓解漏洞。
  • 修复攻击者可触发的致命错误和执行超时,包括回调、上传、导入及清理流程中的故障。

完整技术细节见PHP官方安全公告:CVE-2026-109618和CVE-2026-109619。

PS:临时缓解方案只能阻断部分攻击途径,不能真正解决问题,最终还是要升级官方安全补丁才能够彻底解决。

文章内部分内容及图片来源,特此感谢:PHP官方、AI信息Gap、xzの小站、交流科技圈