Перейти к содержимому
ADMIN
FUTURE
Главная страница » Sysmon + WEF + Wazuh: от событий Windows до сигналов компрометации
FIELD NOTES / 23.10.2026

Sysmon + WEF + Wazuh: от событий Windows до сигналов компрометации

Максим Шаповалов21 мин чтения
Sysmon, WEF и Wazuh: события, проверка доставки и расследование

Не ещё один архив, а маршрут до расследования

Подозрительный процесс запустился на сервере, событие записалось, а администратор ничего не увидел. Построим цепочку Sysmon → WEF → Wazuh и проверим каждое звено, а не только зелёный статус агента.

Привет, коллеги. Я Максим, системный администратор. Мне интересны сигналы, которые помогают ответить на конкретные вопросы: кто запустил удалённое управление, почему rphost создал оболочку, откуда появился доступ к LSASS и кто изменил сам сенсор. Не менее важен другой вопрос: дойдёт ли нужная запись до нас, если источник некоторое время был недоступен?

Я начну не с обещания поймать всё, а с небольшого пилота. Один-два компьютера домена, отдельный Windows Event Collector, агент Wazuh на нём и восемь локальных правил поверх штатного ruleset. Мы сохраним контекст процессов, соберём выбранные соединения и признаки вмешательства в журналы, затем проследим безвредную контрольную команду до менеджера.

Окружение: Windows Server 2022 и Windows PowerShell 5.1; Sysmon 15.22; правила привязаны к исходникам Wazuh 4.14.0. Это выбранные версии примера, не утверждение, что они последние. Схему Sysmon проверяем установленным бинарником; патчи Windows и реальный ruleset фиксируем перед пилотом. Документация сверена 23 октября 2026 года.

Скачать комплект конфигураций и проверок: Sysmon XML, две подписки WEF, фрагмент ossec.conf, восемь правил, два PowerShell-помощника и локальный валидатор. Конфигурации и ожидаемые результаты разобраны ниже.

Архитектура: где можно потерять событие и имя компьютера

На источнике Sysmon пишет Microsoft-Windows-Sysmon/Operational, Windows — Security и System. WEF выбирает записи и доставляет их в ForwardedEvents на WEC. Агент Wazuh читает этот канал через eventchannel; менеджер декодирует событие и применяет правила. Индексация и уведомление — следующие звенья, которые тоже требуют проверки.

Цепочка Sysmon, WEF и Wazuh с раздельной проверкой источника и доставки
Событие проходит три независимые проверки. Исходный computer сохраняем отдельно от личности агента на WEC.

Здесь есть три разных личности. Учётная запись компьютера источника подключается к WEC; служебный контекст на источнике читает журнал; агент Wazuh идентифицирует сборщик. Поэтому agent.name — не имя каждого исходного сервера. В правиле проверяем win.system.computer, в индексированном событии — data.win.system.computer. Канал назначения ForwardedEvents не должен подменять исходный System/Channel внутри записи.

Проверять это лучше по реальному XML и Phase 2 декодера. Иначе все события нескольких сотен узлов окажутся приписаны одному WEC, а «повтор на разных компьютерах» превратится в повтор на одном агенте. Поля providerName, channel и computer берутся из системной части события: декодер Wazuh v4.14.0.

Один агент на WEC заменяет только этот путь сбора пересланных событий. Он не устанавливает FIM, SCA, инвентаризацию, vulnerability detection или active response на удалённые источники. Если эти возможности нужны на каждом компьютере, архитектуру с агентами там рассматривают отдельно. А сам WEC становится критичной точкой: его доступность, очередь и свободное место нельзя оставлять за пределами мониторинга.

Минимум: сигналы плюс контекст, а не только готовые алерты

Решение в лоб — собирать все события. Другая крайность — оставить только записи, которые уже дают алерт. Во втором случае расследовать дерево процесса будет нечем: фоновые, но полезные предшественники заранее выброшены.

Я разделяю поток обнаружения и контекст расследования. В пилоте сохраняю создание процессов; более дорогие классы ограничиваю по задаче. Расширение и сроки хранения выбираем после измерения нагрузки. Набор ниже не покрывает все техники ATT&CK и не является нижней границей достаточной защиты.

Источник / IDЗачем собираемГраница вывода
Sysmon 1Дерево процессов, команда, образ, ProcessGuidКоманда может быть легитимной; одна запись не равна взлому
Sysmon 3, выбранные образыСвязь процесса с направлением, включая внутреннюю сетьНе расшифровывает содержимое и не знает владельца RMM
Sysmon 10 → lsass.exeКто обращался к чувствительному процессуДоступ не доказывает чтение памяти или кражу пароля
Sysmon 4,16,255Остановка, изменение конфигурации, ошибки сенсораПоследнее событие может не успеть уйти
Security 4698,4702Создание и изменение заданийНужен advanced audit; задание не обязательно вредоносно
Security 5136Изменения объектов AD на DCНужны аудит/SACL; это не все изменения файлов SYSVOL
Security 1102; System 104,7045Очистка Security/других журналов; установка службыНужен контекст инициатора и работ

Запуск RMM не означает чужое управление. Обращение к LSASS не равно успешной краже паролей. Новый сервис не обязательно вредоносный. Полезный детект не выносит приговор: он собирает очередь проверок, где видны источник, процесс, инициатор и связь с согласованной работой.

В Wazuh уже есть штатные правила. Нулевой уровень классификатора Sysmon не означает отсутствие детектов во всём ruleset: например, 61620 имеет уровень12. Наши правила дополняют его, а не заменяют. Перед настройкой стоит открыть Sysmon ruleset Wazuh v4.14.0, а не опираться на список ID из чужой установки.

Уровень 1. Sysmon: сохраняем дерево, не прячем внутреннюю сеть

Начинаю с одной рабочей станции и одного прикладного сервера. Создание процессов собираю целиком в рамках пилота: так можно связать родителя, команду и ProcessGuid. Сетевые события оставляю для AnyDesk, TeamViewer, client32 и rphost; обращения к LSASS — для анализа источника и GrantedAccess. Эти имена не исчерпывают семейства RMM и не ловят любое переименование.

Внутренние адреса намеренно не исключены. Если атакующий перемещается внутри компании или RMM подключается к внутреннему посреднику, глобальный exclude RFC1918 уберёт интересующую нас запись. Снижаем объём сначала областью пилота и выбранными процессами, затем — обоснованными исключениями.

<Sysmon schemaversion="4.82">
  <HashAlgorithms>SHA256</HashAlgorithms>
  <EventFiltering>
    <!-- All process creation on the PILOT; retain parent/command-line context. -->
    <RuleGroup name="Process context" groupRelation="or">
      <ProcessCreate onmatch="exclude" />
    </RuleGroup>
    <!-- Internal connections deliberately remain visible. -->
    <RuleGroup name="Selected network" groupRelation="or">
      <NetworkConnect onmatch="include">
        <Image condition="end with">\AnyDesk.exe</Image>
        <Image condition="end with">\TeamViewer.exe</Image>
        <Image condition="end with">\client32.exe</Image>
        <Image condition="end with">\rphost.exe</Image>
      </NetworkConnect>
    </RuleGroup>
    <RuleGroup name="LSASS access context" groupRelation="or">
      <ProcessAccess onmatch="include">
        <TargetImage condition="end with">\lsass.exe</TargetImage>
      </ProcessAccess>
    </RuleGroup>
    <!-- Explicitly disable selected high-volume/unneeded classes in this pilot. -->
    <ProcessTerminate onmatch="include" />
    <ImageLoad onmatch="include" />
    <DriverLoad onmatch="include" />
    <CreateRemoteThread onmatch="include" />
    <RawAccessRead onmatch="include" />
    <FileCreate onmatch="include" />
    <RegistryEvent onmatch="include" />
    <FileCreateStreamHash onmatch="include" />
    <PipeEvent onmatch="include" />
    <WmiEvent onmatch="include" />
    <DnsQuery onmatch="include" />
  </EventFiltering>
</Sysmon>

Схема4.82 взята из опубликованного примера Microsoft. Версия схемы не равна версии бинарника; команда -? config показывает информацию установленного Sysmon, -s — его схему. XML, который прочёл обычный парсер, ещё не прошёл проверку Sysmon. Группы задают groupRelation явно; не переносите представления об AND/OR между разными версиями и вложенными правилами без проверки. Sysmon — Microsoft Learn.

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

# Windows Server 2022 / Windows PowerShell 5.1, approved elevated pilot console.
# Inspect first. Keep the exact previous deployment XML before applying a change.
.\Sysmon64.exe -? config
.\Sysmon64.exe -s
.\Sysmon64.exe -c
# First installation ONLY after approval and review of the supplied XML:
.\Sysmon64.exe -accepteula -i .\sysmon-minimal.xml
# Existing deployment: use -c instead of -i, with a preserved rollback config.
# .\Sysmon64.exe -c .\sysmon-minimal.xml
Get-Service Sysmon64
wevtutil.exe qe Microsoft-Windows-Sysmon/Operational /c:3 /rd:true /f:xml

Ожидаем принятую конфигурацию, работающую службу и события в Operational. ID16 относится к изменению конфигурации, ID4 — к состоянию службы; они не обязаны одновременно появляться при любом вызове команды. Полный конфиг и разбор вывода сохраняем с версией пилота. Для отмены изменения возвращаем прежний XML через -c; удаление ранее существовавшего Sysmon не является корректным универсальным откатом.

Уровень 2. WEF: сначала личности и права источника

Выбираю source-initiated подписки внутри работающего домена. Источники получают FQDN сборщика через отдельную GPO пилотной OU. В политике Computer Configuration → Administrative Templates → Windows Components → Event Forwarding → Configure target Subscription Manager указываем: Server=http://wec01.example.com:5985/wsman/SubscriptionManager/WEC,Refresh=60. Имя example.com заменяется вашим согласованным FQDN.

Refresh=60 — период обращения за настройками подписок, не обещание доставки каждого события за минуту. В XML ниже выбран MinLatency; для него Microsoft описывает batch timeout30секунд. Очереди и отказы добавляют собственную задержку. Настройка производительности WEF.

При доменной аутентификации Kerberos HTTP-транспорт WinRM может защищать сообщения без TLS; это не основание включать Basic или AllowUnencrypted. Рабочие DNS, время, доверие и ожидаемый способ аутентификации проверяем отдельно. Для недоменной или другой модели доверия проектируется HTTPS с сертификатами — рецепт этого пилота туда механически не переносим.

Для чтения Security нужен доступ служебного контекста на источнике. На member-сервере проверяем NETWORK SERVICE в Event Log Readers либо согласованный доступ к каналу; добавление этой личности только на WEC не исправляет отказ чтения Security на удалённом компьютере. DC разбираем отдельно: автоматизацию локальных групп туда не отправляем. Microsoft: подготовка source-initiated подписки.

В комплекте Inspect-WefPilot.ps1 читает состояние с параметром Role Source или Collector. New-WefPilotFiles.ps1 только создаёт XML-файлы с нужным SID и поддерживает -WhatIf. Ни один из них тайно не включает аудит, не меняет ACL и не открывает firewall. Это сознательное разделение проверки и изменения.

Сборщик и две подписки: ограничиваем компьютеры пилотом

Перед настройкой WEC фиксируем существующие listeners, службы, firewall и параметры журналов. Доступ к WinRM на сборщике ограничиваем согласованными источниками. Команды quickconfig меняют состояние служб и могут затронуть listener/firewall; это не безвредная диагностика. Выполняем их только с разрешённой административной консоли пилотного WEC, с подготовленным возвратом прежнего состояния.

# Isolated, approved WEC pilot; elevated Windows PowerShell 5.1.
# Save existing WinRM/WEC/firewall state and limit the listener to pilot sources FIRST.
winrm.exe quickconfig -q
if ($LASTEXITCODE -ne 0) { throw 'WinRM setup failed' }
wecutil.exe qc /q
if ($LASTEXITCODE -ne 0) { throw 'WEC setup failed' }
.\Inspect-WefPilot.ps1 -Role Collector
# Save exact old log settings before resizing; 1 GiB is a PILOT assumption.
wevtutil.exe gl ForwardedEvents
wevtutil.exe sl ForwardedEvents /ms:1073741824
if ($LASTEXITCODE -ne 0) { throw 'Log resizing failed' }

Один гигабайт ForwardedEvents здесь — стартовое допущение, не расчёт ёмкости. Не уменьшайте существующий больший журнал ради совпадения с примером. Исходный размер сохраняем, а возможный откат с уменьшением оцениваем по сохранности событий.

Основная подписка выглядит так; SID-заглушку напрямую импортировать нельзя:

<Subscription xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription">
  <SubscriptionId>AF-Sysmon-Pilot</SubscriptionId>
  <SubscriptionType>SourceInitiated</SubscriptionType>
  <Description>Admin Future pilot: process, selected network, LSASS and sensor state</Description>
  <Enabled>true</Enabled>
  <Uri>http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog</Uri>
  <ConfigurationMode>MinLatency</ConfigurationMode>
  <Query><![CDATA[
    <QueryList><Query Id="0" Path="Microsoft-Windows-Sysmon/Operational">
      <Select Path="Microsoft-Windows-Sysmon/Operational">*[System[(EventID=1 or EventID=3 or EventID=4 or EventID=10 or EventID=16 or EventID=255)]]</Select>
    </Query></QueryList>
  ]]></Query>
  <ReadExistingEvents>false</ReadExistingEvents>
  <TransportName>http</TransportName>
  <ContentFormat>RenderedText</ContentFormat>
  <Locale Language="en-US" />
  <LogFile>ForwardedEvents</LogFile>
  <AllowedSourceDomainComputers>O:NSG:NSD:(A;;GA;;;__PILOT_GROUP_SID__)</AllowedSourceDomainComputers>
</Subscription>

Вторая подписка в архиве выбирает Security4698,4702,5136,1102 и System7045,104. В обеих ReadExistingEvents=false: начинаем с новых записей после активации, а не с неконтролируемого исторического потока. RenderedText выбран для начального пилота. Events компактнее, но не является обязательным форматом для декодера Wazuh; режим проверяем на полном пути, а не назначаем по названию SIEM.

Создайте отдельную AD-группу разрешённых учётных записей компьютеров и получите её настоящий SID. Генератор требует доменный SID и новый выходной каталог, но не проверяет содержимое группы за вас. Группу с пользователями вместо компьютеров одной проверкой синтаксиса не исправить.

# Replace the SID with YOUR approved AD group of pilot computer accounts.
.\New-WefPilotFiles.ps1 -PilotGroupSid 'S-1-5-21-111-222-333-4444' -OutputDirectory C:\WEF-Pilot-Generated -WhatIf
.\New-WefPilotFiles.ps1 -PilotGroupSid 'S-1-5-21-111-222-333-4444' -OutputDirectory C:\WEF-Pilot-Generated
wecutil.exe es
# Import only if these IDs do NOT already exist; never overwrite another subscription.
wecutil.exe cs C:\WEF-Pilot-Generated\wef-sysmon.xml
if ($LASTEXITCODE -ne 0) { throw 'Sysmon subscription import failed' }
wecutil.exe cs C:\WEF-Pilot-Generated\wef-security-system.xml
if ($LASTEXITCODE -ne 0) { throw 'Security subscription import failed' }
wecutil.exe gs AF-Sysmon-Pilot
wecutil.exe gr AF-Sysmon-Pilot
wecutil.exe gr AF-Security-Pilot

Перед cs убедитесь через es, что таких ID ещё нет. После импорта gs показывает настройки, gr — состояние источников; активность сверяем после применения GPO и подключения компьютера. Сам факт существования подписки не доказывает чтение каждого выбранного канала. Синтаксис: wecutil.

Security: события нельзя включить одним XPath

WEF не создаёт отсутствующий аудит. Для4698 и4702 нужна подкатегория Other Object Access Events с нужными параметрами успеха. Сначала читаем auditpol /get /category:*, затем согласуем точное изменение в пилотной политике. Названия auditpol локализуются; команды массового включения всех категорий здесь не нужны.

5136 относится к изменениям объектов AD на DC. Помимо Directory Service Changes нужны подходящие SACL объектов. Изменение GPC в каталоге и правка GPT в SYSVOL — не одно событие и не одна поверхность аудита. Не стоит называть подписку5136 полным наблюдением за GPO. При необходимости добавляем отдельный файловый аудит, изменение полномочий и связь с применением на клиентах.

Очистка Security даёт1102; System104 не заменяет этот сигнал. В штатном ruleset4.14.0 для1102 есть60117, для4698 —60228, для5136 —60229. Мы используем штатную ветку, а не придумываем одинаковую нумерацию для всех версий. Security rules Wazuh4.14.0, аудит заданий, аудит изменений каталога.

Первый пилот разумно начать с member-компьютеров. DC подключать после проверки объёма, прав канала и согласованной SACL-политики, а не как очередной одинаковый Windows-хост. Отсутствие5136 на обычном сервере не означает неисправность WEF.

Уровень 3. Wazuh: читаем ForwardedEvents, не теряем очередь

На WEC уже должен быть зарегистрирован исправный агент. В его существующий ossec.conf добавляем localfile для ForwardedEvents, а client_buffer сливаем с имеющимся блоком. Целиком заменять конфигурацию фрагментом нельзя: потеряются подключение, группы и остальные настройки. Дублирующий client_buffer или повторный сбор того же канала тоже не нужен.

<!-- MERGE into existing ossec_config on the WEC agent. Do not replace the file. -->
<ossec_config>
  <localfile>
    <location>ForwardedEvents</location>
    <log_format>eventchannel</log_format>
  </localfile>
  <client_buffer>
    <disabled>no</disabled>
    <queue_size>20000</queue_size>
    <events_per_second>500</events_per_second>
  </client_buffer>
</ossec_config>

queue_size измеряется в событиях, events_per_second — в событиях в секунду. По документации значения по умолчанию5000 и500; в примере очередь увеличена до20000, скорость оставлена500. Это не настройка, «ускоряющая весь SIEM». У агента на WEC есть и другие источники, а у менеджера — собственные очереди и пределы. client_buffer, очередь и anti-flooding.

Изменение агента применяем в согласованном окне с сохранённым ossec.conf и проверкой службы после перезапуска. В конфигурации eventchannel задаётся канал Windows; это не команда послать в менеджер произвольный XML-файл. Формат WEF и декодирование полей проверяем отдельно. Wazuh: сбор Windows eventchannel.

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

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

Файл adminfuture_rules.xml устанавливаем отдельно в /var/ossec/etc/rules/ на менеджере. Не перезаписываем local_rules.xml и не редактируем файлы штатного ruleset. Диапазон100000–120000 предназначен для пользовательских правил, но это не гарантирует, что конкретные1105xx свободны в вашей установке.

ПравилоРодитель Wazuh4.14.0Что означает сигнал
110501 / 110502sysmon_event1 → 110501Имя RMM / более приоритетный путь запуска; проверить владельца
110510sysmon_event1Серверный процесс создал оболочку или инструмент
110511sysmon_event3Контекст выбранного соединения, не вердикт
110520sysmon_event_10LSASS access для расследования, не доказанный dumping
11054260117Очистка Security; повысили приоритет штатного сигнала
110543sysmon_event4Sysmon остановлен
11054461644 (sysmon_event_16)Конфигурация Sysmon изменена

Обратите внимание на подчёркивание: sysmon_event_10 и sysmon_event_16 отличаются от sysmon_event1 и sysmon_event3. Для16 используем реального родителя61644. Копирование красивого, но несуществующего имени группы ломает детект без ошибки в регулярном выражении. Родители сверены по тегу4.14.0, а не по плавающей ветке master.

<!-- Wazuh 4.14.0 parents. Check IDs against the INSTALLED complete ruleset. -->
<group name="adminfuture,windows,">
  <rule id="110501" level="7">
    <if_group>sysmon_event1</if_group>
    <field name="win.eventdata.image" type="pcre2">(?i)\\(?:AnyDesk|TeamViewer|client32)\.exe$</field>
    <description>AF: RMM process on $(win.system.computer); verify deployment and management owner</description>
    <mitre><id>T1219</id></mitre>
  </rule>
  <rule id="110502" level="9">
    <if_sid>110501</if_sid>
    <field name="win.eventdata.image" type="pcre2">(?i)^[A-Z]:\\(?:Users\\|ProgramData\\|Windows\\Temp\\|PerfLogs\\|\$Recycle\.Bin\\)</field>
    <description>AF: RMM from a review-priority path on $(win.system.computer); establish actual ACLs</description>
  </rule>
  <rule id="110510" level="12">
    <if_group>sysmon_event1</if_group>
    <field name="win.eventdata.parentImage" type="pcre2">(?i)\\(?:rphost|ragent|rmngr|w3wp|httpd|nginx|sqlservr|php-cgi)\.exe$</field>
    <field name="win.eventdata.image" type="pcre2">(?i)\\(?:cmd|powershell|pwsh|certutil|mshta|wscript|cscript)\.exe$</field>
    <description>AF: server process spawned an interpreter/tool on $(win.system.computer); investigate integration versus abuse</description>
  </rule>
  <rule id="110511" level="5">
    <if_group>sysmon_event3</if_group>
    <field name="win.eventdata.image" type="pcre2">(?i)\\(?:AnyDesk|TeamViewer|client32|rphost)\.exe$</field>
    <description>AF: selected-process connection on $(win.system.computer); context, not compromise proof</description>
  </rule>
  <rule id="110520" level="7">
    <if_group>sysmon_event_10</if_group>
    <field name="win.eventdata.targetImage" type="pcre2">(?i)\\lsass\.exe$</field>
    <description>AF: process accessed LSASS on $(win.system.computer); inspect source, access mask and call trace</description>
  </rule>
  <rule id="110542" level="12">
    <if_sid>60117</if_sid>
    <description>AF: Security log cleared on $(win.system.computer); preserve available evidence</description>
  </rule>
  <rule id="110543" level="10">
    <if_group>sysmon_event4</if_group>
    <field name="win.eventdata.state" type="pcre2">(?i)^Stopped$</field>
    <description>AF: Sysmon stopped on $(win.system.computer); distinguish maintenance and interference</description>
  </rule>
  <rule id="110544" level="5">
    <if_sid>61644</if_sid>
    <description>AF: Sysmon configuration changed on $(win.system.computer); verify approved change</description>
  </rule>
</group>

PCRE2-шаблоны работают с декодированным значением поля. Два обратных слеша в XML-регулярном выражении обозначают один слеш Windows-пути; экранирование JSON на экране — другой слой. Не заменяю разделители на «любую пунктуацию» ради совпадения с копией из интерфейса: так легко расширить предикат до посторонних строк.

Проверку совпадений этих полей мы выполнили отдельно; иерархию родителей, порядок конкурирующих правил и итоговый алерт проверяем на реальном потоке установленного Wazuh. XML-парсер, PCRE2 и logtest над преобразованным JSON не заменяют этот сквозной тест eventchannel. Синтаксис правил: Wazuh rules syntax.

Как расследовать сигнал, не превратив исключения в дыру

110510 сообщает, что серверный процесс создал оболочку или инструмент. Смотрю команду ребёнка, пользователя, ParentProcessGuid/ProcessGuid, время и связанную интеграцию. Для rphost это повод проверить внешние обработки и прикладные права; для w3wp — публикацию и веб-журналы. Фраза «серверы никогда не запускают cmd» неверна: легитимная интеграция вполне может это делать. Но её нужно узнать и описать.

110501 означает знакомое имя RMM, а не владение его управляющей стороной. Путь в Program Files не делает доступ разрешённым, подпись вендора не определяет владельца tenant, а совпадающий SHA256 может принадлежать тому же легальному дистрибутиву у атакующего. Поэтому глобального исключения «хэш хороший — забыть» здесь нет. Исключение ограничиваем назначением, узлами, способом установки, управляющей стороной и сроком пересмотра.

110502 повышает приоритет путей Users/ProgramData/Temp и других выбранных каталогов. Это кандидаты для проверки, а не доказанная возможность записи любого пользователя: фактические ACL могут отличаться. По110520 разбираем sourceImage, GrantedAccess и доступный CallTrace; антивирус или разрешённое обслуживание тоже могут обращаться к LSASS.

Частотное правило с different_field=win.system.computer не выдаю за подсчёт десяти уникальных компьютеров. Повторные события от A и одно от B не превращаются в десять разных хостов. Если нужен именно distinct-host threshold по taskName, проектируем отдельную агрегацию с проверенным подсчётом уникальных значений и контролем окна. Иначе красивый сценарий массовой GPO-атаки окажется неверным математическим утверждением.

Установка правил: сначала проверка, затем перезапуск

Сохраняем текущие пользовательские конфигурации менеджера. Для блока ниже нужны Bash, systemd и ripgrep; отсутствие rg останавливает сценарий, а не пропускает проверку ID. Проверяем конфликты во всём установленном ruleset, реальные группы и родительские правила. Наличие номера в примере не гарантирует совместимость с другой версией или уже установленной доработкой.

Внимание: перезапуск Wazuh manager влияет на обработку событий. Менять правила нужно в согласованном окне; перед перезапуском выполняем проверку. При ошибке возвращаем прежнее состояние пользовательских файлов, а не исправляем синтаксис поверх остановленного сервиса. Владельца и права нового файла согласуем с существующими локальными правилами, не назначаем chmod777.

# Linux Wazuh MANAGER only. Separate custom rule file; retain original configuration.
command -v rg >/dev/null || { printf '%s\n' 'ripgrep is required for these review commands; stop here.' >&2; exit 2; }
# Review all installed IDs, not just local_rules.xml.
rg -n 'id="(110501|110502|110510|110511|110520|110542|110543|110544)"' /var/ossec/etc/rules /var/ossec/ruleset/rules
# No matches before installation is expected. Check the pinned parents on YOUR version:
rg -n 'sysmon_event_10|sysmon_event_16|id="60117"|id="61644"' /var/ossec/ruleset/rules
# Place the reviewed kit file at /var/ossec/etc/rules/adminfuture_rules.xml.
# Match approved ownership/permissions of existing custom rules; do not use chmod 777.
# Only after successful validation AND a scheduled change with rollback:
if /var/ossec/bin/wazuh-analysisd -t; then
    systemctl restart wazuh-manager && systemctl is-active wazuh-manager
else
    printf '%s\n' 'Validation failed. Restore the previous custom rule state; DO NOT restart.' >&2
fi

Успех analysisd -t означает проверку загрузки/конфигурации, а не прохождение всех поведенческих сценариев. После перезапуска проверяем службу, ossec.log, фактическое поступление события и результат разбора. Если включена active response, новые правила сначала отделяем от автоматических действий: диагностический пилот не должен сам изолировать сервер по совпадению имени.

Штатные и пользовательские правила могут конкурировать за итоговую ветку. Поэтому проверяем не только наличие желаемого ID в XML, но и конечное правило на каждом положительном и отрицательном событии в установленном движке.

Контрольная команда: проверяем доставку без настоящей атаки

Сначала подписки должны стать активными. ReadExistingEvents=false не предназначен для повторного чтения событий, созданных до подключения. На источнике запускаем безвредную вложенную команду; она не создаёт задание, не ставит RMM и не обращается к LSASS.

# SOURCE, Windows PowerShell 5.1: harmless process-creation canary; no scheduled task.
cmd.exe /d /c "powershell.exe -NoProfile -NonInteractive -Command Write-Output 'AF-WEF-CANARY'"
$Since = (Get-Date).AddMinutes(-10)
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1; StartTime=$Since} | Where-Object { $_.ToXml().Contains('AF-WEF-CANARY') } | Select-Object -First 3 TimeCreated, Id, MachineName, RecordId

На WEC выполняем отдельную проверку чтения; контрольную команду повторно на сборщике запускать не нужно:

# COLLECTOR only, Windows PowerShell 5.1; read after source canary and delivery.
$Since = (Get-Date).AddMinutes(-10)
Get-WinEvent -FilterHashtable @{LogName='ForwardedEvents'; Id=1; StartTime=$Since} | Where-Object { $_.ToXml().Contains('AF-WEF-CANARY') } | Select-Object -First 3 TimeCreated, Id, MachineName, RecordId

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

У этой контрольной команды нет специального правила в восьмёрке. Поэтому отсутствие алерта1105xx ожидаемо и не означает потерю события. На менеджере нужен ограниченный просмотр raw events. На время согласованного теста можно включить logall_json в существующем global-блоке, с оценкой диска, доступа и срока; после проверки вернуть прежнее значение и проверить службу. Не включаем бессрочный архив всех секретных команд ради одной проверки. Wazuh: журналирование событий.

# Wazuh manager, approved temporary raw-event capture window; jq must be installed.
# Replace the source name. Use the real full_log string, not the entire archive wrapper.
jq -r 'select(.data.win.system.computer == "LAB-WS01.example.com") | select(.data.win.system.eventID == "1") | select(.full_log | contains("AF-WEF-CANARY")) | .full_log' /var/ossec/logs/archives/archives.json
/var/ossec/bin/wazuh-logtest
# Paste ONE actual full_log line and inspect Phase 2: normalized JSON may use decoder json.
# This is NOT native Windows eventchannel replay or proof of stock-parent matching.
# Do NOT change rule 60000 on production to force a logtest match.
# This canary has NO dedicated custom detection rule: no 1105xx alert is required.

Важная граница: full_log в архиве может уже содержать нормализованный JSON. Обычный logtest тогда показывает декодер json, а не воспроизводит специальную обработку Windows eventchannel, на которую завязаны штатные родители. Наличие полей и совпадение шаблона не доказывают, что то же правило сработает в живом потоке. Это ограничение разбиралось разработчиками Wazuh; в теге4.14.0 отдельный путь виден в winevtchannel.c. Не меняем правило60000 в production ради красивого результата logtest. Итоговые ID и отрицательные примеры подтверждаем на изолированном настоящем агентском потоке, без атакующих действий на боевых серверах.

Ёмкость: буфер не заменяет расчёт и наблюдение

Размеры журналов выбираем из измеренного потока и допустимого перерыва доставки. У WEF локальный журнал источника служит буфером при недоступном сборщике. Если старые события перезаписались раньше доставки, коллектор не получает уведомления о самом разрыве. Это не означает отсутствие любых ошибок WEF: его Operational-канал содержит состояния, предупреждения и ошибки. Microsoft: WEF для обнаружения вторжений.

Начальный размер источника, например256MiB, и1GiB на WEC — лишь параметры пилота. Их не назначают всем серверам одним махом. При предположении2kB на событие и100EPS получаем720MB за час без учёта дополнительных расходов, различий представления и остальных журналов. Это арифметический пример, не измерение конкретного WEC.

Аналогично, очередь20000 при входе900EPS и выходе500EPS теоретически заполнится за50секунд с пустого состояния. Если поток и нагрузка иные, этот срок неприменим. Большая очередь не исправляет устойчивый дефицит пропускной способности.

Измеряем источник, WEC, агент и менеджер отдельно: события/байты за окно, фактическую задержку, заполнение, reconnect и catch-up. Универсального обещания «сборщик выдержит3000EPS» здесь нет. После потери связи нужен отдельный тест догоняющей доставки и сохранности — успешный canary на здоровой сети этого не доказывает.

Что проверено и как искать разрыв

В комплекте есть воспроизводимая локальная проверка: пять XML-файлов и вложенные QueryList разбираются парсером; восемь ID уникальны; четырнадцать положительных/отрицательных проверок предикатов выполняются настоящим PCRE2 через ripgrep. Этот результат получен при подготовке материала.

# LOCAL validation machine: Python 3 and ripgrep built with PCRE2 are required.
python3 validate-kit.py
# Expected: 5 XML files + embedded queries; 8 unique IDs; 14 PCRE2 checks passed.
# This is NOT a Wazuh, WEF, PowerShell or Sysmon runtime test.

Не выполнялись полный Windows/WEF/Wazuh-стенд, приёмка XML самим Sysmon, выполнение PowerShell-помощников, тест дерева правил и испытание нагрузки. Локальная проверка не делает комплект проверенным production-детектором. Для ввода нужны собственный пилот и результаты по всей цепочке.

СимптомГде проверятьНе делать
На источнике нет canaryПрименение конфига, ID1, временное окно, права чтенияНе чинить Wazuh до появления события
Источник есть, WEC нетSubscriptionManager, runtime status, доступ к каналу, Kerberos/WinRMНе включать TrustedHosts=* и AllowUnencrypted
WEC есть, менеджер не видитАгент, localfile, очередь, соединение и raw captureНе путать отсутствие алерта с отсутствием события
Событие есть, правило не сработалоPhase2, имя поля, группа/родитель, конкурирующие правилаНе подбирать regex по экранированной строке из интерфейса
Все события приписаны WECdata.win.system.computer и исходный XMLНе считать agent.name именем исходного компьютера
Поток пропалОжидаемая активность, heartbeat, журналы доставки и очередьНе ждать единственное событие остановки сенсора

Остановка Sysmon и изменение его XML — полезные сигналы, но последний сигнал может не уйти. Нужен независимый контроль отсутствия ожидаемого потока, состояния источника и доставки. WEF heartbeat говорит о связи подписки, не доказывая поступление всех прикладных событий. Тишину нельзя автоматически объявлять отсутствием атак.

Пилот, откат и следующий уровень

Начинаем с отдельной OU, ограниченной компьютерной группы и двух источников с понятной нагрузкой. Сохраняем конфиги Sysmon, агента и менеджера, исходные параметры журналов, затронутые политики и права. У каждой работы есть окно, исполнитель, причина остановки и проверка после возврата.

Для отката удаляем только подтверждённо свои AF-Sysmon-Pilot и AF-Security-Pilot через wecutil ds; возвращаем прежние XML/настройки и проверяем сбор. Журналы не очищаем. WinRM, firewall и Event Log Readers не отключаем целиком: ими могут пользоваться другие службы. Уменьшение канала не является безусловно безопасным обратным действием. Если новый пользовательский файл правил нужно убрать из загрузки, сохраняем его вне подключаемой директории и возвращаем прежнюю проверенную конфигурацию перед перезапуском.

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

Дальше я бы добавлял PowerShell4104, DNS22, ProcessTampering25, файловые изменения SYSVOL и отдельный сценарий корреляции — по одному, с оценкой объёма и отрицательных примеров. Не потому, что у них нет готового алерта, а потому, что контекст тоже имеет цену и назначение.

Коллеги, как вы подтверждаете владельца легитимного RMM и как проверяете потерю потока, когда сенсор уже ничего не сообщает? Поделитесь в комментариях без секретов и данных заказчиков. Комплект пилота доступен здесь; начните с README и проверок, а не с массового применения.

МШ

Максим Шаповалов

Системный администратор. 17+ лет работы с инфраструктурой.

Обсудить задачу ↗

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх