Wazuh SIEM Advanced Configuration and Rules
Wazuh is an open-source SIEM platform that combines intrusion detection, log analysis, vulnerability scanning, and compliance monitoring. This guide covers writing custom rules and decoders, configuring active response, file integrity monitoring (FIM), vulnerability detection, and compliance dashboards.
Prerequisites
- Wazuh manager 4.x installed and running
- At least one Wazuh agent deployed
- Root or sudo access on the manager
- Familiarity with the Wazuh web interface (Kibana/OpenSearch Dashboards)
For installation, refer to the official Wazuh documentation. Verify the manager is running:
sudo systemctl status wazuh-manager
sudo /var/ossec/bin/agent_control -l # List connected agents
Wazuh Architecture Overview
Key configuration paths:
/var/ossec/etc/ossec.conf- Main manager configuration/var/ossec/etc/rules/- Rule files (local_rules.xml for custom rules)/var/ossec/etc/decoders/- Decoder files (local_decoder.xml for custom decoders)/var/ossec/logs/alerts/alerts.log- Alert log
Rule evaluation order: decoders extract fields → rules match fields → alerts are generated.
Custom Decoders
Decoders parse log messages into structured fields. Write decoders before rules.
Example: Decode a custom application log format:
sudo nano /var/ossec/etc/decoders/local_decoder.xml
<!-- Decode log format: [2024-01-15 10:30:45] WARN user=alice action=login_failed ip=192.168.1.100 -->
<decoder name="myapp">
<!-- Match logs from our application -->
<prematch>^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]</prematch>
</decoder>
<decoder name="myapp-details">
<parent>myapp</parent>
<!-- Extract fields using named groups -->
<regex>^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+) user=(\S+) action=(\S+) ip=(\S+)</regex>
<order>timestamp, level, srcuser, action, srcip</order>
</decoder>
Test your decoder:
sudo /var/ossec/bin/wazuh-logtest
# Paste a sample log line and verify decoded fields
Custom Rules
Rules match decoded events and generate alerts. Rule IDs 100000-119999 are reserved for local rules.
sudo nano /var/ossec/etc/rules/local_rules.xml
<group name="myapp,authentication">
<!-- Rule: Failed login attempt -->
<rule id="100001" level="5">
<decoded_as>myapp-details</decoded_as>
<field name="action">login_failed</field>
<description>MyApp: Failed login attempt by $(srcuser) from $(srcip)</description>
<group>authentication_failed</group>
</rule>
<!-- Rule: Multiple failed logins - brute force detection -->
<rule id="100002" level="10" frequency="5" timeframe="60">
<if_matched_sid>100001</if_matched_sid>
<same_field>srcip</same_field>
<description>MyApp: Possible brute force attack from $(srcip) - 5+ failures in 60s</description>
<group>authentication_failures,pci_dss_10.2.4,pci_dss_10.2.5</group>
</rule>
<!-- Rule: Admin action performed -->
<rule id="100003" level="8">
<decoded_as>myapp-details</decoded_as>
<field name="srcuser">admin</field>
<field name="action">^(?!login)</field>
<description>MyApp: Admin action performed: $(action)</description>
<group>admin_actions</group>
</rule>
<!-- Rule: New user created -->
<rule id="100004" level="6">
<decoded_as>myapp-details</decoded_as>
<field name="action">user_created</field>
<description>MyApp: New user created by $(srcuser)</description>
</rule>
</group>
Reload rules without restarting:
sudo /var/ossec/bin/wazuh-control reload
# Or
sudo kill -HUP $(cat /var/ossec/var/run/wazuh-analysisd.pid)
Test rules with wazuh-logtest:
sudo /var/ossec/bin/wazuh-logtest
# Enter: [2024-01-15 10:30:45] WARN user=alice action=login_failed ip=192.168.1.100
# Verify rule 100001 triggers
Active Response Configuration
Active response runs scripts automatically when rules trigger:
sudo nano /var/ossec/etc/ossec.conf
<!-- In ossec.conf -->
<ossec_config>
<!-- Define a command -->
<command>
<name>firewall-drop</name>
<executable>firewall-drop</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<!-- Active response: block IP for 600 seconds when brute force detected -->
<active-response>
<command>firewall-drop</command>
<location>local</location>
<rules_id>100002</rules_id>
<timeout>600</timeout>
</active-response>
<!-- Active response for SSH brute force (Wazuh built-in rule 5763) -->
<active-response>
<command>firewall-drop</command>
<location>local</location>
<rules_id>5763</rules_id>
<timeout>1800</timeout>
</active-response>
</ossec_config>
Create a custom active response script:
sudo tee /var/ossec/active-response/bin/notify-slack.sh << 'EOF'
#!/bin/bash
# Send Slack notification when alert triggers
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
# Read alert data from stdin
read INPUT_JSON
ALERT=$(echo "$INPUT_JSON" | python3 -c "
import sys, json
data = json.load(sys.stdin)
print(f'Alert: {data.get(\"alert\", {}).get(\"description\", \"Unknown\")}')
print(f'Level: {data.get(\"alert\", {}).get(\"level\", 0)}')
print(f'Source IP: {data.get(\"parameters\", {}).get(\"alert\", {}).get(\"data\", {}).get(\"srcip\", \"N/A\")}')
")
curl -s -X POST "$WEBHOOK_URL" \
-H "Content-type: application/json" \
-d "{\"text\": \"🚨 Wazuh Alert\n${ALERT}\"}"
EOF
chmod 750 /var/ossec/active-response/bin/notify-slack.sh
chown root:wazuh /var/ossec/active-response/bin/notify-slack.sh
File Integrity Monitoring
FIM tracks changes to critical files and directories:
<!-- In /var/ossec/etc/ossec.conf -->
<syscheck>
<disabled>no</disabled>
<!-- Check every 6 hours -->
<frequency>21600</frequency>
<!-- Enable real-time monitoring for critical directories -->
<directories realtime="yes" check_all="yes" report_changes="yes">
/etc/passwd
/etc/shadow
/etc/sudoers
/etc/sudoers.d
/etc/ssh/sshd_config
/var/ossec/etc
</directories>
<directories realtime="yes" check_all="yes">/etc/nginx</directories>
<directories realtime="yes" check_all="yes">/etc/apache2</directories>
<!-- Web root - monitor for webshells -->
<directories realtime="yes" check_all="yes" report_changes="yes">
/var/www/html
</directories>
<!-- Ignore frequently changing files -->
<ignore>/var/www/html/cache</ignore>
<ignore type="sregex">.log$|.tmp$|.swp$</ignore>
<!-- Scan symlinks -->
<follow_symbolic_link>yes</follow_symbolic_link>
</syscheck>
Force an immediate FIM scan:
# Trigger immediate scan on agent
sudo /var/ossec/bin/agent_control -a -r -u AGENT_ID
# View FIM alerts
sudo grep "syscheck" /var/ossec/logs/alerts/alerts.log | tail -20
Vulnerability Detection
Enable vulnerability detection for installed packages:
<!-- In ossec.conf on the manager -->
<vulnerability-detection>
<enabled>yes</enabled>
<interval>12h</interval>
<min_full_scan_interval>6h</min_full_scan_interval>
<run_on_start>yes</run_on_start>
<provider name="canonical">
<enabled>yes</enabled>
<os>focal</os> <!-- Ubuntu version codename -->
</provider>
<provider name="redhat">
<enabled>yes</enabled>
<os>8</os>
</provider>
</vulnerability-detection>
On agents, enable the vulnerability inventory:
<!-- In agent's ossec.conf -->
<wodle name="syscollector">
<disabled>no</disabled>
<interval>1h</interval>
<packages>yes</packages>
<os>yes</os>
<processes>yes</processes>
</wodle>
Check vulnerability results:
# Query the Wazuh API for vulnerabilities
curl -k -X GET "https://localhost:55000/vulnerability/AGENT_ID?severity=critical" \
-H "Authorization: Bearer $TOKEN" | python3 -m json.tool
Compliance Dashboards
Wazuh maps alerts to compliance frameworks automatically. Configure compliance groups in your rules:
<rule id="100005" level="7">
<decoded_as>myapp-details</decoded_as>
<field name="action">config_changed</field>
<description>Configuration change detected</description>
<!-- Map to compliance standards -->
<group>pci_dss_10.2.7,hipaa_164.312.b,nist_800_53_AU.2,gdpr_IV_35.7.d</group>
</rule>
Built-in compliance dashboards in the Wazuh web UI:
- Security > Overview > Compliance - GDPR, HIPAA, PCI DSS, NIST summaries
- Each dashboard shows rule hits mapped to control IDs
Generate a compliance report via API:
# Get auth token
TOKEN=$(curl -k -u admin:admin -X GET "https://localhost:55000/security/user/authenticate?raw=true")
# Get PCI DSS compliance events for last 24h
curl -k -X GET "https://localhost:55000/compliance/pci?limit=100" \
-H "Authorization: Bearer $TOKEN"
Performance Tuning
<!-- /var/ossec/etc/ossec.conf - analysis performance -->
<ossec_config>
<global>
<logall>no</logall> <!-- Don't log all events, only alerts -->
<logall_json>no</logall_json>
<max_output_size>1073741824</max_output_size> <!-- 1 GB max log size -->
</global>
<alerts>
<log_alert_level>3</log_alert_level> <!-- Only log level 3+ alerts -->
</alerts>
<remote>
<connection>secure</connection>
<port>1514</port>
<queue_size>131072</queue_size> <!-- Increase agent message queue -->
</remote>
</ossec_config>
Tune the analysis daemon:
# Check current analysis statistics
sudo /var/ossec/bin/wazuh-control status
tail -f /var/ossec/logs/ossec.log | grep "Events"
# Increase threads for high-volume environments
# In ossec.conf:
# <analysis_threads>4</analysis_threads>
Troubleshooting
Rules not triggering:
# Test with wazuh-logtest
sudo /var/ossec/bin/wazuh-logtest
# Check analysis daemon log for errors
sudo tail -f /var/ossec/logs/ossec.log | grep -E 'ERROR|WARN'
# Verify rule syntax
sudo /var/ossec/bin/wazuh-analysisd -t
Agent not connecting to manager:
# Check agent status
sudo /var/ossec/bin/agent_control -l
# On the agent, check connectivity
sudo /var/ossec/bin/wazuh-control status
sudo netstat -an | grep 1514
FIM not detecting changes:
# Check syscheck is running
sudo grep syscheck /var/ossec/logs/ossec.log | tail -10
# Force a scan
sudo /var/ossec/bin/agent_control -r -u AGENT_ID
Active response not firing:
# Check active response log
sudo tail -f /var/ossec/logs/active-responses.log
# Verify the command script is executable
ls -la /var/ossec/active-response/bin/
Conclusion
Wazuh's extensible rule engine and active response framework make it a powerful SIEM for threat detection and automated response. Custom decoders and rules let you monitor any application log format, while FIM and vulnerability detection provide continuous security posture assessment. Start with custom rules for your most critical applications, enable FIM on sensitive paths, and build active response automations for the highest-confidence alerts to reduce manual incident response workload.


