Недавно добрался наконец то до изучения Wazuh - чтобы была польза от процесса познания, поставил для теста на небольшой больнице и определил задачи, которые он должен решать:

  1. Собираем информацию с двух доменных контроллеров и 4-х серверов приложений на базе Linux Debian.

  2. С DC хотим получать информацию о событиях (в Telegram) изменения членства в административных группах Active Directory (добавление или удаление пользователей)

  3. С Linux машин хотим получать (также в TG) информацию о любых неудачных попытках входа по SSH. Так как у нас в сети только один админ Linux машин и пользуется он SSH ключами - любая неуспешная попытка входа - сигнал опасности - будем сразу делать стойку и разбираться, кто это шарится...

  4. Решение нужно максимально автономное - в консоль Wazuh уже через неделю никто заходить не собирается и события с уровнями Medium и Low будут смотреться только в случае инцидента (например, с группами AD и sshd сервисами). Поэтому нам нужно минимизировать любой мусор, максимально убрав все, что не относится к обозначенным триггерам.

Установка сервера и выбор конфигурации

Установка настолько простая (в режиме all-in-one), что и описывать не стоит (одна команда же по сути), но хочется отметить ряд моментов:

  • Виртуальной машине выдал 16 ядер и 16 Гб ОЗУ (диск на 200 Гб) - после установки Active ОЗУ был чуть больше 3 Гб, спустя 5 дней потребление не особо выросло (подключено 6 агентов). Т.е. - можно поджаться до рекомендуемых 8 Гб, или даже до 6 попробовать (тут каждый сам решает)

  • Установка продолжалась около получаса

Процесс установки Wazuh сервера
Процесс установки Wazuh сервера

Установка 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-интерфейс и смотрим, все ли агенты подключились:

WEB-интерфейс - раздел с агентами
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):

default в JSON формате
default в JSON формате
  • Нам нужно собирать больше полей из карточки событий в 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 и доп-полями (проверками):

Проверка изменения членства в группах AD
Проверка изменения членства в группах AD
Не подфартило с SSH
Не подфартило с SSH

Итоги

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

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

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


  1. slavius
    18.12.2024 09:58

    Спасибо, пригодится.