PHP2Shell: две критические уязвимости в ядре PHP, которые не закрывает ни одна CMS

В ядре PHP обнаружены две критические уязвимости, объединённые под названием PHP2Shell. Они работают ниже уровня CMS: обновление WordPress, Drupal или Joomla не помогает. Уязвимыми остаются миллионы серверов, а атаки начались ещё до выхода патча.

PHP2Shell: две критические уязвимости в ядре PHP, которые не закрывает ни одна CMS

PHP2Shell: две дыры в ядре PHP, которые не закрывает ни одна CMS

В конфигурации Apache с mod_php разбор тела HTTP-запроса происходит до того, как управление передаётся файлу сайта. Можно поставить пустой index.php — атака всё равно сработает. Обновление WordPress, Drupal, Joomla или Magento в этой ситуации ничего не решает: ошибка лежит ниже уровня CMS, в самом интерпретаторе. Владелец сайта может делать всё правильно — ставить сложные пароли, настраивать WAF, следить за обновлениями приложения — и оставаться уязвимым.

Две разные поломки в одном ядре

Уязвимости CVE-2026-109618 и CVE-2026-109619, объединённые под названием PHP2Shell, работают по-разному. Официальная оценка PHP — 9,2 балла из 10 по CVSS v4.0. Уязвимый код присутствовал в ядре более 14 лет, механизмы прослеживаются до PHP 5.4 (март 2012 года).

Первая уязвимость — RCE через повреждение памяти при нехватке памяти (OOM). Когда PHP сталкивается с нехваткой памяти, он прерывает обработку запроса через longjmp() — аварийный переход к обработчику ошибки. Проблема в том, что в некоторых местах память уже выделена, но не инициализирована. При завершении запроса интерпретатор обращается к некорректно инициализированным структурам, и повреждение памяти превращается в выполнение произвольного кода.

Довести запрос до OOM можно, не выходя за видимые лимиты. Для этого используется разбор multipart/form-data. Три конкретных приёма: запрос без корректного Content-Length проходит проверку post_max_size; неограниченное количество заголовков у части multipart занимает в памяти больше, чем по сети; пустые поля загрузки файлов не считаются в max_file_uploads, но создают массивы метаданных. Вложенные имена полей дополнительно умножают работу. Разница между размером сетевых данных и объёмом выделяемой памяти означает, что post_max_size не гарантирует защиту.

Вторая уязвимость — use-after-free «протухшего» глобального состояния воркера. Воркер PHP хранит глобальное состояние: ошибки, сессии, объекты, состояние расширений. Иногда эти данные указывают на память конкретного запроса. Если запрос прерван фатальной ошибкой — нехваткой памяти или таймаутом — сброс состояния может не произойти. Память освобождается, указатель остаётся. Следующий запрос в том же воркере обращается к освобождённой памяти.

Атака двухзапросная: первый запрос оставляет «мусор» в глобальном состоянии, второй его использует. Несколько воркеров снижают шанс попасть в тот же процесс, но не устраняют проблему. Подтверждённые векторы — fatal error backtraces (PHP 8.5, mod_php), жизненный цикл сессий (mod_php и PHP-FPM), утечка памяти процесса. Одна из цепочек использует session.upload_progress — механизм, включённый по умолчанию.

Утечка до эмбарго и атаки до патча

Wiz направила отчёт команде PHP 24 августа 2026 года, PHP подтвердила получение 21 сентября. Предварительное уведомление о внеплановом релизе появилось 20 октября, сам релиз назначили на 21 октября 14:00 UTC.

Дальше хронология пошла не по плану. 21 октября в 13:34 UTC информация опубликована в GitHub Security Advisories — за 26 минут до официального срока. Первые упоминания появились на Hacker News (пост пользователя petecooper, впоследствии удалён). Исследователи Calif по ошибке опубликовали видео с работающим PoC-эксплойтом. Chainguard выпустила готовые образы с исправлениями ещё до официальной публикации, что позволяло изучать патч заранее.

Атаки начались до выхода патча. Amazon Threat Intelligence зафиксировала попытку эксплуатации 17 октября на honeypot'е MadPot — за четыре дня до публичного раскрытия. Как злоумышленник узнал об уязвимостях, неизвестно. Cloudflare развернула временные WAF-правила ещё до публичного выпуска исправления. В день выхода патча, 21 октября, были зафиксированы попытки с использованием PoC-эксплойтов — их отмечали Cloudflare, Hadrian, Patchstack, Vega и watchTowr. Подтверждённых успешных взломов на момент публикации источников нет.

Есть соблазн связать утечку деталей до эмбарго с попыткой эксплуатации 17 октября в причинно-следственную цепочку. Оба факта — утечка и ранняя атака — стоят отдельно.

Что на самом деле нашёл ИИ

Первые признаки OOM-уязвимости находили в 2020 и 2024 годах, но тогда не могли доказать возможность RCE. Проблему CVE-2026-109618 нашли в 2024 году во время внешнего аудита — и исправление месяцами буксовало.

В 2026 году две команды независимо довели эту проблему до эксплойта. Calif работала в рамках инициативы OpenAI «Patch the Planet» с моделью GPT-5.6 Sol. Wiz использовала ИИ-агента Wiz Atlas, Gemini 4 Argon и ту же GPT-5.6 Sol. То, что сделали модели, — не «магия», а ускорение анализа давно известной проблемы: они нашли способы управляемо вызывать OOM, обходить post_max_size и анализировать состояние PHP после аварийного завершения. Паттерн обобщили и использовали для поиска аналогичных проблем. Переход от «мы подозреваем, что это эксплуатируемо» к «вот рабочий эксплойт» занял у людей годы, у ИИ — месяцы.

Миллионы серверов и разрыв между масштабом и инструментами

По данным Palo Alto Networks, публично доступных экземпляров, потенциально подверженных уязвимостям, более 22,6 млн. VirusTotal насчитал более 5,1 млн PHP-хостов, из них ~3,8 млн с открытым хотя бы одним портом. PHP работает примерно на 69–70% сайтов. Затронуты все установки непропатченных версий, обрабатывающие веб-запросы: PHP-FPM, Apache с mod_php, php-cgi, FrankenPHP, LiteSpeed LSAPI. Наибольший риск у mod_php: подтверждён эксплойт без аутентификации при лимитах PHP по умолчанию. FrankenPHP по анализу исходников ведёт себя так же. Для PHP-FPM полного эксплойта первой уязвимости не показали, но для CVE-2026-109619 подтверждена RCE через сессии именно для FPM.

Последствия видны по списку отключённых сервисов. Wikipedia и Internet Archive (последний подтвердил отключение, но публично не связывал его с уязвимостями). Нидерландские MijnOverheid, DigiD, сайт нижней палаты парламента и ресурсы национального центра кибербезопасности. Госструктуры Финляндии. Правозащитная организация noyb. HR-платформа BambooHR — с предупреждением клиентов о возможных проблемах с начислением зарплат. Датская платформа школьной коммуникации, сайты местных властей Франции, немецкий ITZBund (без выявленных инцидентов), 4Chan, Something Awful, игра Shadowverse: Worlds Beyond, часть японских e-commerce сайтов. АНБ США рекомендовало отключать сайты, которые невозможно немедленно обновить.

Теперь практическая часть, где масштаб проблемы сталкивается с реальными инструментами её решения.

Вывод php -v в консоли может показывать не ту версию, которая обслуживает сайт. На серверах с ISPmanager, cPanel, CloudLinux или Remi стоит по несколько PHP, и сайт может работать через другую версию php-fpm. Linux-дистрибутивы переносят исправления в старые версии без изменения номера — вывод php -v может показывать «уязвимую» версию при уже залатанном пакете. Проверять нужно через apt changelog или rpm -q --changelog. Заголовок X-Powered-By ненадёжен: его часто скрывают, а версия может не совпадать с реальной. После установки патча обязательно перезапустить все воркеры — php-fpm и Apache, иначе старый код продолжит работать в памяти. В Docker нужно пересобрать образы, а не просто перезапустить контейнеры.

Временные меры и их цена

До установки патча рекомендуют отключить session.upload_progress.enabled = Off. Техническая деталь, о которой легко споткнуться: директива имеет тип PHP_INI_PERDIR и не меняется через ini_set() во время выполнения — только через php.ini, конфигурацию пула FPM или настройки сервера. Второй вариант — блокировка multipart-запросов на уровне Nginx или Apache. Побочный эффект конкретный: блокируются легитимные загрузки файлов. HTTP 403 в ответ на загрузку — ожидаемое поведение временной меры, а не сбой сайта.

Суть в том, что временные меры сужают отдельные векторы, но не закрывают уязвимость. Отключение upload_progress не помогает против CVE-2026-109618 — там достаточно разбора multipart без него. Разработчики PHP прямо говорят: полностью решает проблему только обновление.

Исправленные версии — 8.2.35, 8.3.36, 8.4.27, 8.5.12. Для PHP 7.4, 8.0 и 8.1 подготовлены минимальные бэкпорты исходного кода, но официальных обновлённых бинарных сборок нет. Для PHP 7.3 и старше исправлений не будет вообще.

История PHP2Shell показывает, где находится настоящее узкое место. Патч существует, но добраться до него — задача, требующая координации между хостингом, вендором операционной системы и владельцем сайта. Каждый из них может сделать свою часть работы правильно — и сайт останется уязвимым, потому что кто-то в цепочке не перезапустил воркер или проверил не ту версию. Четырнадцать лет уязвимый код жил в самом массовом языке веб-разработки не потому, что его никто не искал, — его находили и не могли доказать эксплуатируемость. Понадобились ИИ-модели, чтобы превратить подозрение в рабочий эксплойт. Вопрос теперь не в том, сколько серверов уязвимо, а в том, сколько организаций справятся с обновлением до того, как остальные научатся использовать опубликованный PoC.

Read more

Пять тысяч человек видят ИИ, которого не существует для остальных шести миллиардов

Андрей Карпати оценивает, что лишь пять тысяч человек имеют доступ к вершине возможностей языковых моделей, тогда как шесть миллиардов почти не сталкивались с ними. Разрыв в понимании ИИ растёт, и дело не в доступе, а в сложности задач, которые мы перед ним ставим.

Строительный сектор сжимается: главный риск — в «серой зоне»

Строительный сектор сжимается: главный риск — в «серой зоне»

Число строительных компаний в России сократилось на 4,3% за год. Но главная угроза — не в ликвидированных фирмах, а в десятках тысяч компаний с заблокированными счетами и высоким риском банкротства, которые могут обрушить подрядчиков.

Drex: модель, которая решает, а не говорит

Drex: модель, которая решает, а не говорит

В индустрии, где главным продуктом стал текст, появляется модель, которая отказывается от текста как такового. Drex принимает на вход факты и за один проход выдаёт распределение вероятностей по всем возможным вариантам. Никаких рассуждений вслух, никаких промежуточных выкладок — только числа.

Воронка Карпати: почему экспонента ИИ проходит мимо 99,8% человечества

Воронка Карпати: почему экспонента ИИ проходит мимо 99,8% человечества

Шесть миллиардов человек никогда не взаимодействовали с языковыми моделями. Еще один-два миллиарда хотя бы раз написали запрос в бесплатный ChatGPT. Около двадцати миллионов используют агентов в работе. И примерно пять тысяч человек имеют доступ к внутренним системам OpenAI. Андрей Карпати объясняе…