1. 事件概述与影响范围
1.1 PHP 侧(CVSS v4.0 = 9.2)
| 漏洞编号 | 成因 | 后果 | 严重度 |
|---|---|---|---|
CVE-2026-109618(GHSA-w8hw-w9fx-j79w) | 内存耗尽(OOM)处理不当:内部请求数据仅部分初始化时中断 PHP,请求清理阶段把无效数据当作有效数据处理 | 未认证 RCE | 9.2 |
CVE-2026-109619(GHSA-6wmf-4rv5-p3rp) | stale global state:请求持有的内部状态在其底层内存释放后仍存活,后续请求可能在该状态被重置前使用它 | 未认证 RCE | 9.2 |
修复版本(2026-10-21 发布):PHP 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35。
生命周期:PHP 8.1 及更早版本不再由官方更新,官方另提供 PHP 7.4 / 8.0 / 8.1 的最小源码补丁(minimal source-backports);PHP 8.2 将于 2026-12-31 停止支持(EOL)。
1.2 Node.js 侧(最高 HIGH)
2026-10-21 安全发布共修复 10 个漏洞,覆盖 26.x、24.x、22.x 三条发布线。高危项如下:
| 漏洞编号 | 描述 | 影响发布线 | 严重度 |
|---|---|---|---|
CVE-2026-111497 | Brotli 解码器越界写(out-of-bounds write),可导致远程代码执行 | 26.x / 24.x / 22.x | HIGH |
CVE-2026-105482 | dns.resolve 截断包含 NUL 字符的名称 | 26.x / 24.x / 22.x | HIGH |
CVE-2026-105483 | 当 IP 以全角数字书写时,TLS 证书主机名校验被绕过 | 26.x / 24.x | HIGH |
CVE-2026-106069 | 当主机名松散解析为 IP 地址时,TLS 证书主机名校验被绕过 | 26.x / 24.x / 22.x | HIGH |
CVE-2026-105481 | keep-alive 相关问题 | 26.x / 24.x / 22.x | medium |
CVE-2026-106072 | 非规范 IPv4 主机名证书校验 | 26.x / 24.x / 22.x | medium |
CVE-2026-106074 | crypto 熵缓存 | 26.x / 24.x / 22.x | medium |
CVE-2026-106070 | ZipFile | 26.x | low |
CVE-2026-106071 | 权限模型 | 26.x | low |
CVE-2026-106073 | 权限模型 fs.realpathSync 绕过 | 26.x / 24.x / 22.x | low |
随附依赖更新:c-ares、ca-cert(eMudhra 中间证书妥协)、OpenSSL、SQLite、Undici。
1.3 修复版本判定阈值
| 组件 | 发布线 | 判定“受影响” | 判定“已修复” |
|---|---|---|---|
| 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 | 全部(EOL,无官方版本) | 仅“最小源码补丁”或发行版回移 |
| Node.js | 26.x | < 26.12.1 | ≥ 26.12.1 |
| Node.js | 24.x | < 24.22.1 | ≥ 24.22.1 |
| Node.js | 22.x | < 22.23.4 | ≥ 22.23.4 |
| Node.js | ≤ 20 | 全部(EOL,无补丁) | 无 |
php -v 显示的版本号可能仍低于阈值,但实际已修复。判定发行版包时,必须结合发行版安全公告确认回移状态,避免误判。
1.4 事件时间线(已核实)
| 日期 | 事件 |
|---|---|
| 2026-10-20 | PHP 官方发布补丁预告(Upcoming Critical PHP Security Release),告知将于 10-21 发布 |
| 2026-10-21 | PHP 发布 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35,修复 CVE-2026-109618 / CVE-2026-109619 |
| 2026-10-21 | Node.js 发布 v22.23.4 / v24.22.1 / v26.12.1,修复 10 个漏洞(含 Brotli RCE) |
2. 资产盘点:定位 PHP 与 Node.js
2.1 Linux 定位 PHP
php -v
php --ini
php -i | grep -i "Loaded Configuration\|memory_limit\|post_max_size\|session.upload_progress\|fatal_error_backtraces"
PHP 8.3.35)、主配置文件路径、关键指令当前值。command -v php php-fpm php-cgi php-cgi8.3
which -a php php-fpm php-cgi
whereis php php-fpm
ls -l /usr/bin/php* /usr/sbin/php* /usr/local/bin/php* 2>/dev/null
command -v 返回 shell 解析到的路径;which -a 列出 PATH 中所有同名命令,可发现多版本共存。# Debian / Ubuntu
dpkg -l | grep -i '^ii.*php'
# RHEL / CentOS / Rocky / AlmaLinux
rpm -qa | grep -i '^php'
# Alpine
apk info | grep -i php
php-common、php8.3-fpm、php8.3-cli 等包名与版本。# 运行中的 PHP 相关进程(FPM worker / CGI / mod_php 随 Web 服务器)
ps -eo pid,ppid,user,comm,args | grep -iE 'php-fpm|php-cgi|frankenphp|lsphp|httpd|apache2|nginx' | grep -v grep
# systemd 管理的 PHP 服务
systemctl list-units --type=service --all | grep -iE 'php|fpm|frankenphp|lsws'
# 确认 Web 服务器是否以 mod_php 方式加载
apache2ctl -M 2>/dev/null | grep -i php
httpd -M 2>/dev/null | grep -i php
php8.3-fpm.service)。apache2ctl -M / httpd -M 输出含 php_module 或 php7_module/php8_module,说明 Web 服务器以 mod_php 内嵌方式运行 PHP——官方称此为风险最高的部署形态,应最先处置。
2.2 Linux 定位 Node.js
node -v
npm -v
command -v node npm
which -a node
node -p "process.execPath"
v22.23.3 的版本号与可执行文件路径。多版本共存时 which -a 会列出多个。# Debian / Ubuntu
dpkg -l | grep -iE '^ii.*nodejs|^ii.*npm'
# RHEL / CentOS
rpm -qa | grep -iE 'nodejs|npm'
# Alpine
apk info | grep -i node
# nvm(需在已 source nvm.sh 的 shell 中执行)
nvm ls
nvm current
# pm2 管理的进程
pm2 list
pm2 -v
docker ps --format 'table {{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Ports}}' | grep -iE 'php|node|fpm|nginx|apache'
docker images --format '{{.Repository}}:{{.Tag}}' | grep -iE 'php|node'
2.3 Windows 定位 PHP / Node.js
php -v
where.exe php
Get-Command php -ErrorAction SilentlyContinue | Select-Object Source
# 在常见安装目录下查找(示例:限定盘符与深度,避免全盘扫描过慢)
Get-ChildItem -Path C:\ -Filter php.exe -Recurse -Depth 4 -ErrorAction SilentlyContinue
php.exe 的绝对路径与版本号。node -v
where.exe node
Get-Command node -ErrorAction SilentlyContinue | Select-Object Source
# PHP / Apache / Nginx / Node / IIS 相关服务
Get-Service | Where-Object { $_.Name -match 'php|apache|nginx|node|w3svc|W3SVC' } | Select-Object Name,Status,DisplayName
# 查看监听端口的进程(定位 Web 服务)
Get-NetTCPConnection -State Listen | Select-Object LocalAddress,LocalPort,OwningProcess
3. PHP 修复 SOP
3.1 按运行方式修复
# Debian / Ubuntu(服务名随版本变化,示例为 8.3)
sudo systemctl restart php8.3-fpm
# 平滑重载(部分发行版支持,重载前确认 pid 文件路径)
sudo kill -USR2 "$(cat /run/php/php8.3-fpm.pid)"
# 确认进程与二进制
ps -eo pid,ppid,user,args | grep '[p]hp-fpm'
ls -l /proc/$(pgrep -f 'php-fpm: master' | head -1)/exe
/proc/<pid>/exe 指向升级后的 php-fpm 二进制。systemctl status php8.3-fpm --no-pager 显示 active (running),且启动时间为本次重启时间;随后访问应用关键页面确认返回正常。# 配置语法检查(Debian/Ubuntu)
sudo apache2ctl -t
# 重启 Apache,使 mod_php 重新加载新库
sudo systemctl restart apache2
# RHEL / CentOS
sudo httpd -t
sudo systemctl restart httpd
apache2ctl -M | grep -i php(或 httpd -M | grep -i php)确认模块存在;以应用页面输出的 PHP 版本(或 phpinfo())确认版本已更新。# Nginx + php-cgi:重启承载 php-cgi 的进程管理器或 Web 服务器
sudo systemctl restart nginx
# 若由 supervisor 管理 php-cgi
sudo supervisorctl restart php-cgi
# Windows / IIS + PHP FastCGI(管理员 CMD)
net stop was /y
net start w3svc
# 二进制部署:替换为含补丁的 FrankenPHP 构建后重启
sudo systemctl restart frankenphp
# 容器部署:见 3.3 Docker 小节(拉取新镜像并重建)
# 查看当前 lsphp 版本
/usr/local/lsws/bin/lshttpd -v
# 升级 lsphp 后重启 LiteSpeed
sudo systemctl restart lsws
# 或
/usr/local/lsws/bin/lswsctrl restart
3.2 按发行版升级
sudo apt update
# 升级已安装的 PHP 相关包(包名随版本变化,示例为 8.3)
sudo apt install --only-upgrade php8.3-cli php8.3-common php8.3-fpm
# 如发行版仓库提供修复版本,可显式指定(版本号以仓库为准)
# sudo apt install php8.3=8.3.36-1
php -v
php -v 显示为修复版本,或发行版已回移补丁。sudo dnf clean all
sudo dnf update 'php*'
sudo dnf update php-fpm
php -v
sudo apk update
# 包名随版本变化,示例为 8.3
sudo apk upgrade php83 php83-fpm php83-cli
php -v
3.3 Docker 容器
# 1. 查看当前容器与镜像
docker ps --format 'table {{.ID}}\t{{.Image}}\t{{.Names}}'
# 2. 拉取含补丁的官方镜像(标签中的精确补丁版本以官方镜像仓库为准)
docker pull php:8.3.36-fpm
# 3. compose 场景:更新镜像引用并强制重建
docker compose pull
docker compose up -d --force-recreate
# 4. 验证容器内版本
docker exec <容器名> php -v
php -v 显示修复版本。FROM php:8.3-fpm),建议改为含补丁的精确版本标签(如 php:8.3.36-fpm),避免 latest 或滚动标签带来的不确定性。
3.4 面板环境(宝塔 / phpStudy / LNMP)
- 面板 →「软件商店」→「已安装」→ 找到 PHP-x.x → 选择「升级」或「切换版本」,安装修复版本。
- 升级后重启对应 PHP 服务。命令行示例(服务名与路径随宝塔版本变化):
/etc/init.d/php-fpm-83 restart
- 面板 →「软件管理」→ PHP 版本列表 → 下载并切换到修复版本(8.5.12 / 8.4.27 / 8.3.36 / 8.2.35)。
- 切换后重启 Apache / Nginx 与 PHP 服务。
# 进入 LNMP 安装目录(目录名随安装版本变化)
cd /root/lnmp1.9
./upgrade.sh php
# 按提示选择/输入要安装的 PHP 版本(修复版本)
php -v 显示修复版本;重启 php-fpm 服务。4. Node.js 修复 SOP
4.1 nvm 管理的 Node.js
nvm install 22.23.4 # 或 24.22.1 / 26.12.1,与目标发布线一致
nvm use 22.23.4
nvm alias default 22.23.4 # 设为默认,避免新开 shell 回落旧版本
node -v
# 列出全局包,升级后按需重装
npm ls -g --depth=0
node -v 输出 v22.23.4(或对应修复版本)。node -p "process.versions" 确认核心与依赖版本;重启应用进程。4.2 系统包管理安装的 Node.js
# Debian / Ubuntu(已配置对应发布线仓库)
sudo apt update
sudo apt install --only-upgrade nodejs
node -v
# RHEL / CentOS / Rocky / AlmaLinux
sudo dnf update nodejs
node -v
node -v 显示修复版本。4.3 Docker 镜像
# 拉取修复版本基础镜像
docker pull node:22.23.4
# 若 Dockerfile 使用 FROM node:22,建议固定为含补丁的精确标签:
# FROM node:22.23.4-alpine
# 重新构建并重建容器
docker build -t myapp:patched .
docker compose up -d --force-recreate
# 验证容器内版本
docker exec <容器名> node -v
node -v 显示修复版本;应用健康检查通过。4.4 pm2 管理的进程
# 升级系统 Node.js 后,刷新 pm2 的运行时引用并重启进程
pm2 update
pm2 restart all
pm2 list
# 确认 pm2 daemon 使用的 node 版本
node -v
pm2 list 中所有进程状态为 online;node -v 为修复版本。4.5 CI / 构建镜像
- 更新 CI 基础镜像标签为
node:22.23.4/node:24.22.1/node:26.12.1。 - 若使用
.nvmrc,将其内容改为目标修复版本。 - 若使用 GitHub Actions
actions/setup-node,将node-version指定为修复版本。 - 重新构建并重新部署产物,确保发布环境不残留旧版本运行时。
node -v 一致。5. 补丁前临时缓解
ini_set() 或 .user.ini。
5.1 针对 CVE-2026-109618(OOM 处理导致 RCE)
php_admin_value 下发,防止应用覆盖;并确认没有 pool、目录或应用设置把有限值重新设回。# PHP-FPM pool 配置(如 www.conf)
php_admin_value[memory_limit] = -1
# Apache 配置
php_admin_value memory_limit -1
upload_max_filesize < post_max_size。post_max_size = 8M
upload_max_filesize = 2M
- 限制解码后的请求体大小;
- 限制字段数、multipart 分片数;
- 限制请求头数、嵌套深度。
RLIMIT_AS / RLIMIT_DATA 作为边界,应使用容器或 cgroup 限制资源。5.2 针对 CVE-2026-109619(stale global state 导致 RCE)
session.upload_progress.enabled = 0
sudo systemctl restart php8.3-fpm
# 或平滑重载:sudo kill -USR2 "$(cat /run/php/php8.3-fpm.pid)"
# Apache mod_php:sudo systemctl restart apache2
fatal_error_backtraces = 0
5.3 其他官方补充
rpms.remirepo.net 源在补丁发布当日不提供更新,请改用发行版官方包,或自行从源码构建。6. 修复后验证与复核
6.1 PHP 验证
# 版本核对(CLI / FPM / cgi 各自确认)
php -v
php-fpm8.3 -v 2>/dev/null || php-fpm -v
# 确认运行中 master 进程实际加载的二进制
ls -l /proc/$(pgrep -f 'php-fpm: master' | head -1)/exe
# 确认关键指令当前生效值
php -i | grep -E 'memory_limit|post_max_size|session.upload_progress.enabled|fatal_error_backtraces'
# 功能验证:访问应用关键页面/接口,确认返回 200
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/
6.2 Node.js 验证
node -v
node -p "process.versions"
pm2 list
# 容器场景
docker exec <容器名> node -v
node -v 为 v22.23.4 / v24.22.1 / v26.12.1(或对应发布线修复版本);pm2 进程全部 online。6.3 复核清单
| # | 复核项 | 判定 |
|---|---|---|
| 1 | 所有 Web PHP(FPM / mod_php / cgi / FrankenPHP / LiteSpeed)已升级或确认回移 | 是 / 否 |
| 2 | 所有 PHP 进程/worker 已重启,非仅重启应用 | 是 / 否 |
| 3 | Node.js 已升级到受支持修复发布线,无 20 及更早版本残留 | 是 / 否 |
| 4 | 临时缓解配置(如已启用)在请求解析前生效,未依赖 ini_set()/.user.ini | 是 / 否 |
| 5 | 容器镜像标签已固定到含补丁版本,未使用滚动标签 | 是 / 否 |
| 6 | 升级前后版本号已记录并留痕 | 是 / 否 |
7. 回滚方案
7.1 PHP 回滚
# Debian / Ubuntu(版本号以本地缓存/仓库为准)
sudo apt install php8.3=8.3.35-1
sudo systemctl restart php8.3-fpm
# RHEL / CentOS
sudo dnf downgrade php-fpm php-cli
sudo systemctl restart php-fpm
# 将 compose / Dockerfile 中的镜像标签改回上一个已知可用标签
# 例:php:8.3.36-fpm -> php:8.3.35-fpm(保留的旧标签)
docker compose up -d --force-recreate
docker exec <容器名> php -v
7.2 Node.js 回滚
# nvm
nvm use <上一个版本>
# pm2
pm2 update
pm2 restart all
# Docker:回退镜像标签后重建
7.3 回滚前提与记录
- 升级前保留旧版本包 / 镜像标签 / nvm 版本,确保可回退。
- 变更单记录升级前版本与升级后版本、执行时间、执行人。
- 回滚后立即恢复临时缓解措施,并复核业务功能。
8. FAQ
Q1. 为什么升级 WordPress / Drupal / Joomla 无效?
本次漏洞位于 PHP 运行时(OOM 处理、stale global state),不在应用代码层。应用框架无法修复运行时的内存管理与请求清理缺陷。只有升级 PHP 运行时并重启所有 worker 才算完整修复。
Q2. 发行版包版本号低于阈值,是不是没修?
不一定。发行版可能以回移补丁(backport)方式在同一上游版本号上完成修复。此时版本号可能仍低于 8.3.36 等阈值,但漏洞已修复。判定时必须结合发行版安全公告确认回移状态,避免误判。
Q3. PHP 8.2 还能继续用吗?
PHP 8.2 将于 2026-12-31 停止支持(EOL)。本次虽提供 8.2.35 修复版本,但应尽快规划升级到受支持版本(8.3 / 8.4 / 8.5)。
Q4. PHP 8.1 及更早版本怎么办?
官方不再更新这些版本。官方另提供 PHP 7.4 / 8.0 / 8.1 的最小源码补丁(minimal source-backports)。可行路径:应用最小源码补丁自行编译,或直接升级到受支持版本。请勿继续运行无补丁的旧版本。
Q5. Node.js 20 及更早版本怎么办?
Node.js 20 及更早版本已 EOL,不会有补丁。必须升级到受支持的修复发布线:v22.23.4 / v24.22.1 / v26.12.1。
Q6. 只重启应用进程,不重启 PHP worker 行吗?
不行。漏洞与缓解配置作用在 PHP 运行时与 worker 层。必须重启所有 PHP 进程/worker(FPM worker、mod_php 所在 Web 服务器、php-cgi、FrankenPHP、LiteSpeed),否则新二进制与配置不会生效。
Q7. 用 ini_set() 或 .user.ini 设置缓解项可以吗?
不行。官方要求缓解配置在请求解析前生效,须通过 php.ini / FPM pool / 服务器配置下发,不可依赖 ini_set() 或 .user.ini。
Q8. memory_limit=-1 有什么风险?
它是官方针对 CVE-2026-109618 的缓解项,但放宽内存限制会增加资源耗尽风险。须配合请求体限制,并以容器 / cgroup 作为可用性边界,且仅作临时措施,不能替代升级。
附录 A · 命令速查表
| 场景 | 命令 |
|---|---|
| 查 PHP 版本 | php -v |
| 查 PHP 配置文件 | php --ini |
| 查 PHP 关键指令 | php -i | grep -E 'memory_limit|post_max_size|session.upload_progress.enabled|fatal_error_backtraces' |
| 定位 PHP 可执行文件 | command -v php php-fpm php-cgi / which -a php php-fpm php-cgi |
| 定位 PHP 进程 | ps -eo pid,args | grep -iE 'php-fpm|php-cgi|frankenphp|lsphp' |
| 确认 Apache mod_php | apache2ctl -M | grep -i php / httpd -M | grep -i php |
| 重启 PHP-FPM | sudo systemctl restart php8.3-fpm |
| 重启 Apache(mod_php) | sudo systemctl restart apache2 / sudo systemctl restart httpd |
| 查 Node.js 版本 | node -v / node -p "process.versions" |
| 定位 Node.js | command -v node / node -p "process.execPath" |
| nvm 切换版本 | nvm install 22.23.4 && nvm use 22.23.4 |
| pm2 刷新并重启 | pm2 update && pm2 restart all |
| 查容器镜像 | docker ps --format 'table {{.ID}}\t{{.Image}}\t{{.Names}}' |
| 容器内验证 PHP | docker exec <容器名> php -v |
| 容器内验证 Node | docker exec <容器名> node -v |
| Windows 定位 PHP | where.exe php / php -v |
| Windows 定位 Node | where.exe node / node -v |
| Windows 相关服务 | Get-Service | Where-Object { $_.Name -match 'php|apache|nginx|node|w3svc' } |
附录 B · 参考来源
- PHP 官方公告存档:https://www.php.net/archive/2026.php
- PHP 安全信息:https://www.php.net/security/
- Node.js 安全发布(2026-10-21):https://nodejs.org/en/blog/vulnerability/october-2026-security-releases