
Репозиторий для поиска уязвимых к PHP2Shell систем и связанного анализа
Охота за экспозицией в Defender XDR для PHP2Shell (CVE-2026-109618 / CVE-2026-109619).
v3.3 · 22 окт. 2026
Назначение: Найти подключённые устройства, на которых активно работает PHP и которые могут быть подвержены PHP2Shell.
Область охвата: Defender XDR Advanced Hunting · подключённые конечные точки Windows и Linux · по умолчанию окно поиска 30 дней · только активный PHP. Не охвачено: неактивные установки и неуправляемые устройства. Не может выполняться в Sentinel, поскольку таблица установленного ПО (TVM) доступна для запросов только в Defender XDR.
| Охота | Windows | Linux | Вопрос |
|---|---|---|---|
| 1 | windows/01-any-php.kql | linux/01-any-php.kql | Есть ли PHP? Да/нет для каждого устройства. |
| 2 | windows/02-evidence-breakout.kql | linux/02-evidence-breakout.kql | Детализация доказательств с версиями. |
| 3 | windows/03-safety-net.kql | linux/03-safety-net.kql | Страховочная сеть: устройства, обслуживающие веб-порты, прослушивающий процесс и статус PHP. |
Все проверки событий используют одно окно поиска, let Lookback = 30d; в начале каждой охоты. IP-адреса берутся из последнего отчёта по каждому адаптеру за последние 7 дней. Установленное ПО — это текущий снимок TVM. Проверяются только подключённые конечные точки (OnboardingStatus == "Onboarded", DeviceCategory == "Endpoint").
Устройство считается имеющим обнаруженный PHP, если совпадает любое из следующих условий.
Как сопоставляются имена:
^…$), поэтому оно должно совпадать с полным именем файла, а не с его частью.startswith "php", плюс frankenphp в обеих ОС и lsphp в Linux. Затем регулярное выражение выполняется только по оставшемуся.php9.dll) совпадают автоматически.patterns.test.js прогоняет каждое регулярное выражение по этим примерам. Если вы измените регулярное выражение, обновите примеры там.Windows
| Проверка | Таблица | Совпадения | Почему это важно |
|---|---|---|---|
| Запущенные исполняемые файлы PHP | DeviceProcessEvents | Регулярное выражение ^(php(-cgi|-win)?|frankenphp)\.exe$, которое допускает ровно четыре имени: php.exe (CLI), php-cgi.exe (FastCGI-воркер), php-win.exe (CLI, без консоли), frankenphp.exe (PHP, встроенный в веб-сервер). phpstorm64.exe и другие инструменты php* не совпадают | Доказывает, что PHP запускался. Охота 2 показывает версию из информации о версии бинарного файла (ProcessVersionInfoProductVersion) |
| Загруженные DLL движка PHP | DeviceImageLoadEvents | Регулярное выражение ^php\d*(ts|isapi|apache[\w_]*)?\.dll$: php, любой номер версии, необязательный суффикс ts / isapi / apache…, затем .dll. Примеры приведены в таблице DLL ниже. DLL расширений (php_curl.dll и другие php_*.dll) не совпадают, поскольку подчёркивание не допускается сразу после php | Единственный способ увидеть PHP, работающий внутри другого процесса, например IIS или Apache, где не запускается ни один php*.exe. Охота 2 показывает DLL и процесс, который её загрузил |
| Установленное ПО | DeviceTvmSoftwareInventory | Не регулярное выражение: SoftwareName has "php" (php как отдельное слово в имени) или SoftwareVendor =~ "php" (точное, нечувствительное к регистру) | Ловит зарегистрированные установки. Zip-установки (обычный метод в Windows) обычно не регистрируются |
Примеры DLL движка PHP, которые совпадают с шаблоном Windows
| DLL | Что это | Типичный хост-процесс (показан в hunt 2) |
|---|---|---|
php8.dll, php7.dll | Движок, сборка без поддержки потоков | php-cgi.exe (FastCGI под IIS, nginx или Apache mod_fcgid), php.exe |
php8ts.dll, php7ts.dll, php5ts.dll | Движок, потокобезопасная сборка | httpd.exe (модуль Apache), php.exe |
php8apache2_4.dll, php7apache2_4.dll, php5apache2_2.dll | Загрузчик модуля Apache | httpd.exe |
php5isapi.dll | Устаревший модуль IIS ISAPI (PHP 5.2 и более ранние, не поддерживается) | w3wp.exe |
В таблице перечислены распространённые имена, а не список разрешённых: подходит любое имя, соответствующее шаблону. Имя DLL даёт только мажорную версию. Точная версия берётся из строки процесса php-cgi.exe или php.exe либо из установленного программного обеспечения на том же устройстве.
Linux
| Проверка | Таблица | Совпадения | Почему это важно |
|---|---|---|---|
| Запущенные бинарники PHP | DeviceProcessEvents | Регулярное выражение ^(php[\d.]*|php-(fpm|cgi)[\d.]*|lsphp[\d.]*|frankenphp)$: php, php-fpm, php-cgi или lsphp (LiteSpeed), каждое с необязательной версией из цифр и точек, плюс frankenphp. Примеры: php, php8.3, php83, php-fpm8.3, php-cgi8.2, lsphp83. Такие инструменты, как phpunit, phpize и php-config, не совпадают, поскольку после базового имени могут следовать только цифры и точки | Доказывает, что PHP запускался. Hunt 2 показывает подсказку major.minor, извлечённую из имени, пути или командной строки вторым регулярным выражением, php-?(?:fpm|cgi)?/?(\d+\.\d+) (например, php-fpm8.3 или /etc/php/8.3/ даёт 8.3.x) |
| Установленные пакеты | DeviceTvmSoftwareInventory | Не регулярное выражение: SoftwareName contains "php" (подстрока, поэтому совпадают имена с версиями, такие как php8.3-fpm и libapache2-mod-php8.3) или SoftwareVendor =~ "php" | Единственная проверка для Apache mod_php и для php-fpm, работающего с момента до начала окна: в Linux здесь нет проверки загрузки библиотек, а форкнутые рабочие процессы php-fpm не создают событий запуска процессов |
| Проверка | Таблица | Совпадения | Почему это важно |
|---|---|---|---|
| Активное веб-обслуживание | DeviceNetworkEvents | InboundConnectionAccepted на фиксированном списке портов: 80, 443, 8080, 8443. Loopback исключён (RemoteIPType != "Loopback"). Показывает различные и публичные источники, а также принимающий процесс (via <process>) | Доказывает, что устройство обслуживает запросы, даже если его веб-сервер запустился до начала окна ретроспективного просмотра. ntoskrnl.exe = HTTP.sys (IIS, ADFS, RD Gateway, Windows Admin Center, SSTP) |
| Запущенный веб-сервер | DeviceProcessEvents | Не регулярное выражение: фиксированный список точных имён без учёта регистра (in~). Windows: w3wp.exe, httpd.exe, nginx.exe, caddy.exe, lighttpd.exe, frankenphp.exe. Linux: httpd, apache2, nginx, lshttpd, litespeed, openlitespeed, caddy, lighttpd, frankenphp | Веб-сервер, запустившийся в окне и не загрузивший PHP, даёт «Not seen» с высокой уверенностью. Windows также показывает имена пулов приложений IIS, извлечённые из командной строки w3wp.exe регулярным выражением -ap\s+"?([^"\s]+) |
Значения столбца PHP в hunt 3