PHP Windows 又更新了:版本号没变,Brotli 漏洞修在哪里?
PHP 在 10 月 26 日重新发布了 Windows 安装包,修复同捆 Brotli 的 CVE-2026-111497。PHP 运行时版本没变,检查时需要看安装包和实际加载的依赖。
官方 Windows 包需要确认是否换成带 -1 后缀的新构建;同时检查实际处理外部 HTTP 响应的 PHP 进程及其 cURL/Brotli 依赖。
相关信息
- 漏洞编号
- CVE-2026-111497,Brotli 解码器越界写入
- 官方 Windows 新包
- 8.5.12-1 / 8.4.27-1 / 8.3.36-1 / 8.2.35-1
- 官方包内修复版本
- Brotli 1.2.1
- 关注条件
- 应用或客户端启用自动解压,并处理不可信 Brotli 数据
PHP 的版本号没动,这次换的是包里的库
10 月 21 日,PHP 发布了修复两项运行时漏洞的版本。五天后,PHP 团队又更新了一次 Windows 包:8.5.12-1、8.4.27-1、8.3.36-1 和 8.2.35-1。
这次更新处理的是另一项问题,编号 CVE-2026-111497。出问题的不是上次那两条 PHP 请求处理路径,而是 Windows 包中使用的 Brotli 解码库。新包换入了 Brotli 1.2.1;PHP 源代码和运行时版本没有变化。
所以有个容易踩的坑:把旧的 8.5.12 Windows 包换成 8.5.12-1 后,执行 php -v 仍可能看到 8.5.12。这个输出能告诉你 PHP 的主版本,却不足以区分两次构建。要找回实际安装包、部署记录,或者进一步查看运行环境加载的依赖。
10 月 29 日补充:利用风险与云环境更新
加拿大网络安全中心 10 月 28 日的通报称,CISA 已在 10 月 27 日将 CVE-2026-111497 加入已知被利用漏洞目录。这说明同一个 Brotli 漏洞已有被利用的证据;通报并未说明攻击发生在 PHP Windows 包中,不能据此断定具体 PHP 环境已经遭到攻击。
受影响的也不只有 PHP。AWS 10 月 28 日公告指出,其 Lambda 的 Node.js 和 .NET 运行时涉及此漏洞;如果函数代码、依赖或层自行带入 Brotli,也要分别检查。对于容器镜像,基础镜像更新后仍需重新构建和部署;ZIP 函数的托管运行时按区域分阶段更新,具体状态应以 AWS 公告和函数实际运行时为准。
AWS 还提醒,入口处拦截 Content-Encoding: br 只能处理进入应用的请求,无法拦住应用从上游服务收到的压缩响应。检查 PHP cURL 客户端时,仍要沿实际响应解码路径排查,不能把入口拦截当成补丁。
Brotli 数据是怎么走进 PHP 的
Brotli 是一种压缩格式。一个 PHP 程序如果向外部服务发 HTTP 请求,对方可以返回经过 Brotli 压缩的响应,响应头用 Content-Encoding: br 标明格式。接收端启用自动解压后,libcurl 会调用对应解码器,应用最终拿到解压后的内容。
PHP 官方说明,Windows 包中的 cURL 扩展在开启 HTTP 响应自动解压时可能触及受影响的解码器。cURL 默认不启用这项自动解压,但应用或使用的 HTTP 客户端库可能开启。
例如,对一个已经创建的 cURL 句柄设置下面的选项,会让 libcurl 请求它编译时支持的压缩格式,并开启相应的响应解码。如果该构建支持 Brotli,请求里就可能包含 br。它只是一行配置示例,不需要为了检查漏洞去访问陌生站点。
curl_setopt($handle, CURLOPT_ACCEPT_ENCODING, '');解压器为什么会写出边界
Node.js 对同一个 Brotli 漏洞的公告解释了问题所在:解码流遇到无效的块类型切换时,原来的逻辑把它当成“还需要更多输入”,而不是已经无效的数据。解码器接着向一个固定大小的内部缓冲区追加数据,最终可能写到缓冲区之外。
越界写入意味着进程内存可能被破坏。根据运行环境和输入条件,后果可能包括进程崩溃、内存信息泄露,或进一步导致代码执行;这不等于只要安装了 PHP 就一定会发生远程代码执行。上面的机制来自 Node.js 对同一上游库问题的说明,PHP 应用的具体调用路径仍要按自己的环境确认。
哪些地方值得先查
先找 PHP 向外部发请求的地方:例如导入远程数据、拉取第三方接口,或者通过客户端库读取 HTTP 响应的任务。接着看返回内容能否受不可信对端影响,以及实际请求是否启用了自动解压。
这里有个细节:只在请求头里手写 Accept-Encoding,与通过 libcurl 的自动解码选项启用解压,并不是同一件事。libcurl 文档还提醒,服务端可以返回与请求期望不同的编码。因此,排查时要看实际的响应处理配置,不能只搜请求头里有没有 br。
除了 php -v,还能看什么
先确认部署来源。如果使用 PHP 官方 Windows 构建,查看替换时使用的安装包是否带 -1 后缀,再核对服务进程加载的文件。不要只看下载目录里有没有新包:新包在磁盘上,并不代表旧进程已经退出。
PHP 的 curl_version() 可以报告当前进程所用的 libcurl 信息,并在提供该字段时显示 Brotli 版本。下面的只读示例不会发网络请求;可以在受控环境保存后用对应 PHP CLI 运行:
结果中的 Brotli 版本是定位线索,不是完整的漏洞判定。当前 CLI 使用的 PHP 和库可能不同于 Web 服务或队列进程;字段缺失、发行版回移补丁、静态链接等情况,也需要结合构建商的说明判断。不要为了检查这些信息把 phpinfo 页面长期放到公网。
<?php
$info = function_exists('curl_version') ? curl_version() : false;
if (!is_array($info)) {
echo "当前 CLI 未加载 cURL,或查询失败\n";
exit(1);
}
echo 'libcurl: ', $info['version'] ?? '未报告', PHP_EOL;
echo 'Brotli: ', ($info['brotli_version'] ?? '') ?: '未报告', PHP_EOL;更新后别漏掉正在运行的进程
使用 PHP 官方 Windows 包的环境,应换用对应分支带 -1 后缀的新包。更换文件后,按自己的部署方式重启实际使用它的 PHP、FastCGI 或应用进程,再确认新文件已加载。
Linux 发行版、容器镜像和第三方打包的 PHP 可能通过不同方式提供 Brotli。不要拿 Windows 包的后缀判断这些环境;查对应发行方的安全公告、依赖包和镜像更新记录。如果组件被静态链接,仅更新系统里的共享库未必能修到该程序。
如果暂时不能更新,先梳理哪些请求会处理不可信的 Brotli 响应,并评估关闭相关自动解码、限制可信来源等临时措施的业务影响。临时措施需要覆盖实际调用路径,最终仍应采用供应商提供的修复。
资料来源
- PHP 官方公告:Windows 包更新 ↗
- Brotli 1.2.1 安全修复发布记录 ↗
- Node.js 公告:同一 Brotli 解码器漏洞的机制 ↗
- libcurl 自动响应解码选项 ↗
- PHP 手册:curl_version 返回字段 ↗
- Red Hat 对 CVE-2026-111497 的影响说明 ↗
- 加拿大网络安全中心:Brotli 漏洞与 CISA 已知利用记录 ↗
- AWS:Brotli 漏洞与 Lambda 运行时修复进度 ↗
依据文末原始资料整理;未在 Windows 环境复现或检查具体部署。编辑与更正说明。
修订记录
2026-10-27:首次发布:说明官方 Windows 重打包、Brotli 解码路径与部署检查。
2026-10-29:补充已知利用通报与 AWS Lambda 修复进度,区分 PHP 影响条件和入口拦截的局限。