PHP 8БезопасностьWordPressBitrix

Уязвимость PHP2Shell: что делать, если сайт работает на старом PHP

PHP2Shell - две критические уязвимости PHP, через которые можно выполнить код на сервере без входа на сайт. Исправлены в PHP 8.2.35, 8.3.36, 8.4.27 и 8.5.12; для 8.1 и старше проект PHP обновлений не выпускает. Как узнать версию PHP сайта и что делать, если быстро обновиться нельзя.

РезультатМинута на поддерживаемой ветке или проект миграции
Александр Бутаков
Александр Бутаков
9 мин чтения

PHP2Shell - так в прессе назвали две критические уязвимости в самом PHP: CVE-2026-109618 и CVE-2026-109619. Обе позволяют выполнить код на сервере без авторизации, оценка 9.2 по CVSS v4.0. Лечится обновлением PHP до 8.2.35, 8.3.36, 8.4.27 или 8.5.12. Если сайт работает на PHP 8.1 или старше, проект PHP для этих веток обновлений уже не выпускает, и вот тут начинается настоящая работа.

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

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

Кратко. Обновление WordPress или Битрикса здесь ничего не закрывает: уязвим сам PHP. Выше всего риск, по оценке команды PHP, у Apache с mod_php: там продемонстрирован эксплойт, который срабатывает раньше, чем запускается код сайта, так что плагин безопасности даже не успевает вмешаться. Временные настройки есть, но команда PHP прямо пишет, что безопасной установку они не делают. На поддерживаемой ветке это короткая плановая работа. На PHP 7.4 или 8.1 - миграция.

Что такое PHP2Shell и какие сайты уязвимы

Бюллетень PHP вышел 21 октября 2026 года. Если без терминов, ошибки две:

  • CVE-2026-109618, «RCE через порчу памяти при OOM»: ошибка нехватки памяти может прервать PHP, когда внутренние данные запроса заполнены наполовину, а потом очистка принимает эти битые данные за нормальные (GHSA-w8hw-w9fx-j79w).
  • CVE-2026-109619, «RCE через устаревшее глобальное состояние»: данные одного запроса могут пережить освобождённую под них память, и следующий запрос в том же воркере успевает ими воспользоваться (GHSA-6wmf-4rv5-p3rp).

По словам команды PHP, под угрозой любая установка, которая обслуживает веб-запросы: PHP-FPM, Apache с mod_php, php-cgi, FrankenPHP и LiteSpeed. 26 октября американское агентство CISA внесло обе CVE в свой каталог эксплуатируемых уязвимостей - туда попадают ошибки, которые уже используют в реальных атаках.

Отдельно про путаницу в новостях: CVE-2026-111497 - другая история. Это ошибка в библиотеке распаковки Brotli. PHP пересобрал под неё только Windows-сборки, а уязвимый код, по словам команды PHP, достижим через расширение cURL с автоматической распаковкой ответов. В cURL она по умолчанию выключена, но приложения и HTTP-клиенты могут её включить.

Как узнать версию PHP сайта

Узнать версию PHP сайта - первый шаг, и проверять надо ту, что реально обрабатывает веб-запросы. Это не всегда та, что попадается на глаза первой. Ориентир на конец октября 2026 года: актуальные исправленные версии PHP - 8.5.12, 8.4.27, 8.3.36 и 8.2.35, всё, что ниже в своей ветке, а также любые 7.x, 8.0 и 8.1 уязвимы, если это не сборка дистрибутива с бэкпортом (про неё чуть ниже).

Что запущено у веб-сервера

  • WordPress: «Инструменты» → «Здоровье сайта» → «Информация» → раздел «Сервер».
  • Заголовки ответа: многие серверы отдают версию в X-Powered-By. Если на сайте кэш (в Битриксе, например, композит), добавьте к адресу произвольный параметр, чтобы ответ пришёл от PHP, а не из сохранённой страницы.
  • phpinfo(): файл из одной строки <?php phpinfo(); покажет всё. Удалите его сразу после проверки, это подарок любому сканеру.

Консоль может показать другое

php -v по SSH запускает консольный PHP, а он бывает совсем не тем, что работает у веб-сервера. На одном shared-хостинге на этой неделе сайт уже отвечал с 8.2.35, а консольный PHP на том же сервере был 5.6. Исправлений безопасности для PHP 5 нет уже много лет. В бюллетене перечислены только веб-варианты (FPM, mod_php, CGI и подобные), но через консольный PHP идут cron-задачи и скрипты, так что в инвентаризацию его включить стоит.

Одного номера бывает мало

Дистрибутивы Linux и LTS-вендоры получили патчи заранее, и их сборки после бэкпорта исправления могут сохранить старый номер версии. Если сервер показывает какую-нибудь 8.3.x из пакетов дистрибутива, сначала загляните в бюллетень безопасности вендора и только потом решайте, уязвимы вы или нет. На shared-хостинге спросите хостера.

Как обновить PHP: три ситуации и три объёма работы

Как обновить версию PHP, зависит от одного: насколько далеко вы от поддерживаемой ветки.

  1. Поддерживаемая ветка на своём сервере. На Битрикс-магазине с CRM обновление с 8.3.31 до 8.3.36 свелось к установке пакетов из того же репозитория, что и раньше, и перезапуску Apache. Около минуты собственно работы. Дальше проверки: список модулей до и после совпал (59 штук), php.ini не изменился, свой конфиг opcache сохранился, а новый вариант из пакета лёг рядом как .rpmnew. Ключевые страницы и админка ответили 200. Cron-импорты я проверил отдельно на следующее утро: в фоновых задачах проблемы с PHP вылезают позже всего.
  2. Shared-хостинг. Часть хостеров сама обновляет поддерживаемые ветки. На одном сайте на Битриксе хостер уже перевёл PHP-FPM на 8.2.35: я сверил заголовок ответа на нескольких страницах в обход кэша. Если у вас не обновили, переключите версию в панели хостинга или напишите в поддержку.
  3. PHP 8.1 и старше. Обновлений для этих веток проект PHP больше не выпускает. Он опубликовал минимальные бэкпорты в исходниках для 7.4, 8.0 и 8.1, они пригодятся, если вы сами собираете PHP и LTS-вендора у вас нет; дистрибутивы и LTS-вендоры выпускают свои исправленные пакеты, так что спросите своего. Для обычного небольшого сайта настоящее решение - переход на поддерживаемую ветку. До него команда PHP перечисляет временные настройки и прямо предупреждает, что полное решение - только обновление:
ini
; По мотивам бюллетеня PHP. Задавать на уровне сервера (php.ini, пул FPM,
; конфиг Apache), не через ini_set() и не через .user.ini,
; затем перезапустить все воркеры.
memory_limit = -1
post_max_size = 8M          ; 32M, если сайту нужна загрузка файлов
upload_max_filesize = 4M    ; обязательно меньше post_max_size
session.upload_progress.enabled = 0
fatal_error_backtraces = 0  ; только PHP 8.5

memory_limit = -1 закрывает один путь атаки и открывает дорогу исчерпанию памяти, поэтому рядом стоит ограничить воркер лимитом контейнера или cgroup. С этим блоком можно продержаться дни, но не месяцы.

Хостер обновит сам?

Может быть. Только хостер защищает свою платформу, а за вашу админку он не отвечает, и его экстренные меры могут сломать сайт раньше любого атакующего.

Утром 21 октября, до публикации бюллетеня PHP, один shared-хостер ограничил upload_progress и заблокировал все POST-запросы с типом multipart/form-data. Владельца сайта заранее никто не предупредил. На магазине под Битриксом в админке просто перестали сохраняться карточки товаров: форма редактирования уходит как multipart.

Как понять, что запросы режет хостер, а не сайт

Хватит двух запросов curl:

Bash
# Обычный POST формы проходит
curl -s -o /dev/null -w "%{http_code}\n" -X POST -d "a=1" https://example.com/
# 200

# Тот же POST как multipart/form-data отклоняется
curl -s -o /dev/null -w "%{http_code}\n" -F "a=1" "https://example.com/?probe=test123"
# 403

# Метка не дошла до журнала доступа сайта,
# значит, запрос обрезали ещё до Apache и PHP
grep "probe=test123" /path/to/site/access.log

403 отдавал nginx хостера на любом адресе, включая статические файлы, а запрос с меткой так и не появился в журнале сайта. Значит, дело не в .htaccess, не в CMS и не в настройках безопасности сайта.

Позже поддержка хостинга объяснила логику: ограничения временные, до выхода патчей и обновления PHP. Патчи обычно выходят только для поддерживаемых версий, поэтому для старых исправление не гарантировали и советовали PHP 8.2 или новее после проверки совместимости. На VPS риск и обновление целиком на владельце.

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

Что ломается при переходе на PHP 8 и как это быстро найти

Ядро WordPress или Битрикса с новой версией PHP обычно справляется. Ломается своё: кастомные модули, переопределённые шаблоны, обработчики событий, написанные под PHP 7 и с тех пор не тронутые, и старые плагины.

  • create_function() и each() удалены в PHP 8.0. Код, который их вызывает, падает с фатальной ошибкой.
  • PHP 8 перестал молча приводить типы. array_key_exists() на null или count() от не-массива теперь бросают TypeError, а в Битриксе это часто выглядит как ошибка 500 в админке.
  • Передача null во встроенные строковые функции - deprecated с 8.1, динамические свойства - с 8.2. Deprecated - шум, который стоит убрать потом. Фатальная ошибка - это авария.

Порядок, который у меня работает: копия сайта, лог ошибок, фатальные ошибки по одной, затем отдельно cron и импорт, потому что они падают в фоне, когда главная давно открывается нормально. Два подробных разбора: WordPress после перехода на PHP 8.3 и legacy-Битрикс под PHP 8.

Почему PHP2Shell - это счёт за пять лет без обновлений

Критические ошибки случаются в любой ветке любого языка. Если бы все сайты жили на поддерживаемом PHP, эта уязвимость стала бы поводом для обычных плановых работ. Дорогой она становится только для сайтов, которые не обновлялись лет пять.

Около десяти клиентских сайтов, которые я веду, работают на Битриксе и WordPress и годами не меняли версию PHP. Причины повторяются: «работает - не трогай», незнание, что это вообще важно, нет ответственного за это, нет денег на такого человека.

Самое сильное возражение, которое я слышу: «Мы пять лет на PHP 7.4, и нас ни разу не взломали». Правда, и какое-то время это было разумно. По моему опыту, большинство атак на небольшие сайты шло через плагины и код сайта, и многое закрывали обновление плагина или плагин безопасности. PHP2Shell лежит ниже всего этого. Атака срабатывает до запуска приложения, и ничто из установленного внутри WordPress или Битрикса на неё не влияет, а регулярного релиза для 7.4 у проекта PHP нет.

Второе возражение: «Хостер всё сделает». Для поддерживаемых веток часто да. Про старые хостер написал прямо: без гарантий. А история с multipart показывает, что исправление хостера может на время стоить вам рабочей админки.

Счёт к тому же растёт сам. Прыжок с 7.4 на 8.x ломает куда больше кода, чем с 8.2 на 8.3, потому что главный слом пришёл в 8.0, а в 8.1 и 8.2 добавились новые deprecated. А сама PHP 8.2 перестаёт поддерживаться 31 декабря 2026 года, так что сегодняшняя «безопасная» версия через два месяца станет следующей старой. Маленькие обновления по графику обходятся дешевле одного большого на пожаре.

FAQ

Поможет ли обновление WordPress от PHP2Shell? Нет. Уязвимость в самом PHP, закрывает её только обновление PHP. WordPress, Битрикс, плагины и темы тут ни при чём.

Уязвим ли PHP 7.4? Команда PHP выпустила для 7.4, 8.0 и 8.1 бэкпорты в исходниках, а обычных релизов нет: эти ветки вне поддержки. Если вы не собираете PHP сами и у вас нет LTS-вендора, решение - переход на поддерживаемую ветку.

Защитит ли плагин безопасности или WAF? Плагин безопасности - нет: он работает внутри приложения, а продемонстрированный эксплойт срабатывает до кода приложения. Лимиты на уровне веб-сервера или прокси, о которых пишет бюллетень PHP, снижают риск, но команда PHP прямо говорит, что полное решение - только обновление.

Как обновить PHP на WordPress или Битриксе? На shared-хостинге - сменить версию PHP в панели хостинга, на своём сервере - обновить пакеты и перезапустить веб-сервер. Перед переходом между ветками (например, с 7.4 на 8.x) сделать бэкап и проверить сайт на копии: смотреть лог ошибок, админку, cron и импорт. Подробно - в разборах про WordPress и Битрикс.

Что делать, если хостер до сих пор держит PHP 8.1? Спросить, ставит ли он бэкпорт исправления. Если нет, планировать переход на поддерживаемую ветку, лучше сразу на 8.3 или новее, раз 8.2 заканчивается в декабре, и проверить его сначала на копии сайта.

А если сайт, возможно, уже взломан? Обновление закрывает дыру, но не удаляет то, что уже установлено. Вот как выглядит бэкдор после «чистки» и как его найти.

Статья была полезной?

Нужна помощь с похожей задачей?

Поддержка сайтов →