PHP2Shell 事件复盘:企业应该如何自查、修复与规模化处置

一、事件速览

2026-10-21,PHP 官方修复并披露两个高危远程代码执行(RCE)漏洞,代号 php2shell 。CNVD 编号 CNVD-2026-41674、CNVD-2026-41675,对应 CVE-2026-109618、CVE-2026-109619 。CVSS v4.0 评分 9.2(Critical/严重),CNVD 综合评级"高危"。时间线要点:官方是"修完即公开"------同日放出修复版本并公开细节,留给企业的响应窗口很短。

影响版本与修复版本对照:

影响版本 修复版本
PHP 8.5.x < 8.5.12 8.5.12
PHP 8.4.x < 8.4.27 8.4.27
PHP 8.3.x < 8.3.36 8.3.36
PHP 8.2.x < 8.2.35 8.2.35

PHP 8.1 及更早版本官方不再更新(PHP 团队为 7.4/8.0/8.1 提供最小源码回溯补丁供自行编译)。

两个 CVE 的成因:

  • CVE-2026-109619:use-after-free(释放后使用,CWE-416)。请求拥有的内部状态在底层内存被释放后仍存活,同一 worker 后续请求在常规初始化重置前使用了过期状态,导致 RCE。
  • CVE-2026-109618:OOM corruption(内存不足破坏)。PHP 在内存不足时中断,内部请求数据只初始化了一半,请求清理时把无效数据当作有效数据,导致 RCE。

为什么这次特别危险:

  1. 无需认证:已有验证显示未认证请求可在应用层代码执行前触发漏洞。
  2. PoC 已广泛传播:多国(新加坡、加拿大、荷兰、芬兰、日本等)政府与企业已发预警,部分机构临时关站避险。
  3. mod_php 风险最高:Apache mod_php 部署已有未认证触发验证,风险优先于 FPM/cgi。
  4. 波及面极广:所有对外提供 Web 请求的 PHP 部署(PHP-FPM、mod_php、php-cgi、FrankenPHP、LiteSpeed)均受影响,上层 WordPress、Drupal、Joomla、Magento、MediaWiki、Roundcube、phpMyAdmin、Nextcloud、Laravel、Symfony、WHMCS、OpenCart 等全部在列。换句话说,只要站点跑在受影响的 PHP 上,不论用哪个框架,底层漏洞都在。

处置优先级怎么排?先公网、再内网;先 mod_php、再 FPM/cgi;先 EOL 版本、再接近修复线的版本。一句话:能被未认证请求直接打到的资产排最前,先止血再谈根治。

怎么理解 CVSS 9.2?它意味着无需认证、网络可达即可触发、可破坏完整性与可用性------属于"看到就应当立刻处理"的最高档位。权威口径显示已有超百万台暴露服务器受影响,但目前 PoC 已广泛传播、仍在研究利用链、尚未确认大规模实际利用------这正是应急窗口期,错过就要面对真实入侵。

二、先自查:你到底有没有中招

不要只看 php -v。CLI 版本和 Web 实际版本可能不同,一个常见坑是运维只在 CLI 上升级了 PHP,忘了 Web 用的 FPM/mod_php 还是老版本。务必以 Web 实际版本为准。还有人试图用 .user.ini 或应用内 ini_set('memory_limit', -1) 缓解,但这只是请求级、且可能被应用自身覆盖,对这两个 CVE 的路径防护不可靠------缓解项必须在 SAPI 启动前(php.ini / FPM 池 / 服务器配置)生效。

单台自查:

bash 复制代码
# CLI 版本
php -v

# Web 实际版本(FPM 场景)
php-fpm -v
# 或具体版本
php-fpm8.3 -v

# 当前 Web 用的 SAPI 与关键配置
php -i | grep -E "Server API|memory_limit|session.upload_progress.enabled"

一百台就别逐台手敲了,用循环或 Ansible 批量取:

bash 复制代码
for h in host1 host2 host3; do
  echo "== $h =="
  ssh "$h" 'php -v 2>/dev/null | head -1; php-fpm -v 2>/dev/null | head -1; php -i 2>/dev/null | grep "Server API"'
done

对容器/编排环境,单凭进容器 php -v 不够,要同时检查镜像 tag 与运行中的配置挂载:

bash 复制代码
kubectl exec <pod> -- php -i | grep -E "Server API|memory_limit"
# 核对 Deployment 引用的镜像 digest 是否已更新到修复版本
kubectl get deploy <name> -o jsonpath='{.spec.template.spec.containers[0].image}'

三件必须确认的事:

  1. Web 用的哪个 SAPI :php -i | grep "Server API"。mod_php 风险最高,优先处置。
  2. 是否面向互联网:确认站点公网可达;内网资产也要管,但优先级低于公网暴露资产。
  3. 版本落在哪个区间:对照上面的对照表。注意底层 PHP 版本决定漏洞是否存在,上层框架(WordPress 等)的更新不能替代底层 PHP 升级。

三、修复优先:升级到修复版本

唯一完整解决方案是升级。四个修复版本:8.5.12、8.4.27、8.3.36、8.2.35。

通用升级思路:

  • Debian/Ubuntu(包管理器) :apt update && apt upgrade php8.3(或对应版本),升级后 systemctl restart php8.3-fpm apache2 nginx。注意第三方源(如 ondrej)是否同步了修复版本,先 apt-cache policy php8.3 看候选版本号。
  • RHEL/CentOS :dnf update php 或 yum update php,确认 remi 等源的版本号已到修复线。
  • 源码编译 :从 php.net 下载对应版本源码,configure 参数保持与现有一致,make && make install 后重启。部分 PECL 扩展可能需重新编译,先在非生产环境验证扩展兼容。
  • 容器镜像 :把基础镜像 tag 钉到修复版本(如 php:8.3.36-fpm),重建并滚动发布;建议同时钉镜像 digest,避免 tag 漂移。

PHP 8.1 及更早:官方不再发布二进制更新,但提供了最小源码回溯补丁(7.4/8.0/8.1)。能升到 8.2.35+ 的尽量升;暂时升不动的,至少打回溯补丁(在源码树 git apply 或 patch 后重新编译)并配合下面的缓解措施。

升级后务必验证:再跑一次 php -v / php-fpm -v,确认版本号已到修复线,并做一轮业务冒烟测试(重点看扩展加载、路由、上传功能是否正常)。

生产环境建议灰度推进:先升非核心/内网节点,观察 24 小时无异常再推公网核心。保留旧版本包或镜像,一旦业务异常可快速回退;升级前对配置和代码做快照(尤其 php.ini、FPM 池、.htaccess),避免回滚后配置漂移。

四、不能马上升级?临时缓解配置逐条落地

官方明确:以下只是降低特定攻击路径的暴露,只有升级才是完整解决方案。但应急窗口期,先把这些配置落下去,至少把最危险的路径堵上。

针对 CVE-2026-109618(OOM)

php.ini / FPM 池 / Apache 配置中设置。关键是用 php_admin_value,应用层 ini_set() 无法覆盖它:

ini 复制代码
; FPM 池 (www.conf) 示例
php_admin_value[memory_limit] = -1
php_value[post_max_size] = 8M          ; 不需要上传的应用设 8M
php_value[upload_max_filesize] = 6M    ; 必须低于 post_max_size

需要文件上传的应用把 post_max_size 设 32M、upload_max_filesize 设 24M。Apache mod_php 写法:

apache 复制代码
<IfModule mod_php.c>
  php_admin_value memory_limit -1
  php_admin_value post_max_size 8M
  php_admin_value upload_max_filesize 6M
</IfModule>

确认没有池级/目录级/.user.ini 把它改回有限值------应用层覆盖会让你误以为已缓解,实际仍是漏洞。

为什么 memory_limit=-1 能缓解这条 OOM 路径?OOM corruption 发生在 PHP 因内存不足而中断分配时,设为无限制后该中断路径不再被触发,请求要么正常完成、要么由 cgroup 边界兜底,从而避开了"半初始化数据被当作有效数据"的窗口。

在 Web 服务器或反向代理层对解码后请求大小、输入字段数、multipart 段数、header 数量、嵌套深度设限,这些限制必须覆盖没有可用 Content-Length 的请求(如分块传输)。Nginx 示例:

nginx 复制代码
client_max_body_size 8m;
# header 数量、字段数、嵌套深度可结合 lua 模块或 modsecurity 规则限制

作为纵深防御,可在反向代理叠加 WAF 规则(如 modsecurity CRS 的请求体/参数数量限制)进一步收敛攻击面,但要明确:WAF 只是争取时间,不是修复,核心仍是升级。

容器或 cgroup 限制作为可用性边界,优先采用"只杀受影响 worker"策略。注意:不要用 RLIMIT_AS / RLIMIT_DATA 替代 memory_limit = -1,否则无法真正消除该路径。另外 memory_limit=-1 会让单请求可能吃掉更多内存,必须配请求大小限制和 cgroup 边界,避免被当成 DoS 放大器。

针对 CVE-2026-109619(use-after-free)

ini 复制代码
; 必须在请求解析前生效,用 php.ini / FPM 池 / 服务器配置
; 不要依赖 ini_set() 或 .user.ini(那是请求级,太晚)
php_admin_value[session.upload_progress.enabled] = 0

; PHP 8.5 上额外阻断已确认的 fatal backtrace 路径
php_admin_value[fatal_error_backtraces] = 0

改完重启所有 worker (FPM 用 systemctl restart php8.x-fpm,mod_php 重启 Apache),否则配置不生效。

修复攻击者可触达的 fatal error 和执行超时:排查回调、上传/导入处理、清理阶段的失败点。隐藏诊断信息(error_reporting / display_errors / @)没有用,必须真正修复逻辑。

验证缓解是否生效:用 php -i | grep -E "memory_limit|session.upload_progress.enabled|fatal_error_backtraces" 在 Web 上下文中确认这些值确实为预期(防止应用层覆盖),再观察一段时间有无异常 fatal。

五、当资产不是 1 台而是 100 台:规模化应对框架

一台机器好办,一百台甚至上千台暴露在公网的 PHP 资产,靠手工逐台操作和记脑图不现实。这里给一套"检测→优先级→修复→缓解→隔离→监测→加固"七步闭环方法论,并以 ManageEngine 产品体系为例说明工具如何做编排层。

1. 检测与优先级:先回答"谁在洞里"

我们用 Vulnerability Manager Plus 持续扫描全网主机的操作系统与 1700+ 第三方应用,按 CVSS、可利用性、补丁可用性、威胁情报、EPSS 可能性排序,直接把"PHP 8.3.30 / 低于 8.3.36"这类条目标红并附 CNVD/CVE 与 CVSS,省去人工比对。它的三个能力在这次各有侧重:

  • 零日漏洞缓解视图:把尚无补丁的漏洞单独列出,避免淹没在常规列表里。
  • Web 服务器加固(基于 200+ 条 CIS/STIG 基准):直接识别 mod_php 高危配置、memory_limit 被改回有限值等错配。
  • 高风险软件审计:把 8.1 及更早的 EOL 版本单独拉出来。

这一步直接回答两个问题:哪些主机低于修复线、哪些还在跑 EOL。

2. 修复与缓解:能升就批量升,升不动先全网堵

Endpoint Central 的补丁管理覆盖操作系统、应用与移动端 1100+ 第三方应用,自动扫描-检测-测试-部署,我们用它批量把几百台主机的 PHP 升到修复版本。暂时升不动的,用自定义脚本一键下发缓解配置:

  • 写 php.ini / FPM 池、改 memory_limit=-1。
  • 关 session.upload_progress.enabled、限 post_max_size、关 fatal_error_backtraces。
  • 脚本按刷新周期(我们设每 90 分钟)加启动/登录执行、失败重试,保证全网一致。

这样能避免个别主机被应用层覆盖造成的"假缓解"。

3. 隔离与止血:先把暴露面缩起来

  • 暂无法修复又暴露公网的资产,用系统隔离策略(NAC)按规则隔离,缩小暴露面。
  • 确认失陷的端点,用 Endpoint Central 的 EDR 隔离、终止恶意进程、回滚。

4. 监测利用迹象:盯组合信号,而非单条告警

Log360 集中采集并分析 Web 服务器、应用、认证、终端日志。我们把研判重点放在几类线索:

  • www-data / www 用户起的外连进程。
  • curl|sh 或 wget|bash 这类异常命令执行、反弹 shell 连接。
  • 新出现的提权文件与可疑 cron 项、异常账号登录与提权。
  • 大量指向未知外网 IP 的出站连接。

这些线索单独看未必致命,但组合出现(如"非业务时段 www 用户起了外连 + 新增可执行文件")基本就是失陷信号。EDR 按 MITRE ATT&CK 识别妥协指标(IoC),能在勒索、持久化、横向移动等阶段提前告警,而不是等被加密了才发现。

如果集中日志还没覆盖到某台主机,可以先做一轮命令行初筛,快速定位可疑资产再交给 Log360 做横向关联:

bash 复制代码
# 看 www 用户起的进程与外连
ps -eo user,pid,cmd | grep -E '^www'
ss -antp | grep ESTAB
# 查近期被改的可执行/脚本文件
find /var/www -type f -mtime -1 \( -perm /u+x -o -name '*.php' \) 2>/dev/null

初筛的意义不在于确诊,而在于在百台规模里先把"最不对劲"的那几台挑出来,把人力压到刀刃上。

5. 防止横向移动:在 Web 与内网之间加一道墙

RCE 得手后攻击者常顺手拿服务器特权凭据横向,用 PAM360 收敛服务器凭据、做轮换与审计,在"拿下 Web"与"拿下内网"之间加一道墙。

核心方法论仍是:先升级、升不动就缓解、全程监测。工具把这套流程在一百台机器上编排执行、跑齐跑对。

六、行动清单

  • 跑 php -v 和 php-fpm -v,记录 CLI 与 Web 实际版本(以 Web 为准)
  • 确认 SAPI(php -i | grep "Server API"),标出所有 mod_php 部署
  • 对照影响版本表,列出低于修复线的主机清单
  • 标出所有面向互联网的 PHP 资产(优先处理)
  • 对低于修复线的主机,升级到 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35
  • 升级后重启 FPM/Apache,再跑版本确认 + 业务冒烟测试
  • 不能马上升级的:设 memory_limit=-1 + 限制 post_max_size
  • 关 session.upload_progress.enabled=0 +(8.5)fatal_error_backtraces=0,重启 worker
  • 在反向代理层限制请求大小/字段数/header 数/嵌套深度(覆盖分块传输)
  • 开启日志集中监测,排查是否已被入侵(异常进程/命令/外联)
  • 收敛服务器特权凭据,降低横向移动风险

七、小结

漏洞会反复出现,下一次不一定叫 PHP2Shell。比单次应急更重要的是建立常态化的"资产可见 + 快速修复 + 临时缓解 + 持续监测"能力------这样无论哪个组件爆出 9.2 分的 RCE,你都能在窗口期内把处置流程跑完,而不是从零开始慌。

相关推荐
用户235937172631 小时前
扫码点餐系统的三个工程问题:桌台绑定、订单状态机与打印可靠投递
程序员·php
Initialize293081 小时前
Kafka 消息越堆越多、消费越来越慢?五步查清消费积压
运维
时间售卖铺1 小时前
MySQL 表的约束
运维·数据库·mysql·云原生
广州工博科技2 小时前
SAP Joule for Consultants 如何为自动化与集成项目提供支持?
运维·自动化
Acrellea2 小时前
数据中心这台新变压器,让配电房的电表全失效了
运维·能源
小胡20242 小时前
DzzOffice V2.4.2 版本上线!安全加固 × 网盘体验全面升级
服务器·bootstrap·php·协同办公·dzzoffice
boy快快长大2 小时前
【Jenkins】入门学习
运维·学习·jenkins
叼烟扛炮2 小时前
Linux 学习笔记(九):自动化构建神器 Make 与 Makefile
linux·运维·服务器
北塔软件2 小时前
从根因分析到协同执行,如何让AI运维真正落地?
运维·人工智能