Критическая уязвимость PHP 21 октября: как обновиться на BitrixVM 7, BitrixVM 9 и в Docker
Две RCE в PHP с оценкой 9.2, и сильнее всех задет mod_php, на котором работает BitrixVM. Как обновиться на CentOS 7, где yum update ничего не даст, на EL9, где отстают зеркала Remi, и в Docker, где образ появился почти через три часа после релиза. Плюс временная защита, проверка через админку Битрикса и проверка сервера на взлом.
Автор
Содержание
21 октября разработчики PHP выпустили 8.2.35, 8.3.36, 8.4.27 и 8.5.12 и попросили обновиться немедленно. Новые версии закрывают две уязвимости, CVE-2026-109618 и CVE-2026-109619, обе с оценкой CVSS 9.2. Через них запрос к сайту без всякой авторизации может выполнить на сервере чужой код. Хуже всего с mod_php, а именно на нём работает BitrixVM.
Вечером и ночью мы обновили больше десятка серверов: BitrixVM на CentOS 7 и на EL9, проекты в Docker, пакеты PHP для dev-серверов Омута. Штатная команда сработала примерно на половине. Ниже по каждому стеку: как обновиться и что делать, когда не получается.
Что именно сломано

Обе уязвимости в самом PHP, код сайта тут ни при чём. Подробный разбор лежит в advisory GHSA-w8hw-w9fx-j79w и GHSA-6wmf-4rv5-p3rp. Если коротко:
- CVE-2026-109618. Атакующий отправляет специально собранный запрос как будто с файлом (
multipart/form-data). Пока PHP его разбирает, у него кончается память, и он бросает запрос на полпути. При уборке PHP принимает недоразобранные данные за нормальные, и из этого атакующий собирает выполнение своего кода. - CVE-2026-109619. Когда запрос падает с фатальной ошибкой или нехваткой памяти, в процессе PHP остаются «хвосты» от него. Следующий запрос, который попадёт в тот же процесс, может на них наступить раньше, чем PHP их уберёт. Наступает он в двух местах: когда PHP отслеживает прогресс загрузки файла (
session.upload_progress, включено по умолчанию) и когда на старте запроса PHP ругается на устаревшую настройку из.htaccessили конфига Apache. На PHP 8.5 есть ещё третье место,fatal_error_backtraces.
Затронуты все способы запуска PHP: PHP-FPM, mod_php, php-cgi, FrankenPHP и LiteSpeed. На mod_php обе атаки показаны вживую. BitrixVM как раз ставит nginx, а за ним Apache с PHP-модулем, то есть mod_php.
Исправленные версии:
| Ветка | Исправлено в | Примечание |
|---|---|---|
| 8.5 | 8.5.12 | до обновления выключите fatal_error_backtraces |
| 8.4 | 8.4.27 | |
| 8.3 | 8.3.36 | |
| 8.2 | 8.2.35 | поддержка ветки заканчивается 31.12.2026 |
| 8.1, 8.0, 7.4 | релизов не будет | исправление выложено в исходниках на GitHub, у Remi есть пакеты 8.1.34-6, 8.0.30-21, 7.4.33-31 |
Версии 5.4–7.3 тоже уязвимы, исправлений для них нет.
Как понять, что у вас уже исправлено
Проще всего посмотреть в админке Битрикса. Откройте «Настройки → Инструменты → Диагностика → Настройки PHP». В шапке страницы написано PHP Version, а в строке Server API — Apache 2.0 Handler на BitrixVM или FPM/FastCGI в Docker:

Версия должна быть не ниже исправленной для вашей ветки: 8.2.35, 8.3.36, 8.4.27 или 8.5.12. На PHP 8.1 и 7.4 по номеру версии исправление не видно: в исправленных пакетах Remi остаются 8.1.34 и 7.4.33, меняется только номер сборки пакета. Как его посмотреть, написано в разделе про CentOS 7.
То же самое показывает «Настройки → Инструменты → Командная PHP-строка», если выполнить там:
echo PHP_VERSION, ' ', PHP_SAPI;

Ответ должен быть вида 8.2.35 apache2handler. Обе страницы доступны администратору.
php -v в консоли запускает отдельный PHP. Apache загружает PHP один раз при старте и держит его в памяти, пока его не перезапустят. На тестовом BitrixVM 9 после обновления пакетов без перезапуска Apache php -v уже показывал 8.2.35, а сайт работал на 8.2.34. Админка в этот момент показала бы 8.2.34, и это правильный ответ: пока Apache (httpd) не перезапущен, сайт уязвим.Если обновиться прямо сейчас нельзя
Так бывает с CentOS 7, где пакеты придётся сначала собрать. Разработчики PHP перечисляют меры, которые уменьшают риск, и прямо пишут, что сервер ими до конца не закрыть. Ниже то, что я бы включил на BitrixVM на время до обновления.
Выключить отслеживание прогресса загрузки и уменьшить размер запроса
Отслеживание прогресса загрузки файла (session.upload_progress) — главное место, где срабатывает CVE-2026-109619. Битриксу оно не нужно: в ядре main 26.800 и модулях «Управления сайтом» я не нашёл ни одного обращения к нему. Заодно уменьшим максимальный размер запроса: BitrixVM ставит 1024 МБ, а разработчики PHP против CVE-2026-109618 советуют 32 МБ для сайтов, которые принимают файлы.
Свои настройки PHP в BitrixVM 7 и 9 кладут в файл /etc/php.d/z_bx_custom_settings.ini. По умолчанию его нет. Откройте его на сервере в nano или через SFTP под root, редактор создаст новый файл:
nano /etc/php.d/z_bx_custom_settings.ini
Вставьте в него:
session.upload_progress.enabled = 0
post_max_size = 32M
upload_max_filesize = 30M
; только если у вас PHP 8.5:
; fatal_error_backtraces = 0
Сохраните (в nano: Ctrl+O, Enter, Ctrl+X) и перезапустите Apache:
systemctl restart httpd
Проверьте в админке на той же странице «Настройки PHP». В строке Additional .ini files parsed в конце списка должен появиться /etc/php.d/z_bx_custom_settings.ini. Ниже на странице post_max_size должен быть 32M, а session.upload_progress.enabled — Off. Если файла в списке нет, проверьте, что он лежит именно в /etc/php.d и имеет расширение .ini.
post_max_size и upload_max_filesize, когда обновите PHP.session.upload_progress.enabled = 0 я бы оставил навсегда, разработчики PHP советуют выключать его везде, где он не нужен.
Есть ещё мера memory_limit = -1, разработчики PHP называют её главной против CVE-2026-109618. На BitrixVM я бы её не включал. Это снимает лимит памяти совсем, а Apache держит десятки процессов, и один тяжёлый запрос сможет съесть всю память сервера. На одном из наших серверов процесс админки и с лимитом разрастался до гигабайта.
Убрать устаревшие php_value из .htaccess
Перед каждым запросом Apache применяет строки php_value из .htaccess. Если какая-то из них устарела, PHP на старте запроса выдаёт предупреждение. В этот момент он может наступить на «хвосты» предыдущего упавшего запроса, и так CVE-2026-109619 выполняет чужой код. Уберите такие строки, и до обновления PHP этот путь закрыт. После обновления они уже не опасны, но и пользы от них нет.
Раньше для UTF-8 сайтов на Битриксе в .htaccess писали:
php_value mbstring.func_overload 2
php_value mbstring.internal_encoding UTF-8
На PHP 8 первая строка ни на что не влияет, а вторая как раз выдаёт предупреждение «Use of mbstring.internal_encoding is deprecated» на каждом запросе. Я проверил это на тестовом BitrixVM 9: настройка применяется, а в лог Apache ничего не пишется, так что сами вы это предупреждение не увидите.
Откройте .htaccess в корне сайта. Это можно сделать в админке: «Контент → Структура сайта → Файлы и папки», файл .htaccess, кнопка «Редактировать». Или через SFTP: у основного сайта BitrixVM он лежит в /home/bitrix/www/.htaccess, у дополнительных — в /home/bitrix/ext_www/<домен>/.htaccess.

Удалите строки php_value mbstring.internal_encoding и php_value mbstring.func_overload и сохраните файл. Перезапускать Apache не нужно, .htaccess он перечитывает на каждом запросе. На свежих установках Битрикса таких строк нет, первой строкой будет Options -Indexes.
Если в файле есть другие php_value или php_flag, а сайт без них работает, их тоже лучше убрать: обычно они повторяют то, что BitrixVM уже задаёт в /etc/php.d/bitrixenv.ini. Конфиги самой BitrixVM в /etc/httpd/bx/conf трогать не нужно, настройки там корректные.
Закрыть загрузку файлов на nginx
Самая грубая мера, и в первые часы мы ставили её везде, где могли. Обе атаки в подтверждённом виде идут через запросы с файлами (multipart/form-data), кроме пути через fatal_error_backtraces на PHP 8.5. Если запретить такие запросы всем, кроме своих IP, атаковать нечем. Минус в том, что у посетителей перестанут работать формы с файлами, и это нужно принять на несколько часов. Админка с ваших IP будет работать как обычно.
Правило состоит из двух файлов, их нужно создать в nano или через SFTP. Первый файл описывает, кому можно. Вместо 203.0.113.10 впишите IP офиса или свой, по одному адресу на строку:
Файл: /etc/nginx/bx/maps/z_cve_multipart.conf
# Temporary, CVE-2026-109618/109619: multipart only from trusted IPs. Remove after the PHP update.
geo $cve_multipart_allowed {
default 0;
127.0.0.1 1;
203.0.113.10 1; # office / admin IP
}
map "$cve_multipart_allowed:$http_content_type" $cve_multipart_block {
"~*^0:multipart/" 1;
default 0;
}
Второй файл включает запрет для основного сайта. Для каждого дополнительного сайта положите такой же файл в его папку /etc/nginx/bx/site_settings/<домен>/:
Файл: /etc/nginx/bx/site_settings/default/z_cve_multipart.conf
if ($cve_multipart_block) { return 403; }
Проверьте конфигурацию nginx:
nginx -t
Должно быть две строки, syntax is ok и test is successful. Если nginx пишет ошибку, в ней будет имя файла и номер строки. Если всё в порядке, примените:
systemctl reload nginx
Проверить правило проще всего с телефона через мобильный интернет: отправьте на сайте любую форму с файлом, должна вернуться ошибка 403. Из офиса та же форма должна работать. На тестовом BitrixVM 9 я проверял это запросами с файлом с чужого и с разрешённого адреса: первый получил 403, второй прошёл, обычные формы без файлов работали. На BitrixVM 7 я это правило не запускал, но структура /etc/nginx/bx там та же.
После обновления PHP удалите оба файла и снова выполните systemctl reload nginx.
BitrixVM 9: CentOS Stream, Rocky, Alma 9
Какая у вас BitrixVM, видно в первой строке меню, которое открывается при входе на сервер под root:

PHP здесь ставится из репозитория Remi. В advisory на php.net было написано, что в Remi обновлений в этот день не будет, но исправленные пакеты для EL9 появились там 21 октября, в том числе для старых 8.1, 8.0 и 7.4.
Обновление — три команды. Сначала сбросьте кэш списка пакетов. dnf хранит этот список у себя и без сброса может не увидеть пакеты, вышедшие несколько часов назад:
dnf clean metadata
Затем обновите PHP:
dnf upgrade 'php*'
Is this ok [y/N]. Посмотрите на версию в колонке Version у пакетов php, php-cli, php-common: там должна быть исправленная, например 8.2.35-1.module_php.8.2.el9.remi. Если там 8.2.34 или 8.4.26, обновление уязвимость не закроет. Ответьте N и читайте ниже про отставшие зеркала. Если версия правильная, ответьте y.И перезапустите Apache, без этого сайт останется на старом PHP:
systemctl restart httpd
Пока Apache перезапускается, сайт несколько секунд отдаёт 502.
Если dnf ругается на EPEL или Percona
На тестовом BitrixVM 9 сразу после dnf clean metadata обновление не прошло совсем. dnf не смог скачать список пакетов EPEL и Percona, а без них отказался делать что-либо, в том числе обновлять PHP:

Для обновления PHP эти репозитории не нужны. Скажите dnf пропускать недоступные:
dnf --setopt=skip_if_unavailable=True upgrade 'php*'
dnf напишет Ignoring repositories: epel, … и обновит PHP:

Если dnf предлагает старую версию или не может скачать Remi
Вечером 21-го мы столкнулись с этим дважды. На одном сервере пакеты качались с таймаутами по 30 секунд, и качалась старая 8.4.26. На другом dnf сначала предлагал 8.2.34, а потом не смог скачать список пакетов Remi совсем:
Error: Failed to download metadata for repo 'remi-modular': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried
Причина в зеркалах. dnf берёт пакеты Remi не с основного сервера, а с зеркала поближе, и часть зеркал в тот вечер ещё не получила новые пакеты. Зеркала Яндекса и Timeweb для EL9 вообще отдавали 404.
Сначала попробуйте сбросить кэш dnf целиком, не только список пакетов:
dnf clean all
dnf upgrade 'php*'
dnf clean all удаляет всё, что dnf запомнил о репозиториях, в том числе список зеркал. При следующем запуске он скачает всё заново и может выбрать зеркало, которое уже обновилось. Версию в списке перед y проверьте так же, как выше. Если она всё ещё старая, подождите час-другой: зеркала догоняют основной сервер с задержкой.
У нас на одном сервере сброс не помог, а ждать было некогда. Тогда мы скачали пакеты прямо с основного сервера Remi. Команда длинная, но это одна команда, и файлы репозитория она не меняет:
dnf --setopt=remi-modular.mirrorlist= --setopt=remi-modular.baseurl=http://rpms.remirepo.net/enterprise/9/modular/x86_64/ --setopt=remi-modular.metadata_expire=0 --setopt=timeout=180 upgrade 'php*'
Адрес здесь по HTTP, а не по HTTPS: с одного хостинга основной сервер Remi по HTTPS не отвечал, а по HTTP отдавал всё за секунду. Это безопасно, dnf всё равно проверяет подпись каждого пакета. Версию в списке перед y проверьте так же, как выше.
Другого бесплатного источника PHP 8.4 для EL9 нет. В стандартных репозиториях Rocky и Alma PHP только до 8.3, и на вечер 21 октября там лежала 8.3.33, без исправления.
После обновления
Откройте в админке «Настройки PHP» и проверьте версию, как в начале статьи. Затем запустите «Настройки → Инструменты → Проверка системы» и нажмите «Начать тестирование». Результат должен быть таким же, как до обновления.

Это тестовый BitrixVM 9 после обновления до 8.2.35. Две ошибки в отправке почты к PHP не относятся: на стенде не настроена почта. Если такие ошибки были и до обновления, всё в порядке. Тревожиться стоит, если после обновления покраснело то, что раньше было зелёным, особенно «Наличие необходимых модулей php» и «Обязательные параметры PHP».
Если вы когда-то правили /etc/php.ini или файлы в /etc/php.d, загляните в эти папки через SFTP. Ваши файлы новый пакет не перезаписывает, а свою версию кладёт рядом с окончанием .rpmnew, например php.ini.rpmnew или 10-opcache.ini.rpmnew. Сравните её со своим файлом, перенесите нужное и удалите .rpmnew. На чистом BitrixVM 9 таких файлов не было.
На одном сервере, где PHP ставили давно, dnf заодно заменил пакет php-pecl-geoip на php-rlerdorf-geoip. Это то же расширение geoip в другом пакете, пугаться не нужно.
BitrixVM 7: CentOS 7
На CentOS 7 yum update ничего не найдёт. Remi перестал собирать пакеты для CentOS 7 в июне 2024 года, последние версии там — 8.3.8, 8.2.20, 8.1.29 и 7.4.33-15. Свежий PHP на эту систему можно только собрать самому.
Вариантов у нас было три:
- Собрать пакеты Remi под CentOS 7 самим. Получаются те же пакеты
php-*, что уже стоят, только новее. Конфиги и расширения остаются на месте, откатиться можно на старые пакеты. Этот вариант мы и выбрали. - Собрать PHP из исходников мимо пакетов. Придётся пересобрать все расширения и поменять пути в Apache и cron Битрикса, откатывать тоже сложнее.
- Переехать на EL9. Единственный вариант надолго, но срочную задачу он не решает. Об этом будет отдельная статья.
Своя сборка PHP для CentOS 7
Дальше — как собрать и поставить исправленный PHP на BitrixVM 7 самим, по первому варианту из списка. Рецепт подходит для веток 8.3, 8.2, 8.1 и 7.4.
Это неофициальная сборка PHP, а не замена поддерживаемой системы. Мы собрали её для своих серверов и делимся рецептом как есть, без гарантий: ответственности за работу ваших серверов с этой сборкой мы не несём. Используйте её только как временную меру, чтобы закрыть уязвимость, пока готовите переезд на BitrixVM 9.
- На рабочие серверы BitrixVM 7.5 мы ставили только сборку 8.3. Сборки 8.2, 8.1 и 7.4 проверены в контейнере: собрались, встали поверх пакетов Remi для CentOS 7, сайт ответил на новой версии, откат сработал. На живом сервере с Битриксом мы их не запускали.
- Перед установкой на рабочий сервер сделайте резервную копию сервера и сначала проверьте сборку на копии.
Готовые собранные пакеты мы не выкладываем. Пакет — это бинарный файл: что в него вошло, снаружи не проверить, а ставить его вы будете с правами root на рабочий сервер. Поэтому выкладываем рецепт: несколько текстовых скриптов, всего около 200 строк, которые вы можете прочитать перед запуском. Собирают они из исходного пакета Remi, внутри которого архив PHP с подписью php.net, и эту подпись проверяют. Из нашего в пакеты попадают только патч на 14 строк (нужен для 8.2 и 8.3) и флаги сборки, и то и другое лежит в комплекте текстом.
Шаг 1. Сборка
Собирать нужно не на сервере, а на любой другой машине с Docker: рабочем Mac, Linux-сервере для сборок. Скачайте комплект и распакуйте:
curl -O https://bxmax.ru/files/php-cve-2026-109618/php-el7-kit.tar.gz
tar -xzf php-el7-kit.tar.gz
cd php-el7-kit
Перед запуском откройте файлы в редакторе и посмотрите, что они делают:
build.sh(65 строк) — сборка: подключает репозитории, скачивает исходный пакет с rpms.remirepo.net, проверяет подпись php.net на архиве PHP, собирает пакеты;setup-repos.sh(32 строки) — какие репозитории CentOS 7 подключаются для сборки;php-el7-openssl102.patch(14 строк) — наш единственный патч к коду PHP, ставится только для 8.2 и 8.3;rpmmacros(5 строк) — настройки сборки;install.sh(87 строк) иrollback.sh(12 строк) — установка и откат на сервере.
Скрипты ничего не скачивают с bxmax.ru и никуда ничего не отправляют. Сборка идёт внутри контейнера Docker на вашей машине, на сервер потом попадают только собранные пакеты и два скрипта установки.
Собирать нужно ту же ветку PHP, что стоит на сервере: её видно в админке на «Настройках PHP». Другую ветку install.sh ставить откажется. Номер исходного пакета Remi для каждой ветки:
| Ветка | Параметр для build.sh |
|---|---|
| 8.3 | 8.3.36-1 |
| 8.2 | 8.2.35-1 |
| 8.1 | 8.1.34-6 |
| 7.4 | 7.4.33-31 |
Запустите сборку, подставив свой параметр в конец команды. Для PHP 8.3:
docker run --rm --platform linux/amd64 -v "$PWD":/kit -w /kit centos:7 bash build.sh 8.3.36-1
Скрипт сам поднимет внутри Docker чистую CentOS 7, скачает исходники Remi и PHP, проверит подпись php.net и соберёт пакеты. На Mac с Apple Silicon сборка заняла от 26 до 35 минут в зависимости от ветки, на обычном x86_64-сервере выходит в несколько раз быстрее. В конце скрипт выведет список файлов вида php-…-8.3.36-1.el7.local.x86_64.rpm, они появятся в папке out.
Почему не хватило просто собрать пакеты Remi как есть. Мы прошли три неудачные сборки по 20 минут, пока не нашли всё, что мешает:
- системная библиотека CentOS 7 (glibc 2.17) мешает скомпилировать один из файлов PHP. Лечится флагом компилятора, но передать его пришлось не туда, куда обычно, первая попытка не сработала;
- начиная с майских выпусков 8.2.31 и 8.3.31 код PHP для SSL-соединений использует функцию из OpenSSL 1.1, а в CentOS 7 стоит 1.0.2. Пришлось добавить небольшой патч-переходник. В 8.1 и 7.4 Remi перенёс исправления без этой функции, там патч не нужен;
- пары библиотек нужной версии для CentOS 7 нет, пришлось понизить требования.
Всё это уже учтено в комплекте, ничего править не нужно. Тесты самого PHP при сборке выключены, в эмуляции они идут часами. Это главное, что мы не проверили.
Шаг 2. Проверка на копии
До сервера мы поставили собранные пакеты в контейнер с CentOS 7, Apache и тем же набором пакетов PHP 8.3.8, что на сервере, с копией настроек PHP с сервера. Расширения и настройки после обновления совпали, сайт отвечал, откат на 8.3.8 сработал. Если у вас нестандартный набор расширений, сделайте так же. Если стоит стандартная BitrixVM 7.5 с PHP 8.3, можно сразу переходить к установке.
Сборки 8.2, 8.1 и 7.4 мы проверили так же, но на последних пакетах Remi для CentOS 7 (8.2.20, 8.1.29, 7.4.33-15) и без настроек с рабочих серверов: серверов на этих версиях у нас не было. На этих ветках проверку на копии сервера не пропускайте.
Шаг 3. Установка
Скопируйте на сервер папку php-el7-kit целиком, вместе с папкой out, через SFTP или scp. Например, в /root/php-el7-kit. На сервере под root:
cd /root/php-el7-kit
bash install.sh
Скрипт:
- проверяет, что пакеты скопировались целиком;
- скачивает текущие пакеты PHP в папку
rollback, чтобы было на что откатиться; - сохраняет настройки PHP в
/root/php-backup-<дата>; - запоминает, что отвечали сайты до обновления;
- ставит новые пакеты, перезапускает Apache и сверяет, что сайты отвечают так же.

В конце должно быть HTTP codes unchanged, строка PHP … (cli) с новой версией и имя пакета php-common-…el7.local.x86_64. Потом проверьте версию в админке на «Настройках PHP»: там должна быть та же версия.
В блоке == ini скрипт показывает настройки PHP, которые поменялись вместе с пакетом. На скриншоте из include_path пропал повтор, на 8.3.36 там появляется новая директива memory_hard_limit_percent. Если в этом блоке оказалась ваша настройка, например memory_limit или upload_max_filesize, проверьте свои файлы в /etc/php.d.
На 7.4 номер версии до и после обновления одинаковый, 7.4.33, и админка разницы не покажет. Смотрите на имя пакета в последних строках install.sh: должно быть php-common-7.4.33-31.el7.local.x86_64, число 31 и есть номер исправленной сборки. Позже то же самое покажет команда rpm -q php-common.
Если что-то пошло не так, откатитесь:
bash rollback.sh
Последней строкой будет версия, что стояла до обновления, например PHP 8.3.8 (cli). Папку rollback не удаляйте: часть зеркал Remi для CentOS 7 уже не отдаёт старые пакеты, и второй раз их можно не найти.
Так мы обновили два dev-сервера на BitrixVM 7.5 с 8.3.8 до 8.3.36. Ядро Битрикса (main 22.600 и 26.0) работает, сайты отвечали так же, как до обновления, в логах ошибок нет. Перед публикацией мы ещё раз прогнали скрипты в контейнере: сайт до обновления отвечал на 8.3.8, после — на 8.3.36, после отката снова на 8.3.8. Так же прошли 8.2.20 → 8.2.35, 8.1.29 → 8.1.34 и 7.4.33-15 → 7.4.33-31: сайт отвечал на новой версии, набор расширений не изменился, откат вернул старую.
Docker
Свой Dockerfile на официальном образе php
Если ваш образ собирается от php:8.x-fpm, его нужно пересобрать на свежем базовом образе. Пересоздать нужно все контейнеры на этом образе, а не только php: очереди, планировщик и cron тоже исполняют PHP.
Сначала убедитесь, что на Docker Hub уже лежит новый образ:
docker run --rm php:8.4-fpm php -v
В первой строке должна быть исправленная версия, например PHP 8.4.27 (cli). Если там 8.4.26, новый образ ещё не вышел, и пересборка ничего не даст. Официальные образы вышли не сразу: образ 8.4.27 появился на Docker Hub в 19:43 МСК, почти через три часа после релиза, а до этого теги какое-то время висели пустыми, и скачать их было нельзя.
Затем пересоберите и перезапустите:
docker compose build --pull
docker compose up -d
--pull Docker возьмёт старый базовый образ, который уже лежит у него в кэше. Если деплой у вас идёт скриптом, проверьте, что он действительно пересобирает образ: наш deploy.sh --pull без --build только скачивал образы и ничего не собирал.Проверьте версию в админке на «Настройках PHP» или командой:
docker compose exec php php -v
В ту же ночь сломались три вещи, к PHP напрямую не относящиеся.
PECL отвечал 504. pecl.php.net не выдержал нагрузки, и сборка падала на pecl install redis:
Could not download from "https://pecl.php.net/get/redis-6.3.0.tgz", cannot download "pecl/redis" (File https://pecl.php.net:443/get/redis-6.3.0.tgz not valid (received: HTTP/1.1 504 Gateway Timeout
Мы стали брать phpredis прямо с GitHub с проверкой контрольной суммы:
Файл: docker/php/Dockerfile (фрагмент)
ARG PHPREDIS_VERSION=6.3.0
ARG PHPREDIS_SHA256=cb8f81df1a275599e4f8ddcfec7e1f65ed1953e6f5673649149fd680ebff4cad
RUN curl -fsSL -o /tmp/phpredis.tar.gz \
"https://github.com/phpredis/phpredis/archive/refs/tags/${PHPREDIS_VERSION}.tar.gz" \
&& echo "${PHPREDIS_SHA256} /tmp/phpredis.tar.gz" | sha256sum -c - \
&& mkdir -p /usr/src/php/ext/redis \
&& tar -xzf /tmp/phpredis.tar.gz -C /usr/src/php/ext/redis --strip-components=1 \
&& docker-php-ext-install redis \
&& rm /tmp/phpredis.tar.gz
Пакеты Debian из России шли по 5–10 секунд каждый. Сборка образа растягивалась больше чем на час. Переключение на зеркало Яндекса — одна строка сразу после FROM, с ним те же 71 пакет скачались за секунды:
FROM php:8.4-fpm
RUN sed -i "s|http://deb.debian.org|http://mirror.yandex.ru|g" /etc/apt/sources.list.d/debian.sources
После пересоздания php-контейнера сайт отдавал 502. nginx запомнил адрес старого контейнера и продолжал ходить на него. Около трёх минут сайт лежал, пока мы не перезагрузили nginx. Поэтому после docker compose up -d сразу перезапустите и его:
docker compose restart nginx
Официальное окружение Битрикса env-docker
В bitrix-tools/env-docker версия PHP записана прямо в docker-compose.yml, в строках image: quay.io/bitrix24/php:…. Исправленные образы 8.2.35, 8.3.36, 8.4.27 и 8.5.12-fpm-v1-alpine выложили вечером 21 октября, а docker-compose.yml в репозитории обновили в ночь на 22-е.
Обновите репозиторий командой git pull или поправьте версию в docker-compose.yml вручную. Её нужно поменять в двух местах, у сервисов php и cron. Затем:
docker compose pull php cron
docker compose up -d php cron
Проверьте версию в админке на «Настройках PHP».
Омут: dev-серверы и компьютер
Для dev-серверов Омута мы пересобрали PHP 8.2–8.5 под Linux и утром 22 октября выложили на CDN. Сам сервер новый PHP не скачает, обновление нужно запустить. Способов два.
Из приложения. Откройте в Омуте страницу сервера и нажмите «Обновить агент». Вместе с агентом обновится всё, что стоит на сервере, в том числе все версии PHP, и службы с новой сборкой перезапустятся сами. Кнопка появляется, только когда приложение новее агента на сервере.

Из консоли сервера, если кнопки нет: агент уже той же версии, что приложение, а PHP обновился без новой версии Омута, как сейчас. Зайдите на сервер по SSH и выполните:
sudo omut-agent install
Команда работает на агенте 1.2.1 и новее. Агент сверит установленное со списком на CDN, скачает новый PHP, проверит подпись и перезапустит только PHP-FPM. Сайты, базы и настройки он не трогает. На нашем стенде на Debian 12 это заняло 20 секунд. В конце агент пишет [100%] Omut установлен. Если не хотите заходить по SSH, то же делает команда на компьютере omut server update-agent <имя сервера>. Подробнее — в документации Омута, раздел «Компоненты на dev-сервере».
Проверьте версию в админке сайта на dev-сервере, на странице «Настройки PHP».
На компьютере с macOS, Windows или Linux Омут покажет «Есть обновления компонентов окружения», обновление встанет при следующем запуске окружения. В эту же сборку для macOS и Linux вошли расширения, которые просили в группе: pdo_sqlite, posix, pcntl, soap, xsl, tidy, gmp, calendar, bz2, gettext, ftp, shmop, sysvshm, sysvsem и sysvmsg.
Для PHP 8.1 и 7.4 мы перенесли исправление из пакетов Remi (8.1.34-6 и 7.4.33-31) в сборки для macOS и Linux, они тоже уже на CDN и ставятся так же. Под Windows для 8.1 и 7.4 исправленных сборок нет. Сайты на этих версиях, особенно на dev-сервере, который смотрит в интернет, всё равно лучше перевести на 8.2 или новее: разработчики PHP эти ветки больше не поддерживают, и исправления в них приходят только точечными патчами от Remi.
После обновления: не успели ли взломать
Подробные разборы обеих уязвимостей опубликовали в тот же день, что и исправления. Сервер, который несколько часов простоял на старом PHP, стоит проверить. Мы написали для этого скрипт. Он ничего не меняет на сервере, только читает, работает с низким приоритетом и не мешает сайтам.
Скачайте и запустите его на сервере под root:
curl -O https://bxmax.ru/files/php-cve-2026-109618/compromise-check.sh
bash compromise-check.sh /home/bitrix/www /home/bitrix/ext_www/*
Через несколько минут (на больших сайтах дольше) скрипт напечатает отчёт и сохранит его в /root/compromise-check-<дата>.txt. Он смотрит:
- логи Apache, nginx и PHP за 14 дней: нет ли всплесков нехватки памяти и падений PHP. Атака на CVE-2026-109618 идёт через нехватку памяти, а неудачные попытки обычно роняют процесс;
- файлы сайта: PHP-файлы в
upload, изменения за 30 дней, признаки известных веб-шеллов; - систему: лишних пользователей с правами root, свежие SSH-ключи, задания cron, подозрительные процессы, подменённые системные программы.
Скрипт не выносит вердикт, он собирает улики. Читать отчёт так:
- строки
ok:— всё чисто; - строки
WARNиHIT— смотреть обязательно.HITзначит признак веб-шелла в файле, путь и строка указаны прямо в отчёте; - строки
recent:и списки файлов за 30 дней — это всё, что менялось недавно. Сверьте даты со своими работами: обновление, деплой, установка модуля. Подозрительно то, что вы не можете объяснить; - в последнем разделе на чистом сервере нули или единицы. Десятки
allowed memory exhaustedилиsegfaultза последние дни, особенно 20–21 октября, — повод разбираться, какие запросы шли в это время.
Так выглядит конец отчёта на тестовом BitrixVM 9:
=== 7. webroot /home/bitrix/www
-- PHP/.htaccess inside upload/storage dirs:
total: 0
-- PHP files modified in the last 30 days (by dir, top 15):
2 bitrix/php_interface
1 bitrix
total: 3
-- PHP files owned by the web user outside upload/cache dirs, last 30 days:
-- webshell signatures (non-core code + anything modified in 30 days + uploads):
ok: no signature hits in 4 files
-- long base64 blobs in recently modified PHP:
=== 8. logs: CVE indicators (memory exhaustion / segfault) and requests to PHP in upload dirs, last 14 days
allowed memory exhausted: 0
segfault / heap corruption: 0
Три изменённых файла — dbconn.php, after_connect_d7.php и .settings.php от 23 сентября. В этот день BitrixVM создал сайт и записал в них подключение к базе, признаков взлома в них нет. Выше в том же отчёте был WARN про файл /etc/sudoers.d/orbstack: его оставила система виртуализации, на которой стоит стенд. Каждый такой WARN нужно уметь объяснить, как этот.
На наших серверах признаков взлома скрипт не нашёл. Зато в логах одного сайта нашёлся массовый сканер: с 2 по 21 октября он перебирал известные уязвимые модули Битрикса (sprint.editor, slam.easyform, ipol.sdek, altop, sotbit). К этим CVE он отношения не имеет, но если такие модули у вас стоят, их тоже стоит обновить.
Что я бы сделал сегодня
На BitrixVM 9 и в Docker обновление занимает минуты, откладывать его незачем. Главное — не забыть перезапустить Apache и проверить версию в админке.
На BitrixVM 7 я бы сегодня же пересобрал PHP по рецепту выше, а переезд на EL9 запланировал на ближайший месяц. Каждый следующий патч PHP придётся собирать так же. Старые OpenSSL и компилятор CentOS 7 будут мешать всё сильнее: в этот раз хватило одного переходника, в следующий может не хватить.
session.upload_progress.enabled = 0 я бы оставил и после обновления: Битриксу эта функция не нужна.
Не сходится?
Спросите Домового: он знает документацию и материалы сайта по этой теме. Ответит сразу.
Нужен живой разбор?
Консультация автора BXMax: созвон один на один, 90 минут на вашу задачу по теме «Критическая уязвимость PHP 21 октября: как обновиться на BitrixVM 7, BitrixVM 9 и в Docker».
Комментарии (0)
Пожалуйста, войдите в аккаунт, чтобы оставить комментарий
Оставить комментарийЗагрузка...
Пока нет ни одного комментария. Будьте первым!
Похожие статьи