CVE-2026-109618 & CVE-2026-109619 (PHP2Shell) 实操指南:从雷池规则到PHP升级的完整步骤
前言
2026年10月,PHP官方披露了两个CVSS评分高达9.2的严重漏洞:CVE-2026-109618 与 CVE-2026-109619(社区统称 PHP2Shell)。攻击者无需任何认证即可触发远程代码执行(RCE),且影响 Apache mod_php、PHP-FPM、Docker 等所有主流部署形态。
在官方补丁发布前的“真空期”,雷池 WAF 规则和临时配置修改是争取时间的有效缓冲;而补丁落地后,升级 PHP 版本则是彻底消除风险的唯一路径。本文为你提供了一份从“临时缓解”到“永久修复”的全链路实操指南,包含雷池规则的详细配置、各操作系统及容器环境的升级步骤,以及用于验证风险是否真正消除的闭环检查清单。无论你正处于应急响应的哪个阶段,都能直接复制命令落地执行。

这两个漏洞的影响范围覆盖 PHP 5.4 以来的几乎所有版本,且官方确认没有配置层可以彻底关闭的开关——session.upload_progress 的关闭只能阻断其中一条利用路径,另一条位于 PHP 底层 multipart 解析器中的路径依然存在。因此,下面的操作分为两个阶段:补丁发布前的临时缓解,以及补丁发布后的永久修复。临时缓解的每一步都标注了它的实际边界,避免误以为配置完就安全了。
第一阶段:临时缓解(仅在无法立即升级时使用)
这一阶段的目标是抬高已知利用路径的门槛,而不是消除漏洞。
方案一:配置雷池 WAF 自定义规则
雷池的规则广场已经给出了针对本次漏洞的规则模板,可以直接导入,也可以手动配置。以下是在雷池控制台手动添加的步骤。
第一步:进入自定义规则模块
登录雷池控制台,左侧导航栏选择 “防护配置” → “自定义规则”,点击右上角 “新建规则”。
第二步:命名规则并选择匹配范围
- 名称:建议填写
CVE-2026-109618_109619_php2shell - 匹配范围:选择需要保护的站点或 API 接口
- 动作:在规则尚未充分验证前,建议先设为 “观察” (仅记录不拦截);确认无误报后再切换为 “拦截”
第三步:配置条件组 1(session.upload_progress 相关路径)
在规则编辑区添加一个 AND 条件组,包含以下三个条件:
| 匹配目标 | 参数名 | 匹配方式 | 匹配内容 |
|---|---|---|---|
| POST 参数 | PHP_SESSION_UPLOAD_PROGRESS |
存在 | — |
| POST 参数 | PHPSESSID |
正则表达式 | ^[0-9A-Za-z,-]{16,256}$(注:官方原版为 {16,256},若需降低误报,可缩短为 {16,32},足以覆盖常规业务) |
| 请求 Header | Content-Type |
包含 | multipart/form-data |
第四步:配置条件组 2(multipart 边界模式)
再添加一个 AND 条件组,作为对条件组 1 的补充或独立命中路径:
| 匹配目标 | 参数名 | 匹配方式 | 匹配内容 |
|---|---|---|---|
| POST 参数 | PHP_SESSION_UPLOAD_PROGRESS |
存在 | — |
| 请求 Header | Content-Type |
包含 | multipart/form-data |
| 请求 Body | — | 正则表达式 | Content-Disposition:\s*form-data;\s*name="[^"]+"\r\n(?:[^\r\n]+\r\n)*\r\n[\s\S]{0,32}\x00 |
条件组 1 和条件组 2 之间是 OR 关系,任一条件组整体满足即触发规则。
第五步:保存并验证
点击 “提交” 保存规则。如果选择了“观察”模式,可以在 “事件记录” 中查看是否有真实流量命中该规则;确认没有明显误报后,再回到规则编辑页将动作改为“拦截”。
雷池规则库原文链接:
https://rivers.chaitin.cn/discussion/dbc7qkj1s5rlia466a30#规则库说明
边界说明:这条规则针对的是当时已知的利用链特征。如果攻击者变换 multipart 边界构造或绕过 PHP_SESSION_UPLOAD_PROGRESS 的依赖,规则可能失效。它不能替代补丁。

📌 注:上图截图自雷池 WAF 个人版,仅用于直观演示规则的界面结构与填写位置。实际生产环境建议使用雷池专业版,具体操作请以文中文字说明为准。
方案二:关闭 session.upload_progress(PHP 配置层)
这一步只能阻断 CVE-2026-109619 的部分利用路径,不能覆盖 CVE-2026-109618 通过 multipart 解析器触发的路径。但在无法立即升级时,它仍然是降低攻击面的有效动作。
方式 A:修改 php.ini(全局生效)
- 找到当前生效的
php.ini路径:php --ini | grep "Loaded Configuration" - 编辑该文件,定位到
[Session]段,将session.upload_progress.enabled的值改为0。如果该行被注释,取消注释后再修改:session.upload_progress.enabled = 0 - 如果运行的是 PHP 8.5,建议同时关闭致命错误回溯,进一步压缩 CVE-2026-109619 的触发面:
fatal_error_backtraces = 0 - 保存文件后,必须重启 PHP-FPM 或 Apache,新配置才会对所有 Worker 生效。
方式 B:通过 PHP-FPM Pool 配置(仅影响指定池)
如果你只想对特定站点禁用该功能,而不影响服务器上的其他 PHP 应用,可以在对应的 FPM Pool 配置文件中添加:
php_admin_flag[session.upload_progress.enabled] = off
Pool 配置文件通常位于 /etc/php/{版本}/fpm/pool.d/www.conf 或类似路径。修改后重启 PHP-FPM:
sudo systemctl restart php8.4-fpm # 根据实际版本调整服务名
方式 C:控制面板用户
如果使用宝塔等面板,进入 “PHP 管理” → “配置文件”,搜索 session.upload_progress.enabled,将 On 或 1 改为 0,保存并重载配置即可。
方案三:在 Nginx 层直接阻断 multipart 请求(可选,粒度更粗)
部分安全团队在应急时采取了更激进的做法:在 Nginx 层直接拒绝所有 multipart/form-data 请求,因为两条利用路径最终都依赖 multipart 解析。代价是文件上传功能会全部失效,仅建议在上传非核心业务的边缘节点临时使用。
在站点的 server {} 块中添加:
if ($http_content_type ~* "multipart") {
return 403;
}
重载 Nginx:
sudo nginx -t && sudo nginx -s reload
第二阶段:官方补丁发布后的永久修复
官方补丁于 2026 年 10 月 21 日 发布。PHP 安全团队和独立安全研究者的结论一致:升级到对应修复版本是唯一完整的缓解措施,配置修改和 WAF 规则都不能替代补丁。
修复版本对照:
| 当前分支 | 升级目标 |
|---|---|
| PHP 8.5.x | 8.5.12 |
| PHP 8.4.x | 8.4.27 |
| PHP 8.3.x | 8.3.36 |
| PHP 8.2.x | 8.2.35 |
(注:部分归档页面可能存在抓取滞后,正式批量升级前,强烈建议再次到 php.net 官网确认对应分支的最新安全版。此外,PHP 8.1 及更早版本已 EOL,不再接收官方修复,只能迁移到受支持的版本。)
场景一:Ubuntu / Debian(通过 Ondřej Surý PPA)
第一步:添加 PPA 并更新索引
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
第二步:安装目标版本的 PHP 及常用扩展
以 PHP 8.3 为例:
sudo apt install -y php8.3 php8.3-cli php8.3-fpm php8.3-curl \
php8.3-mbstring php8.3-xml php8.3-zip php8.3-gd php8.3-mysql
如果使用 Apache mod_php,额外安装 libapache2-mod-php8.3。
第三步:切换 Web 服务器使用的 PHP 版本
Apache 用户:
sudo a2dismod php8.2 # 禁用旧版本模块,按实际旧版本号调整
sudo a2enmod php8.3
sudo systemctl restart apache2
Nginx + PHP-FPM 用户:
sudo systemctl disable --now php8.2-fpm
sudo systemctl enable --now php8.3-fpm
然后检查 Nginx 站点配置中的 fastcgi_pass 是否指向新版本的 FPM socket(通常为 /run/php/php8.3-fpm.sock),必要时更新并重载 Nginx。
第四步:验证版本
php -v
CLI 应显示 PHP 8.3.36 或更高。同时确认 Web 环境实际加载的版本。
场景二:CentOS / RHEL / AlmaLinux / Rocky(通过 Remi 仓库)
第一步:安装 Remi 仓库
以 EL9 为例:
sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf install -y epel-release
(注:如果使用浏览器直接访问该 URL 会提示“不支持该文件类型”,属于浏览器的正常表现,在终端使用 dnf install 即可正常安装)
第二步:切换 PHP 模块流
sudo dnf module switch-to php:remi-8.3/common
第三步:安装或更新 PHP 及扩展
sudo dnf install -y php php-fpm php-cli php-common php-mysqlnd \
php-xml php-curl php-mbstring php-zip php-gd php-opcache
第四步:重启服务并验证
sudo systemctl restart php-fpm
sudo systemctl restart httpd
php -v
场景三:Docker 环境
第一步:修改 Dockerfile 中的基础镜像标签
例如:FROM php:8.2-apache 改为 FROM php:8.3.36-apache。
⚠️ 最佳实践:严禁使用 latest 或仅标明大版本的裸标签(如 php:8.3),必须精确锁定到修复漏洞的小版本号,以避免后续基础镜像自动更新引入未知变更或破坏兼容性。
第二步:更新 Dockerfile 并构建
docker build -t myapp:php83 .
# 或 docker-compose build --no-cache
第三步:停止旧容器并启动新容器
docker stop myapp-container && docker rm myapp-container
docker run -d --name myapp-container -p 80:80 -v /宿主机/上传目录:/容器内路径 myapp:php83
# 或 docker-compose down && docker-compose up -d
验证清单
| 检查项 | 命令 / 方式 | 预期 |
|---|---|---|
| CLI PHP 版本 | php -v |
≥ 8.3.36 / 8.4.27 / 8.5.12 / 8.2.35 |
| Web 实际版本 | phpinfo() 页面或 FPM 状态页 |
与 CLI 一致 |
session.upload_progress 状态(如未升级) |
php -i | grep session.upload_progress |
enabled => Off |
| 雷池规则命中情况 | 雷池控制台“事件记录” | 观察模式下有记录、无误报后可切拦截 |
| 文件上传功能(如使用了 Nginx 阻断) | 手动上传一个小文件 | 如返回 403,说明阻断生效,业务可能受影响 |
| POC 攻击载荷验证 | 使用公开的 PoC 在隔离环境或测试环境发起请求 | 确认 WAF 成功拦截,或升级后漏洞不再复现(这是从“完成升级动作”到“确认风险消除”的关键闭环,比单纯核对版本号更可靠) |
写在最后
雷池规则、session.upload_progress = 0、Nginx 层 multipart 阻断,这些措施的定位都是补丁缺位窗口期的缓冲。它们各自只能覆盖一部分已知路径,而且随着利用方式的演化,部分规则可能失效。一旦对应的修复版本可用,升级 PHP 就是终局;临时规则可以保留在纵深防御体系中,但它不再是你依赖的主线。
参考链接汇总
- 雷池规则库(长亭百川云):https://rivers.chaitin.cn/discussion/dbc7qkj1s5rlia466a30#规则库说明
- PHP 官方安全公告归档:https://www.php.net/archive/2026.php#2026-10-21-5
- PHP 官方下载页:https://www.php.net/downloads.php
鄙视CSDN,一点肚量都没有


浙公网安备 33010602011771号