Недавно добрался наконец то до изучения Wazuh - чтобы была польза от процесса познания, поставил для теста на небольшой больнице и определил задачи, которые он должен решать:
Собираем информацию с двух доменных контроллеров и 4-х серверов приложений на базе Linux Debian.
С DC хотим получать информацию о событиях (в Telegram) изменения членства в административных группах Active Directory (добавление или удаление пользователей)
С Linux машин хотим получать (также в TG) информацию о любых неудачных попытках входа по SSH. Так как у нас в сети только один админ Linux машин и пользуется он SSH ключами - любая неуспешная попытка входа - сигнал опасности - будем сразу делать стойку и разбираться, кто это шарится...
Решение нужно максимально автономное - в консоль Wazuh уже через неделю никто заходить не собирается и события с уровнями Medium и Low будут смотреться только в случае инцидента (например, с группами AD и sshd сервисами). Поэтому нам нужно минимизировать любой мусор, максимально убрав все, что не относится к обозначенным триггерам.
Установка сервера и выбор конфигурации
Установка настолько простая (в режиме all-in-one), что и описывать не стоит (одна команда же по сути), но хочется отметить ряд моментов:
Виртуальной машине выдал 16 ядер и 16 Гб ОЗУ (диск на 200 Гб) - после установки Active ОЗУ был чуть больше 3 Гб, спустя 5 дней потребление не особо выросло (подключено 6 агентов). Т.е. - можно поджаться до рекомендуемых 8 Гб, или даже до 6 попробовать (тут каждый сам решает)
Установка продолжалась около получаса

Установка Wazuh агентов на Windows и Linux
# Windows (имя агента должно быть уникальным): Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.9.2-1.msi -OutFile $env:tmp\wazuh-agent; msiexec.exe /i $env:tmp\wazuh-agent /q WAZUH_MANAGER='10.X.XXX.X' WAZUH_AGENT_NAME='DC001' NET START WazuhSvc # Linux (Debian 11 и 12): wget https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.9.2-1_amd64.deb WAZUH_MANAGER='10.X.XXX.X' WAZUH_AGENT_NAME='tessa' dpkg -i ./wazuh-agent_4.9.2-1_amd64.deb systemctl daemon-reload systemctl enable wazuh-agent systemctl start wazuh-agent
После установки заходим в WEB-интерфейс и смотрим, все ли агенты подключились:

Тюнинг настроек на агентах Wazuh
С контроллеров DC при определенных настройках (логирование авторизации - успех/отказ) сразу может посыпаться куча событий, связанных с работой пользователей. Также будут и множество других событий. Находим файл ossec.conf в каталоге C:\Program Files (x86)\ossec-agent, анализируем его настройки - там уже игнорируются ряд событий (EventID). Добавляем ряд своих:
# фрагмент настроек из файла ossec.conf: .... <!-- Log analysis --> <localfile> <location>Application</location> <log_format>eventchannel</log_format> <query>Event/System[EventID != 16384]</query> </localfile> <localfile> <location>Security</location> <log_format>eventchannel</log_format> <query>Event/System[EventID != 5145 and EventID != 5156 and EventID != 5447 and EventID != 4656 and EventID != 4658 and EventID != 4663 and EventID != 4660 and EventID != 4670 and EventID != 4690 and EventID != 4703 and EventID != 4907 and EventID != 5152 and EventID != 5157 and EventID != 4634 and EventID != 4624 and EventID != 4672 and EventID != 4616 and EventID != 4755]</query> </localfile> <localfile> <location>System</location> <log_format>eventchannel</log_format> <query>Event/System[EventID != 5 and EventID != 7040]</query> </localfile> ....
Далее привожу детальное описание всех событий, которые мы будем на агенте игнорировать (добавить/убрать свои по вкусу, посолить, варить до кипения):
Журнал Application:
16384 - Перезапуск службы защиты программного обеспечения успешно запланирован. Это событие регистрируется, когда служба защиты программного обеспечения Windows инициирует перезапуск для поддержания функциональности лицензирования
Журнал Security:
5145 - Доступ к объекту файловой системы. Событие генерируется при попытке доступа к файлу или папке с указанием типа доступа и результата (успех/отказ).
5156 - Установлено разрешенное соединение с сетью. Указывает на успешное сетевое соединение в соответствии с правилами брандмауэра Windows.
5447 - Настройка политики аудита была изменена. Отражает изменение параметров аудита безопасности в системе.
4656 - Запрошен дескриптор объекта. Событие генерируется при открытии объекта (файл, процесс и т. д.) с определенными уровнями доступа.
4658 - Закрыт дескриптор объекта. Системный процесс или пользователь закрыли доступ к ресурсу.
4663 - Доступ к объекту был запрошен. Указывает на попытку доступа к объекту с указанием типа операции (чтение, запись и т. д.).
4660 - Объект был удален. Регистрируется при успешном удалении объекта файловой системы.
4670 - Разрешения на объект были изменены. Фиксирует изменение списка управления доступом (ACL) для объекта.
4690 - Дескриптор объекта был скопирован. Указывает на создание копии дескриптора объекта с передачей прав доступа.
4703 - Изменены разрешения на процесс. Указывает на изменение прав доступа для процессов системы.
4907 - Политика аудита безопасности была изменена. Записывается при обновлении настроек аудита, таких как включение или отключение мониторинга событий.
5152 - Сетевое соединение заблокировано. Брандмауэр Windows заблокировал исходящее сетевое соединение в соответствии с установленными правилами.
5157 - Сетевое соединение заблокировано политикой безопасности. Отклонение входящего сетевого соединения из-за нарушения политики брандмауэра.
4634 - Сеанс входа в систему завершен. Пользователь вышел из системы, завершив активную сессию.
4624 - Успешный вход в систему. Пользователь успешно вошел в систему с указанием учетной записи, метода входа и источника.
4672 - Привилегии были назначены при входе. Системное событие, которое указывает на назначение пользователю привилегий при входе в систему (например, права администратора).
4616 - Системное время было изменено. Генерируется при изменении системного времени в системе.
4755 - Изменена универсальная группа с включенной безопасностью.
Журнал System:
5 - Ошибка доступа к файлу. Например, клиент Kerberos получил ошибку KRB_AP_ERR_TKT_NYV, указывающую на разницу во времени между сервером и клиентом.
7040 - Тип запуска службы был изменен. Пример: тип запуска службы «Фоновая интеллектуальная служба передачи (BITS)» изменен с «Автоматически» на «Вручную».
Какие еще секции я отключил (генерирующие события, которые мне не интересны):
# Первая ... <!-- Security Configuration Assessment --> <sca> <enabled>yes</enabled> <scan_on_start>yes</scan_on_start> <interval>12h</interval> <skip_nfs>yes</skip_nfs> </sca> ... # Отключаем (заменяем yes на no) # Вторая ... <!-- File integrity monitoring --> <syscheck> <disabled>no</disabled> ... # Аналогично - но тут уже меняем no на yes # Третья ... <!-- Policy monitoring --> <rootcheck> <disabled>no</disabled> <windows_apps>./shared/win_applications_rcl.txt</windows_apps> <windows_malware>./shared/win_malware_rcl.txt</windows_malware> </rootcheck> ... # Меняем no на yes # На Windows машинах стоит Kaspersky Security Antivirus, пусть он все это контролирует...
Делаем копию ossec.conf, меняем как описано выше, останавливаем службу, подменяем в C:\Program Files (x86)\ossec-agent, запускаем службу.
На Linux изменений поменьше (без правки EventID), но где то пришлось отключить анализ apache.log, так как нормальную активность с прокси агент воспринимал как DDoS запросы.
Повышение Level для SSHD
В Telegram у нас будут уходить только события с кодом 12 или выше. Поэтому редактируем файл /var/ossec/ruleset/rules/0095-sshd_rules.xml, находим событие с номером 5760 и изменяем приоритет level (на 13, например):
... <rule id="5760" level="13"> <if_sid>5700,5716</if_sid> <match>Failed password|Failed keyboard|authentication error</match> <description>sshd: authentication failed.</description> <mitre> <id>T1110.001</id> <id>T1021.004</id> </mitre> <group>authentication_failed,gdpr_IV_35.7.d,gdpr_IV_32.2,gpg13_7.1,hipaa_164.312.b,nist_800_53_AU.14,nist_800_53_AC.7,pci_dss_10.2.4,pci_dss_10.2.5,tsc_CC6.1,tsc_CC6.8,tsc_CC7.2,tsc_CC7.3,</group> </rule> ...
Можно сразу перезапустить службу wazuh-manager, можно после всех изменений в конце.
Интеграция с Telegram
За основу были взяты файлы из следующего источника: wazuh-telegram, НО, были внесены некоторые изменения:
# В файле /var/ossec/etc/ossec.conf на сервере Wazuh: # В примере уровень 3 - был изменен на 12 # Вместо слова TOKEN вставьте свой ... <integration> <name>custom-telegram</name> <level>12</level> <hook_url>https://api.telegram.org/botTOKEN/sendMessage</hook_url> <alert_format>json</alert_format> </integration> <!-- Active response --> <global> <white_list>127.0.0.1</white_list> ...
Файл custom-telegram на языке BASH в каталоге /var/ossec/integrations/ не менялся, в отличие от файла custom-telegram.py (Python) - в нем пришлось покопаться и сделать много изменений, так как:
Оригинальный скрипт присылает сообщения в формате JSON (что выглядит прямо скажем, грустно в Telegram):

Нам нужно собирать больше полей из карточки событий в Wazuh
Нам может понадобится разные события рассылать в разные группы TG
Нам может понадобится проверять различные условия для формирования более точной информации
Не хотим JSON, хотим Markdown
#!/usr/bin/env python import sys import json import requests from requests.auth import HTTPBasicAuth # XXXX-INFRA CHAT_ID="-4614625XXX" # Read configuration parameters alert_file = open(sys.argv[1]) hook_url = sys.argv[3] # Read the alert file alert_json = json.loads(alert_file.read()) alert_file.close() ### Extract data fields ### alert_level = alert_json['rule']['level'] if 'level' in alert_json['rule'] else "N/A" description = alert_json['rule']['description'] if 'description' in alert_json['rule'] else "N/A" rule_id = alert_json['rule']['id'] if 'id' in alert_json['rule'] else "N/A" agent = alert_json['agent']['name'] if 'name' in alert_json['agent'] else "N/A" agent_ip = alert_json['agent']['ip'] if 'ip' in alert_json['agent'] else "N/A" src_ip = alert_json.get('data', {}).get('srcip', "N/A") system_message = alert_json.get('data', {}).get('win', {}).get('eventdata', {}).get('memberName', "N/A") subject_user_name = alert_json.get('data', {}).get('win', {}).get('eventdata', {}).get('subjectUserName', "N/A") event_id = alert_json.get('data', {}).get('win', {}).get('system', {}).get('eventID', "N/A") # Determine action based on event ID action = "N/A" if event_id in ["4728", "4756"]: action = "Пользователь добавлен в группу" elif event_id in ["4729", "4757"]: action = "Пользователь удален из группы" # Generate message based on rule ID if rule_id == "5760": message = f"*Wazuh Alert 🚨*\n\n" \ f"*Описание:* {description}\n" \ f"*Уровень:* {alert_level}\n" \ f"*Агент:* {agent}\n" \ f"*IP-адрес агента:* {agent_ip}\n" \ f"*IP-атакующего:* {src_ip}" else: # CHAT_ID="-19XXXXXXX1" message = f"*Wazuh Alert 🚨*\n\n" \ f"*Описание:* {description}\n" \ f"*Уровень:* {alert_level}\n" \ f"*Агент:* {agent}\n" \ f"*IP-адрес агента:* {agent_ip}\n" \ f"*Сообщение:* {system_message}\n" \ f"*Редиска:* {subject_user_name}\n" \ f"*Action:* {action}" # Generate request data msg_data = { 'chat_id': CHAT_ID, 'text': message, 'parse_mode': 'Markdown' # Using Markdown formatting } headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} # Send the request requests.post(hook_url, headers=headers, data=json.dumps(msg_data)) sys.exit(0)
Немного уточнений:
В разделе Python скрипта ###Extract data fields### Вы можете добавлять любые поля из любых карточек различных событий в Wazuh - главное, если их нет в текущей карточке, определять их значения как N/A
За счет if...elif...elif...else вы можете описать любое количество разных событий от разных ситуаций, проверяя их по rule_id (в моем случае я проверяю на правило sshd, если нет, то это правило с группами AD). Далее схема масштабируется как Вам угодно
Меняя значение переменной CHAT_ID можем отправлять события разным группам (и людям)
Как по итогу выглядят уведомления сейчас, в формате Markdown и доп-полями (проверками):


Итоги
Минимизировали события, получаем красивые уведомления в TG, события с важностью ниже 12 в основном связаны с нормальной активностью админов (зашли по SSH, подключились по RDP) - можно анализировать уже по запросу и их не тысячи, а единицы.

Всем удачи в изучении Wazuh и подгонки его под себя и свои хотелки!
