PHP для Windows: экстренная пересборка 8.2–8.5 из-за RCE в Brotli (CVE-2026-111497)

PHP выпустил пересобранные официальные пакеты для Windows версий 8.2–8.5. Причина — CVE-2026-111497 в библиотеке сжатия Brotli, которая входит в состав этих сборок. Уязвимость позволяет повредить память и потенциально выполнить код. Пересборка вышла через пять дней после релизов от 21 октября, закрывавших две RCE-уязвимости PHP2Shell.

Как атака доходит до уязвимого кода

Дыра в Brotli достижима через расширение cURL, когда оно автоматически распаковывает HTTP-ответы. По умолчанию cURL так не делает, но приложения и HTTP-клиентские библиотеки могут включить эту опцию сами.

Автоматическая декомпрессия означает, что cURL просит у сервера сжатый ответ и распаковывает его. В коде PHP за это отвечает опция CURLOPT_ENCODING, а пустое значение принимает любой формат, который поддерживает cURL. Библиотека Guzzle по умолчанию выставляет именно пустое значение для запросов, которые отправляет через cURL, — это видно в коде релизов 7.16.1 и 8.3.1. Судя по этому коду и описанию самой PHP, приложение с настройками Guzzle по умолчанию на прошлонедельных Windows-сборках выполняет условие для достижения уязвимости. The Hacker News не проверял это на системе с Windows.

Атака приходит в виде специально сформированного сжатого ответа от сервера, к которому обращается PHP-приложение.

Номера сборок и как их отличить

Пересобранные пакеты получили номера 8.5.12-1, 8.4.27-1, 8.3.36-1 и 8.2.35-1. Исходный код PHP в них тот же, поэтому исправления PHP2Shell сохраняются, а внутрь теперь включён Brotli 1.2.1 — исправленная версия.

Вместе с каждым пакетом PHP публикует перечень компонентов (software bill of materials). Для прошлонедельных сборок x64 Non Thread Safe всех четырёх версий в этих списках указан Brotli 1.2.0 — одна из уязвимых версий.

Поскольку сама версия PHP не изменилась, php -v покажет одно и то же число до и после обновления. Новую сборку опознают по -1 в имени файла — например, php-8.5.12-1-nts-Win32-vs17-x64.zip — и по хешу SHA-256, указанному на странице загрузок. PHP советует пользователям Windows ставить новые сборки оттуда.

Оценки серьёзности и статус эксплуатации

Google оценил уязвимость в 9.2 из 10, то есть как критическую, по шкале CVSS 4.0. Red Hat дал 8.1, или Important, по CVSS 3.1.

Исследователи Imperva выполнили код через эту уязвимость на одной официальной сборке Node.js, и им потребовалось несколько попыток. В уведомлении PHP об атаках ничего не сказано. В оценке CISA от 23 октября эксплуатация не зафиксирована, и на момент того обновления уязвимости не было в каталоге Known Exploited Vulnerabilities.

Уязвимость нашли исследователи OpenAI. Google исправил её в Brotli 1.2.1, 1.1.1 и 1.0.10, когда она была впервые раскрыта 21 октября. Node.js, Bun и другое ПО, которое поставляет собственную копию Brotli, тоже выпустило исправления.

Что делать, если обновиться пока нельзя

Готового обходного пути в уведомлении PHP нет. OpenAI советует до установки обновления отключить автоматическую декомпрессию Brotli в HTTP-клиентах и предупреждает, что удалить br — имя Brotli в заголовке Accept-Encoding — недостаточно: «само по себе это не мешает серверу прислать его».

В коде PHP это значит не задавать CURLOPT_ENCODING: без этой опции cURL ответы не распаковывает. В Guzzle нужно выставить опцию запроса decode_content в false — она отключает любое автоматическое декодирование, поэтому ответы в gzip тоже будут приходить сжатыми.

Тем, кто уже ставит обновление, стоит свериться с перечнем компонентов: если в нём Brotli 1.2.1, сборка новая. Заодно проверьте, не включена ли автоматическая распаковка там, где она не нужна: это снижает поверхность атаки и на будущее. Для приложений на Windows-серверах с PHP это особенно актуально — веб-стек часто тянет за собой зависимости, о которых администратор не помнит.

Если вы уже обновлялись после 21 октября ради уязвимостей PHP2Shell, учтите: те сборки закрывают RCE в самом PHP, но содержат уязвимый Brotli 1.2.0. Нужна именно пересборка с суффиксом -1. Похожая история с зависимостями — в разборе октябрьского обновления Windows 11, где исправления тоже не всегда видны с первого взгляда.

Частые вопросы

Какие версии PHP затронуты?

Официальные Windows-сборки PHP 8.2, 8.3, 8.4 и 8.5, выпущенные 21 октября, — в них Brotli 1.2.0. Исправлены пересборки 8.2.35-1, 8.3.36-1, 8.4.27-1 и 8.5.12-1.

Как понять, что у меня новая сборка?

По суффиксу -1 в имени файла (например, php-8.5.12-1-nts-Win32-vs17-x64.zip) и по хешу SHA-256 со страницы загрузок. php -v не поможет: версия PHP не менялась.

Уязвимость уже эксплуатируют?

В уведомлении PHP об атаках не сообщается. В оценке CISA от 23 октября эксплуатация не зафиксирована, и в каталог Known Exploited Vulnerabilities уязвимость на тот момент не входила.

Насколько это опасно по оценкам вендоров?

Google поставил 9.2 из 10 (Critical) по CVSS 4.0, Red Hat — 8.1 (Important) по CVSS 3.1.

Мой код использует Guzzle. Я под угрозой?

Guzzle в релизах 7.16.1 и 8.3.1 по умолчанию выставляет пустой CURLOPT_ENCODING, то есть принимает любой формат сжатия. По коду библиотеки и описанию PHP приложение с настройками по умолчанию на прошлонедельных Windows-сборках выполняет условие для достижения уязвимости.

Можно ли просто убрать br из Accept-Encoding?

Нет. OpenAI предупреждает, что это само по себе не мешает серверу прислать Brotli. Нужно отключать автоматическую декомпрессию в клиенте.

Что именно отключить в PHP и Guzzle?

В PHP — не задавать CURLOPT_ENCODING. В Guzzle — выставить опцию запроса decode_content в false. Учтите, что тогда перестанут распаковываться и ответы в gzip.

Это касается только Windows?

Речь об официальных Windows-пакетах PHP. Исправления Brotli 1.2.1, 1.1.1 и 1.0.10 вышли у Google, а собственные копии библиотеки уже обновили Node.js, Bun и другое ПО.

Источник: thehackernews.com