一条请求,拿下服务器:PHP「php2shell」双漏洞引爆全网,修复窗口正在关闭

11
发布时间:2026-10-23 11:39:51

2026年10月21日,PHP官方紧急提前发布了安全补丁——比原计划早了一天。原因是漏洞细节已经泄露。这两个编号为 CVE-2026-109618 和 CVE-2026-109619 的漏洞,被社区迅速冠以「php2shell」的代号:你部署的是一个网站,攻击者拿到的是一个 shell。

它不需要登录、不需要用户交互,也不依赖上层应用的任何漏洞。只要你的服务器能接收 HTTP 请求,并且跑着 PHP,就可能被一条精心构造的请求直接拿下。更麻烦的是,PoC 已经公开,在野利用已经开始。

这篇文章将为你梳理这次事件的技术根因、影响范围,以及一份可以照着做的处置清单。


一、这不是"又一个 RCE",这是引擎层的塌陷

多数 Web 漏洞出在业务代码里:一处未校验的输入、一个不安全的反序列化、一条拼接出来的 SQL。这类问题有共同特点——它们发生在 PHP 开始执行业务逻辑之后。因此,登录鉴权、参数校验、WAF 规则都能起到拦截作用。

php2shell 不属于这一类。

它的触发点在业务代码执行之前,位于 PHP 引擎处理请求的准备与清理阶段。这意味着应用层的所有防御几乎全部失效:你没机会校验参数,因为代码根本还没跑到那里。

漏洞一:CVE-2026-109618 —— OOM 引发的内存破坏

PHP 在内存耗尽时,会通过 longjmp() 强行跳出当前执行上下文。问题在于,如果此时请求内存尚未完全初始化就被标记为"可访问",后续的 request shutdown 清理流程就会把这个无效的半成品状态当作正常数据来处理,进而造成内存破坏。

攻击者无需突破 post_max_size。只需构造一个包含大量 header、嵌套字段名或密集空文件控件的 multipart/form-data 请求,就能在不超限的前提下耗尽 memory_limit,把服务逼进 OOM 路径。Apache mod_php 这类无条件执行请求关闭流程的 SAPI 风险最高。

漏洞二:CVE-2026-109619 —— 跨请求残留的全局脏指针

worker 进程释放某个请求的内存后,error、session、object、extension 等全局状态里,仍残留着指向已释放内存的指针。攻击者在同一个 worker 上先后发送两个请求:第一个当"生产者"留下脏状态,第二个当"消费者"触发访问。这就构成了一个跨请求的 Use-After-Free。

后果分两档:轻则泄露敏感内存(密钥、Cookie、接口凭证),重则直接远程代码执行。官方已确认 session.upload_progress 是其中一条可利用路径。

官方补丁的核心改动,是用"软 OOM + 硬 OOM _exit()"替代了 longjmp(),并新增了硬内存上限,同时清理了跨请求残留的全局状态。


二、影响范围:比你想象的宽

版本对照表

PHP 分支 受影响版本 修复版本

 

PHP 分支 受影响版本 修复版本
PHP 8.5 < 8.5.12 8.5.12
PHP 8.4 < 8.4.27 8.4.27
PHP 8.3 < 8.3.36 8.3.36
PHP 8.2 < 8.2.35 8.2.35
8.1 / 8.0 / 7.4 及更早 全部受影响 已停止维护,无正式版本,仅提供最小源码补丁自行编译,或向发行版/LTS 厂商索取回溯包

部署形态

Apache mod_php(风险最高,已有免登录 RCE 验证)、PHP-FPM(含 Nginx + mod_proxy_fcgi)、php-cgi、FrankenPHP、LiteSpeed LSAPI、Docker PHP-FPM 镜像、Windows 下的 php-cgi.exe、cPanel/Plesk 面板内置运行时,以及各类厂商设备内置的 PHP 运行时。

上层产品无一幸免

WordPress、Drupal、Joomla、Laravel、Symfony、Magento、MediaWiki、phpBB、Nextcloud、phpMyAdmin、Roundcube、WHMCS、OpenCart、WooCommerce……只要底层是 PHP 就受影响,与应用框架自身是否发布新版本无关。这也是本次事件中最常见的误判点。

暴露面量级

W3Techs 统计显示,全球约四分之三的网站使用 PHP;VirusTotal 与 Shodan 估算可探测的 PHP 主机达数百万台,全网约 2600 万资产可能落入潜在影响范围;Shodan 数据显示,公网暴露且版本号显示为 8.1 及更老的服务器约 88 万台。日本网站 PHP 使用率高达 92%,成为重灾区。奇安信 Xlab 已捕获全球数千个源 IP 发起的数万次攻击,行为涵盖植入后门、挖矿、远控连接与凭据窃取。


三、第一步:先把资产摸清楚(这里最容易踩坑)

排查听起来简单,但实际踩坑率极高。

坑一:php -v 查的是 CLI,真正干活的是 FPM 或 Apache 模块。 两者版本可能完全不同,只查 CLI 会漏掉真实风险。

1# CLI 版本(仅供参考)
2php -v
3
4# 真正处理请求的版本
5php-fpm -v
6ps aux | grep php-fpm
7
8# Apache mod_php
9httpd -M | grep php
10# 或在 Web 根目录放一个仅含 <?php phpinfo(); ?> 的临时文件查看(事后务必删除)

坑二:Docker 和 K8s 里的 PHP 最容易被遗忘。 CI 环境、Sidecar、Init 容器、老的基础镜像 layer,都是盲区。

1docker ps --format '{{.Names}}' | xargs -I{} docker exec {} sh -c 'php -v 2>/dev/null || php-fpm -v 2>/dev/null'
2docker inspect <image> | grep -i php

坑三:响应头把版本号贴在脑门上。 顺手检查并关闭 expose_php = Off,这虽不能修漏洞,但能降低被批量扫描命中的概率。


四、根治:升级,并且要重启

补丁下载地址:https://www.php.net/downloads.php
安全公告:https://www.php.net/archive/2026.php#2026-10-21-5

1# Ubuntu / Debian(ondrej 源)
2apt update && apt install php8.3
3systemctl restart php8.3-fpm apache2     # 必须重启
4
5# CentOS / RHEL(Remi 源)
6yum update php php-fpm php-* --enablerepo=remi
7systemctl restart php-fpm httpd
8
9# Docker:改基础镜像后重新构建,沿用旧 layer 等于没修
10FROM php:8.3.36-fpm

升级后五件必做事:

  1. 重启全部常驻 worker。 只替换二进制不重启进程,旧进程仍运行旧代码,风险一点没少。
  2. K8s 滚动重启所有 Pod,确认没有旧 ReplicaSet 继续服务,顺带检查 Sidecar 与 Init 容器。
  3. 复核内存与上传配置。 新版以软/硬 OOM 替代 longjmp(),需重新评估 memory_limit、post_max_size、max_file_uploads,避免业务因限制变更出现异常中断。
  4. 验证生效。 用 php-fpm -v 或临时 phpinfo() 确认运行版本,再对自有授权资产做复测。
  5. 兼容性回归测试。 重点检查 Redis、Swoole、Xdebug、IonCube 等扩展与新版本的 ABI 兼容性,先灰度再全量。

EOL 版本只有三条路: 首选迁移到维护中的分支(建议 8.3/8.4);次选向发行版或商业 LTS 厂商索取回溯补丁;兜底是网络隔离加 IP 白名单加 WAF 虚拟补丁,并列入限期下线计划。


五、来不及升级?先做这些(但请记住:没有完整缓解方案)

官方口径很明确:升级是唯一安全选择。以下措施只能争取时间。

配置层

1; 物理拔除 CVE-2026-109619 的主要利用路径
2session.upload_progress.enabled = 0
3
4max_file_uploads = 5
5post_max_size = 32M
6upload_max_filesize = 10M
7expose_php = Off
8fatal_error_backtraces = 0        ; PHP 8.5

关于 memory_limit,不同机构的建议方向相反(CNVD 系倾向 -1,部分厂商主张收紧)。更稳妥的做法是在前端严格限制请求体大小、字段数、part 数、header 数与嵌套深度,后端按业务下限调小 post_max_size,而不是简单关掉内存限制。另外,不要使用 RLIMIT_AS / RLIMIT_DATA,它们会在漏洞触发路径上引发内存分配失败,反而加剧风险。

降低跨请求利用成功率(应急用)

1pm.max_requests = 1               ; PHP-FPM
2MaxConnectionsPerChild 1          ; Apache

代价是每个请求结束后回收 worker,高 QPS 站点性能下降明显,仅作应急。

WAF 虚拟补丁

核心规则:拦截请求体中含 PHP_SESSION_UPLOAD_PROGRESS 的 multipart 请求;补充拦截 part/header 数异常、空 file 控件密集、Content-Length 缺失却持续传输数据的异常 multipart。为确实使用该功能的业务路径设置例外白名单。阿里云 WAF/云防火墙、腾讯云 T-Sec WAF、奇安信云防护、聚铭 WAF、F5 等均已覆盖专项规则。规则能争取时间,但不能替代升级。

补偿控制

  • 限流:成功利用通常需要数千至数万次请求。对上传及表单提交接口做速率限制、封禁高频来源 IP,可显著抬高攻击成本。
  • 出站默认拒绝:仅放通业务必需目标,阻断反弹 shell 与横向移动。这是防止被攻陷主机变成跳板的关键一环。
  • 权限收敛:PHP 进程以低权限账户运行;上传目录禁止脚本执行;站点目录只读。注意 disable_functions 对本漏洞无效——攻击发生在引擎层。
  • 暴露面收敛:非必要系统临时下线,管理入口改经 VPN 或 IP 白名单。

六、监测与失陷处置

重点监测指标:PHP-FPM / apache2 进程异常退出或频繁重启;Web worker 派生 sh、bash、curl、wget、python 等子进程;站点或上传目录新增可疑脚本(尤其伪装成图片的 .php);异常外联与 DNS 隧道;日志中出现海量 multipart 请求、请求体含大量垃圾字符或 PHP 反序列化数据。

疑似失陷的处置顺序:先隔离后取证(断网或安全组隔离,保留内存镜像、进程快照、Web 日志与审计日志);不要就地清理,建议重建主机而非修补,因为 UAF 类入侵的后门形态不确定;强制轮换一切凭证,包括数据库密码、API Key、云服务 AK/SK、SSH 密钥、证书私钥、Cookie 签名密钥——假设它们已全部泄露;排查同网段主机、跳板机、备份库是否被触及;按规定履行报告义务,涉及个人信息或重要数据的,需按《网络安全法》《数据安全法》《个人信息保护法》及等保要求上报。长期不修复高危漏洞本身即构成合规风险。


七、几个必须纠正的误判

  • "我用了 WordPress 最新版就安全了" —— 错。框架更新不包含 PHP 引擎补丁。
  • "我打了补丁就完了" —— 错。不重启 worker 不生效,Docker 不改基础镜像重构建也不生效。
  • "我是内网系统,不急" —— 错。UAF 泄露可导致 Cookie 与密钥外泄,沦陷主机也常被用作内网跳板。
  • "开了 disable_functions 就安全" —— 与本漏洞无关。
  • "全球 70% 网站已被攻陷" —— 不准确。70% 是使用 PHP 的占比,是潜在暴露面而非已攻破数量。但鉴于已在野利用,窗口期正在快速收窄。

顺带提醒:同一天 Node.js 也发布了最高严重级别更新——CVE-2026-111497,Brotli 解码器越界写入,影响 22.x/24.x/26.x,需升至 22.23.4 / 24.22.1 / 26.12.1+。同时维护前后端或 SSR 服务的团队,建议一并排查。


处置时间表(建议)

时限 动作

 

时限 动作
0–4h 资产盘点与版本核查,公网-facing 业务优先,无法升级的高危系统评估临时下线
24h 完成互联网暴露系统的处置决策,部署 WAF 虚拟补丁与限流,开启出站管控与监控
72h 完成全部对外 PHP 服务升级与重启验证,EOL 环境实施网络隔离
7天 全量环境升级完毕,入侵排查与凭证轮换,整改台账归档

php2shell 的危险之处不在于技术有多精巧,而在于它绕过了我们习惯依赖的所有防线:鉴权拦不住,校验拦不住,WAF 常规规则拦不住,甚至业务代码还没来得及运行,事情就已经结束了。