Эксплуатация PHP2Shell привела к запуску 35 оболочек от имени веб-сервера

PHP2shell

Записи сетевых пакетов и события процессов на трёх узлах показывают 35 завершённых запросов этапа выполнения, после каждого из которых веб-сервер Apache породил командную оболочку с правами пользователя веб-сервера. Оболочка запускалась как прямой дочерний процесс рабочего процесса Apache, а не прикладного кода. Три запуска пришлись на адрес из хостинговой сети OVH US, ещё 32 - на адрес из сети Interserver. Это два кластера адресов отправки, а не указание на двух операторов. Ошибки PHP возникали на этапе запуска запроса, до кода приложения, что согласуется с уязвимостью движка PHP, а не отдельной системы управления содержимым.

Описание

Цепочка на каждом узле состояла из четырёх запросов с разными ролями. Первый создавал давление на память, второй вызывал раскрытие памяти через значение идентификатора сессии размером около 819 КБ, третий снова давил на память, четвёртый содержал команду. По данным анализа первые три тела запросов в разобранных успешных цепочках совпадали побайтно, а четвёртое менялось вместе с адресными значениями и текстом команды. Размеры тел составляли примерно 1 МБ, 33,1 МБ, 279 КБ и 451 КБ. Первый и второй запросы иногда повторялись перед переходом к следующей стадии. Все подтверждённые запросы этапа выполнения шли по открытому HTTP, без заголовка User-Agent, с десятисимвольным разделителем составного тела и одинаковым порядком заголовков.

Apache записал 52 cookie размером около 819 КБ. Из них 51 полный ответ восстановлен по пакетам и подтверждён клиентом, для одного ответа на втором узле запись начинается с середины. Раскрытые значения содержали повторяющиеся слова, похожие на 64-битные указатели, причём одно слово повторялось 1095 раз в представительской выборке. Ведущий указатель различался по абсолютной величине между тремя узлами, а адресное слово в четвёртом запросе сохраняло ту же относительную разницу. Это поддерживает подстройку под рандомизацию адресного пространства на каждом узле, а не случайное совпадение одного жёстко заданного адреса.

Выполнение фиксировалось не по коду ответа HTTP. Ошибка PHP, крупный идентификатор сессии или падение рабочего процесса сами по себе доказательством не считались. Решающим было появление неожиданной оболочки с родительским процессом Apache, а в части случаев - независимо наблюдавшиеся дочерние процессы id, PHP CLI или curl. Наборы пакетов по всем 35 случаям опубликованы вместе с записями Apache и событиями процессов.

Что осталось неясным

Не установлено, какая именно реализация клиента отправляла запросы. Публичную ревизию эксплойта, изученную 24 октября, отличает отбрасывание раскрытых указателей ниже определённого порога, и в ранних успешных цепочках таких значений не встречалось, а в двух более поздних cookie на третьем узле подходящие указатели были. Поэтому нельзя утверждать, что каждый успешный запуск требовал изменённой версии кода. Не установлено и то, скачивался ли второй этап: загрузка не наблюдалась. Попытки получить файл заканчивались неудачей из-за отсутствия wget, запрос PHP CLI завершился таймаутом, а записи в каталоги веб-сервера отклоняла файловая система.

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

Оба адреса на 24 октября числились за хостинговыми сетями: первый за OVH US LLC, второй за Interserver, Inc. Обратная запись первого адреса указывала на его же узел, обратная запись второго не подтверждалась соответствующей прямой записью в проверке. Регистрация сети и обратные записи описывают инфраструктуру, а не людей за ней.

Отдельно в том же снимке два других адреса отправляли запросы, по форме совпадающие с эксплуатационными, и сопровождались ошибками PHP или падениями рабочих процессов. Ни запуска оболочки, ни cookie размером около 819 КБ для них не зафиксировано. Речь идёт о попытках, а не о состоявшемся выполнении команд.

Наблюдения сделаны на трёх одноразовых приманках, которые имитировали обычные страницы на PHP. Узлы работали под PHP 8.4.26 в режиме mod_php с одним рабочим процессом и лимитом памяти 128 МБ, поэтому цепочка описана для намеренно благоприятной конфигурации. Надёжность эксплуатации при другом числе рабочих процессов, других сборках PHP и другом прикладном коде эти записи не измеряют. Снимок ограничен окном, последние закрытые сегменты которого датированы временем с 19:26 до 19:31 по UTC, а перечисленные признаки могут давать ложные срабатывания.

Индикаторы компрометации

Комментарии: 0