Привет, Хабр! Меня зовут Даниил Лопаткин, я ML-инженер в группе машинного обучения Positive Technologies. Расскажу, как в PT Application Firewall Cloud работает обнаружение аномалий в профиле трафика и зачем мы его сделали.

Межсетевой экран уровня веб-приложений (WAF) записывает каждое срабатывание правила защиты. У крупного клиента за сутки набираются десятки и сотни тысяч таких событий. Большая часть из них — привычный фон: боты, сканеры, перебор типовых путей, превышения лимита запросов. Следит за ними обычно небольшая команда центра мониторинга безопасности (SOC), и отвечает она сразу за много приложений. Просматривать события безопасности каждого вручную она не успевает. Начало целенаправленного сканирования или эксплуатация недавно опубликованной уязвимости теряются среди остальных событий, и их замечают с опозданием.

Задача и польза

Мы хотели, чтобы система сама сообщала специалистам SOC о моментах, когда картина атак на приложения клиента заметно изменилась, и сразу давала материал для разбора. Отдельные события клиент по-прежнему смотрит в интерфейсе продукта. Уведомление приходит, когда меняется соотношение правил, которые срабатывают на его трафике.

Система сравнивает текущий трафик с привычным для конкретного клиента и отсылает оповещение только при существенном отличии. Почасовая проверка сообщает о всплеске в пределах пары часов, суточная обнаруживает медленные сдвиги, которых за час не видно. В письме уже есть всё для начала разбора: объём событий по сравнению с обычным, пять ведущих правил сейчас и раньше, число уникальных векторов атаки и ссылки в события PT AF за нужный период. Писем немного: в среднем одно в неделю на клиента.

Обычно уведомление приходит в одной из таких ситуаций:

  1. Началось сканирование или фаззинг. В топ резко выходит правило обхода каталогов или внедрения кода, причём с сотнями разных полезных нагрузок.

  2. Кто-то эксплуатирует опубликованную уязвимость. Появляются срабатывания правил для конкретной CVE.

  3. Изменилось само приложение. После релиза на легитимные запросы начинает срабатывать правило, которого раньше в событиях приложения не было. Это тоже повод проверить настройки защиты.

Объём событий и характер трафика

Самый простой детектор — порог на количество событий: «если за час срабатываний втрое больше обычного, сообщить». С ним две проблемы.

Объём трафика сам по себе колеблется: по времени суток, по дням недели, из-за рекламных кампаний. Порог, подобранный для одного клиента, у другого даёт либо поток ложных тревог, либо вовсе не срабатывает.

Кроме того, по объёму не понять, что за трафик пришёл. Атака может начаться на фоне спада легитимной нагрузки, и общее число событий не вырастет. Бывает и наоборот: событий стало вдвое больше, соотношение правил прежнее, и это просто вырос трафик.

Так было у одного из клиентов в начале июня. В 10:00 объём событий почти не изменился: 5 332 против 5 025 в среднем за предыдущие часы, рост на 6 %. Порог по числу событий такой час пропустил бы, хотя в это время на приложение шла атака. Объём вырос только в 11:00, более чем вдвое. Суточным ростом нагрузки это не объясняется: остальные правила весь день давали 3–6 тысяч событий в час, как и в предыдущие четыре дня, и весь прирост пришёлся на SQL-инъекции.

Рисунок 1
Рисунок 1. Число событий тенанта из примера по часам: правило SQL injection и остальные правила. Красным отмечены часы, которые детектор профиля счёл аномальными.

Поэтому мы смотрим на состав событий: какие правила срабатывают и в какой пропорции. На рисунке 2 те же часы показаны по составу: вверху доли трёх ведущих правил, внизу расстояние между профилем часа и базовым профилем (как оно считается, объясню дальше).

До 10:00 картина ровная: почти все события дают ошибки заголовка Accept-Encoding и боты. В 10:00 появляются SQL-инъекции, и расстояние резко растёт, хотя объём в этот час почти прежний. Детектор отмечает аномалии в 10:00 и 11:00. Потом атака продолжается, но к этому времени она уже попала в базовый период, и детектор не повторяет одно и то же каждый час. В 17:00 атака на час прерывается. Профиль резко меняется в обратную сторону, и детектор отмечает и это.

Рисунок 2
Рисунок 2. Профиль трафика тенанта из примера и расстояние до базового профиля по часам.

Профиль трафика тенанта

Каждый клиент PT AF Cloud — это тенант, отдельное пространство со своими приложениями и настройками. Для каждого тенанта и каждого периода (часа или суток) мы строим профиль: распределение событий по правилам защиты. Доля правила — это число его срабатываний, делённое на все события тенанта за период. Благодаря долям профили клиентов с разным объёмом трафика можно сравнивать напрямую.

Вот профили базового периода и часа из примера:

Правило

Базовый период

Час атаки

SQL injection

—

28 %

Invalid Accept-Encoding

50 %

29 %

Automated bot User-Agent

26 %

24 %

Server-side request forgery (SSRF)

9 %

7 %

Duplicate Request Header

8 %

3 %

Остальные правила

7 %

9 %

Привычные правила никуда не делись, но почти треть событий теперь даёт правило, которого раньше в топе не было.

Базовый период складывается из нескольких предыдущих периодов, в которых у тенанта были события. Профили этих периодов усредняются с весами по числу событий. Иначе час с десятком событий влиял бы на базовый профиль так же, как час с десятью тысячами.

Мера изменения: расстояние Йенсена — Шеннона

Два профиля надо как-то сравнить. Мы используем расстояние Йенсена — Шеннона (Jensen–Shannon distance, JSD). Для текущего профиля P и базового Q:

M = \frac{1}{2}(P + Q), \qquad \mathrm{JSD}(P, Q) = \sqrt{\frac{1}{2} D_{\mathrm{KL}}(P \parallel M) + \frac{1}{2} D_{\mathrm{KL}}(Q \parallel M)},

Расхождение Кульбака — Лейблера в формуле вычисляется с логарифмом по основанию 2.

Расстояние лежит между 0 и 1. Ноль означает, что профили совпадают, единица — что у них нет ни одного общего правила. Поэтому порог имеет один и тот же смысл для любого клиента. Мера симметрична: исчезновение привычного правила и появление нового дают одинаковый вклад. Если все правила выросли в одной пропорции, расстояние останется нулевым, поэтому рост трафика тревоги не вызывает.

Есть и практическая причина. Расхождение Кульбака — Лейблера между текущим и базовым профилем уходит в бесконечность, как только срабатывает правило, которого в базе не было. А именно такие случаи нам и интересны. Йенсен — Шеннон сравнивает оба профиля со средним M, и новое правило даёт конечный вклад: чем больше его доля, тем ближе расстояние к единице. На рисунке 2 час атаки хорошо выделяется на фоне соседних.

Когда изменение считается аномалией

Большое расстояние само по себе ещё не аномалия. У некоторых тенантов трафик небольшой и разнообразный, и профиль заметно меняется от часа к часу. Пример такого тенанта показан на рисунке 3. С одним фиксированным порогом такие клиенты получали бы письма постоянно.

Поэтому период считается аномальным, только если выполнены два условия сразу:

  1. JSD выше заданного порога, то есть изменение заметно само по себе.

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

z = \frac{\mathrm{JSD}t - \overline{\mathrm{JSD}}}{\sigma{\mathrm{JSD}}}.

Первое условие защищает от мелких колебаний у стабильных клиентов. У них стандартное отклонение маленькое, и даже незначительный сдвиг формально даёт большую z-оценку. Второе защищает от «шумных» клиентов: если профиль тенанта и так каждый час заметно меняется, очередной сдвиг того же масштаба тревоги не вызовет.

На рисунке 3 сверху тенант с небольшим трафиком, около 140 событий в час. Медианное расстояние до базового профиля у него 0,62, и с одним фиксированным порогом письма приходили бы почти каждый час. Но для этого тенанта такой уровень обычен, z-оценка остаётся небольшой, и за трое суток детектор не отметил ни одного часа. Снизу тенант с ровным профилем, у которого медианное расстояние 0,13. Утром 25 сентября расстояние выросло до 0,62, и детектор отметил этот час. Ещё три часа оно оставалось повышенным, но всплеск уже вошёл в историю тенанта, z-оценка снизилась, и повторных уведомлений не было.

Рисунок 3
Рисунок 3. Расстояние до базового профиля по часам у тенанта с шумным профилем и у тенанта со стабильным профилем.

Есть и ограничение для «холодных» клиентов: z-оценка не считается, пока у тенанта не накопится история, так что новый клиент начинает получать уведомления после короткого периода наблюдения.

Частота проверки

Детектор работает в двух режимах, и у каждого свои длина базового периода, глубина истории, минимум событий и пороги.

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

Суточный режим считает профиль за сутки по московскому времени и сравнивает его с несколькими предыдущими сутками. Он видит изменения, которые распределены по суткам и ни в одном отдельном часе не выделяются, например постепенный рост доли одного типа атак. Базового периода в несколько суток хватает, чтобы сгладить разницу между буднями и выходными.

Что получает клиент

Вернёмся к случаю из примера. По часу 10:00 клиент получил такое письмо:

Рисунок 4
Рисунок 4. Уведомление по случаю из примера.

Это информативный и понятный способ визуализации, но мы работаем над новыми UI-инструментами и более удобными способами доставки информации для пользователей.

В шапке письма указаны период, режим проверки и число событий по сравнению со средним за базовый период. Ниже идут две таблицы с ведущими правилами: за текущий период и за базовый. Ссылки «открыть в PT AF» ведут в веб-UI на события тенанта за оба периода, так что разбор можно начать прямо из письма. В конце перечислены возможные причины и рекомендуемые действия.

Из таблиц видно, что профиль событий изменился сильно. Правило SQL injection, которого в базовом периоде не было среди ведущих, вышло на второе место с долей 28 %. Все 1 490 его срабатываний пришли с одного IP-адреса и содержали 1 041 уникальный вектор атаки.

Больше всего говорит столбец «Уникальные вектора атак». Это число разных значений, на которые сработало правило: параметров, заголовков, фрагментов тела запроса. Вместе с числом событий и IP-адресов он помогает понять, что происходит:

Картина

Вероятное объяснение

Много событий, мало IP-адресов, сотни уникальных векторов

Сканер или фаззер перебирает полезные нагрузки

Много событий, много IP-адресов, один-два вектора

Массовая эксплуатация конкретной уязвимости или распределённый бот

Много событий, много IP-адресов, одно значение, совпадающее с легитимным параметром

Вероятно ложное срабатывание после изменения приложения

Случай из примера соответствует первой строке: один IP-адрес и 1 041 вектор, то есть работал сканер, который автоматически перебирал полезные нагрузки. Эксперт, который разбирал это уведомление, нашёл в запросах классические приёмы эксплуатации SQL-инъекций.

Сколько это в цифрах

Возьмём данные работы в проде за сентябрь 2026 года.

Показатель

Значение

Событий межсетевого экрана за четыре недели

Десятки миллионов в сутки

Событий в сутки у типичного тенанта (медиана)

около 2 300

Событий в сутки у крупных тенантов (90-й перцентиль)

около 90 000

Аномалий, выявленных PT AF Cloud, за четыре недели

около 1 100 (около 40 в сутки)

На одного клиента выходит примерно одно уведомление в неделю. Половина тенантов, которым письма приходили, получала не больше одного в неделю, девять из десяти — не больше трёх-четырёх. Треть тенантов за четыре недели не получила ни одного письма: их профиль не менялся.

У типичного тенанта около 16 тысяч событий в неделю сводятся к одному письму, где уже указано, какие правила изменили картину и где смотреть в интерфейсе AF. Команда SOC, которая ведёт десятки приложений нескольких клиентов, получает несколько таких писем в неделю.

Насколько полезны уведомления

Мало знать, сколько писем приходит. Надо понимать, сколько из них стоят внимания. Эксперты по защите веб-приложений вручную разобрали 519 уведомлений, отправленных 141 тенанту за две недели, с 31 мая по 14 июня 2026 года, и прокомментировали каждое. По их комментариям мы разделили уведомления на атаки, ошибки настройки защиты (например, правило срабатывает на легитимный трафик) и шум.

Рисунок 5. Классы отправленных уведомлений по комментариям экспертов.
Рисунок 5. Классы отправленных уведомлений по комментариям экспертов.

Об атаке или ошибке настройки сообщают 360 из 519 писем (69 %), и по ним специалисту есть что делать. Полезные изменения до клиента доходят почти все: из 371 найденной детектором аномалии, которую эксперты отнесли к атакам или ошибкам настройки, отправлено 360, то есть 97 %.

Шумом эксперт называл изменения, после которых делать нечего. Например, атака закончилась: объём упал, а правило, которое раньше доминировало, ушло из топа. Или выросла доля ботов либо ложных срабатываний, скажем правила SSRF на легитимные заголовки, но признаков эксплуатации нет. Или доли привычных правил перераспределились при умеренном росте трафика без новых атакующих правил.

Отдельно посмотрели, как менялся объём при атаках. Каждая шестая атака (44 из 275) пришла на фоне снижения общего числа событий, почти треть (79) — при росте меньше чем в полтора раза. Детектор, который следит только за объёмом, их бы не заметил.

Как это устроено внутри

Профили всех тенантов пересчитываются каждый час, и вычислительных ресурсов самого PT AF Cloud для этого недостаточно. Поэтому события безопасности выгружаются в хранилище данных Security Lakehouse, а обе проверки запускаются по расписанию в Apache Airflow и выполняются на ресурсах хранилища.

Рисунок 6. Упрощённая схема решения.
Рисунок 6. Упрощённая схема решения.

Cуточный режим строит профили по промежуточной таблице суточных агрегатов, почасовой берёт события за последние часы напрямую.

Обнаружение и отправку мы разделили на две задачи. Детектор сохраняет готовый пакет уведомлений, а рассылает его отдельная задача. Если сервис уведомлений временно недоступен, Airflow повторяет только отправку и не пересчитывает профили. Чтобы повтор не дублировал письма, для каждого уведомления отдельно отмечается доставка клиенту и во внутренний канал, и при перезапуске уходит только то, что ещё не ушло. Все найденные аномалии с метриками пишутся в отдельную таблицу, по ней мы оцениваем качество детектора и подбираем пороги.

Итоги

Из десятков миллионов событий в сутки детектор выявляет около сорока аномалий на всё облако, в среднем одну в неделю на клиента. Около 70 % уведомлений, по комментариям экспертов, сообщают об атаке или ошибке настройки. Почти треть атак при этом не меняет объём трафика заметно, и без сравнения профилей пользователи бы их пропускали.

Если такие проекты интересны, следить за новостями ML и ИИ можно в канале ML-команды PT — False Positive.

Попробовать PT AF Cloud можно на открытом стенде: https://demo.ptcloud.ru/

Комментарии (0)