Внезапно, как всегда: (не)выученные уроки инцидента PHP2Shell

В конце октября вокруг PHP развернулась одна из самых громких дискуссий о безопасности open source этого года. Две критические уязвимости под общим именем PHP2Shell допускали удалённое выполнение кода без аутентификации, а их раскрытие сопровождалось утечками и спором между поставщиками. После первых дней громких заголовков в СМИ тревога успела смениться скепсисом. Пока одни участники сообщества яростно выясняли, почему исправления задержали, другие спрашивали: а не преувеличена ли вовсе опасность?

Разница в реакции была разительна. В Нидерландах из предосторожности отключили государственные порталы, а в Германии прикрыли сайты города Мюнстер и его онлайн-сервисы. Университет Хельсинки временно закрыл свой экземпляр образовательной платформы Moodle и несколько других сервисов, чтобы защитить пользовательские данные. Три дня спустя исследователь Джеймс Павур предложил взломать свой PHP-сервер и забрать биткоины примерно на 500 долларов. Его, наоборот, смущало, что громких предупреждений много, а сообщений о реальных жертвах мало. 

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

Как «застряло» исправление для известной проблемы

PHP2Shell объединяет уязвимости CVE-2026-109618 и CVE-2026-109619. Обе получили рейтинг опасности 9,2 по CVSS 4.0. В первом случае достижение лимита памяти могло прервать создание внутренних данных запроса. Затем при очистке запроса PHP обращался к этим незавершённым данным как к корректным, что приводило к повреждению памяти. Во втором случае после завершения запроса оставались ссылки на уже освобождённую память. Другой запрос, попавший к тому же рабочему процессу, мог обратиться к этим ссылкам до сброса старого состояния. Эксплойт использует ошибки работы с памятью, чтобы выполнить код с правами процесса PHP, обслуживающего веб-запросы.

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

По отчёту PHP Foundation, первые признаки проблемы с исчерпанием памяти нашли ещё в 2024 году, но цепочку удалённого выполнения кода тогда не установили. Варианты исправления затрагивали совместимость, производительность и сторонние расширения, а команда, принимавшая решения консенсусом, не смогла выбрать компромисс, так что работу неоднократно останавливали и возобновляли. Лишь в августе 2026 года исследователи компании Calif передали разработчикам результаты, наглядно показывавшие удалённое выполнение кода. В отчёте участники фонда признали структурный провал, связанный с принятием решений и нехваткой ресурсов.

Было бы несправедливо сказать, что фонд сознательно отказывался исправлять критическую уязвимость. В 2024 году конкретный способ удалённого выполнения кода ещё не был установлен, а каждый вариант исправления создавал новые риски. Исправление требовало изменить поведение PHP в момент, когда у приложения заканчивается память. А от этого в том числе зависела работа сторонних расширений. Уже после выпуска патча обнаружилась показательная проблема: при разборе большого XML-документа некоторые сборки PHP вместо обычной ошибки нехватки памяти завершали рабочий процесс целиком. После этого пришлось готовить отдельное исправление для XML-расширения.

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

С нехваткой людей ситуация ещё неприятнее, поскольку об этом давно известно за пределами экосистемы PHP. После инцидента Heartbleed в 2014 году Linux Foundation создала Core Infrastructure Initiative, чтобы финансировать сопровождение критических open source проектов до следующего кризиса. Несмотря на подобные инициативы, двенадцать лет спустя PHP Foundation вынуждена раз за разом обращаться к организациям, которые зависят от её кода, с просьбой оплачивать постоянную работу специалистов. От этого зависит и сама работа с уязвимостями. Без специалистов некому проверить отчёт и подготовить исправление, а без оперативного добавления в базы знаний командам сложнее сопоставить предупреждения поставщиков со своим ПО. Можно вспомнить, что в прошлом году под угрозой оказался контракт поддержки программы CVE, которая как раз обеспечивает регистрацию угроз.

Конечно, деньги не разрешат любой технический спор. Но от команды нельзя одновременно ждать глубокого исследования, совместимого патча, проверки чужих отчётов (часто целиком сгенерированных ИИ-агентами) и круглосуточной координации, не предоставив ей людей для этой работы. Иначе обсуждение безопасности каждый раз начинается с удивления, что общедоступный код поддерживает вполне конечное число разработчиков и им ещё нужно время на сон и еду. Для компаний, которые на этом коде зарабатывают, нехватка ресурсов у мейнтейнеров должна быть сигналом к тому, чтобы активнее вкладываться в сопровождение, не дожидаясь потенциальных инцидентов.

Трудности согласования приводят к трудностям обновления

К октябрю 2026 года патчи были наконец подготовлены. Поставщикам пакетов и контейнерных образов оставалось собрать свои версии, чтобы пользователи могли обновиться в согласованный момент. По хронологии Foundation, после утечки идентификаторов CVE выпуск перенесли с 22 на 21 октября. Затем специалисты Calif ошибочно опубликовали демонстрационное видео эксплойта, копии которого начали быстро расходиться. Утром 21 октября произошел переломный момент – поставщик контейнерных образов Chainguard выпустил исправленные сборки более чем за шесть часов до согласованного срока.

Остальные поставщики в этот момент ещё готовили пакеты, тогда как атакующий уже мог изучать изменения в опубликованных бинарных файлах. Если PHP установлен на сервере из репозитория дистрибутива, то его администратору нужен обновлённый пакет из этого репозитория. Chainguard же выпустила контейнерный образ – чтобы воспользоваться им, пришлось бы менять способ развёртывания приложения. Поэтому PHP Foundation и настаивали на общем сроке, к которому обновления смогут подготовить другие поставщики.

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

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

А что там с масштабом угрозы?

Разногласия были и в том, что именно можно считать подтверждённой атакой и насколько она серьёзна, причем до того, как стали доступны версии с исправлением. Например, Amazon Threat Intelligence обнаружила в телеметрии MadPot попытку эксплуатации PHP2Shell за четыре дня до публичного раскрытия уязвимости.

Преждевременные и резкие выводы регулярно появлялись в сообщениях об успешных взломах. Аналитики Unit 42 отозвали раннюю атрибуцию другого инцидента с инфраструктурой европейского госучреждения к кампании PHP2Shell, поскольку не смогли подтвердить связь с конкретными CVE. 

Публичные PoC тоже давали поводы для недоверия. Разработчик Элиас Тейлор ещё 21 октября предложил проверить, что именно они доказывают и доказывают ли вообще. В трёх выбранных им репозиториях он не нашёл обещанного взлома обычной установки PHP и написал в своём блоге: «Но эксплуатировать [эту уязвимость] непросто. Уж точно не так легко, как Log4Shell, Heartbleed, RoRYaml и тому подобное».

Консультант по безопасности Лукас Лёйтьес опубликовал одну из самых заметных статей под звучным названием «I want my Wednesday back» («Верните мне мою среду»). Его раздражали рекомендации отключать сайты: к тому времени в Нидерландах уже закрыли доступ к государственным порталам. Запросы из изученного им PoC должны были попадать к одному рабочему процессу PHP, а балансировка и посторонний трафик мешали выдержать нужную последовательность, поэтому для нагруженных сайтов он считал остановку чрезмерной мерой. Его страх можно понять: если советовать отключение сервиса при появлении каждой сложной уязвимости, то в следующий раз предупреждение могут просто проигнорировать.

Исследователи VulnCheck тем временем сообщали в отчете, что лишь небольшая часть просмотренных публичных PoC содержала рабочие эксплойты. При этом стоит отметить, что уже 22 октября сама компания подготовила рабочий эксплойт для PHP 8.4.26 на 64-битных системах x86. Он обходил защиту ASLR, которая случайным образом размещает данные и код в памяти, и работал при отключённом показе ошибок PHP. Найденная исследователями утечка памяти помогала определить нужные адреса.

К 24 октября исследователь под ником 0x4D31 опубликовал журналы атак на три своих honeypot-сервера с PHP. Он сопоставил входящие запросы с запуском процессов и подтвердил 35 случаев, когда после запроса атакующего на сервере запускалась командная оболочка. Лёйтьес, который ранее выражал скептицизм, сослался на эти журналы в обновлении своей статьи. 25 октября он предположил, что массовая эксплуатация малопосещаемых сайтов уже началась, хотя сохранил возражения насчёт нагруженных систем.

Затем компания Dream Research описала кампанию против PAN-OS, программного обеспечения межсетевых экранов Palo Alto Networks. По её данным, атакующий скомпрометировал 25 серверов, объединив PHP2Shell с уязвимостью ядра Linux Fragnesia для повышения привилегий. В обновлении своего отчёта от 29 октября Unit 42 подтвердила инструментарий атакующего и результаты. В этой кампании злоумышленники получали доступ к межсетевым экранам Palo Alto Networks через открытые в интернет веб-интерфейсы управления PAN-OS.

Инженер Intruder Бенджамин Марр тоже сначала счёл, что шум вокруг PHP2Shell может оказаться сильнее самой угрозы, и взялся сам проверить её на PAN-OS. Первый эксплойт работал при прямом подключении к Apache на устройстве, а внешний доступ через nginx ломал цепочку. Однако в обновлении от 3 ноября Марр уже показал выполнение команды через интерфейс управления PAN-OS 12.1.2. Для этого он изменил способ утечки памяти с учётом ограничений nginx. По итогам работы он пересмотрел оценку — оказалось, что злоумышленнику достаточно один раз подобрать цепочку для распространённого продукта с одинаковыми сборкой и настройками PHP, чтобы затем применять её к другим таким устройствам. 

Забавным образом проверка эксплойта на том самом сервере с биткоинами тоже закончилась успешным взломом. Павур признал, что недооценил угрозу. Участник испытания приспособил эксплойт к его конфигурации и извлёк секрет, а автор подтвердил выполнение команды по журналам. С выплатой награды, впрочем, вышла заминка: извлечённый ключ не позволял перевести деньги из нужного кошелька, и приз пришлось отправлять отдельно. Тем не менее и в этом случае скептику пришлось признать поражение.

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

PHP может быть в вашем продукте, даже если вы на нём не пишете

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

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

Поэтому по собственному коду трудно судить обо всём ПО, которое требуется сервису для работы. Часто организация не в курсе, какие языки используются у неё «под капотом», пока она не озаботится сборкой из исходников. Во время инцидента эти сведения всё равно придётся собрать, только времени на это будет сильно меньше.

Уроки на будущее

С поиском критически уязвимого ПО внутри чужих продуктов и открытых компонентов отрасль уже сталкивалась многократно, например, после кампании Log4Shell (которая, кстати, до сих пор имеет последствия). За последний год таких поводов становится всё больше. И тем не менее в сообществе снова приходится объяснять, почему язык собственных приложений не определяет, касается ли организации уязвимость интерпретатора.

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

Безусловно, выстроить такую работу между инцидентами сложнее, чем один раз обновить PHP. Сведения о компонентах меняются вместе с поставками, а за их проверку и обновление кто-то должен отвечать постоянно. В России этот порядок уже описывает ГОСТ Р 56939-2024 и проект стандарта по композиционному анализу, в котором для средств разработки и ПО среды функционирования, которые не являются заимствованными компонентами продукта, используется понятие привлекаемого ПО. При таком учёте нужно сохранять связь программы с приложениями, которые от неё зависят, и ответственным за обновление. Обнаружив уязвимость в среде исполнения, команда сможет найти затронутые сервисы, даже если их код не менялся со времени последней проверки. Заказчику готового продукта, например, стоит заранее выяснить у поставщика, какие компоненты и среды входят в поставку, как он сообщает об их уязвимостях и в какие сроки выпускает исправления. Разработчику, в свою очередь, предстоит поддерживать эти сведения вместе с продуктом.

Участники инцидента сделали свои выводы, по крайней мере в краткосрочной перспективе. Руководитель Chainguard Дэн Лоренц публично объяснил досрочный выпуск и извинился перед разработчиками PHP за дополнительный стресс. Участники PHP Foundation уже начали менять порядок принятия решений, чтобы сложный фикс не застревал в ожидании консенсуса. От потребителей этого кода тоже стоит ждать изменений в своей зоне ответственности. Организация, которая при следующей утечке снова начнёт выяснять, где у неё установлен PHP и как его обновить, не сможет сослаться на недостаток информации. После нескольких подобных инцидентов ей придётся объяснять уже собственное бездействие.

Источник: habr.com

0 0 голоса
Рейтинг новости
1
0
Подписаться
Уведомить о
0 комментариев