2026 年 10 月 21 日,PHP 官方一次性修复了两项可导致未授权远程代码执行的严重漏洞:CVE-2026-109618 和 CVE-2026-109619。两项漏洞的 CVSS v4.0 评分都是 9.2。它们不是某个框架、插件或网站程序的问题,而是出在 PHP 处理 Web 请求的底层流程里。只要服务器让 PHP 对外处理请求,就应该尽快核对版本并完成升级。
这次事情值得认真对待,但也不必被“PHP2Shell”这个传播名称吓得先停掉所有网站。对普通站长来说,最重要的动作只有三个:确认网站实际使用的 PHP 版本、升级到包含补丁的版本、升级后检查日志和业务是否正常。临时改配置只能降低部分利用路径的风险,不能代替补丁。
这次到底出了什么问题
两项漏洞都发生在 PHP 请求生命周期的边缘位置。平时一次请求从初始化、执行程序到清理结束,内部状态应当有始有终;漏洞出现时,这条链路在异常情况下被打断,PHP 后续又把不完整或已经失效的数据当成了有效数据继续使用。
CVE-2026-109618:内存耗尽后的错误清理
PHP 遇到内存耗尽时,会中止当前处理流程。问题在于,某些请求数据可能正处于“分配了内存但还没有完整初始化”的状态。如果此时发生内存分配失败,后续清理阶段仍可能读取或判断这块无效状态。攻击者可以利用特制请求反复触发这一条件,并把原本应该只是报错退出的情况推向远程代码执行。
Apache mod_php 的风险尤其高,因为攻击可以在网站自身的 PHP 代码运行之前触发。PHP-FPM 在部分启动失败场景下会直接退出子进程,条件相对苛刻一些,但 PHP 官方仍将 FPM、php-cgi、FrankenPHP 和 LiteSpeed 等处理 Web 请求的环境列入影响范围,不能因为使用了 Nginx + PHP-FPM 就忽略更新。
CVE-2026-109619:跨请求残留的全局状态
PHP 工作进程会连续处理多个请求,错误、会话、对象和扩展等信息中有一部分由全局状态保存。这些状态本应在释放本次请求内存之前彻底清理,但在致命错误、超时或异常清理过程中,某个指针可能仍然指向已经释放的内存。后续请求在正常初始化之前提前使用这份旧状态,就会形成“释放后使用”问题。
通俗地说,前一个请求留下了一张已经作废的门卡,后一个请求却在换新门卡之前拿它开门。攻击者需要同时安排能够“留下旧状态”的请求和能够“读取旧状态”的请求,利用难度不是最低的一档,但一旦成功,结果仍可能是远程代码执行。
它会带来什么危害
远程代码执行不是单纯让某个页面报错。成功利用后,攻击代码通常会以 PHP Web 工作进程的系统账号运行。实际危害取决于服务器权限配置,常见后果包括:
- 读取网站配置文件和数据库账号,进一步获取用户或订单数据;
- 在网站目录写入后门、篡改页面、插入跳转或恶意脚本;
- 窃取环境变量、API 密钥、对象存储凭据和第三方服务令牌;
- 利用错误的目录权限读取同一台服务器上的其他站点;
- 建立定时任务、异常进程或持续化入口,补丁安装后仍然潜伏;
- 耗尽内存和工作进程,造成网站间歇性不可访问。
因此,补丁解决的是“新的攻击还能不能进来”,日志和文件检查解决的是“修复前是否已经进来过”。公网服务器如果在漏洞披露后仍运行旧版 PHP,不建议只更新完就结束。
先确认版本:这些版本才算完成修复
| PHP 分支 | PHP 官方安全版本 |
|---|---|
| PHP 8.2 | 8.2.35 或更高 |
| PHP 8.3 | 8.3.36 或更高 |
| PHP 8.4 | 8.4.27 或更高 |
| PHP 8.5 | 8.5.12 或更高 |
PHP 8.1 及更早分支已经不再由 PHP 官方发布常规安全版本。部分 Linux 发行版、商业长期支持服务和面板厂商会回移补丁,因此旧分支不能只看上游版本号,要以发行版或服务商的安全公告为准。长期来看,继续把生产站点留在停止维护的分支上,下一次仍会遇到相同的被动局面。
普通服务器如何修复
1. 先备份,再确认网站实际运行版本
备份网站目录、数据库、PHP 配置和 Web 服务器配置。如果使用云服务器,条件允许时再做一次磁盘快照。随后确认每个站点实际绑定的 PHP 版本,不要只运行一次 php -v 就下结论:命令行 PHP 与 Nginx、Apache 实际调用的 PHP-FPM 可能不是同一个版本。
2. 使用发行版安全更新或官方修复版本
Debian、Ubuntu、RHEL、Rocky Linux、AlmaLinux 等系统,优先使用发行版或可信仓库提供的安全更新;自行编译 PHP 的服务器,则重新编译并安装对应的官方安全版本。使用 Docker 的站点要拉取包含补丁的新镜像并重新创建容器,仅重启旧容器不会改变 PHP 版本。
# Debian / Ubuntu:先查看将要更新的包,再执行更新
sudo apt update
sudo apt list --upgradable
sudo apt upgrade
# RHEL / Rocky Linux / AlmaLinux
sudo dnf check-update
sudo dnf update 'php*'
发行版可能采用“旧版本号 + 安全补丁回移”的方式,版本字符串不一定与 PHP 官网完全相同。此时应以发行版安全公告和软件包变更记录为准,不要为了追求相同的数字混用第三方软件源。
3. 重启服务并做业务回归
升级后必须重启对应的 PHP-FPM、Apache、LiteSpeed 或容器,确保旧工作进程全部退出。随后至少检查首页、后台登录、文件上传、表单提交、数据库读写、计划任务和支付回调等核心功能。
宝塔面板详细修复方法
第一步:查清每个网站用了哪个 PHP
登录宝塔面板,进入“网站”列表,查看各站点对应的 PHP 版本;也可以打开站点“设置 → PHP 版本”逐个确认。服务器安装了多个 PHP 版本时,要记录哪些版本仍被网站、定时任务或命令行脚本使用。只更新一个默认版本,无法保护仍连接旧 PHP-FPM 的站点。
第二步:完成备份
- 在“网站”中备份站点目录,或通过文件管理器打包关键目录;
- 在“数据库”中备份网站数据库,并确认备份文件能够下载或恢复;
- 在 PHP“设置 → 配置修改”中备份当前
php.ini内容,记录已安装扩展; - 生产服务器尽量选择低峰期更新,因为 PHP 服务重启会带来短暂中断。
第三步:刷新宝塔软件列表
进入“软件商店 → 已安装”,先点击右上角“更新软件列表 / 支付状态”。如果不先刷新,面板可能仍显示旧安装包,看不到这次紧急修复版本。安装 PHP 安全补丁本身不要求先升级宝塔面板。
第四步:PHP 7.4 及以上直接在软件商店更新
找到服务器正在使用的 PHP,点击“更新”,按提示安装对应安全版本。宝塔 Linux 面板当前提供的修复版本如下:
| 分支 | 宝塔 Linux 修复版本 | 说明 |
|---|---|---|
| PHP 7.4 | 7.4.34 | 宝塔回移补丁,建议尽快迁移新分支 |
| PHP 8.0 | 8.0.31 | 宝塔回移补丁,建议尽快迁移新分支 |
| PHP 8.1 | 8.1.35 | 宝塔回移补丁,建议尽快迁移新分支 |
| PHP 8.2 | 8.2.35 | PHP 官方安全版本 |
| PHP 8.3 | 8.3.36 | PHP 官方安全版本 |
| PHP 8.4 | 8.4.27 | PHP 官方安全版本 |
| PHP 8.5 | 8.5.12 | PHP 官方安全版本 |
更新过程中不要关闭面板任务,也不要同时改动 PHP 配置。完成后进入“软件商店 → PHP → 设置”,重新核对扩展、禁用函数和配置项是否仍符合业务需要。
第五步:宝塔 Linux 的 PHP 7.0 至 7.3
这些分支早已停止官方维护,宝塔此次提供了回移补丁包,但官方也明确建议先在测试环境验证。进入宝塔“终端”,只选择与当前分支对应的一条命令执行,不要把四条命令全部复制运行:
# PHP 7.0 → 宝塔修复版 7.0.34
curl -fL -o php7_cve.sh https://download.bt.cn/install/php7_cve.sh && bash php7_cve.sh install 70
# PHP 7.1 → 宝塔修复版 7.1.34
curl -fL -o php7_cve.sh https://download.bt.cn/install/php7_cve.sh && bash php7_cve.sh install 71
# PHP 7.2 → 宝塔修复版 7.2.35
curl -fL -o php7_cve.sh https://download.bt.cn/install/php7_cve.sh && bash php7_cve.sh install 72
# PHP 7.3 → 宝塔修复版 7.3.34
curl -fL -o php7_cve.sh https://download.bt.cn/install/php7_cve.sh && bash php7_cve.sh install 73
这些命令来自宝塔官方公告,但旧分支的扩展兼容性差异较大。执行前务必备份,并在完成后检查站点访问、上传、数据库连接和定时任务。应把这次补丁当成过渡方案,而不是继续长期使用 PHP 7.0 至 7.3 的理由。
第六步:宝塔 Windows 面板需要特别注意
宝塔 Windows 面板已经提供 PHP 8.2.35、8.3.36、8.4.27 和 8.5.12。PHP 8.1 及更早版本目前没有与 Linux 面板相同的完整旧版修复包,只能先做临时缓解并尽快迁移到受支持的 PHP 分支。不要把 Linux 的安装脚本拿到 Windows 服务器上运行。
暂时不能升级时,宝塔里怎样临时降低风险
下面这些设置不是完整修复。PHP 官方明确说明,安装包含补丁的版本才是唯一完整方案。
进入“软件商店 → 已安装 → PHP → 设置 → 配置修改”,在实际加载的 php.ini 中关闭 Session 上传进度:
session.upload_progress.enabled = 0
PHP 8.5 还可以增加:
fatal_error_backtraces = 0
保存后回到 PHP 设置页重启该 PHP 服务,确保所有工作进程重新读取配置。这些设置必须在请求解析前生效,不能只在网站代码中调用 ini_set(),也不要依赖站点目录里的 .user.ini。
同时根据业务限制请求体大小。没有大文件上传需求的站点可参考:
post_max_size = 8M
upload_max_filesize = 6M
需要上传较大文件时,可以根据实际情况设置为 32M 等合理值,但 upload_max_filesize 应小于 post_max_size。修改前先确认网站是否有备份导入、视频上传或批量文件处理功能。
PHP 官方还提到 memory_limit = -1 可以削弱已确认的内存耗尽利用路径,但这会取消 PHP 自身的内存上限。普通宝塔服务器如果没有容器或 cgroup 资源隔离,不建议直接照抄,否则一次异常请求可能拖垮整台服务器。它更适合有独立工作进程资源限制和运维经验的环境。
更新完别急着关面板:再做这几项检查
- 核对版本:在软件商店和站点 PHP 设置中确认实际版本,不要只看命令行默认 PHP。
- 确认服务:检查 PHP-FPM、Nginx 或 Apache 是否正常,错误日志有没有持续出现扩展加载失败。
- 测试业务:登录后台、上传文件、提交表单、查询数据库,并检查支付和消息回调。
- 检查近期文件:关注网站目录中突然出现或最近被修改的陌生 PHP 文件,先比对备份,不要见到近期文件就直接删除。
- 查看异常行为:检查访问日志、PHP 错误日志、计划任务、异常进程和异常外连。如果已经出现陌生后门,仅升级 PHP 不足以完成处置。
- 规划迁移:仍在使用 PHP 8.1 及更早版本的站点,安排插件和主题兼容性测试,尽快迁移到仍受官方维护的分支。
最后说一句
这次漏洞最容易产生两个误区:一是“我用的是 Nginx + PHP-FPM,所以不受影响”,二是“关掉 Session 上传进度就算修好了”。前者忽略了 PHP 官方列出的完整影响范围,后者把临时缓解当成了补丁。对公网网站来说,正确顺序始终是先升级、再验证、再排查,配置加固只能放在补丁之外。
你这次升级时遇到了扩展不兼容、宝塔看不到更新,还是服务器仍在使用旧 PHP?欢迎在评论区说说具体版本和环境,大家可以一起补充排查经验。
参考资料
你认为这个网站怎么样?
-人
-人
-人
-人
-人
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...