21 октября 2026 года команда PHP выпустила внеплановые релизы 8.5.12, 8.4.27, 8.3.36 и 8.2.35. Они закрывают две критические уязвимости в ядре, каждая с оценкой 9.2 по CVSS v4.0. В обеих подтверждено удалённое выполнение кода без авторизации, причём для одной из них — ещё до того, как управление дойдёт до кода вашего приложения.
Релиз планировали на 17:00 МСК, но бюллетени появились около 16:30: подробности утекли раньше эмбарго. Ниже — разбор официальных бюллетеней без пересказа слухов, скрипт для проверки сервера и временные меры для тех, кто не может обновиться прямо сейчас.
Коротко
CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
Бюллетень | GHSA-w8hw-w9fx-j79w | GHSA-6wmf-4rv5-p3rp |
Суть | RCE через порчу состояния при нехватке памяти (OOM) | RCE через use-after-free «протухшего» глобального состояния воркера |
CVSS v4.0 | 9.2 ( | 9.2 ( |
Авторизация | не нужна | не нужна |
Подтверждённая RCE | Apache mod_php | Apache mod_php; сценарий с сессиями — также PHP-FPM |
Исправлено в | 8.2.35, 8.3.36, 8.4.27, 8.5.12 | 8.2.35, 8.3.36, 8.4.27, 8.5.12 |
Все ветки до 8.1 включительно официально не поддерживаются, и исправлений для них от PHP не будет.
Что именно сломано
CVE-2026-109618: OOM и longjmp()
Когда скрипту не хватает памяти (memory_limit), PHP прерывает обработку запроса через longjmp(). Проблема в том, что в некоторых местах память запроса уже доступна, но ещё не инициализирована. Если любое выделение памяти падает в этот момент, процедура завершения запроса потом работает с невалидными данными. Это и превращается в RCE.
Самое неприятное — способы гарантированно довести запрос до OOM, не выходя за видимые лимиты. Все они связаны с разбором multipart/form-data:
multipart-запрос без корректной длины тела может пройти проверку
post_max_sizeи продолжать слать данные;у части multipart может быть неограниченное количество заголовков, а в памяти PHP они занимают гораздо больше, чем по сети;
пустые поля загрузки файлов не считаются в
max_file_uploads, но создают массивы метаданных, а вложенные имена полей умножают эту работу.
Почему mod_php страдает сильнее всего: Apache с mod_php вызывает завершение запроса, даже если старт запроса упал. Разбор тела происходит ещё до вашего кода, поэтому атака не зависит от приложения: у вас может быть хоть пустой index.php. По данным бюллетеня, полная RCE подтверждена против mod_php с лимитами PHP по умолчанию. FrankenPHP, по анализу исходников, ведёт себя так же. PHP-FPM в этом сценарии просто убивает воркер, но после нормального старта OOM всё ещё опасен: FPM считается уязвимым, хотя полного эксплойта под него не показали.
CVE-2026-109619: «протухшее» состояние между запросами
Воркер PHP хранит глобальное состояние: ошибки, сессии, объекты, состояние расширений. Иногда оно указывает на память конкретного запроса. Если запрос прервался фатальной ошибкой (в том числе из-за той же нехватки памяти или таймаута), сброс этого состояния может не произойти. Память запроса освобождается, а указатель остаётся. Следующий запрос в том же воркере обращается к нему раньше нормальной инициализации — получается use-after-free.
Для атаки нужны два запроса: один оставляет мусор, второй его использует. Несколько воркеров снижают шанс попасть в тот же процесс, но не устраняют проблему. Подтверждено:
RCE через путь с fatal error backtraces (PHP 8.5) против mod_php;
RCE через жизненный цикл сессий против mod_php и PHP-FPM;
утечка памяти процесса.
Проверяем сервер за минуту
Один бинарник
php -v
Безопасные версии: 8.2.35+, 8.3.36+, 8.4.27+, 8.5.12+.
Но php -v в консоли часто показывает не ту версию, которая обслуживает сайт. На серверах с ISPmanager, cPanel, CloudLinux или Remi стоит по несколько PHP, а сайт может работать через php-fpm другой версии.
Все PHP на машине
Скрипт ищет PHP в типичных местах (системные пакеты, Remi, cPanel EA, CloudLinux alt-php, ручные сборки) и сравнивает каждую версию с исправленной:
#!/usr/bin/env bash # Ищет PHP на сервере и сравнивает версии с исправленными (PHP2Shell, 21.10.2026) fixed() { case "$1" in 8.2) echo 35;; 8.3) echo 36;; 8.4) echo 27;; 8.5) echo 12;; esac; } for bin in /usr/bin/php* /usr/sbin/php-fpm* /usr/local/bin/php* /usr/local/sbin/php-fpm* \ /opt/remi/php*/root/usr/bin/php /opt/remi/php*/root/usr/sbin/php-fpm \ /opt/cpanel/ea-php*/root/usr/bin/php /opt/alt/php*/usr/bin/php \ /opt/php*/bin/php /usr/local/php*/bin/php; do [ -x "$bin" ] && [ -f "$bin" ] || continue case "$(basename "$bin")" in phpize*|php-config*) continue;; esac v=$("$bin" -v 2>/dev/null | head -n1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1) [ -n "$v" ] || continue branch=${v%.*}; patch=${v##*.}; need=$(fixed "$branch") if [ -z "$need" ]; then case "$branch" in 8.[6-9]) status="тестовая ветка, проверьте вручную";; *) status="EOL: исправления от PHP не будет";; esac elif [ "$patch" -ge "$need" ]; then status="OK" else status="УЯЗВИМ: нужна $branch.$need или новее"; fi printf '%-45s %-8s %s\n' "$bin" "$v" "$status" done
Пример вывода:
/usr/bin/php7.4 7.4.33 EOL: исправления от PHP не будет /usr/sbin/php-fpm8.4 8.4.26 УЯЗВИМ: нужна 8.4.27 или новее /opt/remi/php85/root/usr/bin/php 8.5.12 OK
⚠️ Важно про пакеты дистрибутивов. Debian, Ubuntu, RHEL и другие часто переносят исправления в старую версию, не меняя её номер. Скрипт покажет «уязвим», хотя пакет уже залатан. В таком случае смотрите changelog пакета (
apt changelog php8.2-fpm,rpm -q --changelog php-fpm | head) и трекер безопасности своего дистрибутива по номерам CVE. И наоборот: ветки 7.x и 8.0/8.1 из сторонних репозиториев вряд ли получат исправление вообще.
Docker
docker ps --format '{{.Names}}' | while read c; do printf '%-30s ' "$c"; docker exec "$c" php -v 2>/dev/null | head -n1 || echo "php не найден" done
Не забудьте пересобрать образы, а не только перезапустить контейнеры: в базовом образе php:8.x должна оказаться исправленная версия.
Если доступа к консоли нет
WordPress: «Инструменты» → «Здоровье сайта» → «Информация» → «Сервер».
1С-Битрикс: «Настройки» → «Инструменты» → «Проверка системы».
Виртуальный хостинг: версия обычно видна в панели. Обновление PHP — задача хостера, напишите в поддержку и уточните сроки.
Заголовок
X-Powered-By(curl -sI https://example.com | grep -i powered) — ненадёжно: его часто скрывают, а версия в нём может не совпадать с реальной.
Обновляемся
После обновления пакетов обязательно перезапустите все воркеры (php-fpm, Apache), иначе в памяти продолжит работать старый код:
# Debian/Ubuntu, пример для 8.3 из ondrej/php apt update && apt install --only-upgrade 'php8.3*' systemctl restart php8.3-fpm # или apache2 для mod_php # RHEL/Alma/Rocky с Remi dnf upgrade 'php*' systemctl restart php-fpm
Затем снова прогоните скрипт или php -v и проверьте сайт.
Если обновиться прямо сейчас нельзя
Оба бюллетеня прямо пишут: полноценная защита — только обновление. Всё ниже лишь сужает поверхность атаки, пока вы готовите обновление.
Против CVE-2026-109618 (OOM):
Принудительный
memory_limit=-1на уровне администратора (php_admin_valueв пуле FPM или конфиге Apache) с перезапуском всех воркеров. Это убирает предсказуемый лимит, на котором построен эксплойт. Но сервер теряет защиту от прожорливых скриптов, поэтому ограничивайте память снаружи (cgroup/контейнер) и следите за нагрузкой.Не используйте
RLIMIT_AS/RLIMIT_DATAкак замену: по бюллетеню это как раз переводит PHP в уязвимую ветку.Держите консервативный
post_max_size, уменьшитеmax_input_nesting_levelиmax_input_vars, ограничьте размер тела и количество частей multipart на фронтенде (nginx, WAF).Если сайт не принимает
multipart/form-data(нет загрузки файлов и форм с файлами), режьте такие запросы на фронтенде.
Против CVE-2026-109619 (stale state):
На PHP 8.5:
fatal_error_backtraces=0на уровне администратора — убирает подтверждённый путь к RCE.session.upload_progress.enabled=0— закрывает подтверждённый сценарий с сессиями. Авторы бюллетеня советуют выключить его и после обновления, если функция не нужна.Если производительность не критична —
pm.max_requests=1в пуле FPM: каждый воркер обрабатывает один запрос, и «мусору» не к кому перейти.Ищите и устраняйте фатальные ошибки и предупреждения, которые атакующий может вызвать запросом: загрузки, импорты, страницы ошибок, деструкторы, обработчики вывода.
Что делать владельцам сайтов на PHP 7.x и 8.0/8.1
Это самая болезненная часть. В рунете огромное количество сайтов на Битриксе, WordPress и самописных движках со старым PHP. Исправлений для этих веток не будет, а временные меры выше не дают полной защиты.
Реальный выход один — переезд на поддерживаемую ветку (8.2+). Это не всегда «поменять версию в панели»: старые модули, плагины и самописный код могут сломаться. Поэтому порядок такой:
Сделать полный бэкап сайта и базы.
Развернуть копию на новой версии PHP и прогнать основные сценарии: каталог, корзина, оплата, формы, админка.
Исправить несовместимости (обычно это устаревшие функции,
each(),create_function(), строгие типы, изменения вmysqli).Переключить боевой сайт и временно включить меры из раздела выше, пока переезд не завершён.
Чек-лист
[ ] Найти все PHP на сервере, а не только тот, что в
php -v.[ ] Обновить до 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 или проверить бэкпорт в пакете дистрибутива.
[ ] Перезапустить php-fpm и Apache.
[ ] Пересобрать Docker-образы.
[ ] Если обновиться нельзя — включить временные меры и запланировать обновление.
[ ] Если ветка 7.x / 8.0 / 8.1 — планировать переезд, а не ждать патча.
[ ] Проверить логи на всплески ошибок нехватки памяти и фатальных ошибок при разборе POST-запросов.
Источники
Анонс на php.net и ChangeLog PHP 8
GHSA-w8hw-w9fx-j79w / CVE-2026-109618
GHSA-6wmf-4rv5-p3rp / CVE-2026-109619
Tenable: FAQ по PHP2Shell
BleepingComputer
Если не хотите разбираться сами — могу помочь: проверю, какие версии PHP реально обслуживают ваши сайты, обновлю их или перенесу проект со старого PHP 7.x на актуальную ветку с проверкой работоспособности. Пишите в Telegram: @sonic_h1.
