Недавно добрался наконец то до изучения 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 и подгонки его под себя и свои хотелки!
slavius
Спасибо, пригодится.