Кратко: PHP2Shell — так называют две критические уязвимости в ядре PHP, закрытые 21 октября 2026 года: CVE-2026-109618 и CVE-2026-109619. Обе получили оценку 9,2 (критический уровень) по шкале CVSS v4.0. В худшем случае злоумышленнику вообще не нужна учётная запись: достаточно специально сформированных HTTP-запросов, чтобы выполнить код на веб-сервере (RCE). Проблема не в вашем приложении, а в самом PHP. Поэтому под угрозой даже безупречный код на WordPress или Laravel и простейший сайт «Hello World», если они работают на уязвимой версии PHP. Единственное полное решение — обновить PHP до версии 8.5.12, 8.4.27, 8.3.36 или 8.2.35 (либо установить исправленный пакет вашего дистрибутива) и перезапустить все рабочие процессы PHP (воркеры). В компании Partnerfy мы не стали ждать официального патча: примерно за три часа до его выхода мы применили на своих серверах временную меру защиты, сделали полные резервные копии аккаунтов и уровень за уровнем усилили оборону. В этой статье мы рассказываем, как была обнаружена уязвимость, что она собой представляет технически, что нужно сделать вам и что сделали мы.
Статья написана для владельцев бизнеса и технических команд, чей сайт, платформа электронной коммерции или программное обеспечение на заказ работают на PHP. Технические подробности основаны на официальном объявлении проекта PHP о безопасности, бюллетенях безопасности PHP на GitHub (GitHub Security Advisories, GHSA) и публикациях исследователей, обнаруживших уязвимости. Там, где источники противоречат друг другу, мы говорим об этом прямо. Ситуация быстро меняется. Статья актуальна на вечер 21 октября 2026 года.
Что такое PHP2Shell и почему это так серьёзно?
PHP — один из самых распространённых серверных языков в вебе. На PHP работают WordPress, WooCommerce, Drupal, Joomla, Magento и Laravel. Серьёзность PHP2Shell определяют три особенности:
- Аутентификация не требуется. Злоумышленнику не нужно регистрироваться на вашем сайте, знать пароль или заполнять форму. Достаточно специально сформированных запросов.
- Атака может сработать ещё до запуска кода приложения. По данным проекта PHP, наибольшему риску подвержены установки Apache с
mod_php. Там было показано, что неаутентифицированный запрос запускает атаку до выполнения какого-либо кода приложения. Обновлённые плагины, чистый код и проверки безопасности внутри приложения этот путь не закрывают. - Масштаб крайне широк. По данным проекта PHP, под угрозой находятся «все установки PHP, обслуживающие веб-запросы»: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP и LiteSpeed. По данным Wiz, одной из команд, обнаруживших уязвимости, хотя бы одна из двух уязвимостей затрагивает каждую версию PHP, выпущенную за последнее десятилетие, вплоть до 5.4. Это утверждение о масштабе принадлежит Wiz; в официальном бюллетене PHP перечислены только поддерживаемые ветки 8.2–8.5.
Оценки звучат жёстко. Wiz называет эти находки «одними из самых серьёзных уязвимостей, обнаруженных в PHP». Судя по заявлениям, о которых сообщала пресса, Национальный центр кибербезопасности Великобритании (NCSC) рекомендовал отключить от сети системы, которые нельзя обновить немедленно. CERT-EU также посоветовал изолировать доступные из интернета приложения до установки патча. Исследователь безопасности Кевин Бомонт (Kevin Beaumont) хорошо подытожил положение дел: «Ситуация с PHP приведёт к массе инцидентов».
Как всё вскрылось? Хронология событий
История PHP2Shell начинается в 2024 году и выливается в одну из самых бурных недель 2026 года в сфере кибербезопасности. Всё время указано в UTC.
| Дата | Что произошло? |
|---|---|
| 2024 г. | PHP прошёл первый за многие годы независимый аудит безопасности (финансирование — Sovereign Tech Agency, организация — OSTIF, исполнитель — Quarkslab). Исправляя одну из найденных проблем, разработчик ядра PHP заметил первые признаки нехватки памяти (out-of-memory, OOM), лежащей в основе CVE-2026-109618. Конкретного пути атаки найти не удалось, и исправление месяцами ждало своей очереди. Сегодня PHP Foundation открыто называет эту задержку «структурным провалом». |
| 30 июля 2026 г. | Компания Calif, работающая в сфере безопасности, начала аудит PHP в рамках программы «Patch the Planet». |
| 11 августа 2026 г. | Исследователь из Calif сообщил разработчикам PHP о безусловной уязвимости удалённого выполнения кода, вызванной той же первопричиной. В тот же день OpenAI (Codex Security) независимо сообщила о той же первопричине. |
| 19–24 августа 2026 г. | Исследователи Wiz нашли отдельные пути атаки, подтвердили RCE на Drupal и WordPress и 24 августа сообщили о них команде безопасности PHP. |
| 20 октября, ~15:00 UTC | За два дня до скоординированного раскрытия номера обеих CVE начали распространяться на форумах и в соцсетях — вместе с неверным временем выхода и неверной оценкой CVSS (10,0). Технические подробности не утекли. |
| 20 октября, ~19:30 UTC | PHP опубликовал предварительное объявление и перенёс выход патча на день раньше: на 21 октября, 14:00 UTC, вместо 22 октября. |
| 20 октября, ~20:00 UTC | Calif, одна из компаний, сообщивших об уязвимости, случайно опубликовала видео, на котором её демонстрационный эксплойт (proof of concept, PoC) срабатывает против нескольких целей. Видео скопировали и разнесли по сети, что ускорило гонку за созданием рабочих PoC. |
| 21 октября, ~03:00 UTC | Cloudflare развернула первый набор правил WAF против известных векторов атак. Он включён по умолчанию для всех клиентов, в том числе на бесплатном тарифе. |
| 21 октября, 07:41 UTC | Chainguard в одностороннем порядке опубликовала образы с патчем более чем за шесть часов до скоординированного релиза, нарушив эмбарго. |
| 21 октября, ~14:00 UTC | Вышли PHP 8.5.12, 8.4.27, 8.3.36 и 8.2.35. |
| 21 октября, ~14:20 UTC и далее | watchTowr сообщила, что её сеть ловушек (honeypot) фиксирует активные попытки эксплуатации обеих CVE. Cloudflare также сообщила о начале первых атак: злоумышленники изменяют полезную нагрузку, чтобы обойти начальные правила. |
На момент публикации ни один открытый источник не подтвердил, что конкретный сервер был успешно взломан через эти уязвимости. Но попытки уже начались, и исследователи ждут длинного хвоста последствий. Как сказал специалист по реагированию на инциденты Хэл Померанц (Hal Pomeranz): «У этой истории будет длинный хвост».
Фактор ИИ: разрыв между патчем и эксплойтом теперь измеряется часами
Ещё одна деталь делает PHP2Shell историей именно 2026 года: ИИ-модели сыграли роль и в обнаружении уязвимости, и в поиске пути к её эксплуатации. Команда OpenAI Codex Security независимо сообщила об одной из находок. А Wiz пишет: «Передовые ИИ-модели существенно снизили этот барьер, превратив давний дефект в эксплойт». Ошибка, которая в 2024 году оставалась теоретической, в 2026-м с помощью машин превратилась в оружие. Для защищающейся стороны вывод ясен: отсчёт начинается в момент выхода патча, а роскоши «посмотрим на выходных» больше нет.
Что происходит на техническом уровне? Две уязвимости, две разные первопричины
Обе уязвимости относятся к ошибкам безопасности памяти. Обе связаны с тем, как PHP реагирует на фатальные ошибки (прежде всего на нехватку памяти), возникающие во время обработки запроса. Но механизмы у них разные.
CVE-2026-109618: «недостроенные» данные в момент, когда заканчивается память
Когда во время запроса превышается лимит памяти (out-of-memory, OOM), PHP резко покидает текущий контекст с помощью механизма longjmp() и прерывает запрос. Официальный бюллетень описывает проблему так: в определённые моменты память запроса становится доступной ещё до полной инициализации. Если именно в этот момент выделение памяти завершается сбоем, PHP некорректно учитывает такой ранний выход, и память остаётся в недопустимом состоянии. Затем процедура завершения запроса считывает эти недостроенные данные и действует на их основе. Результат — повреждение памяти, а при правильно подготовленной атаке — выполнение кода.
Представьте кухню ресторана: официант заполняет бланк заказа, его внезапно зовут в другое место, и бланк остаётся заполненным наполовину. Смена, которая закрывает кухню, считает заказ полным и выполняет всё, что в нём написано. Если злоумышленник может дописать этот бланк как угодно, кухней фактически управляет он.
Как же злоумышленник попадает именно в этот момент? Приёмы, перечисленные в бюллетене, опираются на формат multipart/form-data, который используется для загрузки файлов:
- Multipart-запросы, в которых не указана пригодная для использования длина содержимого, могут обойти начальную проверку
post_max_size. - Одна часть multipart-запроса может содержать неограниченное количество заголовков.
- Пустые поля файлов не учитываются в лимите
max_file_uploads, но всё равно создают массивы метаданных файлов. - Вложенные имена полей многократно увеличивают объём работы по построению массивов.
Иными словами, злоумышленник формирует запрос, который подводит PHP к границе памяти в самый неподходящий момент. Как отмечает Wiz, PHP разбирает multipart-запросы на этапе старта запроса, до завершения обычной инициализации модулей. Apache mod_php, в свою очередь, безусловно выполняет процедуру завершения, даже если старт запроса закончился неудачей. Поэтому вся цепочка может отработать без единой строки кода вашего приложения. Полноценный RCE подтверждён по HTTP против mod_php в типичной конфигурации prefork с несколькими рабочими процессами при стандартных лимитах PHP на входные данные и память. С PHP-FPM ситуация другая, поскольку при неудачном старте запроса рабочий процесс завершается: анализ исходного кода указывает на то, что FPM также может быть затронут, но полноценный эксплойт против FPM для этой уязвимости пока не продемонстрирован.
CVE-2026-109619: «призрак» предыдущего запроса
Рабочие процессы PHP не завершаются после одного запроса: один и тот же процесс обслуживает множество запросов подряд. PHP хранит глобальное состояние: состояние ошибок, сессий, объектов и расширений. В бюллетене поясняется, что часть этого состояния удерживается рабочим процессом, но на самом деле указывает на память, принадлежащую одному запросу. Если запрос завершается в неожиданный момент, такие указатели остаются висеть. Следующий запрос, попавший в тот же рабочий процесс, обращается к этому устаревшему состоянию раньше, чем обычная инициализация успеет его сбросить. Это классическая ошибка use-after-free (использование уже освобождённой памяти). При стратегически подготовленном расположении данных в куче она может привести к полноценному удалённому выполнению кода.
Аналогия: в отеле ключ-карта предыдущего гостя всё ещё работает, а новый гость заходит в номер до уборки. Вещи предыдущего гостя по-прежнему внутри.
У этой уязвимости есть и другое измерение — утечка данных. По данным Wiz, раскрытая память может содержать пароли, токены аутентификации, API-ключи и сертификаты, относящиеся к другим запросам или к самому серверу. Один из подтверждённых путей — функция session upload progress (отслеживание хода загрузки через сессию). Она включена по умолчанию, и приложению даже не нужно вызывать session_start(): обработка сессии может начаться раньше обычной инициализации сессии. В бюллетене также указан второй подтверждённый путь — обратная трассировка фатальных ошибок (fatal error backtrace) в PHP 8.5. RCE через жизненный цикл сессии подтверждён и на mod_php, и на PHP-FPM.
Важное замечание: согласно официальным описаниям PHP, CVE-2026-109618 связана с недостроенными данными в момент нехватки памяти, а CVE-2026-109619 — с устаревшим состоянием, которое остаётся между запросами. Некоторые источники (включая Wiz) сопоставляют приёмы атаки с номерами CVE иначе. В этой статье мы следуем бюллетеням безопасности PHP на GitHub.
Кого это затрагивает? Таблица версий
| Ветка PHP | Затронуты | Версия с исправлением | Примечания |
|---|---|---|---|
| 8.5 | Версии до 8.5.12 | 8.5.12 | Активная поддержка |
| 8.4 | Версии до 8.4.27 | 8.4.27 | Активная поддержка |
| 8.3 | Версии до 8.3.36 | 8.3.36 | Только исправления безопасности |
| 8.2 | Версии до 8.2.35 | 8.2.35 | Поддержка заканчивается 31 декабря 2026 года |
| 8.1, 8.0, 7.4 | Затронуты | Официального релиза нет | Команда PHP опубликовала только минимальные патчи на уровне исходного кода. Обратитесь к поставщику дистрибутива или LTS либо перейдите на поддерживаемую версию. |
| 7.3 и более ранние, 5.x | Затронуты, по данным Wiz | Патча нет | Единственный выход — переход на новую версию. |
Неважно, какое приложение вы используете. Wiz проводила демонстрации на официальных образах WordPress, Drupal и Joomla. Дело не в том, что уязвимы сами эти платформы, а в том, что все они работают на PHP. Обновление ядра WordPress или плагинов эту уязвимость не устранит; обновлять нужно сам PHP на сервере.
Для понимания масштаба: согласно анализу Mallory на основе данных Shodan, на 20 октября в интернете насчитывалось примерно 884 000 серверов, сообщавших в HTTP-заголовках о PHP 8.1 или более старой версии. Эти версии не могут получить официальные патчи. Это подсчёт по заголовкам, а не проверенное число затронутых систем, но он показывает, насколько длинным, скорее всего, окажется хвост.
Что сделала компания Partnerfy? Шестиуровневая защита, которая не ждала патча
Когда новость об уязвимости просочилась, картина была предельно ясной: до официального патча оставались часы, а злоумышленники уже готовились. Вдобавок все в мире одновременно пытались скачать обновления, так что репозитории пакетов работали под сильной нагрузкой и зависали. Поэтому мы не стали рассуждать в духе «подождём патча» и выстроили защиту уровень за уровнем.
1. Раннее реагирование: временная мера за несколько часов до официального патча
Наша DevOps-команда внимательно следила за новостями об утечке и первыми техническими оценками и примерно за три часа до выхода официального патча отключила session.upload_progress.enabled на уровне всего сервера. Именно эту временную меру PHP рекомендует для CVE-2026-109619. Причём мы не просто переключили настройку, а сделали это в правильном месте. Команда PHP требует применять этот параметр на уровне основной конфигурации (php.ini / конфигурация сервера), а не через ini_set() или .user.ini. Наше изменение внесено именно на этом уровне и проверено в рабочей конфигурации.
2. Пограничный уровень: отсеиваем атаки ещё до сервера
Наш корпоративный сайт partnerfy.co и проекты, которые мы обслуживаем за Cloudflare, защищены пограничной сетью Cloudflare. Рано утром 21 октября Cloudflare по умолчанию развернула первый набор правил WAF против известных векторов PHP2Shell. В результате значительная часть подозрительных запросов отсеивается, не доходя до наших серверов. Поскольку, по сообщениям, злоумышленники изменяют полезную нагрузку, чтобы обойти начальные правила, мы никогда не считаем этот уровень достаточным сам по себе: сразу за ним стоят остальные.
3. Усиленная конфигурация PHP: лишаем злоумышленника следующего хода
Конфигурация PHP на наших серверах была усилена задолго до этого кризиса. Функции, выполняющие системные команды (system, popen, proc_open и подобные), отключены; удалённое включение файлов (allow_url_include) отключено. Скажем честно: RCE на уровне памяти теоретически может обойти эти ограничения. Но на практике первое, что делает злоумышленник, — открывает командную оболочку, скачивает инструменты или оставляет веб-шелл. Эти ограничения делают критически важные шаги после взлома намного сложнее и намного «шумнее». А шум — верный способ попасться.
4. Изоляция аккаунтов: даже если дверь открылась, коридор остаётся запертым
Каждый аккаунт на наших серверах работает в собственной изолированной файловой «клетке». Даже если в одном аккаунте реализуется худший сценарий, возможности злоумышленника для горизонтального перемещения к файлам и процессам других аккаунтов серьёзно ограничены. Разрыв одного звена не означает, что рвётся вся цепь.
5. Резервные копии на случай катастрофы: готовность к худшему
Перед окном установки патчей мы сделали полные резервные копии аккаунтов на наших серверах. Цель проста: если что-то пойдёт не так, вопрос будет звучать не «что мы потеряли?», а «к какой чистой точке восстановления мы возвращаемся?». Хорошая стратегия безопасности — это не только блокировка атак, но и возможность быстро вернуться в чистое состояние, даже если атака удалась.
6. Патчи, перезапуски и поиск индикаторов
По мере появления официальных исправленных пакетов в каналах дистрибутивов мы устанавливаем их на серверы, а затем перезапускаем все рабочие процессы PHP. Перезапуск обязателен: старые рабочие процессы, которые продолжают работать, используют старый код. Поскольку патч вводит новый жёсткий лимит памяти, мы заодно пересматриваем настройки памяти с учётом этого.
Параллельно мы изучили журналы доступа на предмет индикаторов, описанных исследователями. Конкретный пример: примерно через три часа после выхода патча на корень нашего сайта и на такие пути, как /api и /app, пошла серия POST-запросов с одного облачного IP-адреса, который поочерёдно выдавал себя за различных ботов поисковых систем и ИИ-сервисов (CCBot, Amazonbot, ClaudeBot и другие). Все до единого эти запросы были отклонены с кодом 403 серверным уровнем безопасности, не дойдя до нашего приложения. Мы не можем утверждать наверняка, что это были попытки эксплуатации PHP2Shell, но время и схема с поддельной идентификацией соответствуют массовому сканированию, начавшемуся после выхода патча. На момент публикации мы не обнаружили в наших системах никаких признаков компрометации.
Подход Partnerfy: мы никогда не доверяем безопасность одному замку. Фильтрация на границе, усиление защиты на сервере, изоляция между аккаунтами, резервные копии в тылу, быстрое реагирование на передовой. Если один уровень пробит, следующий уже на посту.
Что делать вам? Пошаговый чек-лист
1. Узнайте версию PHP
В cPanel проверить её можно на экране «MultiPHP Manager» или «Select PHP Version», а при доступе к серверу — командой php -v. Будьте внимательны: версия PHP в командной строке может отличаться от той, на которой работает ваш сайт. Самый надёжный способ — спросить у хостинг-провайдера, какую версию PHP использует ваш сайт, или проверить её через временную страницу phpinfo() и сразу удалить эту страницу. Если вы на виртуальном хостинге, обновление — задача не ваша, а вашего хостинг-провайдера. Спросите его сегодня же: «Вы установили патч от PHP2Shell?»
2. Обновите PHP и выполните перезапуск
Целевые версии: 8.5.12, 8.4.27, 8.3.36 или 8.2.35. В пакетах дистрибутивов Linux номер версии может выглядеть иначе. Как рекомендует и Debian, ищите номер CVE в журнале изменений пакета (changelog), а не полагайтесь на номер версии. После обновления перезапустите Apache, PHP-FPM и все долгоживущие рабочие процессы PHP.
3. Если обновиться сразу нельзя: временные меры
Начнём с предупреждения самого проекта PHP: эти меры «снижают подверженность конкретным путям атаки, но не делают установку безопасной». Единственное полное решение — обновление.
| Временная мера | Какая уязвимость | Ограничение |
|---|---|---|
session.upload_progress.enabled = 0 (в php.ini, пуле FPM или конфигурации сервера; не через ini_set() или .user.ini), затем перезапуск всех рабочих процессов | 109619 | Закрывает подтверждённые пути через сессии, но не другие варианты. На 109618 не влияет. |
post_max_size: 8M, если вы не принимаете загрузку файлов, 32M, если принимаете; upload_max_filesize — ниже этого значения. На фронтальном уровне (веб-сервер / прокси) — лимиты на количество полей, частей и заголовков, а также на глубину вложенности. Если ваше приложение не использует multipart, блокируйте такие запросы на фронтальном уровне. | 109618 | Сужает поверхность атаки, но полностью проблему не решает. |
memory_limit = -1, заданный так, чтобы приложения не могли его изменить (например, через php_admin_value). Лимит памяти вместо этого задавайте на уровне контейнера / cgroup. | 109618 | Низкоуровневый сбой выделения памяти всё равно может привести на уязвимый путь. Не используйте RLIMIT_AS / RLIMIT_DATA: они могут задействовать тот же путь. |
Только PHP 8.5: fatal_error_backtraces = 0, затем перезапуск | 109619 | Закрывает только подтверждённый путь через backtrace. |
Удалите INI-настройки уровня запроса, которые выдают предупреждения до старта запроса. Подавление предупреждений через error_reporting, display_errors или @ не помогает. | 109619 | Зависит от окружения; полностью проблему не решает. |
| WAF (например, начальный набор правил Cloudflare) | Известные векторы | Злоумышленники изменяют полезную нагрузку, чтобы обойти правила. |
4. Если у вас старая версия PHP: с обновлением нельзя тянуть
PHP 8.1 и более ранние версии больше не получают обновлений от проекта PHP. Для сайта на этих версиях настоящее решение — не патч, а переход на новую версию. Помните: поддержка PHP 8.2 также заканчивается 31 декабря 2026 года. Переход на 8.2.35 сегодня избавит вас от проблемы, но если вы войдёте в 2027 год на 8.2, при следующем кризисе патча для вас не будет. Если ваш устаревший код не работает на новых версиях PHP, значит, пришло время для проекта по модернизации ПО.
5. Проверьте наличие признаков компрометации
Индикаторы, которые исследователи рекомендуют проверить после установки патча:
- необычные multipart-запросы, сразу за которыми следуют ошибки лимита памяти или всплески ответов HTTP 500;
- неожиданно большие или некорректные cookie
PHPSESSID; - необъяснимые перезапуски или сбои рабочих процессов PHP;
- запуск процессами php-fpm, httpd или apache2 командной оболочки, интерпретатора или инструмента загрузки (например, sh, bash, curl или wget);
- новые файлы в корневом каталоге сайта (веб-шеллы), новые задания cron, новые учётные записи пользователей.
Поскольку атака происходит ниже уровня приложения, в журналах приложения она может оставить очень мало следов. Проверяйте журналы веб-сервера и PHP. Если что-то выглядит подозрительно, изолируйте сервер, сохраните журналы и только затем проводите расследование. CVE-2026-109619 может приводить и к раскрытию памяти, поэтому при сомнениях имеет смысл также сменить пароли баз данных, API-ключи и секреты сессий.
Урок этого кризиса: безопасность — не продукт, а рефлекс
PHP2Shell наглядно показал три вещи. Во-первых, каким бы чистым ни было ваше приложение, вы защищены лишь настолько, насколько защищена платформа, на которой оно работает. Во-вторых, в эпоху ИИ разрыв между патчем и эксплойтом сократился до часов. В-третьих, когда случаются утечки и нарушения эмбарго, подход «будем действовать по официальному графику» рушится. Выигрывают команды, которые узнают новость в первый же час, применяют временную меру, держат резервные копии наготове и никогда не доверяют защиту одному замку.
В компании Partnerfy этот рефлекс входит в стандарт наших услуг: управляемый хостинг и администрирование серверов, кибербезопасность, а также резервное копирование и аварийное восстановление. Мы — компания по разработке ПО с головным офисом в провинции Sakarya и офисами в Турции, Германии, России и Ирландии — поможем вам выяснить, на какой версии PHP работает ваш сайт, уязвим ли он для PHP2Shell и как подготовиться к окончанию поддержки PHP 8.2. Свяжитесь с нами, и мы вместе проверим ваш сайт.
Источники
- PHP: объявление о безопасности от 21 октября 2026 года
- GHSA-w8hw-w9fx-j79w: CVE-2026-109618 (RCE через повреждение памяти при OOM)
- GHSA-6wmf-4rv5-p3rp: CVE-2026-109619 (RCE через устаревшее глобальное состояние)
- The PHP Foundation: сегодняшний релиз безопасности PHP и то, как мы усиливаем защиту PHP
- Wiz: исследование PHP2Shell
- Help Net Security: уязвимости PHP2Shell закрыты
- The Hacker News: PHP выпустил экстренные патчи для двух критических уязвимостей