Дайджесты новостей
Системный администратор в ночной серверной перед экраном терминала с алертом уязвимости php2shell и статусом обновления PHP.

Уязвимость php2shell в PHP core: механика исчерпания памяти и удалённое исполнение кода

Если ты администрируешь веб-серверы или разрабатываешь бэкенд на PHP, последние дни наверняка запомнились экстренными ночными дежурствами. По индустрии прокатилась ударная волна: исследователи из Wiz опубликовали технические подробности критической цепочки уязвимостей в ядре языка PHP, получившей собирательное имя php2shell (идентификаторы CVE-2026-109618 и CVE-2026-109619).

Оценка серьезности по шкале CVSS v4.0 составляет пугающие 9.2 из 10 (Critical). И этот рейтинг абсолютно оправдан: уязвимость позволяет неавторизованному злоумышленнику удаленно выполнить произвольный код (Remote Code Execution, RCE) на сервере через единственный специально сформированный HTTP POST-запрос.

Самое неприятное в этой истории — вектор атаки. Твое приложение может быть написано по лучшим стандартам индустрии: ты можешь использовать фреймворк Laravel или Symfony со строгой типизацией, параметризованными SQL-запросами и санитайзингом пользовательского ввода. Но php2shell бьет глубже: эксплойт срабатывает внутри низкоуровневого парсера ядра языка на языке C до того, как управление вообще дойдет до твоего PHP-скрипта.

Анатомия атаки: как multipart ломает рантайм

Давай разберем по винтикам, как безобидная загрузка формы превращается в удаленный системный шелл.

Пошаговая схема цепочки атаки php2shell в парсере rfc1867.c от переполнения памяти до захвата шелла.

Стандарт HTTP определяет формат multipart/form-data для передачи файлов и полей форм: данные разбиваются на части, разделенные текстовыми границами (boundary). За разбор этого потока байтов в ядре PHP отвечает файл main/rfc1867.c.

Вот какая цепочка событий разворачивается при атаке:

  1. Аномальный входящий поток: атакующий отправляет HTTP POST-запрос с типом multipart/form-data. В заголовках запроса намеренно опускается или искажается заголовок Content-Length, либо включается потоковая передача Transfer-Encoding: chunked.
  2. Мусорная лавина: тело запроса содержит тысячи мелких пустых полей формы, глубоко вложенные заголовки и специально подобранные бинарные последовательности, имитирующие структуры внутренних указателей языка Си.
  3. Искусственный OOM: парсер rfc1867.c начинает жадно выделять память под каждое поле в куче Zend Engine. В определенный момент процесс упирается в системный лимит memory_limit (или исчерпывает оперативную память процесса) и выбрасывает фатальную ошибку Fatal error: Allowed memory size exhausted.
  4. Роковая процедура завершения (Shutdown Routine): казалось бы, процесс должен безопасно упасть и завершиться. Но Zend Engine устроен так, что при фатальной ошибке он запускает специальный обработчик аварийной очистки ресурсов, чтобы освободить дескрипторы файлов и очистить кэш.
  5. Разыменование поврежденного указателя: код очистки структур данных наивно предполагает, что связные списки и хэш-таблицы входящей формы были полностью и корректно инициализированы. Однако из-за внезапного сбоя памяти список оказался «разорванным». Очищающий цикл берет контролируемое атакующим значение из недостроенного буфера, считает его адресом функции деструктора и передает управление по этому адресу.

В результате процессор переходит к исполнению шелл-кода, внедренного в тело запроса. Поскольку веб-сервер (будь то PHP-FPM, Apache mod_php, LiteSpeed или современный FrankenPHP) работает от имени системного пользователя www-data или nginx, атакующий получает полноценный доступ к файловой системе сервера и базе данных.

Почему правила WAF — лишь временная повязка

Как только новость о php2shell стала публичной, крупнейшие провайдеры сетевой безопасности и CDN (включая Cloudflare, Fastly и AWS WAF) экстренно развернули правила сигнатурного анализа для блокировки подозрительных POST-запросов с аномальным количеством multipart-секций.

Однако полагаться исключительно на WAF в этой ситуации смертельно опасно. Опытные исследователи безопасности уже продемонстрировали несколько методов обхода статических фильтров:

  • разбиение границ multipart на микро-чанки TCP;
  • манипуляции с кодировками символов перевода строки (\r\n против \n);
  • внедрение редких и нестандартных заголовков полей, которые игнорируются простыми регулярными выражениями WAF, но корректно проглатываются внутренним парсером PHP.

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

Официальные патчи и процедура обновления

Команда безопасности PHP Group выпустила внеочередные срочные релизы для всех поддерживаемых стабильных веток:

  • ветка 8.5 получила обновление 8.5.12;
  • ветка 8.4 пропатчена до 8.4.27;
  • ветка 8.3 обновлена до 8.3.36;
  • ветка 8.2 получила версию 8.2.35.

Для проверки текущей версии рантайма на сервере выполни команду в терминале:

php -v
# Либо проверь версию конкретно запущенного сокета пула:
php-fpm8.4 -v

Если ты используешь популярные серверные дистрибутивы Debian или Ubuntu с официальными репозиториями Ондрея Суры (ppa:ondrej/php), процедура обновления выглядит стандартно:

sudo apt update
sudo apt install --only-upgrade php8.4-fpm php8.4-cli php8.4-common
# Критически важно: обязательно перезапусти службу после обновления!
sudo systemctl restart php8.4-fpm

В Docker-окружениях необходимо пересобрать образы с обновлением базовых тегов php:8.4-fpm-alpine или принудительно запустить apk upgrade --no-cache в Dockerfile.

Ловушка устаревших версий (EOL)

Самая большая драма разворачивается вокруг проектов, работающих на старых версиях PHP: 8.1, 8.0, 7.4 и древнее. Все они официально достигли статуса End-of-Life (EOL), а значит, официальная команда разработки PHP не выпускает для них бесплатные патчи безопасности.

Если твой легаси-проект застрял на PHP 7.4, у тебя есть три пути:

  1. Экстренная миграция на ветку 8.2+ (самый правильный, но трудоемкий путь).
  2. Использование дистрибутивов с длительной поддержкой: Red Hat Enterprise Linux, Ubuntu Pro и Debian LTS бэкпортируют исправления безопасности в старые системные пакеты.
  3. Коммерческая поддержка: приобретение сторонних патчей (например, от TuxCare или специализированных вендоров).

Как проверить сервер на признаки взлома

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

# Ищем командные оболочки и утилиты, запущенные дочерними процессами PHP-FPM
ps -ef --forest | grep -E 'php-fpm.*(sh|bash|curl|wget|nc|python)'

Любое появление процесса /bin/sh или /bin/bash, родителем которого выступает php-fpm, является стопроцентным маркером успешной компрометации системы.

Общий тренд: бинарные парсеры под прицелом

Инцидент с php2shell совпал по времени с обнаружением еще одной критической уязвимости — переполнения буфера в Си-декодере Brotli, встроенном в платформу Node.js. Это наглядно показывает, что специалисты по безопасности смещают фокус с прикладного кода на низкоуровневые сетевые парсеры рантаймов. Внимательно следи за обновлениями базовых образов и не откладывай установку системных патчей.