Почему автоматизация багхантинга упирается в триаж
ИИ-агенты генерируют сотни находок за прогон. Проблема в том, что 80-90% из них - ложные срабатывания. Без фильтрации ручной триаж превращается в бесконечный просмотр мусора. Автоматизация сместила узкое место: раньше мы тратили время на поиск уязвимостей, теперь - на проверку того, что нашёл агент.
Решение - трёхслойная система верификации, которая отсеивает ложные срабатывания на каждом этапе. Плюс пайплайн из двух агентов: один ищет кандидатов (recall), второй критически проверяет (precision). Разделение ролей предотвращает confirmation bias - ситуацию, когда агент подтверждает собственные находки просто потому, что сам их сгенерировал.
В материале разберу архитектуру, которую собрал на основе 16,5 тыс. записей из writeup'ов и disclosed-репортов, жёстких правил и MCP-инструментов для активной проверки гипотез. Без воды - только цифры, примеры и конфигурация.
Архитектура трёхслойной верификации: отсев на каждом этапе
Система построена на последовательной фильтрации. Каждый слой решает свою задачу: быстрый отсев очевидного мусора, контекстная проверка по базе знаний, активное тестирование. Слои идут по нарастанию стоимости проверки - дёшево отбрасываем на первом шаге, дорого проверяем только то, что прошло первые два.
Слой 1: Жёсткие правила - быстрый фильтр для агента
Первый слой - детерминированные правила, которые отсекают очевидный мусор за миллисекунды. Никакого ML, только проверки на уровне кода.
Какие правила работают:
- Исключение известных ложных паттернов. Например, агент любит находить «XSS» на страницах, где пользовательский ввод вообще не попадает в HTML. Правило проверяет, есть ли в ответе сервера отражение входных данных - если нет, находка отбрасывается.
- Валидация форматов ответа. Агент сообщил об SQL-инъекции, но не привёл валидный payload? В мусор. Нашёл открытый S3-бакет, но URL не резолвится? В мусор.
- Базовые эвристики. Если агент утверждает, что нашёл RCE на форме обратной связи, а в ответе сервера нет признаков выполнения команд - отбрасываем.
Правила жёсткие и негибкие. Они не поймут новый тип уязвимости, но отсекут 40-50% мусора на входе. Для сложных случаев - следующие слои.
Слой 2: RAG-база знаний - контекстная проверка по 16,5 тыс. записей
Второй слой - retrieval-augmented generation на основе базы из 16,5 тыс. записей. В неё вошли публичные writeup'ы с HackerOne, Bugcrowd, disclosed-репорты из открытых программ и собственные находки команды.
Как это работает:
- Precision-агент получает кандидата от recall-агента - например, предполагаемую SQL-инъекцию в параметре
user_id. - RAG-модуль извлекает из базы топ-10 наиболее похожих кейсов: тот же тип уязвимости, похожий контекст (веб-приложение, PHP, MySQL), аналогичный вектор атаки.
- Агент сравнивает находку с эталонными примерами. Если кандидат структурно не похож ни на один подтверждённый кейс - вероятность ложного срабатывания высокая.
Пример: агент нашёл «SQL-инъекцию» в параметре, который всегда передаётся как целое число и преобразуется в int на стороне сервера. RAG находит десятки кейсов, где SQL-инъекции происходили в строковых параметрах без экранирования, и ни одного - в целочисленных с приведением типов. Вердикт: ложное срабатывание.
Ограничения слоя: база должна покрывать типы уязвимостей, которые вы ищете. Если вы охотитесь за специфическими багами в Kubernetes, а база состоит из отчётов по веб-уязвимостям - RAG не поможет. Качество проверки прямо зависит от релевантности и актуальности данных.
Слой 3: MCP-инструменты - активная проверка гипотез
Третий слой - самый ресурсоёмкий и самый точный. MCP-инструменты (Model Context Protocol) выполняют активные действия для подтверждения или опровержения уязвимости.
Три ключевых инструмента в арсенале:
- OOB-взаимодействие (out-of-band). Для проверки blind-уязвимостей - XXE, SSRF, blind SQL-инъекций. Агент внедряет payload, который инициирует запрос на подконтрольный сервер. Если callback пришёл - уязвимость подтверждена. Нет callback'а - кандидат отправляется в мусор. Инструмент незаменим для случаев, когда результат атаки не виден в ответе сервера.
- Headless-браузер. Для клиентских атак - XSS, CSRF, DOM-based уязвимости. Браузер открывает страницу с внедрённым payload'ом и проверяет, выполнился ли скрипт, появилось ли всплывающее окно, изменился ли DOM. Без этого инструмента агенты массово генерируют ложные XSS - payload вставился в HTML, но не выполнился из-за CSP или санитайзеров.
- Nuclei. Автоматическое сканирование по шаблонам. Если агент нашёл потенциально уязвимый эндпоинт, Nuclei прогоняет по нему готовые тесты. Шаблоны покрывают тысячи известных уязвимостей - от exposed .git до CVE в конкретных версиях фреймворков.
Пример из практики: recall-агент сообщил о SSRF в эндпоинте загрузки изображений. Первый слой пропустил - URL валидный, формат ответа корректный. Второй слой нашёл похожие кейсы в базе - SSRF через загрузку аватаров действительно встречается. Третий слой сделал запрос через OOB-сервер: payload сработал, callback пришёл. Уязвимость подтверждена.
Этот слой потребляет больше всего времени и ресурсов, но даёт наивысшую точность. Мы запускаем его только для кандидатов, прошедших первые два фильтра - обычно это 5-10% от исходного потока.
Пайплайн из двух агентов: разделение recall и precision
Ключевая архитектурная идея - не пытаться сделать одного агента, который ищет и проверяет одновременно. Это прямой путь к confirmation bias. Вместо этого мы разделили роли.
Recall-агент: максимизация покрытия
Первый агент настроен на полноту (recall). Его задача - найти как можно больше кандидатов, даже ценой большого количества ложных срабатываний.
Конфигурация recall-агента:
- Широкие правила сканирования - все эндпоинты, все параметры, все HTTP-методы.
- Минимум ограничений в промпте - агент не фильтрует находки, а сообщает обо всём подозрительном.
- Температура выше среднего - для генерации разнообразных гипотез.
На выходе получаем поток из сотен кандидатов, где 80-90% - шум. Это нормально. Вся фильтрация - задача precision-агента.
Precision-агент: критическая верификация
Второй агент получает кандидата и не знает, откуда тот взялся. Он оценивает находку непредвзято, используя все три слоя верификации.
Логика работы precision-агента:
- Получить кандидата от recall-агента.
- Прогнать через жёсткие правила - отсечь очевидный мусор.
- Запросить RAG-базу - найти похожие подтверждённые кейсы.
- Если кандидат проходит первые два слоя - запустить MCP-инструменты для активной проверки.
- Сформировать вердикт: подтверждено / ложное срабатывание / требуется ручная проверка.
Предотвращение confirmation bias достигается за счёт изоляции: precision-агент не видит цепочку рассуждений recall-агента. Он получает сухой факт - «в параметре X обнаружена потенциальная SQL-инъекция» - и проверяет его с нуля. На практике это означает, что precision-агент может отклонить находку, которую recall-агент посчитал перспективной, если RAG не находит аналогов, а MCP-тест не даёт подтверждения.
Результат разделения ролей: количество ложных срабатываний, доходящих до человека, сократилось примерно в 8-10 раз. Точные цифры зависят от целевого приложения, но порядок именно такой.
Этот подход перекликается с общим инженерным паттерном верификации в LLM-агентах, который мы разбирали на примере биомедицинских проектов с хакатона Anthropic: генеративная модель работает в связке с контуром проверки, и верификацию стоит закладывать в архитектуру сразу.
Практические результаты и ограничения подхода
После внедрения пайплайна время ручного триажа сократилось с нескольких часов до 20-30 минут на прогон. Количество находок, требующих внимания человека, упало с 200-300 до 15-25, из которых 5-10 действительно подтверждались.
Реальный кейс: тестирование веб-приложения на 50 эндпоинтов. До внедрения:
- Recall-агент генерировал 247 находок за прогон.
- Ручная проверка занимала 4-5 часов.
- Подтверждённых уязвимостей: 3-4.
После внедрения трёхслойной верификации и разделения агентов:
- Первый слой отсеял 120 находок - невалидные URL, отсутствие отражения в ответе, синтаксические ошибки в payload'ах.
- Второй слой отсеял ещё 90 - RAG не нашёл похожих подтверждённых кейсов.
- Третий слой проверил оставшиеся 37 кандидатов: 29 отброшены (нет callback'а, скрипт не выполнился, nuclei не подтвердил), 8 подтверждены.
- Ручная проверка: 15 минут на верификацию 8 находок, 7 подтверждены.
Ограничения, о которых нужно знать:
- Зависимость от базы знаний. RAG-слой бесполезен, если вы ищете уязвимости в новых технологиях, по которым ещё нет публичных отчётов. Базу нужно постоянно пополнять.
- Ресурсоёмкость MCP-инструментов. OOB-сервер должен быть доступен 24/7, headless-браузер потребляет CPU, nuclei требует актуальных шаблонов. Для небольших команд это может быть барьером.
- Пропуск новых типов уязвимостей. Жёсткие правила по определению не ловят то, чего не видели раньше. RAG не поможет, если атака принципиально новая. Система хорошо отсеивает шум, но не гарантирует, что не пропустит zero-day.
- Недетерминированность LLM. Оба агента работают на языковых моделях, и их поведение может меняться от прогона к прогону. Мы используем метрику pass@k для оценки стабильности - аналогично подходу Motorway и AWS, который мы детально разбирали в отдельном материале.
Система не идеальна. Она не заменит опытного пентестера и не найдёт сложные логические уязвимости, требующие понимания бизнес-логики. Но она решает конкретную проблему - лавину ложных срабатываний, которая хоронит автоматизацию багхантинга.
Как внедрить такой пайплайн в свой процесс багхантинга
Внедрение итеративное. Не пытайтесь собрать все три слоя сразу - начните с первого и наращивайте по мере роста потока находок.
Шаг 1: Жёсткие правила. Соберите статистику по ложным срабатываниям за неделю. Выпишите топ-10 паттернов, которые повторяются чаще всего. Напишите под каждый детерминированную проверку. Это даст быстрый выигрыш - 30-40% мусора уйдёт сразу.
Шаг 2: База знаний. Начните собирать writeup'ы и disclosed-репорты по вашим целевым технологиям. Для веб-приложений это тысячи отчётов с HackerOne. Для мобильных приложений - меньше, но достаточно для старта. Векторизуйте тексты, настройте retrieval по косинусному сходству. Не гонитесь за объёмом - 2-3 тыс. релевантных записей дадут заметный эффект.
Шаг 3: MCP-инструменты. Подключите OOB-сервер (подойдёт interactsh из комплекта nuclei), headless-браузер (Playwright или Puppeteer), nuclei с базовым набором шаблонов. Интегрируйте через MCP - это даст агенту стандартизированный интерфейс для вызова инструментов.
Шаг 4: Разделение агентов. Настройте recall-агента на полноту - температура 0.8-0.9, минимум ограничений в промпте. Precision-агента - на точность: температура 0.1-0.2, строгие критерии подтверждения. Изолируйте их контексты.
Предостережения:
- Не экономьте на мониторинге. Логируйте решения на каждом слое - без этого вы не поймёте, где система ошибается.
- Пайплайн можно кастомизировать под типы уязвимостей. Для XSS критичен headless-браузер, для IDOR - RAG-база, для blind-инъекций - OOB-сервер. Не включайте все инструменты для каждой находки - это расточительно.
- Периодически аудируйте отклонённые находки вручную. Выборочная проверка 5-10% отбракованных кандидатов покажет, не зарезала ли система что-то важное.
Тема автоматизации багхантинга через ИИ-агентов активно развивается. Показателен кейс, который мы разбирали ранее: агент, созданный для разработки, не выполнил ни одной боевой задачи, но стал незаменимым инструментом для аналитиков. Вывод универсален - начинайте внедрение с режима «спроси про систему», а не «сделай за меня». В случае с багхантингом это означает: сначала постройте верификацию, потом подключайте поиск.