
Обнаружения Zeek и Suricata для «php2shell» CVE-2026-109618 и CVE-2026-109619
Детекторы Zeek и правила Suricata для HTTP-индикаторов, связанных с "php2shell" CVE-2026-109618 / CVE-2026-109619 — потенциальной RCE в обработке памяти longjmp() в PHP. Результаты выявляют подозрительный трафик или потенциально затронутое программное обеспечение.
Требуется Zeek 7.0.0 или новее. Установка через Zeek Package Manager:
zkg install https://github.com/corelight/php2shell-detect
Загрузите установленные пакеты с помощью @load packages в конфигурации Zeek.
Для прямой выгрузки загрузите /path/to/php2shell-detect/scripts.
Пакет использует стандартные API Zeek для HTTP, анализа файлов, уведомлений и кластеризации.
Пакет проверяет длину имён полей POST, выбранные структуры сериализованных данных и повторяющиеся MIME-заголовки. Он также сопоставляет связанные подозрительные транзакции с помощью настроенных сессионных cookie. Заголовки ответов предоставляют отдельный инвентарь версий PHP. Трафик должен быть виден HTTP-анализатору Zeek; зашифрованный HTTP требует расшифровки перед проверкой.
Все типы уведомлений находятся в пространстве PHP2SHELL:::
| Уведомление | Наблюдение |
|---|---|
PHP_Crash_Sequence | Связанные подозрительные HTTP-транзакции в рамках одной сессии |
Multipart_Header_Flood | Чрезмерное повторение распознанных MIME-заголовков |
Large_Form_Key | Необычно длинное имя поля формы в URL-кодировке |
Serialized_Integer_Overflow | Необычно большой сериализованный целочисленный токен |
Serialized_Integer_Collisions | Распознанный шаблон сериализованного целочисленного ключа |
Serialized_String_Collisions | Распознанный шаблон сериализованного строкового ключа |
Serialized_Duplicate_Array | Повторяющийся шаблон сериализованной записи массива |
Serialized_Object_Repetition | Повторяющийся шаблон сериализованного объекта |
Potentially_Affected_PHP_Version | Заголовок ответа сообщает версию в пределах настроенного диапазона затронутых версий |
Результаты записываются в стандартный notice.log; пакет не создаёт дополнительный
поток журнала. Поле sub уведомления предоставляет ограниченный контекст, такой как имя заголовка,
глубина транзакции, счётчики и короткий экранированный образец тела POST. Образцы по умолчанию
ограничены 64 необработанными байтами до экранирования; установите
notice_body_sample_bytes=0, чтобы их опустить. Cookie и их дайджесты используются
только в памяти и не записываются в журнал этим пакетом.
По умолчанию каждый отдельный индикатор запроса может порождать уведомление для каждой транзакции.
Повторные совпадения одного и того же индикатора подавляются. Установите detect_only_once=T,
чтобы прекратить проверку тела после первой находки в запросе в каждой транзакции.
Уведомления инвентаря версий не зависят от находок в запросах.
Все настройки используют пространство имён PHP2SHELL:::
| Настройка | По умолчанию | Эффект |
|---|---|---|
detect_only_once | F | Сообщать о каждом отдельном индикаторе запроса; T останавливается после первой находки |
max_trans_depth | 3 | Проверять первые три HTTP-транзакции на соединение; 0 означает все |
inspect_cookies | T | Использовать сессионные cookie для корреляции |
session_cookie_names | {"PHPSESSID"} | Имена cookie, используемые для связывания сессий |
correlation_window | 1 min | Максимальный возраст ожидающего состояния корреляции сессии |
max_pending_sessions | 1000 | Ограничение числа сохраняемых записей в каждой таблице корреляции |
inspect_post_bodies | T | Проверять данные сущности POST и MIME-заголовки |
http_body_analysis_byte_depth | 8388608 | Консервативный предел в 8 MiB на работу по проверке тела POST, общий для MIME-частей; 0 отключает доставку тела |
body_overlap_bytes | 256 | Сохраняемое перекрытие для шаблонов, пересекающих фрагменты тела |
large_form_key_bytes | 65536 | Порог длины имени формы в байтах на проводе |
multipart_header_threshold | 128 | Число повторяющихся распознанных MIME-заголовков, необходимое для находки |
notice_body_sample_bytes | 64 | Максимальное число необработанных байтов тела на образец уведомления; 0 опускает образцы |
detect_affected_php_versions | T | Включить инвентарь версий по заголовкам ответов |
php_version_notice_interval | 1 hr | Подавлять уведомления о версиях для каждого IP сервера по портам и версиям |
php_fixed_patch_versions | 8.2: 35, 8.3: 36, 8.4: 27, 8.5: 12 | Предварительный первый исправленный патч для каждой ветки |
Например:
redef PHP2SHELL::detect_only_once = T;
redef PHP2SHELL::notice_body_sample_bytes = 0;
redef PHP2SHELL::session_cookie_names += { "custom_session" };
POST-инспекция использует чанки анализа файлов с ограниченным перекрытием, а не сборку целых тел. Подсчёт имён форм учитывает разделители значений и необработанное завершение NUL. Только подходящие POST-сущности получают анализатор; бюджеты тел и лимиты транзакций намеренно ограничивают область обнаружения. Эти индикаторы неполны и также могут совпадать с доброкачественным трафиком.
В кластере Zeek воркеры направляют небольшие наблюдения сессий прокси с помощью
Cluster::publish_hrw(). Обе стадии для одной и той же сессии достигают одного и того же
прокси, который сопоставляет их и напрямую поднимает PHP_Crash_Sequence. Уведомление
сохраняет ID соединения, UID и глубину транзакции последующего запроса; peer_descr
идентифицирует прокси. Воркеры не сохраняют полные записи соединений или HTTP
для обратных вызовов.
Триггеры и несопоставленные последующие запросы истекают после correlation_window,
при этом max_pending_sessions ограничивает каждую таблицу. Прокси сохраняют первый несопоставленный
последующий запрос для каждого ключа сессии. Триггер ищет этот ключ напрямую, чтобы обрабатывать
сообщения, приходящие в обратном порядке; более поздние несопоставленные последующие запросы для того же
ключа объединяются, пока эта запись не будет сопоставлена или не истечёт. Сопоставление использует временные метки
наблюдений и клиента, сервера, порт сервера, HTTP-хост и дайджест сессии.
Автономный Zeek коррелирует локально. Требуется нормальная связность с прокси.
Уведомления прокси используют стандартное подавление уведомлений с ключом по UID и глубине транзакции
для correlation_window. Это не зависит от находок воркеров и
не останавливает инспекцию тел воркерами. Одновременные совпадения для разных
сессионных cookie на разных прокси всё ещё могут порождать дублирующиеся уведомления
до того, как распространится кластерное подавление.
Проверяются внешние заголовки ответа Server и X-Powered-By, включая
ответы на GET. Имена заголовков нечувствительны к регистру. Затронутая нижняя
граница — PHP 5.4.0. Следующие пороги предполагают, что следующий патч после
последних стабильных релизов, проверенных 18 октября 2026 года, устранит обе ошибки:
| Ветка | Последний стабильный на момент проверки | Предварительный первый исправленный релиз |
|---|---|---|
| 8.2 | 8.2.34 | 8.2.35 |
| 8.3 | 8.3.35 | 8.3.36 |
| 8.4 | 8.4.26 | 8.4.27 |
| 8.5 | 8.5.11 | 8.5.12 |
Настроенные исправленные релизы и более поздние патчи в той же ветке не вызывают оповещений. Ветки без настроенного порога остаются кандидатами. Распространённые суффиксы вендоров используют базовую числовую версию. Баннеры могут отсутствовать, быть переписаны или отражать сборку вендора с бэкпортированными исправлениями, поэтому это лишь подсказки для инвентаризации.
Три правила в
[suricata/php2shell.rules][rules]
работают независимо от Zeek. Установка пакета Zeek с помощью zkg не
загружает эти правила в Suricata. Все три правила включены в файл;
параметры конфигурации Zeek на них не влияют.