Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Реклама на форуме платная! Обращаться к Admin.
    Произошла смена домена с maza.one на maza1.top!!!

PHP2Shell: две RCE в ядре PHP без авторизации. Кто уязвим и как проверить сервер за минуту

ЮрКисс

Member
LV
0
 
Регистрация
Авг 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: подробности утекли раньше эмбарго. Ниже — разбор официальных бюллетеней без пересказа слухов, скрипт для проверки сервера и временные меры для тех, кто не может обновиться прямо сейчас.

Коротко​

​
CVE-2026-109618​
CVE-2026-109619​
Бюллетень​
Суть​
RCE через порчу состояния при нехватке памяти (OOM)​
RCE через use-after-free «протухшего» глобального состояния воркера​
CVSS v4.0​
9.2 (AV:N/AC:H/AT:P/PR:N/UI:N)​
9.2 (AV:N/AC:H/AT:P/PR:N/UI:N)​
Авторизация​
не нужна​
не нужна​
Подтверждённая 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+). Это не всегда «поменять версию в панели»: старые модули, плагины и самописный код могут сломаться. Поэтому порядок такой:

  1. Сделать полный бэкап сайта и базы.
  2. Развернуть копию на новой версии PHP и прогнать основные сценарии: каталог, корзина, оплата, формы, админка.
  3. Исправить несовместимости (обычно это устаревшие функции, each(), create_function(), строгие типы, изменения в mysqli).
  4. Переключить боевой сайт и временно включить меры из раздела выше, пока переезд не завершён.

Чек-лист​

  • [ ] Найти все 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-запросов.

Источники​

© https://habr.com/ru/articles/1097362/
 

Пинг форума и аптайм

Averaged results for https://maza.one

uptime counter
Назад
Сверху