Silent Wazuh — tuning, event minimization, notifications in Telegram

Recently, I finally got around to studying Wazuh - to make the learning process useful, I set it up for testing in a small hospital and identified the tasks it should solve:

  1. We collect information from two domain controllers and 4 application servers based on Linux Debian.

  2. From the DC, we want to receive information about events (in Telegram) of changes in membership in Active Directory administrative groups (adding or removing users)

  3. From Linux machines, we want to receive (also in TG) information about any unsuccessful SSH login attempts. Since we only have one Linux machine admin in our network and he uses SSH keys - any unsuccessful login attempt is a danger signal - we will immediately investigate who is wandering around...

  4. The solution needs to be as autonomous as possible - no one plans to log into the Wazuh console in a week and events with Medium and Low levels will only be looked at in case of an incident (for example, with AD groups and sshd services). Therefore, we need to minimize any garbage, removing as much as possible everything that does not relate to the designated triggers.

Server installation and configuration selection

The installation is so simple (in all-in-one mode) that it is not even worth describing (just one command, essentially), but I would like to note a few points:

  • Allocated 16 cores and 16 GB of RAM (200 GB disk) to the virtual machine - after installation, Active RAM was just over 3 GB, after 5 days the consumption did not grow much (6 agents connected). That is, you can reduce it to the recommended 8 GB, or even try to 6 (everyone decides for themselves)

  • The installation took about half an hour

Installing Wazuh agents on Windows and Linux

# Windows (agent name must be unique):
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 and 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

After installation, we log into the WEB interface and check if all agents are connected:

Tuning settings on Wazuh agents

From DC controllers with certain settings (authorization logging - success/failure), a bunch of events related to user activity can immediately fall. There will also be many other events. We find the ossec.conf file in the C:\Program Files (x86)\ossec-agent directory, analyze its settings - a number of events (EventID) are already ignored there. Add a number of your own:

# fragment of settings from the ossec.conf file:
....

  
  
    Application
    eventchannel
    Event/System[EventID != 16384]
  

  
    Security
    eventchannel
    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]
  

  
    System
    eventchannel
    Event/System[EventID != 5 and EventID != 7040]
  

....

Next, I provide a detailed description of all the events that we will ignore on the agent (add/remove your own to taste, salt, boil until boiling):

Application log:

  • 16384 - The restart of the software protection service is successfully scheduled. This event is logged when the Windows Software Protection Service initiates a restart to maintain licensing functionality

Security log:

  • 5145 - Access to the file system object. The event is generated when attempting to access a file or folder with the type of access and result (success/failure) specified.

  • 5156 - Allowed connection to the network established. Indicates a successful network connection according to Windows Firewall rules.

  • 5447 - Audit policy settings were changed. Reflects changes to security audit settings in the system.

  • 4656 - Object handle requested. The event is generated when an object (file, process, etc.) is opened with specific access levels.

  • 4658 - Object handle closed. A system process or user closed access to the resource.

  • 4663 - Access to the object was requested. Indicates an attempt to access an object with the type of operation specified (read, write, etc.).

  • 4660 - Object was deleted. Logged when an object in the file system is successfully deleted.

  • 4670 - Permissions on the object were changed. Records changes to the Access Control List (ACL) for the object.

  • 4690 - Object handle was duplicated. Indicates the creation of a copy of the object handle with the transfer of access rights.

  • 4703 - Permissions on the process were changed. Indicates changes to access rights for system processes.

  • 4907 - Security audit policy was changed. Logged when audit settings are updated, such as enabling or disabling event monitoring.

  • 5152 - Network connection blocked. Windows Firewall blocked an outgoing network connection according to established rules.

  • 5157 - Network connection blocked by security policy. Incoming network connection rejected due to firewall policy violation.

  • 4634 - Logon session ended. The user logged out, ending the active session.

  • 4624 - Successful logon. The user successfully logged on with the account, logon method, and source specified.

  • 4672 - Privileges were assigned at logon. A system event indicating that privileges were assigned to the user at logon (e.g., administrator rights).

  • 4616 - System time was changed. Generated when the system time is changed.

  • 4755 - Universal security-enabled group was changed.

System Journal:

  • 5 - File access error. For example, the Kerberos client received the KRB_AP_ERR_TKT_NYV error, indicating a time difference between the server and the client.

  • 7040 - The service startup type was changed. Example: the startup type of the "Background Intelligent Transfer Service (BITS)" was changed from "Automatic" to "Manual".

What other sections did I disable (generating events that I am not interested in):

# First
...
  
  
    yes
    yes
    12h
    yes
  
...
# Disable (replace yes with no)

# Second
...
  
  

    no
...
# Similarly - but here we change no to yes

# Third
...
  
  
    no
    ./shared/win_applications_rcl.txt
    ./shared/win_malware_rcl.txt
  
...
# Change no to yes
# Kaspersky Security Antivirus is installed on Windows machines, let it control all this...

We make a copy of ossec.conf, change it as described above, stop the service, replace it in C:\Program Files (x86)\ossec-agent, start the service.

There are fewer changes on Linux (without editing EventID), but somewhere I had to disable the analysis of apache.log, as normal activity with the proxy agent was perceived as DDoS requests.

Increasing Level for SSHD

In Telegram, we will only receive events with a code of 12 or higher. Therefore, we edit the file /var/ossec/ruleset/rules/0095-sshd_rules.xml, find the event with the number 5760 and change the priority level (to 13, for example):

...

  
    5700,5716
    Failed password|Failed keyboard|authentication error
    sshd: authentication failed.
    
      T1110.001
      T1021.004
    
    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,
  
...

You can immediately restart the wazuh-manager service, or you can do it after all changes at the end.

Integration with Telegram

The files from the following source were taken as a basis: wazuh-telegram, BUT, some changes were made:

# In the file /var/ossec/etc/ossec.conf on the Wazuh server:
# In the example, level 3 was changed to 12
# Replace the word TOKEN with your own
...
  
    custom-telegram
    12
    https://api.telegram.org/botTOKEN/sendMessage
    json
  

  
  
    127.0.0.1
...

The custom-telegram file in BASH language in the /var/ossec/integrations/ directory has not been changed, unlike the custom-telegram.py file (Python) - it had to be dug into and many changes made because:

  • The original script sends messages in JSON format (which looks, frankly, sad in Telegram):

  • We need to collect more fields from the event card in Wazuh

  • We may need to send different events to different TG groups

  • We may need to check various conditions to form more accurate information

  • We don't want JSON, we want 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 = "User added to group"
elif event_id in ["4729", "4757"]:
    action = "User removed from group"

# Generate message based on rule ID
if rule_id == "5760":
    message = f"*Wazuh Alert 🚨*\n\n"               f"*Description:* {description}\n"               f"*Level:* {alert_level}\n"               f"*Agent:* {agent}\n"               f"*Agent IP address:* {agent_ip}\n"               f"*Attacker IP:* {src_ip}"
else:
#    CHAT_ID="-19XXXXXXX1"
    message = f"*Wazuh Alert 🚨*\n\n"               f"*Description:* {description}\n"               f"*Level:* {alert_level}\n"               f"*Agent:* {agent}\n"               f"*Agent IP address:* {agent_ip}\n"               f"*Message:* {system_message}\n"               f"*Subject User Name:* {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)

Some clarifications:

  • In the Python script section ###Extract data fields### you can add any fields from any event cards in Wazuh - the main thing is to determine their values as N/A if they are not in the current card

  • Using if...elif...elif...else you can describe any number of different events from different situations, checking them by rule_id (in my case I check for the sshd rule, if not, then it's the AD groups rule). Then the scheme scales as you like

  • By changing the value of the CHAT_ID variable, we can send events to different groups (and people)

How do notifications look now, in Markdown format with additional fields (checks):

Results

Minimized events, we get beautiful notifications in TG, events with importance below 12 are mainly related to normal admin activity (logged in via SSH, connected via RDP) - can be analyzed on request and they are not thousands, but a few.


Integrating Wazuh with Telegram for convenient notifications

Good luck to everyone in studying Wazuh and customizing it to your needs and desires!

Comments