Критические уязвимости PHP от 21 октября 2026: до какой версии обновиться и как сделать это безопасно

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

Что произошло

Команда PHP выпустила версии 8.5.12, 8.4.27, 8.3.36 и 8.2.35. Они исправляют две уязвимости:

  • CVE-2026-109618 — повреждение памяти при обработке нехватки памяти (out of memory). PHP прерывается, когда внутренние данные запроса заполнены лишь частично, а при очистке принимает эти данные за корректные;
  • CVE-2026-109619 — «устаревшее» глобальное состояние. Данные одного запроса переживают освобождение памяти, и следующий запрос в том же рабочем процессе может ими воспользоваться.

Обе уязвимости получили оценку 9,2 по CVSS 4.0 и при определённых условиях позволяют выполнить код на сервере без авторизации. Под угрозой все установки PHP, которые обслуживают веб-запросы: PHP-FPM, Apache с mod_php, php-cgi, FrankenPHP, LiteSpeed. Самый высокий риск — у mod_php: там атака срабатывает ещё до того, как запустится код приложения.

По данным CERT-EU на 23 октября, в сети уже ходят proof-of-concept эксплойты. Значит, вероятность реальных атак высокая, и откладывать обновление нельзя.

Официальные источники: бюллетень PHP, поддерживаемые версии PHP, CERT-EU 2026-018.

До какой версии обновиться

Ветка PHP Минимальная исправленная версия Поддержка безопасности до
8.5 8.5.12 31.12.2029
8.4 8.4.27 31.12.2028
8.3 8.3.36 31.12.2027
8.2 8.2.35 31.12.2026
8.1 и ниже исправления от проекта PHP нет ветки не поддерживаются

Для PHP 8.1 и старше проект PHP новых версий не выпускает. Есть три пути: бэкпорт от поставщика ОС или LTS-поставщика, минимальные патчи для сборки из исходников (команда PHP выложила их для 7.4, 8.0 и 8.1) или переход на поддерживаемую ветку.

Не нужно переводить всё на PHP 8.5. Обновляйтесь в пределах своей ветки: сайт на 8.3 — до 8.3.36 и новее, на 8.4 — до 8.4.27. Патч-версия внутри ветки исправляет ошибки и почти никогда не ломает совместимость. Переход 8.3 → 8.5 — это уже обновление платформы: устаревшие функции, новые требования библиотек и отдельное тестирование. Ветку стоит менять, только если ваша больше не получает исправлений, например 8.1 и ниже. А 8.2 получает исправления только до конца 2026 года, так что её переход стоит запланировать отдельно.

Какой PHP на самом деле обслуживает сайт

Частая ошибка — проверить php -v и успокоиться. Это версия консольного PHP (CLI). Сайт может работать совсем на другой версии через PHP-FPM, а на одном сервере часто стоят сразу несколько веток.

Какие версии установлены и какие пулы PHP-FPM запущены:

ls /usr/bin/php* /usr/sbin/php-fpm*
systemctl list-units --type=service | grep -i php
ps -eo user,pid,cmd | grep "php-fpm: " | grep -v grep

Какой сокет использует каждый сайт в Nginx:

grep -Rn "fastcgi_pass" /etc/nginx/sites-enabled/ /etc/nginx/conf.d/

Для Apache — подключён ли mod_php или запросы уходят в FPM:

apache2ctl -M | grep -i php
grep -Rn "SetHandler.*php" /etc/apache2/

Версия конкретного FPM, на сокет которого указывает сайт:

php-fpm8.4 -v

Если проекты работают в Docker, смотрите версию внутри контейнера: docker exec <контейнер> php -v. Версия на хосте здесь ни при чём.

Номер версии — ещё не вся правда

Debian, Ubuntu, RHEL и другие дистрибутивы часто переносят исправления в старую версию (backport) и не меняют основной номер. Пакет может называться 8.1.2-1ubuntu2.x, но уже содержать патч. Бывает и наоборот: номер свежий, а сборка самодельная и без патча.

Поэтому проверяйте источник пакета и его changelog, а не только номер:

# Откуда пакет и какая версия доступна (Debian/Ubuntu)
apt-cache policy php8.4-fpm

# Есть ли в changelog установленного пакета нужные CVE
zcat /usr/share/doc/php8.4-common/changelog.Debian.gz | grep -m5 -i "CVE-2026-1096"

# RHEL, AlmaLinux, Rocky
rpm -q --changelog php-common | grep -m5 -i "CVE-2026-1096"

Статус пакетов дистрибутива смотрите в его трекере безопасности: Ubuntu, Debian. Если PHP стоит из стороннего репозитория, например из PPA ondrej/php на Ubuntu, исправление приходит оттуда, и changelog — тоже его.


План безопасного обновления

1. Аудит: что есть на сервере

Перед любыми изменениями соберите картину:

  • ОС и её версия, веб-сервер (Nginx, Apache);
  • все установленные версии PHP и откуда они поставлены;
  • пулы PHP-FPM: какой сайт на какой версии и каком сокете;
  • проекты, их домены, фреймворки (Laravel, WordPress, Symfony, самописный код) и нужные расширения;
  • фоновые задачи: cron, очереди, Supervisor, systemd timers. Они работают через CLI, и его тоже нужно обновить;
  • Docker-контейнеры и свои PHP-образы;
  • как устроен деплой и как сейчас откатываются изменения;
  • свободное место на диске.

Результат удобно свести в таблицу: проект, домен, версия PHP, пул, уровень риска (доступен ли из интернета) и план. На этом этапе ничего не меняйте.

2. Резервные копии

Сохраните всё, что понадобится для восстановления:

  • конфигурации Nginx/Apache и виртуальных хостов;
  • конфигурации PHP и пулов PHP-FPM (/etc/php/);
  • crontab, задания systemd и Supervisor;
  • список установленных пакетов и модулей каждой версии PHP;
  • базы данных и загрузки пользователей, если изменение может их затронуть.
B=/root/php-upgrade-backup-$(date +%Y%m%d); mkdir -p "$B" && chmod 700 "$B"
tar czf "$B/etc.tar.gz" /etc/nginx /etc/php /etc/cron.d /var/spool/cron/crontabs
dpkg -l | grep -E "^ii\s+php" > "$B/php-packages.txt"
php-fpm8.4 -m > "$B/php8.4-fpm-modules.txt"
gzip -t "$B/etc.tar.gz" && echo "архив цел"

Если хостинг умеет делать снапшоты сервера, сделайте снапшот: это самый быстрый откат. Копию лучше хранить и за пределами сервера.

Учтите неочевидную деталь: сторонние репозитории обычно удаляют старые пакеты, как только выходит новая версия. Откатиться через apt install php8.4-fpm=<старая версия> уже не выйдет. Если нужен план отката, сохраните старые файлы пакетов до обновления.

3. Совместимость и тест

При обновлении внутри ветки (8.4.26 → 8.4.27) требования проекта не меняются: composer.json и composer.lock трогать не нужно. Не запускайте composer update: это обновит библиотеки, которые к уязвимости отношения не имеют.

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

Если стенда нет, проверьте хотя бы, что все нужные расширения доступны для новой версии: apt-get -s install --only-upgrade <пакеты> покажет, что именно установится, ничего не меняя.

4. Обновление по одному

  • Обновляйте только пакеты PHP, а не всю систему. Без apt upgrade и dist-upgrade:

    sudo apt-get update
    sudo apt-get install --only-upgrade -o Dpkg::Options::=--force-confold \
      $(dpkg -l | awk '/^ii +php8\.4-/{print $2}')
    

    Флаг --force-confold сохраняет ваши изменённые конфиги.

  • По одной ветке за раз. Если на сервере несколько версий, начните с той, от которой зависит меньше всего сайтов, и проверьте результат.

  • Помните про общие пулы. Если несколько сайтов работают в одном пуле PHP-FPM, обновление затронет их все сразу. Проверять нужно каждый.

  • Проверяйте конфигурацию перед перезагрузкой: php-fpm8.4 -t, nginx -t.

  • При обновлении пакет сам перезапускает PHP-FPM, и сайт на секунду-две отвечает 502. Делайте это в спокойное время.

  • Старые версии не удаляйте, пока не убедились, что всё работает.

На этом сайте обновление 8.4.26 → 8.4.27 дало примерно 2 секунды ответов 502, пока PHP-FPM перезапускался.

5. Проверка после обновления

Ответа 200 мало: страница может открываться, а форма или вход — не работать. Проверьте:

  • реальную версию PHP у сайта. Служба PHP-FPM должна быть перезапущена после установки, иначе в памяти остался старый код:

    php-fpm8.4 -v
    systemctl status php8.4-fpm | grep Active   # время запуска — после обновления
    
  • главные страницы и коды ответов, отсутствие 500, 502 и 503;

  • вход, сессии и формы (POST-запросы);

  • админку, загрузку файлов, отправку почты;

  • cron и очереди — они идут через CLI, так что проверьте и php -v;

  • набор расширений, сравнив с сохранённым списком: diff <(php-fpm8.4 -m) "$B/php8.4-fpm-modules.txt";

  • логи веб-сервера, PHP-FPM и приложения.

6. Если что-то сломалось

  1. Остановите дальнейшие обновления.
  2. Найдите последнее изменение и верните его: конфиг из копии, снапшот или старые пакеты.
  3. Убедитесь, что сайт работает, и запишите причину.

Откат на уязвимую версию — только временная мера, чтобы вернуть сайт. Такой сервер нельзя считать защищённым. Если исправление поставить не получается, ограничьте доступ к уязвимому сервису из интернета, пока не найдёте решение.


Если обновиться прямо сейчас нельзя

Команда PHP прямо пишет: полностью уязвимости закрывает только обновление. Меры ниже лишь сужают отдельные пути атаки и сервер безопасным не делают.

Против CVE-2026-109618 (нехватка памяти):

  • установить memory_limit=-1 так, чтобы приложение не могло его переопределить, например через php_admin_value в пуле FPM. Тогда ограничение памяти внутри PHP не сработает, но системная нехватка памяти по-прежнему может привести к уязвимому сценарию;
  • уменьшить post_max_size: 8M, если сайт не принимает файлы, и 32M, если принимает. upload_max_filesize должен быть меньше post_max_size;
  • ограничить размер запросов, число полей и заголовков на уровне веб-сервера или прокси.

Против CVE-2026-109619 (устаревшее состояние):

  • выключить session.upload_progress.enabled в php.ini или в пуле FPM и перезапустить все рабочие процессы. ini_set() и .user.ini для этого не подходят;
  • на PHP 8.5 — fatal_error_backtraces=0;
  • исправить фатальные ошибки и таймауты, до которых может дотянуться атакующий.

Пример для пула PHP-FPM:

; /etc/php/8.4/fpm/pool.d/example.conf
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 16M
php-fpm8.4 -t && sudo systemctl reload php8.4-fpm

Обратите внимание: 23 октября команда PHP отдельно посоветовала держать session.upload_progress.enabled=0 даже после обновления — до следующего регулярного релиза. Это защита от ещё одной, маловероятной уязвимости (CVE-2026-115560). Эта функция только показывает прогресс загрузки файла, и сайты ею почти не пользуются. Laravel на неё не опирается совсем, так что выключение обычно ничего не ломает.

Docker

В контейнерах PHP обновляется пересборкой образа, а не пакетом на хосте:

  • укажите точную исправленную версию в Dockerfile, например FROM php:8.4.27-fpm, а не latest или просто 8.4;
  • пересоберите образ без кэша (docker build --pull --no-cache) и перезапустите контейнеры;
  • проверьте версию внутри: docker exec <контейнер> php -v.

Не забудьте про сторонние образы и программы, в которые PHP встроен: их исправленные версии выпускают их авторы.

После обновления: проверьте, не взломали ли сервер раньше

Обновление закрывает дыру, но не удаляет то, что атакующий мог оставить до патча. Уязвимости публичны, эксплойты уже ходят, поэтому стоит проверить сервер. CERT-EU конкретных признаков не публиковал, ниже — общая практика:

# PHP-файлы, появившиеся или изменённые после раскрытия уязвимостей
find /var/www -name "*.php" -newermt "2026-10-20" -not -path "*/vendor/*" -ls

# PHP-файлы в папках загрузок, где их быть не должно
find /var/www -path "*upload*" -name "*.php" -ls

# Задания cron всех пользователей и подозрительные процессы
for u in $(cut -d: -f1 /etc/passwd); do crontab -u "$u" -l 2>/dev/null | sed "s/^/$u: /"; done
ps -eo user,pid,etime,cmd --sort=-etime | grep -E "www-data|nginx|apache" | head -20

Ещё стоит просмотреть:

  • логи веб-сервера за 20–24 октября: необычные multipart/form-data запросы, аномально большие тела запросов, всплески 500 и 502;
  • новых пользователей ОС и ключи в ~/.ssh/authorized_keys;
  • неожиданные исходящие соединения: ss -tnp.

Если нашли следы взлома, недостаточно просто удалить файл. Изолируйте сервер, восстановите его из чистой копии, сделанной до появления первых следов взлома, и смените все секреты: пароли БД, ключи API, APP_KEY, SSH-ключи.

На будущее: автоматические обновления

На Ubuntu unattended-upgrades по умолчанию ставит обновления безопасности только из репозиториев Ubuntu. Если PHP стоит из PPA или другого стороннего репозитория, патч сам не приедет. Так было и на этом сайте: сервер три дня после релиза оставался на уязвимой версии, пока PHP не обновили вручную. Либо добавьте репозиторий в разрешённые источники unattended-upgrades, либо подпишитесь на новости php.net и бюллетени своего дистрибутива.

Чек-лист

  1. Узнать, какие версии PHP есть на сервере и какая обслуживает каждый сайт (FPM, Apache, Docker), а не только php -v.
  2. Сверить их с исправленными: 8.5.12, 8.4.27, 8.3.36, 8.2.35. Для пакетов дистрибутива — проверить changelog на CVE-2026-109618 и CVE-2026-109619.
  3. Сделать резервные копии конфигов, списка пакетов и модулей, при необходимости — БД и снапшот.
  4. Обновлять в пределах своей ветки, только пакеты PHP, по одной версии за раз, без composer update.
  5. Проверить конфиги (php-fpm -t, nginx -t), затем сайты: страницы, вход, формы, админку, cron, логи.
  6. Убедиться, что PHP-FPM перезапущен после установки и отдаёт новую версию.
  7. Оставить session.upload_progress.enabled=0 до следующего релиза PHP.
  8. Проверить сервер на признаки взлома до патча.
  9. Настроить автоматические обновления или подписку на бюллетени, чтобы следующий патч не прошёл мимо.