10月21日晚,php官方紧急发布安全更新,修复cve-2026-109618和cve-2026-109619两个严重漏洞。它们可导致未经身份验证的远程代码执行——不需要账号密码,一个构造好的http请求就可能打穿服务器;而且攻击发生在应用代码运行之前,waf、框架和cms自带的防护在这个阶段都还没启动。漏洞信息此前已在论坛上被提前泄露,安全机构甚至发现了早于官方通报数天的利用尝试。
很多人的第一反应是:赶紧把网站和插件更新到最新版。但这次真不一定管用——问题出在服务器底层的PHP运行环境里,网站程序和插件的升级,替代不了PHP本身的安全更新。本文按“找到受影响实例—选择修复路径—部署更新—确认生效—排查异常”的顺序展开,给你一套能验收的处置方案。
确认修复范围
两个漏洞的技术成因:前者(CVE-2026-109618)是内存不足(OOM)中断PHP时,内部请求数据只初始化了一部分,请求清理阶段却把无效数据当有效数据处理的缺陷;后者(CVE-2026-109619)是请求拥有的内部状态在其内存被释放后仍然残留,同一worker进程的后续请求可能在正常初始化之前误用这些“过期状态”。具体利用条件随运行方式、配置和应用而变化。PHP官方公告将处理Web请求的PHP安装列为排查对象。

修复基线如下。同一分支已经发布的更高版本,也应以官方和供应商的安全公告为准。
| 当前分支 | 本次官方修复版本 | 处理原则 |
|---|---|---|
| 8.2 | 8.2.35 | 升级至包含修复的同分支版本 |
| 8.3 | 8.3.36 | 升级至包含修复的同分支版本 |
| 8.4 | 8.4.27 | 升级至包含修复的同分支版本 |
| 8.5 | 8.5.12 | 升级至包含修复的同分支版本 |
| 8.1及更早 | 核对厂商回移补丁或迁移 | 不能把停止官方维护等同于所有厂商都无补丁 |
发行版可能把修复回移到较旧的上游版本。因此,看到版本号低于上表,不应直接下结论;要继续核对完整软件包版本、厂商针对这两个CVE的公告及修复状态。反过来,只收到“更新成功”的提示,也不能证明线上实例已经使用修复代码。


排查受影响实例:别只跑一条php -v
一台机器可能同时装着多个PHP版本。终端里的php属于CLI,Nginx转发的可能是另一个PHP-FPM实例,宝塔中的不同网站还可能绑定不同版本。排查要落到每个域名、每个后端实例。
# 只读取信息,不修改配置
command -v php
php -v
php --ini
ps -eo pid,lstart,args | grep -E '[p]hp-fpm|[a]pache2|[h]ttpd|[l]sphp'
systemctl list-units --type=service --all | grep -Ei 'php|apache|httpd|lsws'
# 容器环境另查;以下命令需要Docker访问权限
docker ps --format 'table {{.Names}} {{.Image}} {{.Status}}'
这些命令只是入口,不保证覆盖自编译、面板或非systemd环境。随后检查站点配置中的fastcgi_pass、FPM监听端口或socket、Apache加载模块以及容器服务映射,把域名和真正处理它的PHP进程对应起来。配置输出可能包含内部地址,留在受控环境检查,不要贴到公开论坛。
- 清单至少记录:域名、服务器或容器、PHP分支、完整软件包/镜像版本、运行方式、配置路径、负责人、修复状态。
- 负载均衡后面的所有节点都要列出,不能只验证一台。
- 同机旧站、测试域名、定时任务、内部OA/CRM和第三方设备也应确认,公网Web实例优先处置。
怎么确认网站真正在跑的PHP版本
实例太多、不想逐台手工排查的话,第八节汇总了几个社区现成工具,可以辅助检测和处置。
优先使用托管平台的运行环境信息、现有受保护的管理页面或内部诊断接口。确需临时验证时,可在已经限制管理员访问且禁止缓存的位置,放一个只返回必要信息的页面;不要在公网留下完整phpinfo()。下面的代码本身不包含访问控制。
<?php header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
echo json_encode([
'php_version' => PHP_VERSION,
'sapi' => PHP_SAPI,
'memory_limit' => ini_get('memory_limit'),
'post_max_size' => ini_get('post_max_size'),
'upload_max_filesize' => ini_get('upload_max_filesize'),
'session_upload_progress' => ini_get('session.upload_progress.enabled')
], JSON_UNESCAPED_SLASHES);
核验结束后立即移除临时页面。它能确认Web运行版本及部分配置,不能单独识别厂商回移补丁,也不能证明其他节点全部完成更新。

面板、Linux、Docker、Windows分别怎么修
动手前导出PHP配置和扩展清单,备份应用配置与必要数据,准备可恢复的快照或镜像。备份应保存在Web目录之外。测试登录、数据库、上传和关键接口;如果已有入侵迹象,先保留证据并隔离风险。
1. 宝塔、面板或托管主机
- 在站点设置中逐个记录绑定的PHP版本,再到面板的软件管理中检查相应PHP是否有包含修复的更新。
- 同为PHP 8.2,也要确认实际补丁版本;只切换版本标签或重装原来的旧包,并不算完成修复。
- 面板提供修复版本后,先在测试站点核对扩展、数据库连接及业务兼容性,再按维护安排更新对应PHP实例。
- 重启实际承载该站点的PHP服务,重新从Web端验证。未必需要重启整台服务器。
- 共享主机无法自行更新时,向服务商索要两个CVE的修复状态、完整版本、上线时间和验证结果;服务商暂时无法修复时评估访问限制或迁移。
不要因为网站由面板管理,就再用系统包管理器安装另一套PHP来“覆盖”。面板、自编译与发行版安装路径可能不同,更新错对象会产生“命令行已升级,网站仍是旧版”的假象。
2. Ubuntu / Debian:以PHP 8.2-FPM为示例
以下仅适用于确实由APT管理、软件包和服务名与示例一致的主机。其他分支替换成真实名称。先核对供应商公告,再查看候选版本;仓库没有修复包时,更新索引不会自动变出补丁。
# 读取当前已安装的PHP包
dpkg-query -W -f='${Package} ${Version}\n' 'php*'
# 更新仓库索引,再检查候选包
sudo apt update
apt-cache policy php8.2-fpm php8.2-cli php8.2-common
# 核对将发生哪些变更,不执行安装
sudo apt-get -s install --only-upgrade php8.2-fpm php8.2-cli php8.2-common
确认候选包已包含本次修复,且模拟结果没有意外切换分支或移除关键依赖,再执行升级。把已安装、实际需要的mysql、curl、mbstring、xml等扩展一并纳入兼容性检查,不要照单安装自己没有使用的扩展。
sudo apt-get install --only-upgrade php8.2-fpm php8.2-cli php8.2-common # 若二进制不在PATH中,请使用实际安装路径 sudo /usr/sbin/php-fpm8.2 -t # 先确认配置检查成功,再在维护窗口重启 sudo systemctl restart php8.2-fpm systemctl is-active php8.2-fpm sudo journalctl -u php8.2-fpm --since '15 minutes ago' --no-pager
Apache mod_php用户应升级实际加载的libapache2-mod-php对应包,先运行apache2ctl configtest,再重启apache2;Apache代理到FPM的部署,重点是更新并替换FPM进程。服务名均需以本机为准。包升级可能触发自动重启,生产环境应提前安排。
3. RHEL / Rocky / AlmaLinux等RPM环境
先确认PHP来自发行版仓库、模块流、厂商长期支持还是面板。不同来源的包名可能完全不同;不要在应急期间随意切换模块流或叠加来源不明的仓库。
rpm -qa | grep -Ei '^php|^lsphp' dnf list --installed 'php*' dnf check-update 'php*' # check-update返回100通常表示发现可更新包,不等于检查失败。 # 以下仅适用于实际包名和服务名均匹配的发行版安装: sudo dnf upgrade php php-cli php-common php-fpm sudo php-fpm -t sudo systemctl restart php-fpm systemctl is-active php-fpm
如果使用带版本前缀的软件包,更新和重启对象也必须改成对应实例。是否修复以该发行版或支持厂商的CVE公告为依据,不能拿上游版本号直接否定回移补丁。
4. Docker:拉取镜像后,还要替换运行中的容器
先判断Compose里的PHP服务是直接引用image,还是通过build构建。下面假设服务名为php,需替换成自己的服务名;两条路径任选适合的一条。
# 路径A:直接使用镜像。先在Compose中指定已核实包含修复的标签/摘要。 docker compose pull php docker compose up -d --no-deps --force-recreate php # 路径B:自建镜像。先更新Dockerfile中的PHP基础镜像。 docker compose build --pull php docker compose up -d --no-deps --force-recreate php # 两种路径均需验证 docker compose ps docker compose exec php php -v docker compose logs --since=15m php
Docker官方文档说明,build --pull会尝试拉取较新的基础镜像,但如果Dockerfile仍锁定没有修复的旧标签或旧摘要,重新构建也不会自动升级到安全版本。只执行pull或restart,同样不能保证运行容器已换成新镜像。
重建前确认数据库和上传文件有持久化存储,不要用down -v来更新PHP。多副本服务逐个替换并检查健康状态;容器内php -v仍主要验证CLI,最终要通过真实Web请求核对。
5. Windows / IIS FastCGI 或 Apache
- 核对Web服务器配置中的
php-cgi.exe或Apache模块实际路径,记录位数、TS/NTS构建类型和加载的扩展。 - 选择与现有部署方式相匹配、包含修复的PHP发行包,备份配置后部署;不要把新版本文件随意混进旧目录。
- 迁移必要的
php.ini设置与兼容扩展,检查扩展是否存在加载错误,再更新FastCGI路径或模块配置。 - 按维护流程回收并确认旧FastCGI进程退出;必要时停止再启动对应应用池,或重启实际Apache服务,随后从网站端验证。

升不了级时,怎么先争取时间
官方给出的临时措施针对特定触发路径。以下示例偏向FPM池配置,适用于维护人员已经确认配置位置的环境。必须同时考虑业务兼容性和可用性;如果无法可靠缓解,先在网关限制访问或暂时停用受影响服务。

先处理上传进度:session.upload_progress.enabled=0
在对应FPM池配置中,可由管理员设置如下参数。PHP 8.5的第二项才适用;不要不分版本全部粘贴。配置需在请求解析前生效,应用代码里的ini_set()不能替代。PHP-FPM配置文档解释了池级管理配置的语法。
; 对应FPM池配置,不是普通PHP脚本 php_admin_flag[session.upload_progress.enabled] = off ; 仅PHP 8.5,阻断已确认的fatal backtrace路径 php_admin_flag[fatal_error_backtraces] = off
内存不足路径:不要只抄一个memory_limit=-1
官方将管理员强制设置memory_limit=-1列为OOM路径的临时缓解之一,但底层分配失败仍可能触发问题;同时,解除PHP单请求内存上限会引入耗尽资源的风险。它需要结合前端请求限制、资源隔离和监控,由维护人员评估。不要为此关闭操作系统的内存保护,也不要把RLIMIT_AS或RLIMIT_DATA当成等价替代。
; 仅在完成容量评估、前端限制和资源隔离后考虑 php_admin_value[memory_limit] = -1 php_admin_value[post_max_size] = 8M php_admin_value[upload_max_filesize] = 4M
上面的8M/4M是小请求业务的示例,不适合直接套到大文件上传站点。Nginx若设置client_max_body_size,也要协调请求总量与业务需求;它只限制请求体大小,不能替代对字段数量、multipart部分数量、嵌套深度等维度的控制。确实不需要multipart请求的应用,才考虑在入口阻断该类型。
另外,要清理请求初始化前产生的无效、废弃配置警告,以及可由外部请求触发的致命错误和超时。关闭display_errors或隐藏日志,只是让错误不显示,不能修复状态管理问题。完成配置检查后重启所有相关worker,并从Web端核验。具体边界以过期状态漏洞公告及OOM漏洞公告为准。

修复验证
- 软件包层:保留两个CVE的厂商公告、已安装完整版本或镜像摘要,确认更新的是线上实际使用的PHP。
- 进程层:记录重启时间,核对master和worker已完成替换,避免旧进程继续处理请求。
- Web层:通过真实域名或受控直连方式验证每个后端节点,排除CDN缓存和命令行版本造成的误判。
- 业务层:检查登录、后台、数据库读写、上传、计划任务和队列;观察5xx、PHP错误、内存及进程异常。
- 配置层:如果用了临时缓解,确认它在每个池和节点生效。修复并稳定运行后,再逐项评估恢复正常内存限制等设置。
不要在生产网站上运行来路不明的漏洞利用脚本来“验收”。版本、厂商补丁状态、进程替换和业务验证能提供明确的维护证据;确需安全测试,应在授权的隔离环境进行。

入侵排查:怀疑被攻击时,升级之外还要做什么
英国NCSC的处置建议包括评估入侵迹象和后门。补丁能关闭漏洞,却不会自动删除攻击者已经留下的文件、账号或计划任务。

- 先隔离:在负载均衡或网关摘除可疑实例,限制其对外连接,保留必要的应急管理通道。
- 再留证:保存访问日志、PHP和Web服务日志、容器日志、进程与网络信息,必要时对磁盘或实例做快照。先记录,不要急着删除可疑文件。
- 对照基线:比较受信任发布包、代码仓库或镜像,检查Web目录与上传目录异常脚本、计划任务、新增账号及SSH密钥;文件修改时间只能提供线索。
- 查凭据:若有证据表明配置、进程内存或密钥可能泄露,从干净环境轮换数据库、对象存储、API等凭据,并撤销旧令牌和会话。
- 恢复:无法确认主机可信时,使用修复后的干净镜像或系统重建,迁入经过检查的数据;不要仅删一个webshell便宣布结束。
某个上传进度参数、一个可疑POST请求或一次内存错误,都不能单独证明入侵成功;同样,日志中没有特征,也不能证明安全。日志排查可重点关注包含PHP_SESSION_UPLOAD_PROGRESS字样的POST请求。调查起点也不能只从补丁安装时刻算起——Amazon威胁情报发现,早在10月17日(比公开通报早4天)就出现过针对这两个漏洞的利用尝试。调查范围应结合资产暴露期、日志保留情况和可靠情报综合确定。
更新后故障:502、扩展报错、上传失败怎么定位
更新后502:先看FPM是否启动,再核对Nginx或Apache连接的端口/socket是否正确,以及socket权限是否变化。换分支后,旧站点配置可能仍指向旧socket。
提示缺少扩展:对照更新前的扩展清单,从同一受信任来源安装兼容版本,再检查Web端。CLI加载扩展成功,不代表FPM加载了同一套配置。
上传失败或413:核对代理层限制、post_max_size与upload_max_filesize是否协调;请求体含有额外表单开销,不能把文件上限与请求总量上限设成相同大小后就认为没有问题。
更新后仍显示旧版:检查是否更新错安装路径、漏掉节点、没有重建容器、旧worker仍在运行,或验证页面被缓存。
确需回退:优先使用包含修复的上一稳定构建或修正配置和扩展;如果只有存在漏洞的旧包可回退,应先保持隔离,解决兼容性后再恢复对外服务。
现有工具:检测、升级辅助与临时缓解
补丁发布后一两天内,GitHub 上出现了几个针对 PHP2Shell 的社区工具。它们能省掉一部分逐台手工操作的时间,但定位各不相同,成熟度也有限——选型前先看下面这张表。
| 项目 | 能做什么 | 能否完成修复 |
|---|---|---|
| MakFly/php2shell-check | 检查本地、SSH 主机和 Docker 中的 PHP,输出修复建议;apply.sh 通过包管理器升级 PHP、重启服务后复查 |
协助安装修复;Docker 镜像仍需另行重建 |
| KyleClouthier/php2shell-check | 快速找出机器上的多个 PHP 安装,提示哪些分支需要更新;附带一个用后自删的网站侧版本检查文件 | 检测工具,不负责升级 |
| Blue-B/php2shell-guard | PHP 版本扫描(含发行版回移补丁判断)、Web 侧验证、临时阻断规则、疑似入侵排查 | 辅助检测与临时缓解,不能替代补丁 |
| ersinkoc/php-fix | 一键批量关闭 session.upload_progress,支持 dry-run、检查和备份回滚等模式,另有一些故障排查思路 |
临时缓解——名字虽叫 fix,但并没有完整修复 PHP 底层漏洞 |
使用这些工具有几点提醒:它们都是补丁发布后迅速出现的社区项目,运行前先通读脚本内容,优先在测试环境验证;带自动升级、重启行为的工具,要按第三节的要求先备份配置和数据、留好回退路径;工具显示“已修复”不等于修完,仍要按第五节的方法逐台核验。这类工具大多按特定发行版和目录结构编写,换环境前先确认适用性;是否采用,自行评估后再决定。
“网站能打开”“插件是最新版”“已经点过升级”,都不等于这次PHP漏洞处理完成。真正完成的标志,是每个实际承载业务的PHP实例都获得修复,更新已经生效,异常也有人检查。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











