PHP2Shell: как защитить сайт от критических уязвимостей PHP

Две критические уязвимости PHP, найденные с помощью ИИ: какие версии обновлять, что делать владельцам WordPress, VPS и Docker и как действовать при подозрении на взлом.

PHP2Shell: исправленные версии PHP 8.2.35, 8.3.36, 8.4.27 и 8.5.12

21 октября 2026 года вышли исправления PHP2Shell: двух критических уязвимостей PHP, которые позволяют атаковать сервер через HTTP без входа в админку. Владельцу WordPress недостаточно обновить плагины. Исправление нужно установить в сам PHP, который обслуживает сайт, а затем заменить работающие процессы.

Ниже разбираем устройство проблемы и практические варианты защиты: обычный хостинг, VPS, панели управления, Docker, Windows и устаревшие приложения. Это инструкция по обновлению и реагированию, без запуска эксплойтов на рабочем сайте.

Что сделать прямо сейчас

  1. Установить, какой PHP обслуживает каждый сайт, и кто его обновляет: хостер, администратор VPS или поставщик контейнера.
  2. Установить исправленный выпуск своей ветки либо пакет с подтверждённым исправлением от поставщика ОС.
  3. Перезапустить соответствующие PHP-процессы и проверить работу сайта. При Apache mod_php обновление относится и к процессам Apache.
  4. Если исправление пока недоступно, ограничить доступ к уязвимому обработчику и применить временные меры из раздела ниже.
  5. При признаках вторжения начать расследование. Обновление не удаляет уже установленную злоумышленником закладку.

Исправленные upstream-выпуски: PHP 8.2.35, 8.3.36, 8.4.27 и 8.5.12. Более новый выпуск той же поддерживаемой ветки тоже подходит. Дистрибутив может перенести патч в пакет со старым номером PHP: в этом случае ориентиром служит бюллетень поставщика и полная версия пакета. Официальное сообщение PHP.

В чём суть PHP2Shell

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

В первом случае опасен некорректный выход из обработки запроса; во втором важна последовательность запросов к одному процессу. Это объясняет, почему исправления в коде отдельного сайта не устраняют весь класс проблем. Технические первоисточники: OOM corruption и stale global state.

Результат успешной эксплуатации может включать выполнение кода с правами обслуживающего процесса. Это не обязательно root. Однако даже пользователь сайта часто имеет доступ к конфигурации приложения, базе данных и служебным ключам. Поэтому ограниченные права процесса снижают последствия, но не делают уязвимость безобидной.

Какую роль сыграл ИИ

Wiz описывает использование Atlas, Gemini 4 Argon и GPT-5.6 Sol при поиске ошибок, разработке проверочных цепочек и проверке исправлений. Исследователи подтвердили выполнение кода на Drupal и WordPress и показали сценарии раскрытия памяти, из которой могут утекать секреты. Работа велась с координацией раскрытия и выпуском патчей. Исследование Wiz.

Формулировка «ИИ взломал PHP» скрывает важную часть истории: модели помогали исследователям превратить сложные ошибки памяти в работающие цепочки эксплуатации. Из публикации не следует, что все сайты на PHP уже взломаны. Для владельца сайта практический вывод проще: сложность уязвимости больше не даёт оснований откладывать исправление.

WordPress, PHP-FPM, Apache: кто под угрозой

Команда PHP относит к зоне риска веб-установки с PHP-FPM, mod_php, CGI, FrankenPHP и LiteSpeed. Для mod_php показан сценарий до запуска кода приложения. У FPM и других обработчиков условия отличаются; наличие FPM само по себе не подтверждает безопасность. Подробности по каждому механизму приведены в официальных advisories выше.

Название CMS здесь не служит границей защиты. Обновлять нужно среду исполнения WordPress, Drupal, Joomla, интернет-магазина или собственного приложения. Если на VPS десять сайтов и три версии PHP, проверка только главного домена оставит часть инфраструктуры без внимания.

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

Как проверить версию PHP и не перепутать её с CLI

Следующие команды только собирают информацию:

php -v
php --ini
systemctl list-units --type=service --all 'php*'
ps -eo pid,lstart,args | grep -E '[p]hp-fpm|[a]pache2|[h]ttpd|[l]sphp|[f]rankenphp'

php -v показывает интерпретатор командной строки. Сайт может работать через другой бинарный файл и другой php.ini. Сопоставьте домен с конфигурацией виртуального хоста, сокетом FPM, пулом и установленным пакетом. В панели управления проверьте выбранный обработчик каждого сайта. Описание CLI-параметров PHP.

Версию веб-обработчика можно узнать через существующую закрытую диагностику приложения. Если нужен временный диагностический endpoint, ограничьте его доступ административным адресом или аутентификацией, выводите только необходимые поля и удалите после проверки. Не оставляйте публичную страницу phpinfo: она раскрывает лишние сведения о сервере. Функция phpversion() возвращает версию текущего интерпретатора, но сама по себе не доказывает наличие vendor-backport.

Удобный результат инвентаризации: список «домен → обработчик → пакет/образ → исправление → время замены процессов». Для балансировщика добавьте каждый backend. Иначе один забытый узел продолжит принимать запросы со старым PHP.

Вариант 1. Обычный или управляемый хостинг

Попросите поддержку подтвердить исправление именно двух CVE и замену рабочих процессов. Ответ «у вас актуальная версия WordPress» на этот вопрос не отвечает. Переключение в панели с 8.2 на 8.3 тоже ничего не гарантирует без номера исправленного выпуска.

Проверьте, пожалуйста, устранены ли CVE-2026-109618 и CVE-2026-109619 для PHP-обработчика моего домена. Сообщите полную версию установленного пакета или ссылку на бюллетень с backport и подтвердите перезапуск всех обслуживающих процессов после обновления. Если патча пока нет, какие временные ограничения применены и когда будет обновление?

Если хостер не может оперативно исправить среду, варианты на время ожидания: закрыть динамический сайт на уровне прокси, отдавать статическую техническую страницу либо перенести приложение в подтверждённо исправленную среду. Страница обслуживания внутри самой CMS слабее: запрос всё равно сначала доходит до PHP.

Вариант 2. VPS с Debian или Ubuntu

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

Пример ниже относится к уже установленному PHP 8.3 из DEB-репозитория. Имена пакетов и службы нужно сверить со своим сервером; для PHP из панели или самостоятельной сборки этот пример не подходит.

sudo apt update
dpkg-query -W 'php8.3*'
apt-cache policy php8.3-fpm php8.3-common php8.3-cli
apt-mark showhold
sudo apt-get -s install --only-upgrade php8.3-fpm php8.3-common php8.3-cli

Симуляция показывает предстоящие изменения. Проверьте источник пакета и наличие исправления в бюллетене репозитория. Добавьте к обновлению установленные PHP-расширения той же ветки, если для них поставщик выпустил согласованные обновления. Не снимайте удержания пакетов вслепую.

sudo apt-get install --only-upgrade php8.3-fpm php8.3-common php8.3-cli
sudo php-fpm8.3 -t
sudo systemctl restart php8.3-fpm
systemctl is-active php8.3-fpm
journalctl -u php8.3-fpm --since '10 minutes ago' --no-pager

Путь к FPM-бинарнику может отличаться. Если проверка конфигурации завершается ошибкой, сначала устраните её. Не перезапускайте заведомо неисправную службу. Основные принципы работы с APT описаны в документации Ubuntu.

При mod_php обновляют установленный пакет вроде libapache2-mod-php8.3, проверяют конфигурацию Apache и заменяют его процессы. При связке Nginx → FPM один перезапуск Nginx не заменяет PHP. Полный перезапуск FPM кратковременно прерывает текущие запросы; на нескольких backend-узлах выполняйте замену поочерёдно с выводом узла из балансировки.

Вариант 3. AlmaLinux, Rocky Linux и RHEL

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

rpm -qa | grep -E '^php|^rh-php'
dnf list --installed 'php*'
dnf check-update 'php*'
dnf updateinfo list --security

Для обычных системных пакетов возможен такой вариант, но только после просмотра предлагаемой транзакции и подтверждения исправленного сборочного номера:

sudo dnf upgrade 'php*'
sudo php-fpm -t
sudo systemctl restart php-fpm

dnf check-update может вернуть код 100, когда обновления найдены: это не ошибка загрузки. Если используется параллельная коллекция, замените команды соответствующими её пакетами и службой. Не переключайте поток и не смешивайте репозитории без плана миграции. Официальная основа: обновление пакетов через DNF.

Вариант 4. FASTPANEL, Plesk, cPanel и другие панели

Панель может устанавливать собственные сборки PHP вне системных каталогов. Поэтому успешное apt upgrade ещё не доказывает, что изменился обработчик сайта.

  1. В карточке каждого домена запишите выбранную ветку PHP и способ запуска.
  2. Проверьте наличие исправленной сборки у поставщика панели. Если показано только «PHP 8.3», уточните полный номер.
  3. Обновите нужный обработчик штатным способом панели и замените его процессы.
  4. Повторите проверку через веб-запрос к каждому сайту, включая поддомены.

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

Вариант 5. PHP или WordPress в Docker

Обновление PHP на хосте не меняет интерпретатор внутри контейнера. Перезапуск старого контейнера также не устанавливает исправление. Нужны новый образ и пересоздание сервиса.

Сначала проверьте фактическую конфигурацию:

docker compose ps
docker compose images
docker compose exec php php -v

Здесь php является примером имени сервиса. В WordPress-сборке это может быть wordpress. Если образ закреплён по старому тегу или digest, измените ссылку на проверенный исправленный образ. Сам по себе pull старого неизменяемого digest ничего не исправит.

Для готового обновлённого образа:

docker compose pull php
docker compose up -d --no-deps --force-recreate php
docker compose exec php php -v

Для собственного Dockerfile сначала обновите базовый образ, затем пересоберите:

docker compose build --pull php
docker compose up -d --no-deps --force-recreate php

Не используйте down -v: удаление томов не требуется для установки патча и может уничтожить данные. Убедитесь, что файлы сайта и база хранятся в предусмотренных постоянных томах. Проверьте PHP в итоговом образе, особенно если он многоступенчатый. Поведение команд: Compose up и Compose build.

FrankenPHP, LiteSpeed, Windows и собственная сборка

FrankenPHP может поставляться как самостоятельный бинарник со встроенным PHP. Тогда обновлять нужно соответствующую сборку, а не случайный системный пакет. Для LiteSpeed проверьте используемые обработчики lsphp и замените процессы по инструкции поставщика. Для IIS/FastCGI в Windows установите совместимую исправленную сборку, сохраните нужные расширения и конфигурацию, затем замените FastCGI-процессы или соответствующий пул приложения.

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

Для PHP 8.1 и старше основной путь: поддерживаемая ветка либо поставщик LTS с подтверждённым backport. Из-за серьёзности случая команда PHP также подготовила минимальные исходные backport-патчи для 7.4, 8.0 и 8.1. Это исключительная помощь сборщикам, а не возобновление полноценной поддержки старых веток. Ссылки на патчи находятся в официальном сообщении PHP.

Если обновиться пока нельзя: временные меры и их ограничения

Для CVE-2026-109618 advisory предлагает административно закрепить memory_limit=-1, ограничивать размер и сложность входящих запросов и использовать контейнерные или cgroup-границы. Но отказ выделения памяти всё ещё возможен. RLIMIT_AS и RLIMIT_DATA для замены этого лимита не подходят: они могут вызвать опасный путь отказа. Техническое объяснение и ограничения.

Не отключайте лимит PHP на маленьком общем VPS без расчёта памяти и изоляции. Один запрос способен повлиять на доступность соседних сайтов. Если нет возможности безопасно применить временную схему, закрытый PHP-endpoint или временная статическая версия лучше непроверенного изменения лимитов.

Для подтверждённых путей CVE-2026-109619 рекомендуются session.upload_progress.enabled=0, а на PHP 8.5 также fatal_error_backtraces=0, с заменой всех рабочих процессов. Настройки должны действовать до разбора запроса; ini_set() и FPM .user.ini для этой цели недостаточны. Скрытие предупреждений не устраняет обращение к опасному состоянию. Другие варианты уязвимости остаются, поэтому это временная мера. Рекомендации для stale global state.

Любые изменения ограничений проверьте на реальных сценариях сайта: загрузке изображений, импорте, оформлении заказа, работе API и вебхуков. Нельзя выдавать ограничение, которое ломает половину функций, за завершённое обновление.

Поможет ли Cloudflare и другой WAF

Cloudflare сообщает о включении защиты для пользователей бесплатного и платного WAF с 03:02 UTC 21 октября. Компания также наблюдала атакующий трафик и изменение полезной нагрузки для обхода правил. Сам Cloudflare рекомендует установить исправление PHP и оставить WAF дополнительным уровнем защиты. Разбор Cloudflare.

Проверьте, что домен действительно проксируется, нужные правила не отключены и нет исключений для уязвимых путей. Если origin доступен напрямую или поддомен обходит CDN, часть запросов может не проходить через WAF. Ограничивать доступ к origin нужно с учётом мониторинга, сертификатов, служебных интеграций и аварийного доступа. Один оранжевый значок в DNS не заменяет такую проверку.

Как понять, что сервер уже атаковали

Сочетание HTTP-запроса и необычного дочернего процесса веб-сервера полезнее одного поиска слова PHP2Shell в access.log. Elastic выделяет запуск оболочки обслуживающим процессом как сильный сигнал для расследования. Но отсутствие shell не исключает раскрытие памяти. Материал Elastic о детектировании.

Corelight выпустила открытые средства обнаружения для Zeek и Suricata. Их можно включить в существующий сетевой мониторинг, учитывая доступность расшифрованного HTTP-трафика. Срабатывание требует анализа, а отсутствие срабатываний не является доказательством чистоты. Описание подхода, репозиторий детекторов.

При расследовании сопоставьте время подозрительных запросов с ошибками PHP, перезапусками worker-процессов, исходящими соединениями, новыми файлами и изменениями задач cron. Проверьте новые учётные записи, ключи SSH, права доступа и необычные обращения к секретам. Каждая отдельная аномалия может иметь обычное объяснение; важна общая временная линия.

Порядок действий при подозрении на компрометацию

  1. Ограничьте доступ к затронутому приложению, сохранив отдельный доверенный административный канал.
  2. Сохраните журналы, снимок диска и сведения о процессах для расследования. Не стирайте подозрительные файлы до фиксации.
  3. Установите границы доступа: отдельный пользователь сайта, весь контейнер, соседние приложения или root.
  4. Восстанавливайте сервис в чистой исправленной среде. Переносите проверенные данные, а не весь старый сервер вместе с неизвестными исполняемыми файлами.
  5. С чистого устройства смените и отзовите доступные атакующему секреты: базу данных, API-ключи, бот-токены, облако, резервные копии. При необходимости аннулируйте активные сессии пользователей.
  6. Проверьте последствия для пользователей и данных, подключите специалистов по реагированию и выполните применимые обязанности по уведомлению.

Для WordPress дополнительная проверка ядра:

wp core verify-checksums --include-root

Запускайте её от пользователя сайта в каталоге нужной установки, предпочтительно на изолированной копии при расследовании. Команда сравнивает ядро с эталоном WordPress.org. Она не проверяет всю базу, произвольные плагины и серверные закладки. Чистые checksum не равны заключению «взлома не было». Документация WP-CLI.

Как убедиться, что исправление действительно установлено

  • Сохранены версия пакета или digest образа и подтверждение исправления от поставщика.
  • Каждый домен и backend использует именно обновлённый обработчик.
  • Старые рабочие процессы завершились; новый процесс запущен после установки исправления.
  • Работают главная, статьи, админка, формы, загрузки, API и фоновые задания.
  • Нет новых 502/504, ошибок расширений и заметной деградации памяти или времени ответа.
  • Временные аварийные настройки пересмотрены после установки патча.

Запуск публичного PoC на production для этой проверки не требуется. Он может нарушить доступность и создать дополнительный риск. Проверка версии веб-обработчика, происхождения исправленного пакета и замены процессов даёт администратору более полезный результат.

Короткие ответы на частые вопросы

Достаточно ли обновить WordPress?

Нет. WordPress и PHP обновляются отдельно. Обновление CMS полезно, но не устанавливает исправление в интерпретатор.

Нужно ли сразу переходить на PHP 8.5?

Нет: выпущены исправления нескольких веток. Срочное обновление внутри совместимой ветки обычно уменьшает объём изменений. Переход между ветками требует проверки приложения и расширений.

Сайт работает и не тормозит. Значит, всё нормально?

Работоспособность не подтверждает отсутствие уязвимости или утечки. Проверяйте исправление, а не только доступность.

Поможет ли перезагрузка VPS?

После установки правильных пакетов она заменит процессы. До установки патча сервер снова запустит уязвимый PHP. Перезагрузка также не удаляет последствия состоявшегося взлома.

Что считать завершением работы?

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