- Регистрация
- Авг 27, 2026
- Сообщения
- 48
- Реакции
- 18
21 октября 2026 года команда PHP выпустила внеплановые релизы 8.5.12, 8.4.27, 8.3.36 и 8.2.35. Они закрывают две критические уязвимости в ядре, каждая с оценкой 9.2 по CVSS v4.0. В обеих подтверждено удалённое выполнение кода без авторизации, причём для одной из них — ещё до того, как управление дойдёт до кода вашего приложения.
Релиз планировали на 17:00 МСК, но бюллетени появились около 16:30: подробности утекли раньше эмбарго. Ниже — разбор официальных бюллетеней без пересказа слухов, скрипт для проверки сервера и временные меры для тех, кто не может обновиться прямо сейчас.
Все ветки до 8.1 включительно официально не поддерживаются, и исправлений для них от PHP не будет.
Самое неприятное — способы гарантированно довести запрос до OOM, не выходя за видимые лимиты. Все они связаны с разбором multipart/form-data:
Для атаки нужны два запроса: один оставляет мусор, второй его использует. Несколько воркеров снижают шанс попасть в тот же процесс, но не устраняют проблему. Подтверждено:
Объяснить с
Безопасные версии: 8.2.35+, 8.3.36+, 8.4.27+, 8.5.12+.
Но php -v в консоли часто показывает не ту версию, которая обслуживает сайт. На серверах с ISPmanager, cPanel, CloudLinux или Remi стоит по несколько PHP, а сайт может работать через php-fpm другой версии.
#!/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
Объяснить с
printf '%-30s ' "$c"; docker exec "$c" php -v 2>/dev/null | head -n1 || echo "php не найден"
done
Объяснить с
Не забудьте пересобрать образы, а не только перезапустить контейнеры: в базовом образе php:8.x должна оказаться исправленная версия.
# 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):
Реальный выход один — переезд на поддерживаемую ветку (8.2+). Это не всегда «поменять версию в панели»: старые модули, плагины и самописный код могут сломаться. Поэтому порядок такой:
Релиз планировали на 17:00 МСК, но бюллетени появились около 16:30: подробности утекли раньше эмбарго. Ниже — разбор официальных бюллетеней без пересказа слухов, скрипт для проверки сервера и временные меры для тех, кто не может обновиться прямо сейчас.
Коротко
| CVE-2026-109618 | CVE-2026-109619 |
|---|---|---|
Бюллетень | ||
Суть | RCE через порчу состояния при нехватке памяти (OOM) | RCE через use-after-free «протухшего» глобального состояния воркера |
CVSS v4.0 | 9.2 (AV:N/AC:H/AT | 9.2 (AV:N/AC:H/AT |
Авторизация | не нужна | не нужна |
Подтверждённая 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 |
Что именно сломано
CVE-2026-109618: OOM и longjmp()
Когда скрипту не хватает памяти (memory_limit), PHP прерывает обработку запроса через longjmp(). Проблема в том, что в некоторых местах память запроса уже доступна, но ещё не инициализирована. Если любое выделение памяти падает в этот момент, процедура завершения запроса потом работает с невалидными данными. Это и превращается в RCE.Самое неприятное — способы гарантированно довести запрос до OOM, не выходя за видимые лимиты. Все они связаны с разбором multipart/form-data:
- multipart-запрос без корректной длины тела может пройти проверку post_max_size и продолжать слать данные;
- у части multipart может быть неограниченное количество заголовков, а в памяти PHP они занимают гораздо больше, чем по сети;
- пустые поля загрузки файлов не считаются в max_file_uploads, но создают массивы метаданных, а вложенные имена полей умножают эту работу.
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; doprintf '%-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 (нет загрузки файлов и форм с файлами), режьте такие запросы на фронтенде.
- На 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

