Уязвимость в декодере Brotli позволяет уронить рабочий процесс PHP на обычном сайте WordPress, хотя сам WordPress эту библиотеку не поставляет. Ошибка возникает при разборе сжатого ответа: декодер записывает данные за границы своего буфера. Чтобы её вызвать, достаточно, чтобы WordPress запросил внешний адрес, а сервер злоумышленника ответил повреждённым потоком. Затронуты сборки Brotli, выпущенные до исправления, и все приложения, которые разбирают сжатые ответы через эту библиотеку.
CVE-2026-111497 доходит до WordPress через libcurl и pingback
Идентификатор ошибки - CVE-2026-111497, его назначил Google и оценил в 9,2 из 10. Уязвимы версии Brotli с 1.0.3 по 1.2.0, исправления вышли 21 октября 2026 года в 1.0.10, 1.1.1 и 1.2.1. 27 октября CISA внесла ошибку в каталог уязвимостей с подтверждённой эксплуатацией и дала федеральным агентствам США срок до 10 ноября. Сама запись CVE опубликована 22 октября и обновлена 27-го, а публичное раскрытие сведений в ней датировано 27 февраля 2026 года.
Обновлять в WordPress нечего. Платформа не поставляет Brotli, а подключает системную библиотеку через libcurl при каждом исходящем запросе. Поэтому ни в ядре, ни в плагинах нет файла, который закрывает ошибку. И во входящем запросе нет примет атаки: полезная нагрузка приходит в ответе с чужого сервера, а не в обращении к сайту.
Каждый исходящий запрос WordPress проходит через встроенный HTTP-слой, библиотеку Requests и транспорт cURL. Транспорт при создании соединения просит libcurl принимать любое сжатие и распаковывать его самостоятельно, и отменить это настройками WordPress нельзя. Ответ, где указано сжатие Brotli, уходит в декодер ещё внутри libcurl, до того как PHP увидит первый байт. Отключение распаковки на стороне WordPress не помогает: к этому моменту libcurl уже распаковал тело.
Повреждённый поток заставляет декодер писать за границы буфера в соседнюю область памяти. Формально ошибку относят к записи за границы буфера и к непроверенному возвращаемому значению: результат разбора не проверяется. Уронить рабочий процесс просто, и это работает на любой сборке, поэтому несколько сотен запросов подряд держат сайт недоступным. Раскрытие памяти и исполнение кода - задачи другого порядка, их готовят отдельно под каждую цель.
Публичные доказательства концепции уже есть, а 27 октября появилась лабораторная работа, которая проводит ошибку через pingback. Она описывает два исхода: рабочий процесс падает сразу или зависает с полной загрузкой ядра от нагрузки меньше ста байт. Автор прямо пишет, что исполнения кода в работе нет и удалённое выполнение вслепую не подтверждено. Рабочие цепочки исследователи собрали для сборок Node.js и Bun, но они опираются на фиксированное смещение в конкретной сборке и на подбор номера сокета. Для PHP под Apache или FPM публичной цепочки пока нет.
Самый короткий путь - pingback, механизм обратных ссылок в XML-RPC (удалённый вызов процедур по HTTP). Метод pingback.ping входит в стандартный набор, учётной записи не требует и принимает адрес источника. WordPress сам запрашивает этот адрес, а сервер злоумышленника отвечает тем самым повреждённым потоком. На стандартной установке XML-RPC включён, приём pingback открыт, и хотя бы одна запись его принимает. Атака идёт по сети, учётные данные не нужны, отдельного действия от владельца сайта тоже не требуется.
Многие сайты этот путь давно закрыли. Управляемые хостинги часто блокируют обработчик XML-RPC на периметре, а инструкции по усилению отключают его годами. Проверять надо, а не предполагать, потому что "XML-RPC отключён" означает две разные вещи. Блокировка на веб-сервере закрывает маршрут. Популярный фильтр отключения XML-RPC - нет: он снимает только методы, требующие входа, а pingback к ним не относится.
Отличить одно от другого можно одним запросом. Отправьте pingback, указав источником локальный адрес: WordPress отклонит его до запроса, поэтому проверка безопасна для своего же сайта. Ответ, который не является XML, или сообщение об отсутствующем методе означают, что маршрут закрыт. Любой другой ответ означает, что обработчик сработал и путь открыт.
Проблема в транспорте, поэтому XML-RPC - не единственный вход. Любой плагин, который запрашивает указанный посетителем адрес на стороне сервера, попадает в тот же декодер: предпросмотр ссылок, импорт изображений, проверка вебхуков, прокси аватарок. Так называемая безопасная обёртка добавляет только фильтр внутренних адресов и нестандартных портов. На признак сжатия в ответе она не смотрит, поэтому обычный сервер злоумышленника на 443 её проходит.
Межсетевой экран для веб-приложений (WAF) здесь почти бесполезен. Он решает по тому, что прислал посетитель, а полезная нагрузка приходит позже и с другого сервера. Чтобы отличить такой pingback от настоящего, экрану пришлось бы самому сходить по адресу и распаковать ответ, то есть выполнить шаг, который роняет процесс. PHP-файрвол не успевает и этого: он работает внутри WordPress, а распаковка идёт ниже, в libcurl, до запуска PHP. Правило может лишь целиком запретить метод pingback, а это закрывает один маршрут и не трогает ошибку.
Единственная мера, которая убирает саму ошибку, - обновление Brotli до 1.0.10, 1.1.1 или 1.2.1 либо установка обновления пакета libbrotli1 из дистрибутива. Проверка здесь неочевидна по двум причинам. Официальный образ wordpress:latest до сих пор ставит уязвимый libbrotli1, поэтому повторная загрузка образа не помогает: пакет надо обновить в своём слое сборки. И номер версии библиотеки ничего не говорит: Debian и Ubuntu переносят исправление в существующий выпуск 1.1.0. Смотреть надо ревизию пакета - у пропатченной машины она отличается суффиксом, который зависит от дистрибутива и выпуска.
Обходные меры ошибку не исправляют. В записи CVE их нет, ниже - то, что сокращает число путей к уязвимому коду, пока идёт обновление.
Самая широкая мера - запретить libcurl распаковывать ответы вообще. Небольшой плагин обязательного типа или файл темы переводит исходящие запросы в режим без сжатия, и тело от злоумышленника не доходит до декодера. Так закрываются сразу pingback, oEmbed (встраивание чужого содержимого по ссылке), ленты и запросы плагинов. Цена - WordPress перестаёт просить сжатые ответы, что на исходящем трафике мало что меняет. Мера отказывает мягко: если сервер пришлёт сжатое тело вопреки запросу, WordPress распакует gzip сам, средствами PHP, вдали от уязвимого кода.
Вторая мера - снять метод pingback из списка методов XML-RPC. Именно снять: обычный фильтр отключения XML-RPC его не трогает. Такой способ надёжнее блокировки по имени метода, потому что WordPress раскодирует ссылки на символы и блоки CDATA до вызова, и метод можно записать по-разному. Третья - запретить доступ к обработчику XML-RPC на уровне веб-сервера, тогда запрос отбрасывается до запуска PHP. Она закрывает только pingback, поэтому её сочетают с запретом распаковки. Дальше идёт аудит плагинов, которые запрашивают чужие адреса, и, где возможно, вывод исходящих запросов через прокси с разрешённым списком узлов. Ни одна из мер не заменяет обновление библиотеки.
Искать следы лучше в исходящем трафике. Ответ, помеченный как сжатый Brotli, на запрос WordPress - уже странность: обычно платформа получает обычный текст или gzip. Ещё подозрительнее маленькое тело, которое раздувается при распаковке, и ответ блоками, обрывающийся посередине. Прокси с журналом покажет и то, и другое.
На периметре ищите POST к обработчику XML-RPC без аутентификации, где pingback указывает на адрес, с которым сайту незачем общаться. Всплески таких запросов и домены, зарегистрированные недавно, - повод разобраться. Так же смотрят на точки плагинов, принимающие адрес от посетителя.
На хосте падение видно сразу: Apache и PHP-FPM пишут о дочернем процессе, завершившемся по сигналу 11, а дамп памяти с библиотекой декодера в трассировке снимает вопросы. Но не каждое срабатывание оставляет дамп. Лабораторная работа даёт и другой исход - процесс, занявший всё ядро без падения, поэтому проверку падений дополняют наблюдением за загруженными процессами и запросами, которые обрываются по таймауту. Одинаковое падение на однотипных запросах означает либо попытку уронить сайт, либо попытку сделать больше. Во втором случае признак - процесс веб-сервера, запускающий командную оболочку или обращение к незнакомому узлу.
Сейчас практический риск сводится к упавшим рабочим процессам и простою, который они дают. Раскрытие памяти и исполнение кода остаются труднее и требуют работы под конкретную сборку. Именно эти сценарии определяют высокую оценку ошибки.