Houndoom — сканер веб‑шеллов
Я довольно давно разбираю заражённые сайты. Обычно это чужой проект, к которому меня подключают после взлома: нужно проверить файлы, найти оставшиеся бэкдоры и понять, что придётся чистить.
Для этой работы я написал Houndoom — сканер веб-шеллов и бэкдоров на Go. Мне нужен был инструмент, который можно запустить на чужом сервере по SSH без установки зависимостей. Получить отчёт, разобрать находки, убрать сканер.
Go подошёл в первую очередь из-за сборки в один бинарник. На целевой машине не нужен PHP-интерпретатор для самого сканера или отдельный рантайм. Обход файлов выполняется параллельно через пул горутин. Сравнительных замеров с другими сканерами у меня пока нет.
Как запустить сканер веб-шеллов
Houndoom проверяет содержимое файлов: известные шеллы вроде r57 и c99, бэкдоры с eval и base64, инъекции, вредоносный JavaScript. Для WordPress и Bitrix есть отдельные детекторы, которые учитывают устройство CMS.
После сборки сканера проверку директории с сохранением HTML-отчёта можно запустить так:
houndoom scan /var/www/site --report=html --output=report.html
В отчёте у находки есть путь к файлу, строка, сработавшая сигнатура и фрагмент кода. По ним можно открыть исходник и проверить, почему сканер на него ругается.
Это тестовые сэмплы, поэтому по времени на скриншоте нельзя судить о скорости проверки большого сайта. И само срабатывание ещё нужно разобрать: подозрительная конструкция может оказаться обычным кодом плагина.
Проверка по SSH
Чтобы не копировать бинарник и отчёт руками, я добавил remote-scan. Сначала можно посмотреть план без подключения к серверу:
houndoom remote-scan --host user@host --path /var/www/site --plan
Та же команда без --plan запросит подтверждение и начнёт проверку:
houndoom remote-scan --host user@host --path /var/www/site
Сканер определяет архитектуру сервера, загружает подходящий бинарник во временный каталог и запускает его. JSON-отчёт забирает на локальную машину. В конце удаляет временный каталог; при ошибке тоже пытается выполнить очистку.
Файлы сайта сканер читает, автоматического лечения в этом режиме нет. Временные файлы на сервере всё же создаются, а SSH-подключение может попасть в системные логи.
Для подключения используются системные ssh и scp, поэтому работают настройки из ~/.ssh/config, в том числе ProxyJump. Аутентификация идёт через ssh-agent. Отчёт и журнал удалённых команд сохраняются локально в ~/.houndoom/engagements/.
Деобфускация
Вредоносный PHP часто прячут в слоях base64, gzinflate, str_rot13 и других преобразований. Пока эти слои не сняты, сигнатура может не увидеть код внутри.
В Houndoom декодирование написано на Go: сканер извлекает строки и применяет поддерживаемые преобразования. PHP из проверяемого файла при этом не запускается. Есть восемь деобфускаторов и ограничение рекурсии в 100 уровней. Отдельный файл можно разобрать командой:
houndoom deob suspicious.php
У исполнения кода при деобфускации уже были неприятные последствия. В ноябре 2025 Patchstack опубликовали разбор RCE в Ai-Bolit: деобфускатор вызывал PHP-функции, имена которых получал из подозрительного файла, без проверки допустимости этих функций. Уязвимость исправили в версии 32.7.4.0.
Статический разбор требует своей реализации для каждого поддерживаемого способа упаковки. Если сканер не смог снять обфускацию, считать файл безопасным на этом основании нельзя.
Проверки WordPress
Кроме содержимого файла, я учитываю его расположение. Например, PHP в wp-content/uploads/ заслуживает проверки: обычно WordPress хранит там загруженные картинки и документы. В детекторе это отдельное условие:
if d.uploadsPathRe.MatchString(lower) && file.Extension == "php" {
findings = append(findings, d.structureFinding(file, "WP-STRUCTURE-001",
"PHP File in Uploads Directory",
"PHP file found in wp-content/uploads/ - this directory should only contain media files",
"php_in_uploads", models.SeverityHigh, 1.5, 90))
}
Ещё одна проверка — auto_prepend_file в .user.ini. Через эту настройку можно подключить PHP-файл перед выполнением скриптов в области действия конфига. При разборе заражения нужно посмотреть, на какой файл она указывает и что в нём находится.
Отдельно проверяется wp-content/mu-plugins/. Плагины из этой папки загружаются автоматически. В админке они показаны в разделе Must-Use, но обычной кнопкой отключения воспользоваться нельзя. Поэтому чистка через отключение стандартных плагинов может оставить такой бэкдор работающим.
Ложные срабатывания
У плагинов безопасности есть собственные сигнатуры малвари. Если искать в них те же паттерны, можно получить отчёт о заражении самого антивируса.
Для известных security-плагинов я подавляю совпадения по WP-сигнатурам. В ядре WordPress и ряде известных плагинов подавление уже: убираются сигнатуры подозрительного использования API, которое в этом контексте нормально. Проверки бэкдоров и малвари для них остаются включёнными.
У такого решения есть цена. Принадлежность файла к известному плагину определяется по пути, а сам плагин тоже может быть взломан. Подавление уменьшает количество ложняков, но его нельзя использовать как подтверждение целостности файлов. При разборе заражения эту часть сайта всё равно нужно проверять.
Разбор через Claude
После сканирования находки можно передать Claude: получить объяснение кода и дополнительную оценку срабатывания. В локальном CLI это включается флагом --ai. Основной поиск работает без модели.
В этом режиме фрагменты исходников отправляются в Anthropic. Если клиент запрещает передачу кода внешним сервисам, --ai использовать нельзя. Для работы через Claude Code есть скилл /houndoom-scan, который запускает удалённую проверку и помогает разобрать отчёт. В его инструкциях содержимое файлов обозначено как недоверенные данные; проверять выводы модели всё равно приходится самому.
Houndoom я использую для разовой проверки файлов сайта. У проекта пока нет собственного фида угроз и опубликованной оценки качества обнаружения. Пустой отчёт не доказывает, что сайт чист, а найденный бэкдор ещё нужно связать с причиной взлома и устранить её.
Код и инструкция по запуску: github.com/IvanShishkin/houndoom.