Перейти к основному содержанию
Блог

Новости

PHP CVE-2026-109618 и CVE-2026-109619: пошаговое обновление сервера

Центр кибербезопасности предупредил о двух уязвимостях в PHP. Какие версии исправлены, как проверить сервер и какие ловушки встречаются на реальных серверах.

· 10 мин. чтения

Фото: Markus Spiske markusspiske, CC0 · Wikimedia Commons

В октябре 2026 года национальный центр кибербезопасности опубликовал предупреждение о двух уязвимостях в PHP — CVE-2026-109618 и CVE-2026-109619. Они затрагивают веб-сайты, информационные системы, панели управления и другие сервисы на PHP. Проверять нужно PHP-FPM, Apache mod_php и любые другие PHP-окружения.

В этой статье мы превращаем рекомендации из предупреждения в практические шаги и показываем ловушки, с которыми сами столкнулись при обновлении реальных серверов. Они выглядят мелочами, но именно из-за них сервер, который считается «обновлённым», продолжает работать на старом уязвимом PHP.

Что известно и что нет

Исправленные версии (или более поздние в той же ветке):

  • PHP 8.2.35
  • PHP 8.3.36
  • PHP 8.4.27
  • PHP 8.5.12

Если PHP установлен из пакетов дистрибутива (Ubuntu, Debian, RHEL и другие), номер версии может отличаться: дистрибутивы переносят исправление в старый номер версии (backport). В этом случае установку исправления нужно подтвердить по бюллетеню безопасности производителя дистрибутива.

В наших источниках технические детали уязвимостей не опубликованы, поэтому мы не строим догадок о механизме. Практический вывод один: найти каждую систему с PHP, обновить её и убедиться, что обновление действительно работает.

Обновить пакет — половина работы. Вторая половина — убедиться, что старые процессы остановлены и работает новый бинарный файл.

Почему это важно для экспертизы

Официальная экспертиза кибербезопасности проверяет и версии программного обеспечения. Если сервер работает на версии PHP с опубликованной уязвимостью, это становится отдельным пунктом отчёта. Кроме того, многие серверы сами раскрывают версию PHP через заголовок X-Powered-By: PHP/8.3.x. Это тоже фиксируется как раскрытие информации и позволяет проверяющему определить версию с первого взгляда.

Обновить PHP и скрыть версию до подачи на экспертизу — одна из самых дешёвых и быстрых в устранении находок.

Шаг 1: найдите все установки PHP

Сначала инвентаризация. Начните с систем, доступных из интернета: сайты, порталы, панели управления. На одном сервере часто стоит несколько PHP, и далеко не все они установлены одним менеджером пакетов.

# Установленные через менеджер пакетов
ls /usr/bin/php* /usr/sbin/php-fpm* 2>/dev/null
dpkg -l | grep -E '^ii\s+(php|lsphp)' | awk '{print $2, $3}'
rpm -qa | grep -Ei '^(php|lsphp)'          # RHEL/Alma/Rocky

# PHP, собранный самой панелью (панели в стиле aaPanel)
ls -d /www/server/php/*/ 2>/dev/null

# OpenLiteSpeed lsphp
ls -d /usr/local/lsws/lsphp*/ 2>/dev/null

# Запущенные сейчас процессы PHP
ps -eo pid,user,cmd | grep -E 'php-fpm|lsphp|apache2|httpd' | grep -v grep

Для контейнеров:

docker ps --format '{{.Names}}  {{.Image}}'
docker exec <контейнер> php -v

Сведите результат в таблицу: сервер, источник PHP (apt, панель, LiteSpeed, контейнер), версия, какой сайт использует, доступен ли из интернета.

Шаг 2: определите, какой именно PHP работает

Здесь первая ловушка. Команда php -v показывает только версию CLI — то есть первого бинарника php в PATH. А сайт обслуживает PHP-FPM, mod_php или lsphp, и их версия может быть совсем другой.

Правильный способ — посмотреть бинарный файл работающего мастер-процесса:

pgrep -a php-fpm
# 1234 php-fpm: master process (/etc/php/8.3/fpm/php-fpm.conf)

ls -l /proc/1234/exe
# /proc/1234/exe -> /usr/sbin/php-fpm8.3

/usr/sbin/php-fpm8.3 -v

С PHP панели то же самое: ls -l /proc/<pid>/exe покажет путь вроде /www/server/php/83/sbin/php-fpm, и проверять нужно версию именно этого бинарника.

Если в выводе ls -l /proc/<pid>/exe в конце стоит (deleted), это важный признак: пакет обновлён, файл на диске заменён, но в памяти всё ещё работает старый бинарник. Пока такой процесс не перезапущен, уязвимость не закрыта.

Шаг 3: обновите каждый источник

Пакеты дистрибутива (apt, dnf)

# Debian/Ubuntu
apt update
apt install --only-upgrade 'php8.3*'

# Подтвердить исправление по changelog
apt changelog php8.3-fpm 2>/dev/null | grep -E 'CVE-2026-10961[89]'

# RHEL и производные
dnf update 'php*'
rpm -q --changelog php-fpm | grep -E 'CVE-2026-10961[89]'

Если PHP установлен из стороннего репозитория, номера версий там обычно совпадают с официальными версиями PHP, и их можно напрямую сравнить со списком выше.

PHP, собранный панелью

Панели в стиле aaPanel сами собирают PHP из исходников и кладут его в папки вроде /www/server/php/83. apt upgrade эту копию вообще не трогает. Владелец сервера может прогнать обновление apt и решить, что «всё обновлено», а сайт продолжит работать на PHP панели.

Такой PHP обновляется через собственный менеджер ПО панели или пересобирается. Затем проверьте версию бинарника напрямую:

/www/server/php/83/bin/php -v
/www/server/php/83/sbin/php-fpm -v

OpenLiteSpeed и lsphp

OpenLiteSpeed поставляется со своими пакетами lsphp (lsphp83, lsphp84 и т. д.). Они обновляются из репозитория LiteSpeed и не связаны с обычными пакетами php8.3-*:

apt install --only-upgrade 'lsphp83*'
systemctl restart lsws
ps -eo pid,lstart,cmd | grep lsphp | grep -v grep

Последней командой убедитесь, что процессы lsphp запущены после перезапуска — старых процессов остаться не должно.

Контейнеры

Перезапуска контейнера недостаточно: он поднимется из старого образа. Образ нужно пересобрать из обновлённого базового образа:

docker build --pull --no-cache -t myapp:latest .
docker compose up -d --force-recreate
docker exec <контейнер> php -v

Если в Dockerfile указан общий тег вроде FROM php:8.3-fpm, --pull подтянет последнюю патч-версию. Если версия зафиксирована (php:8.3.20-fpm), поменяйте тег на исправленную версию.

Неиспользуемые версии

Ещё одна ловушка: на сервере лежит когда-то установленный для тестов CLI php8.1 или php8.5. Ни один сайт его не использует, но он тоже уязвим, и сканеры экспертизы могут его найти. Два пути: обновить или удалить. Перед удалением проверьте, что cron-задачи и скрипты к нему не обращаются:

grep -rE 'php8\.1|php8\.5' /etc/cron* /var/spool/cron 2>/dev/null
apt purge 'php8.1*'

Шаг 4: перезапустите и подтвердите

После обновления пакетов PHP-сервисы и рабочие процессы обязательно перезапускаются:

systemctl restart php8.3-fpm        # или сервис панели для её PHP
systemctl restart apache2           # если используется mod_php
systemctl restart supervisor        # очереди Laravel и другие воркеры

Воркеры очередей, долгоживущие PHP-скрипты и демоны — отдельные процессы, и они тоже могут остаться на старом бинарнике. Затем проверьте:

for p in $(pgrep -f 'php'); do ls -l /proc/$p/exe; done | grep deleted

Эта команда ничего не должна вывести. В Debian/Ubuntu утилита needrestart также показывает сервисы, работающие со старыми библиотеками.

И наконец, скройте заголовок версии. В php.ini:

expose_php = Off

За nginx можно дополнительно добавить fastcgi_hide_header X-Powered-By;.

Если обновить сразу нельзя

Иногда обновиться немедленно не получается: старое приложение не работает на новой версии или нужно окно изменений. В этом случае:

  • Временно ограничьте внешний доступ к системе — например, оставьте админ-панель доступной только из внутренней сети или через VPN.
  • Примените временные меры, рекомендованные производителем.
  • Включите фильтрацию на WAF.

Но важно понимать: фильтры WAF и временные настройки не устраняют уязвимость полностью. Они лишь дают время. Чётко определите план и срок обновления.

Проанализируйте логи

Параллельно с обновлением проверьте, не использовалась ли уязвимость раньше. Ищите в логах веб-сервера, PHP и систем безопасности подозрительные запросы, несанкционированные изменения файлов и неожиданные процессы:

# Недавно изменённые или созданные PHP-файлы
find /var/www -name '*.php' -newermt '2026-10-01' -ls

# PHP-файлы в папках вроде uploads
find /var/www -path '*uploads*' -name '*.php'

# Процессы от имени пользователя веб-сервера
ps -u www-data -o pid,lstart,cmd

# Внешние соединения PHP-процессов
ss -tnp | grep -E 'php|lsphp'

В access-логе стоит обратить внимание на POST-запросы к незнакомым .php-файлам, необычно длинные параметры, много ошибочных ответов с одного адреса за короткое время.

Если обнаружены признаки инцидента, в первую очередь сохраните логи и доказательства (сделайте копии, ничего не удаляйте) и сообщите в Центр. Как выглядит очистка взломанного сайта, мы подробно показали в статье разбор бэкдора в WordPress.

Короткий чек-лист

  1. Учтены все установки PHP на всех серверах: apt/dnf, панель, lsphp, контейнеры.
  2. Для каждого сайта через /proc/<pid>/exe определено, какой бинарник PHP его обслуживает.
  3. Версии 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 или выше, а для пакетов дистрибутива исправление подтверждено бюллетенем.
  4. Неиспользуемые версии PHP обновлены или удалены.
  5. PHP-FPM, Apache, lsws и воркеры перезапущены, бинарников (deleted) не осталось.
  6. Контейнеры пересобраны из нового образа.
  7. expose_php = Off, заголовка X-Powered-By нет.
  8. Для систем, которые нельзя обновить, внешний доступ временно ограничен и срок обновления определён.
  9. Логи проанализированы, подозрительные файлы и процессы проверены.

Итог

Технически закрыть эти уязвимости несложно, но на реальных серверах PHP обычно стоит в нескольких местах, и если хотя бы одно упущено, сервер остаётся уязвимым. Нужно пройти все четыре шага: инвентаризация, обновление, перезапуск и подтверждение.

Хотите узнать, какой PHP на самом деле работает на вашем сервере и нет ли других открытых мест? Оставьте заявку на сканирование — агент Claude AI и наш специалист изучат настройки сервера, а мы поможем закрыть найденные дыры и подготовиться к экспертизе.