- BrainTools - https://www.braintools.ru -

На синтетике 0 ложных эскалаций, на реальном потоке 39 из 100: как я делал локального L1-аналитика SOC

На моём тестовом наборе модель показывала 55 из 55 верных вердиктов и ни одной ложной эскалации. Потом я дал ей 100 реальных алертов с лабораторного стенда Wazuh. Она зря подняла на вторую линию 39 из них и к некоторым дописала инцидент, которого не было.

Этот разрыв определил всю дальнейшую работу. Ниже что я построил, какие цифры получил и чего эти цифры не доказывают. Код и веса открыты: GitHub [1], Hugging Face [2].

Задача

Первая линия SOC тонет в однотипных алертах, а облачные LLM часто нельзя использовать: логи не должны покидать периметр. Я хотел получить помощника, который работает на обычном ноутбуке с 8 ГБ видеопамяти, ничего не отправляет наружу и готовит для второй линии проверяемую карточку.

Название kezekshi по-казахски значит «дежурный». В основе дообученная Gemma 4 E2B под лицензией Apache 2.0.

На вход один алерт как пакет доказательств E1…En. На выход JSON: вердикт из четырёх классов, краткое описание, утверждения со ссылками на номера доказательств, техники MITRE ATT&CK, чего не хватает и что проверить дальше. Ссылки нужны, чтобы вывод модели можно было проверить кодом, а не верить ему на слово.

Что сработало на обучении

Трудные негативы полезнее новых типов атак. PowerShell -enc из агента SCCM, vssadmin create от бэкапа, скан Nessus по заявке, impossible travel через корпоративный VPN: поверхность выглядит как атака, но в пакете есть явный признак легитимности. Я добавил 14 таких кейсов, и набор негативов вырос с 8 до 22. Ложных эскалаций на нём осталось 0, а recall не просел.

Правило в промпте иногда дешевле дообучения. Рубрика тяжести поначалу уронила recall на незнакомых типах с 20/20 до 16/20: все четыре промаха это OAuth-согласие, прочитанное как штатное действие. Одно правило, что согласие приложению, выдача прав или новый метод MFA без подтверждения в пакете это минимум suspicious, вернуло 20/20 без видеокарты.

Режим размышления дообученной модели вредит. Рабочий режим без него.

Удар о реальный поток

Теневой прогон по реальным алертам стенда показал то, с чего я начал. На высокочастотных правилах, которых нет в синтетике (FIM реестра 751, 752, 750, rootcheck 510), модель завышала тяжесть и сочиняла нарратив.

Я сделал две вещи.

Первая: дообучил модель на 215 реальных benign-кейсах стенда. Замер на 100 отложенных алертах:

Версия

Совпадение вердикта

Лишние эскалации

v4, только синтетика

39/100

39/100

v5, плюс реальный шум

96/100

0/100

Вторая: перестал звать модель там, где исход от неё не зависит. Инъекции в логах и операционный шум из белого списка решаются детерминированно ещё до модели, причём контекст всё равно эскалирует: изменение в автозапуске или защитной службе из белого списка выпадает. На 3000 алертах стенда 98,1 % решилось без модели, 1,9 % ушло в неё. Это примерно в 50 раз меньше вызовов при тех же решениях об авто-закрытии.

Памятка правил страхует и саму модель. Пример из тестовых алертов в репозитории: на попытке входа по SSH под несуществующей учёткой v6 ответила false_positive, памятка сказала suspicious, и алерт ушёл человеку.

Схема ответа оказалась дешевле новой версии

Шестая версия выросла в обучении [3] до 3546 примеров и стала точнее на знакомых типах, но брак ответа вырос: на типах вне обучения 9 из 20 карточек не проходили проверку. Я посмотрел сырые ответы и увидел причину: в ссылке на доказательство модель писала имя поля ev1 вместо номера E1.

Вместо переобучения я стал собирать схему Ollama под каждый алерт. Разрешены только E-id этого алерта и кандидаты MITRE из локального индекса. Заодно нашлась ошибка [4] подбора: короткие триггеры искались как подстроки, и tor срабатывал на monitor.

Набор

Показатель

Было

Стало

Типы вне обучения (20)

брак ответа

9/20

0/20

Типы вне обучения (20)

MITRE, полнота

13/36

25/36

Типы вне обучения (20)

MITRE, точность

13/46

25/34

Типы вне обучения (20)

атаки подняты в L2

20/20

20/20

Знакомые типы (76)

брак ответа

12/76

1/76

Знакомые типы (76)

атаки подняты в L2

42/42

42/42

Знакомые типы (76)

ложные эскалации

0/34

1/34

Реальный шум (100)

совпадение вердикта

97/100

93/100

Реальный шум (100)

ложные эскалации

0/100

1/100

Плата видна в таблице: появились единичные лишние эскалации, а проверка ссылок стала формальной. Теперь номер всегда существует, но подходит ли он к утверждению, схема не гарантирует.

Подсказка меняет ответ

Самый неприятный результат этой серии. Когда в индексе появился кандидат T1555.004, более ранняя v5.1 начала писать про «массовый сбор учётных данных» о штатном чтении Credential Manager процессом Outlook. Список кандидатов работает как намёк на атаку.

Я добавил в промпт оговорку, что кандидаты подобраны по словам и атаку не означают. Recall на новых типах упал с 20/20 до 18/20: OAuth-согласие и IDOR закрылись как штатные. Оговорку я убрал. Для SOC лишняя эскалация дешевле пропущенной атаки, но это компромисс, а не решение.

Чего эти цифры не доказывают

  • Recall на реальных атаках не измерен. В реальном наборе только шум. 20/20 получено на пяти семействах атак, этого мало.

  • Часть кейсов почти совпадает с обучением. 30 из 76 знакомых и 63 из 100 реальных совпадают с точностью до цифр. Вне этих совпадений вердикт на прежней схеме был 44/46 и 34/37.

  • Реальный шум не проверяет хвост. Почти весь такой поток закрывает белый список, а строка про 100 алертов описывает модель без него.

  • Эталон реального шума это суждение одного аналитика, а не решения дежурной смены.

Поэтому контур работает в режиме assist: сам закрывает только детерминированный шум, всё, что дошло до модели, смотрит человек. Как разгрузка от шума и черновик карточки он полезен. Как автономный решатель эскалаций не проверен.

Что открыто

В репозитории [1] код контура поверх Wazuh (только чтение), схема ответа, индекс ATT&CK, скрипты обучения и оценки, руководство оператора. Веса v6 [2] лежат на Hugging Face: GGUF на 4,9 ГБ, который ставится в Ollama одной командой.

Датасета нет, и это осознанно: обучающий набор опирается на материалы учебного курса и на алерты закрытого стенда. Модель можно запустить на своих алертах, но метрики из статьи из открытых файлов не воспроизвести. Как собрать свой набор, описано в docs/dataset.md.

Перед публикацией весов я проверил, не выдаёт ли модель имена машин стенда. Во входах обучения они есть, в ответах нет, а ошибка считается только по ответу. За 306 попыток имена не появились, как и синтетическое имя, которое стояло в 144 ответах из обучения. Риск это снижает, но запоминание [5] полностью не исключает.

Дальше

Следующий шаг это управляемые атаки на стенде и разбор их дежурным: только так появится настоящий recall контура. Скрипт для этого уже есть, eval/recall_eval.py.

Если вы работаете в SOC или MSSP, мне интересно другое: какая доля потока у вас реально решается памяткой и где такой контур сломается первым. Напишите в комментариях.

Автор: ipgleg

Источник [6]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/38125

URLs in this post:

[1] GitHub: https://github.com/oleg-vdv/kezekshi-l1

[2] Hugging Face: https://huggingface.co/oleg-vdv/kezekshi-l1

[3] обучении: http://www.braintools.ru/article/5125

[4] ошибка: http://www.braintools.ru/article/4192

[5] запоминание: http://www.braintools.ru/article/722

[6] Источник: https://habr.com/ru/articles/1104570/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1104570

www.BrainTools.ru

Rambler's Top100