Любой SOC рано или поздно упирается в одну и ту же проблему: правила обнаружения написаны под конкретный SIEM, живут в его интерфейсе и умирают вместе с ним. Сменил Splunk на Elastic, перешёл на другую платформу, и половина накопленной экспертизы пропала. Sigma решает это так же, как Snort-правила в своё время решили задачу для сетевых IDS: один описательный формат, который потом транслируется в запросы под нужную систему.

В этой статье мы разберём, как писать Sigma-правила, которые реально работают, а не просто красиво выглядят в репозитории. Примеры привязаны к лабораторной сети: домен itpages.lab.local, подсеть 192.168.10.0/24, SIEM на srv-siem01, контроллер домена srv-dc01, веб-сервер srv-web01. Мы говорим об обнаружении: описываем тактики MITRE ATT&CK и признаки в логах, но не способы проведения атак.

Что такое Sigma и зачем она нужна

Sigma это YAML-файл, описывающий что искать в логах, а не как это искать в конкретной системе. В файле есть метаданные (кто автор, какая тактика ATT&CK, насколько правило шумное), источник логов (категория, продукт, сервис) и блок detection с условиями. Конвертер (sigma-cli с backend-ами под нужные платформы) превращает всё это в запрос под Splunk, Elastic, Microsoft Sentinel и другие системы.

Практическая польза для небольшой команды очевидна: правила хранятся в git, проходят ревью, версионируются и не привязаны к вендору. Для тебя это ещё и способ документировать, зачем вообще нужно каждое обнаружение.

Шаги

Шаг 1. Начни с гипотезы, а не с синтаксиса

Самая частая причина плохих правил: автор сначала открывает редактор, а потом думает. Правильный порядок обратный. Сформулируй одну фразу: какое поведение защитника должно насторожить и в каком логе оно оставляет след. Например: на сервере srv-web01 процесс веб-сервера не должен порождать интерпретатор командной строки. Это поведенческий признак, он относится к тактике Execution и хорошо виден в логах создания процессов (Sysmon Event ID 1 или Security 4688 с включённым аудитом командной строки).

Проверь, что нужный лог вообще собирается. Если Sysmon не стоит на srv-web01 или события не доезжают до srv-siem01, правило бесполезно, как бы красиво оно ни было написано. Источник данных первичен.

Шаг 2. Скелет правила

Минимальный набор полей, который стоит заполнять всегда:

title: Web Server Process Spawning Command Interpreter
id: 5d1c2a40-8b7e-4c55-9f3a-0a6b1e7d2c11
status: experimental
description: Процесс веб-сервера порождает cmd или powershell. Для штатной работы сайта это нетипично.
author: IT-Pages Blue Team
date: 2026/10/13
references:
  - https://attack.mitre.org/tactics/TA0002/
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\w3wp.exe'
      - '\httpd.exe'
      - '\nginx.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
  condition: selection_parent and selection_child
falsepositives:
  - Плановые скрипты обслуживания, запускаемые из пула приложений
level: high
tags:
  - attack.execution
  - attack.t1059

Обрати внимание на несколько деталей. Поле id это UUID, он нужен, чтобы правило можно было однозначно отслеживать при переименованиях. Статус experimental честно говорит, что правило ещё не обкатано. В tags лежит привязка к тактике и технике ATT&CK: это позволит потом строить карту покрытия.

Шаг 3. Модификаторы и логика условий

Сила Sigma в модификаторах после имени поля: |contains, |startswith, |endswith, |re, |all, |cidr. Они делают правило читаемым и переносимым. Пара полезных приёмов.

Первый: список значений внутри одного поля означает ИЛИ, а несколько полей внутри одного блока означают И. Второй: блоки комбинируются в condition через and, or, not, а также через 1 of selection_* и all of selection_*. Третий: исключения оформляй отдельным блоком filter и подключай через not filter, так видно, что именно ты считаешь легитимным и почему.

Пример правила на аномальную аутентификацию с использованием сети лаборатории. Логи с srv-dc01, событие 4625 (неуспешный вход):

title: Multiple Failed Logons From Single Internal Host
id: a3f9e0b2-14c7-4d1a-8e21-7c5b90d3f6aa
status: experimental
description: Серия неуспешных входов с одного адреса внутренней сети. Требует агрегации по времени.
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 4625
    IpAddress|cidr: '192.168.10.0/24'
  filter_service:
    IpAddress: '192.168.10.5'
  condition: selection and not filter_service | count() by IpAddress > 10
  timeframe: 5m
falsepositives:
  - Забытый пароль у пользователя
  - Служебные учётные записи с устаревшим паролем в сохранённых заданиях
level: medium
tags:
  - attack.credential_access
  - attack.t1110

Агрегирующие условия поддерживаются не всеми backend-ами одинаково. Если твой конвертер не умеет count(), правило превращается в простое условие, а порог реализуется на стороне SIEM как correlation rule. В современных версиях спецификации для этого есть отдельный формат корреляционных правил, но проверь поддержку в своём backend-е заранее.

Шаг 4. Сопоставление полей (pipelines)

Это место, где большинство новичков спотыкается. Sigma использует общие имена полей (Image, ParentImage, CommandLine), а в твоём SIEM они могут называться иначе: process.executable в Elastic ECS, NewProcessName в Security 4688 и так далее. Для этого существуют pipelines, то есть файлы сопоставления, которые конвертер применяет при трансляции.

Практический совет: заведи в репозитории каталог pipelines/ и храни там сопоставление именно для своих источников с srv-dc01, srv-web01 и других хостов. Один раз настроил, дальше все правила работают единообразно.

Шаг 5. Конвертация и проверка синтаксиса

Конвертацию выполняй в CI-пайплайне или на административной рабочей станции, а не на боевом сервере SIEM:

# проверка валидности всех правил
sigma check rules/

# конвертация в запросы под выбранную платформу
sigma convert -t splunk -p pipelines/itpages-windows.yml rules/windows/ -o out/splunk_queries.txt

Команда sigma check ловит синтаксические ошибки, неизвестные модификаторы и дубликаты идентификаторов. Включи её как обязательный шаг в merge request: правило с ошибкой не должно попадать в основную ветку.

Шаг 6. Тестирование на данных

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

  1. Ретроспективный прогон. Запусти сконвертированный запрос по логам за 30 дней на srv-siem01. Сколько срабатываний? Если сотни, правило слишком широкое. Если ноль, возможно, нужное поле просто не парсится.
  2. Проверка на безобидной активности. Разбери каждое срабатывание: легитимно оно или нет. Причины ложных срабатываний переноси в блок falsepositives и в фильтры.
  3. Контролируемая проверка. В изолированной тестовой среде воспроизведи безопасное событие, соответствующее логике правила (например, запусти штатную утилиту из нужного родительского процесса на тестовой машине), и убедись, что алерт появился. Никаких реальных вредоносных инструментов для этого не нужно: достаточно воспроизвести сам артефакт в логе.

Шаг 7. Жизненный цикл правила

Статусы в Sigma помогают управлять зрелостью: experimental до обкатки, test после первых прогонов, stable когда ложные срабатывания под контролем. Договорись в команде, что в продуктивный режим с отправкой уведомлений дежурным попадают только правила от test и выше, а экспериментальные пишут в отдельный индекс и разбираются раз в неделю.

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

Шаг 8. Карта покрытия и работа с ложными срабатываниями

Когда правил становится больше двух десятков, начинается управленческая задача: понять, что ты вообще покрываешь. Поле tags с привязкой к тактикам и техникам ATT&CK даёт готовую основу. Выгрузи все теги из репозитория, построй простую таблицу по тактикам (Initial Access, Execution, Persistence, Credential Access, Lateral Movement, Exfiltration) и посмотри, где пусто. Пустые клетки это не повод срочно писать правила ради галочки, а повод спросить себя: есть ли у нас вообще логи, на которых это можно увидеть?

Отдельно заведи в репозитории файл с известными исключениями для лабораторной сети. Например, список служебных учётных записей, адресов сканеров уязвимостей и плановых задач на srv-web01. Фильтры в правилах ссылаются на эти списки, и когда в инфраструктуре что-то меняется, ты правишь одно место, а не двадцать правил. Так же полезно записывать решение по каждому ложному срабатыванию: что это было, почему легитимно, кто подтвердил. Через полгода эта история сэкономит часы, когда новый дежурный увидит знакомый алерт и спросит, что с ним делать.

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

Напоследок о культуре работы. Правила обнаружения живут долго, а люди в команде меняются, поэтому договорись о едином стиле: одинаковые заголовки (что обнаруживается, а не как), обязательное описание ложных срабатываний, обязательные теги ATT&CK. Пусть в репозитории лежит шаблон нового правила, чтобы автор не начинал с чистого листа. Такая дисциплина кажется бюрократией ровно до первого ночного инцидента, когда дежурному нужно за минуту понять, что значит незнакомый алерт.

И ещё одно наблюдение из практики: храни рядом с правилом небольшой набор тестовых событий в виде примеров логов, на которых оно должно срабатывать, и примеров, на которых не должно. Автоматическая проверка этих примеров в CI защищает от регрессий, когда кто-то правит фильтр и случайно ломает условие. Это занимает десять минут на правило, а экономит часы отладки.

Если правил становится много, разделяй репозиторий по источникам: windows, linux, network, web. У каждого раздела свой владелец, свой pipeline и свой график ревью. Так проще поддерживать порядок и передавать работу новым людям.

Частые ошибки и как их избежать

  • Привязка к конкретному имени файла или хэшу. Такое правило обходится тривиальным переименованием. Ищи поведение: цепочку родитель-потомок, необычные аргументы, нетипичное время и источник. Индикаторы компрометации годятся как дополнение, но не как основа.
  • Слишком широкие условия без фильтров. Правило, которое срабатывает по двести раз в день, дежурные начнут игнорировать через неделю. Лучше узкое правило с высоким доверием, чем широкое, которое глушится целиком.
  • Игнорирование источника логов. Правило написано под Sysmon, а на хосте стоит только стандартный аудит без командной строки. Перед написанием проверь, какие поля реально приходят в srv-siem01, и зафиксируй требования к аудиту в описании правила.

Что дальше

Защита строится из нескольких слоёв — вот соседние темы серии: