22.10.2026 22 мин чтения

Критическая уязвимость PHP 21 октября: как обновиться на BitrixVM 7, BitrixVM 9 и в Docker

Две RCE в PHP с оценкой 9.2, и сильнее всех задет mod_php, на котором работает BitrixVM. Как обновиться на CentOS 7, где yum update ничего не даст, на EL9, где отстают зеркала Remi, и в Docker, где образ появился почти через три часа после релиза. Плюс временная защита, проверка через админку Битрикса и проверка сервера на взлом.

Критическая уязвимость PHP 21 октября: как обновиться на BitrixVM 7, BitrixVM 9 и в 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-серверов Омута. Штатная команда сработала примерно на половине. Ниже по каждому стеку: как обновиться и что делать, когда не получается.

Что именно сломано

Security advisory на php.net от 21 октября

Обе уязвимости в самом 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:

«Настройки PHP» на BitrixVM 9 после обновления: PHP 8.2.35, Apache 2.0 Handler

Версия должна быть не ниже исправленной для вашей ветки: 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;

    

«Командная PHP-строка»: 8.2.35 apache2handler

Ответ должен быть вида 8.2.35 apache2handler. Обе страницы доступны администратору.

⚠️ Важно
Админке здесь можно верить больше, чем консоли. Она работает в том же процессе Apache, что и сайт, а 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.

⚠️ Внимание
Если в админке грузят архивы больше 30 МБ, после этой правки загрузка сломается. Верните 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.

Так .htaccess со старыми строками php_value выглядит в редакторе админки

Удалите строки 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:

Меню BitrixVM 9 при входе под root

PHP здесь ставится из репозитория Remi. В advisory на php.net было написано, что в Remi обновлений в этот день не будет, но исправленные пакеты для EL9 появились там 21 октября, в том числе для старых 8.1, 8.0 и 7.4.

Обновление — три команды. Сначала сбросьте кэш списка пакетов. dnf хранит этот список у себя и без сброса может не увидеть пакеты, вышедшие несколько часов назад:

        dnf clean metadata

    

Затем обновите PHP:

        dnf upgrade 'php*'

    
⚠️ Проверьте
Перед установкой dnf покажет список пакетов и спросит 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:

dnf падает на недоступном EPEL после сброса кэша

Для обновления PHP эти репозитории не нужны. Скажите dnf пропускать недоступные:

        dnf --setopt=skip_if_unavailable=True upgrade 'php*'

    

dnf напишет Ignoring repositories: epel, … и обновит PHP:

Обновление PHP на BitrixVM 9 с пропуском недоступных репозиториев

Если 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 после обновления PHP до 8.2.35

Это тестовый 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 на эту систему можно только собрать самому.

Вариантов у нас было три:

  1. Собрать пакеты Remi под CentOS 7 самим. Получаются те же пакеты php-*, что уже стоят, только новее. Конфиги и расширения остаются на месте, откатиться можно на старые пакеты. Этот вариант мы и выбрали.
  2. Собрать PHP из исходников мимо пакетов. Придётся пересобрать все расширения и поменять пути в Apache и cron Битрикса, откатывать тоже сложнее.
  3. Переехать на 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 и сверяет, что сайты отвечают так же.

install.sh на CentOS 7 с PHP 7.4.33-15 из remi-php74: обновление до 7.4.33-31

В конце должно быть 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 я бы оставил и после обновления: Битриксу эта функция не нужна.

Опубликовано 1 день назад

Не сходится?

Спросите Домового: он знает документацию и материалы сайта по этой теме. Ответит сразу.

Нужен живой разбор?

Консультация автора BXMax: созвон один на один, 90 минут на вашу задачу по теме «Критическая уязвимость PHP 21 октября: как обновиться на BitrixVM 7, BitrixVM 9 и в Docker».

Выбрать время Ближайшее: 24 октября, суббота, 13:00–14:30 по Москве

Комментарии (0)

Пожалуйста, войдите в аккаунт, чтобы оставить комментарий

Оставить комментарий

Похожие статьи

Мы используем файлы cookie для улучшения работы сайта. Продолжая использовать сайт, вы соглашаетесь с нашей политикой конфиденциальности.
AI Домовой

AI Домовой История

на связи

пишет…

Можно закрыть чат и перейти на другую страницу. Когда ответ будет готов, на кнопке Домового появится отметка.

Нет истории чатов
AI Домовой

Нужна авторизация

Войдите, чтобы задавать вопросы AI Домовому.

Войти