PHP2Shell: Один файл для загрузки — и весь сервер ваш

Фото: Tumisu (Pixabay) — https://pixabay.com/photos/cloud-network-finger-6181051/

Источник: Varonis•

PHP2Shell: Один файл для загрузки — и весь сервер ваш

Сколько серверов отделяет от утечки ваших секретов всего одна некорректная загрузка файла? 

Сколько серверов отделяет от утечки ваших секретов всего одна некорректная загрузка файла?

PHP2Shell — это пара критических уязвимостей, которые позволяют неаутентифицированным злоумышленникам удаленно выполнять код на PHP-установках, обслуживающих веб-запросы. Поскольку на PHP работает примерно 70% веб-сайтов в мире, а ошибки срабатывают до выполнения любого кода приложения, даже полностью обновленный сайт на WordPress, Drupal или Joomla остается уязвимым до тех пор, пока не будет обновлен базовый PHP, и злоумышленники активно ищут такие системы.

Calif, исследовательская компания по безопасности, работающая в рамках инициативы Patch the Planet от OpenAI, обнаружила эти уязвимости первой 1 августа и сообщила о них разработчикам PHP 11 августа. Wiz Research обнаружила их независимо.

Что нам известно на данный момент

  • Две критические уязвимости в самом PHP. CVE-2026-109618 и CVE-2026-109619 находятся в ядре, поэтому даже защищенный код приложения не может защитить уязвимый сервер. Неаутентифицированный удаленный злоумышленник может прочитать память PHP-воркера (пароли, токена, API-ключи) и в некоторых случаях запустить код на сервере.
  • Широкий охват. Уязвимы все версии PHP, начиная с 5.4, во всех средах: PHP-FPM, Apache modphp, php-cgi, FrankenPHP и LiteSpeed, причем наибольший риск представляет modphp.
  • Подтверждено на реальных платформах. Удаленное выполнение кода было продемонстрировано на последних образах контейнеров WordPress, Drupal и Joomla. Даже простое PHP-приложение "Hello World" может быть уязвимо.
  • Исправление выпущено, но утечка произошла первой. Исправленные релизы вышли 21 октября: PHP 8.5.12, 8.4.27, 8.3.36 и 8.2.35. Для PHP 8.1 и более старых версий официальных релизов не будет.

Почему это важно

Большинство команд запишут это как две уязвимости в PHP, которые теперь исправлены. Однако масштаб проблемы гораздо шире.

  • Уязвимости находятся ниже уровня приложения. CVE-2026-109618 и CVE-2026-109619 расположены в среде выполнения PHP, поэтому используемый фреймворк, CMS или пользовательский код не имеют значения. Эксплуатация может произойти до того, как выполнится какой-либо код приложения, а это означает, что логи на уровне приложения могут практически ничего не зафиксировать.
  • Ошибки в самом приложении не требуются. Атака не зависит от уязвимого плагина, слабого механизма входа или небрежной обработки сессий. Сайт с чистым кодом все равно может быть уязвим, если базовый PHP не обновлен.
  • Атаку можно провести без аутентификации. Злоумышленнику не нужны учетная запись, пароль или первоначальный доступ — достаточно возможности отправить запрос на ваш сервер.
  • Стоимость создания эксплойта снизилась. Исследователи сообщают, что модели ИИ сократили время на то, что раньше требовало месяцев специализированной работы, до нескольких дней. Десятилетние классы уязвимостей, которые когда-то считались непрактичными для превращения в оружие, теперь доступны, и злоумышленники имеют доступ к тем же инструментам.

Учитывая, что на PHP работает огромная часть интернета — от WordPress и Drupal до внутренних инструментов, к которым никто не прикасался годами, — вопрос заключается не в том, используете ли вы его. Вопрос в том, где именно и удастся ли вам обнаружить каждый экземпляр.

Что нужно предпринять на этой неделе

Обнаружение

  • Ищите признаки фазы настройки. Некорректные или необычные запросы multipart-загрузки, за которыми следуют ошибки нехватки памяти (memory-limit) или всплески HTTP-ответов 500, являются паттерном для поиска.
  • Проверяйте исходящие cookies. Слишком большой или некорректный PHPSESSID в ответе может указывать на то, что память процесса утекает обратно клиенту.
  • Фиксируйте создание процессов во время обработки загрузок. PHP-воркер никогда не должен порождать дочерний процесс во время синтаксического анализа загружаемого файла и до выполнения кода приложения. Считайте это надежным индикатором.

Эти признаки помогают в расследовании. Они не заменяют установку патчей.

Устранение уязвимостей

  • Составьте инвентаризацию всех установок PHP. Выходите за рамки очевидных веб-приложений. Учитывайте встроенное ПО, программно-аппаратные комплексы и забытые внутренние инструменты.
  • Сначала исправьте системы, смотрящие в интернет. Перейдите на PHP 8.5.12, 8.4.27, 8.3.36 или 8.2.35 в зависимости от используемой ветки.
  • Смените секреты на уязвимых серверах. Если злоумышленник мог прочитать память воркера до того, как вы установили патч, считайте учетные данные, токены и API-ключи, находившиеся в этой памяти, скомпрометированными.

Хотите узнать, как единичный сбой по нехватке памяти превращается в выполнение кода? Читайте дальше.

Подробный разбор того, что нам известно о PHP2Shell

В бюллетене безопасности PHP описаны четыре ошибки, классифицированные как два CVE. Вместе они составляют уязвимость PHP2Shell. Первые три имеют общую «предфазу», которая подготавливает их успех и по сути позволяет достичь конечной цели удаленного выполнения кода (RCE). Четвертая представляет собой более внутренний процесс, и детали ее эксплуатации не раскрывались.

Чтобы понять, как они влияют на сервер, нам сначала потребуется рассмотреть несколько концепций.

Что за PHP? Краткий глоссарий

  • PHP-воркер веб-сервера. Процесс, который обрабатывает HTTP-запрос и переиспользуется для последующих запросов, вместо того чтобы перезапускаться каждый раз.
  • Парсинг multipart-запросов. Чтение PHP входящего запроса multipart/form-data (загрузка файла) и разбиение его на помеченные части. Этот процесс начинается очень рано.
  • Обработка прогресса загрузки сессии. Функция PHP, которая отслеживает прогресс загрузки файла, чтобы страница могла отображать полосу прогресса. Она работает во время синтаксического анализа сервером multipart-запроса.
  • Сессия. Способ PHP запоминать пользователя между запросами (cookie PHPSESSID).
  • Лимит памяти (memory limit). Максимальный объем памяти, который может использовать один запрос.
  • Глобальные указатели движка. Внутренние служебные переменные, которые движок PHP использует для отслеживания глобального состояния выполнения. Здесь важны три из них: PS(id) — идентификатор сессии; BG(unserialize) — состояние десериализатора (состояние восстановления исходного массива или объекта из сериализованной строки); EG(last_fatal_error_backtrace) — хранит информацию о последней ошибке.
  • PS(id): идентификатор сессии.
  • BG(unserialize): состояние десериализатора (состояние восстановления исходного массива или объекта из сериализованной строки).
  • EG(last_fatal_error_backtrace): хранит информацию о последней ошибке.
  • Очистка воркера. Нормальный процесс завершения в PHP должен выполняться между запросами на переиспользуемом воркере, сбрасывая глобальные указатели движка, чтобы следующий запрос начинался с чистого листа. Цепочка уязвимостей существует потому, что фатальные ошибки нехватки памяти прерывают запрос до выполнения этой очистки, оставляя указатели устаревшими.
  • OPcache. Разделяемая память, содержащая прекомпилированный байт-код скриптов, который могут читать все воркеры, что исключает необходимость повторного чтения и компиляции одного и того же PHP-файла.

Теперь, когда мы знакомы с терминологией, перейдем к части, которая делает всё это возможным.

Предфаза

Основная концепция, используемая здесь, — это использование памяти после ее освобождения (use-after-free или UAF): память освобождается, но указатель на нее сохраняется и используется позже. Если злоумышленник добивается размещения новых данных в этой освобожденной памяти, PHP воспринимает байты злоумышленника как собственную доверенную структуру.

Злоумышленник отправляет специально сформированный multipart-запрос на загрузку, который приводит к исчерпанию памяти PHP во время обработки прогресса загрузки сессии на раннем этапе запроса. Запрос неожиданно завершается, очистка воркера пропускается, и остаются устаревшие указатели. Это может привести к раскрытию памяти или ее повреждению.

Последовательность действий злоумышленника:

  • Создание «подготавливающего» запроса. Злоумышленник отправляет запрос multipart/form-data с данными о прогрессе загрузки сессии, размер которых рассчитан на исчерпание памяти во время синтаксического анализа.
  • Ранний парсинг до приложения. Обработка прогресса загрузки выполняется до завершения нормального запуска PHP, поэтому глобальные указатели движка настраиваются на раннем этапе.
  • Фатальная ошибка из-за нехватки памяти. Запрос превышает memory_limit; PHP прерывает работу и освобождает кучу (heap) запроса.
  • Очистка пропускается. Указатели никогда не сбрасываются.
  • Рабочий процесс выживает и используется повторно. Тот же рабочий процесс обрабатывает следующий запрос, все еще удерживая устаревшие указатели.
  • Использование памяти. Данные злоумышленника занимают одно из освобожденных распределений (каждый указатель имеет собственное отдельное распределение).

Это конфигурация, от которой зависят первые три уязвимости.

Уязвимость 1: Раскрытие памяти удаленного процесса

После предварительной фазы другой многочастный запрос в том же рабочем процессе по-прежнему доверяет освобожденному распределению PS(id). PHP считывает повторно занятые байты как действующий идентификатор сеанса и кодирует их в URL-адрес в куки-файле ответа PHPSESSID. Злоумышленник может просто прочитать куки-файл, чтобы получить утечку памяти рабочего процесса. Это позволяет им преодолеть неопределенность адресов, что делает следующий шаг к RCE практичным.

Уязвимость 2: Использование памяти после освобождения в десериализаторе

Здесь освобожденному распределению BG (unserialize) доверяют вызывать повреждение памяти. PHP продолжает «десериализацию», используя память, возвращенную злоумышленником, как если бы она все еще была действительной, превращаясь в примитив повреждения памяти. В сочетании с утечкой из Уязвимости 1 эта уязвимость использовала неопределенность адресов для достижения неавторизованного RCE и была продемонстрирована на платформах WordPress, Drupal и Joomla.

Уязвимость 3: Использование памяти после освобождения в трассировке фатальных ошибок

Еще одно злоупотребление указателем EG(last_fatal_error_backtrace). Если тот же рабочий процесс отправляет диагностическое событие (любую последующую ошибку или предупреждение) после сбоя очистки, он может получить доступ к освобожденному указателю до повторной инициализации состояния. PHP обновит или уничтожит трассировку указателя и перейдет к памяти, возвращенной злоумышленником. Это использование после освобождения может быть превращено в повреждение памяти, которое может привести к RCE.

Уязвимость 4: Путаница типов в OPcache (отдельный поток, между рабочими процессами)

В отчете об уязвимости Wiz не описываются конкретные запросы или шаги для этой уязвимости, а упоминается лишь сбой внутреннего механизма. Итак, вкратце:

  • Общий кэш скомпилированного кода. OPcache хранит предварительно скомпилированный байт-код в разделяемой памяти, чтобы каждый рабочий процесс мог использовать его повторно вместо перекомпиляции (php.net: «устраняет необходимость для PHP загружать и синтаксически анализировать скрипты при каждом запросе»).
  • Два трекера. Локальный трекер процесса (CG(map_ptr_last)) и общий трекер (ZCSG(map_ptr_last)) оба отслеживают степень заполнения разделяемой памяти.
  • Сбой выделения в процессе обновления. В промежутке между обновлением двух трекеров сбой выделения может привести к рассинхронизации общего трекера с тем, что было записано.
  • Повторное использование между рабочими процессами. Wiz утверждает, что это может позволить другому рабочему процессу повторно использовать этот слот памяти, и он разрешится в указатель неверного типа. Это вызывает путаницу типов и повреждает общее состояние OPcache, которое впоследствии было использовано для достижения RCE. То, как и когда это происходит, не уточняется, поэтому воспринимайте это как общую схему уязвимости, а не как точную последовательность.

Влияние на продукты Varonis

Varonis оценила влияние этих уязвимостей на все свои продукты и предприняла необходимые меры по устранению.

Продукт

Статус уязвимости

Varonis SaaS

Не затронуты

Varonis DAC

Не затронуты

Varonis Atlas

Не затронуты

Varonis Interceptor

Ранее затронуты; полностью исправлены

На дату публикации компания Varonis не выявила признаков компрометации, связанных с этими уязвимостями. Все затронутые среды Varonis Interceptor исправлены. Никаких действий от клиентов не требуется. Затронутые компоненты Varonis исправлены, а продукты Varonis SaaS, DAC и Atlas не уязвимы к данным CVE.

Ссылки

Как Varonis может помочь

Varonis помогает клиентам противостоять PHP2Shell и другим угрозам путем обнаружения подозрительного латерального перемещения и аномального доступа к данным, а затем автоматически изолирует скомпрометированные учетные записи для защиты конфиденциальных данных.

Управляемое обнаружение угроз и реагирование на них (MDDR) обеспечивает дополнительный уровень защиты наряду с установкой исправлений: эксперты Varonis круглосуточно и без выходных мониторят активность данных, расследуют такие угрозы, как доступ к конфиденциальным данным с помощью украденных учетных данных, и принимают меры по их изоляции. Клиенты получают круглосуточную экспертную поддержку без необходимости нанимать собственный штат специалистов.

Резюме

PHP2Shell — это цепочка, порожденная одним непримечательным событием: запросом, у которого заканчивается память и который пропускает этап очистки. На основе этого единственного устаревшего указателя исследователи получили раскрытие памяти, два варианта использования после освобождения и отдельную путаницу типов OPcache, и все это ниже уровня приложения и присутствует еще со времен PHP 5.4.

Гавриэль Фрид (Gavriel Fried) — исследователь облачной безопасности в компании Varonis. До работы в Varonis опыт работы Гавриэля в сфере кибербезопасности включал различные исследовательские должности, такие как облачные технологии, системы управления идентификацией (Identity), UEBA, технологии обмана (Deception), сети и DPI, Red Teaming, цифровая криминалистика и анализ вредоносного ПО. Гавриэль исследует потенциальные атаки, злоупотребления, уязвимости и аномалии в облачных сервисах и SaaS

О чём эта статья

Ещё в разделе «Данные и аналитика»

Все →

Ещё от Varonis