Wazuh alerts¶
If you already run Wazuh, Signalith can take in the alerts your Wazuh manager raises. They are mapped onto Signalith's data models, so logons from Wazuh show up next to logons from Fluent Bit, file integrity alerts land in Filesystem, configuration assessment results in Configuration_Check, antivirus alerts in Malware, and everything else in Alerts. Detections, dashboards and searches work on them like on any other event.
What to know first¶
- Wazuh agents keep reporting to a Wazuh manager. Wazuh agents only talk to a Wazuh manager, over Wazuh's own encrypted protocol, and Signalith does not speak it. Signalith takes the alerts from the manager, so you keep the manager (and its rules, decoders and agent enrollment) running.
- Alerts, not every event. The manager writes an alert when an event matches one of its rules
at or above its alert level (
log_alert_level, 3 by default). Events that match no rule stay on the manager and are not sent. - New alerts only. Alerts raised before you set this up are not sent.
There are two ways to send alerts. Use Fluent Bit unless you cannot install anything on the manager.
| Fluent Bit on the manager | The manager's syslog output | |
|---|---|---|
| Install | Fluent Bit on the manager | nothing |
| Transport | HTTPS to /api/ingest, checking Signalith's certificate |
syslog over UDP, unencrypted |
| Buffering | kept on disk and sent again if Signalith is down | none: alerts sent while Signalith is unreachable are lost |
| Long alerts | up to 1 MB each | very long alerts can be cut short (see below) |
Fluent Bit on the Wazuh manager¶
Open Add data, pick Wazuh and follow the steps. In short, on the machine that runs the Wazuh manager:
- Install Fluent Bit 3.1 or later:
curl https://raw.githubusercontent.com/fluent/fluent-bit/master/install.sh | sh - Save Signalith's CA certificate as
signalith-ca.pem(when Signalith uses HTTPS). - Save the generated configuration as
fluent-bit.conf. - Put both in place:
sudo install -m 644 -o root -g root signalith-ca.pem /etc/fluent-bit/signalith-ca.pem && sudo install -m 600 -o root -g root fluent-bit.conf /etc/fluent-bit/fluent-bit.conf - Restart Fluent Bit:
sudo systemctl enable --now fluent-bit && sudo systemctl restart fluent-bit
The configuration tails the file the manager writes its alerts to, one JSON alert per line, and
sends each line with the tag wazuh. The page fills in the address, ingest token and
certificate checks; the input part looks like this:
[INPUT]
Name tail
Tag wazuh
Path /var/ossec/logs/alerts/alerts.json
DB /var/lib/fluent-bit/signalith-wazuh.db
Buffer_Chunk_Size 64k
Buffer_Max_Size 1M
Skip_Long_Lines On
storage.type filesystem
alerts.json is written when <jsonout_output>yes</jsonout_output> is set under <global> in
the manager's /var/ossec/etc/ossec.conf, which is the default. Fluent Bit runs as root, so it
can read the file; it follows the file when the manager rotates it each day.
If Fluent Bit already runs on the manager for something else, add the [INPUT] above and the
[OUTPUT] from the generated file to your own configuration instead. Keep the tag wazuh: it is
how Signalith knows the lines are Wazuh alerts.
The manager's syslog output (no agent)¶
The Wazuh manager can send each alert as JSON over syslog to Signalith's
syslog receiver. In /var/ossec/etc/ossec.conf on the manager, add:
<ossec_config>
<syslog_output>
<server>192.168.1.20</server>
<port>514</port>
<format>json</format>
</syslog_output>
</ossec_config>
with Signalith's address as server (the Syslog option on Add data shows it), then turn
on the manager's syslog client and restart it:
Add <level>7</level> inside <syslog_output> to send only alerts of that rule level and above.
Signalith recognizes a syslog message whose text is a Wazuh JSON alert (an object with rule and
agent) and maps it exactly like an alert sent by Fluent Bit. host is the Wazuh agent the alert
is about, and dvc is the manager that sent it.
The manager sends syslog over UDP, unencrypted and without retries, so use this route on a network
you trust. Very long alerts (with a long full_log) can be cut short by the manager's syslog
output; a cut alert is not valid JSON, so it is stored as a plain syslog event (searchable by its
text, but not mapped). The Fluent Bit route does not have this limit.
How alerts are mapped¶
Every Wazuh alert gets these fields, whatever model it lands in:
| Field | From the alert |
|---|---|
_time |
timestamp |
host, dest |
agent.name |
signature_id |
rule.id |
signature |
rule.description |
vendor_product |
Wazuh |
sourcetype |
wazuh:alerts |
_raw |
the whole alert, as JSON |
mitre, mitre_tactic |
rule.mitre.id, rule.mitre.tactic (lists) |
wazuh_rule_level |
rule.level (0 to 15) |
wazuh_rule_groups |
rule.groups (a list) |
wazuh_agent_id, wazuh_agent_name, wazuh_agent_ip |
agent.id, agent.name, agent.ip |
wazuh_manager |
manager.name |
wazuh_decoder |
decoder.name |
wazuh_location |
location, such as /var/log/auth.log or EventChannel |
Then the alert goes to the first model that fits:
Filesystem: file integrity monitoring (syscheck) alerts.
| Field | From the alert |
|---|---|
action |
syscheck.event: added becomes created; modified, deleted |
file_path, file_name |
syscheck.path, and its last part |
file_hash |
syscheck.sha256_after, lower case |
file_size |
syscheck.size_after |
user |
syscheck.audit.user.name (who-data), else syscheck.uname_after (the file's owner) |
process_path, process_name, process_id |
syscheck.audit.process.name, its file name, syscheck.audit.process.id |
Registry: syscheck alerts about Windows registry keys and values (rule group
syscheck_registry, or a path starting with HKEY_): action, registry_path,
registry_key_name, registry_value_name (syscheck.value_name), user and process as above.
Configuration_Check: Security Configuration Assessment results (data.sca.type is check).
| Field | From the alert |
|---|---|
check_id |
data.sca.check.id |
check |
data.sca.check.title |
result |
data.sca.check.result (or status on older managers): passed is pass, failed is fail, not applicable is n/a |
reference |
data.sca.check.compliance, such as cis: 5.2.8; pci_dss_v4.0: 7.2.1 |
detail |
data.sca.check.reason |
benchmark |
data.sca.policy, the policy name |
rule_id is left empty: it is for SCAP Security Guide rules. SCA scan summaries go to Alerts.
Windows events (data.win.system): Signalith's own Windows parser reads them, from the event
data Wazuh sends by name, so they get the same fields as events from Fluent Bit on Windows:
4624 and 4625 logons go to Authentication, 4688 process creation to Endpoint, account and group
changes (4720, 4726, 4728, 4732, 4756) to Change, and Sysmon 1 and 3 to Endpoint and
Network_Traffic. The Windows event ID is kept in wazuh_win_event_id. Other Windows events
continue below.
Authentication: alerts whose rule groups include authentication_success,
authentication_failed, authentication_failures or invalid_login (sshd, PAM, sudo, su,
Windows and others).
| Field | From the alert |
|---|---|
action |
success or failure, from the rule group |
app |
decoder.parent, else decoder.name, such as sshd or pam |
user |
data.dstuser, else data.srcuser, else data.win.eventdata.targetUserName |
src_user |
data.srcuser, when it differs from data.dstuser (sudo, su) |
src, src_port |
data.srcip, data.srcport (Windows: ipAddress, ipPort) |
Malware: antivirus alerts, so they are found with every other antivirus's (see the Malware dashboard):
- Wazuh's ClamAV integration (rule groups
clamdorfreshclam): the ClamAV message infull_logis read like a ClamAV log, givingsignature,file_path,actionand, for definition updates,type=health.vendor_productisClamAV. - VirusTotal matches (
data.virustotal.maliciousis 1):signaturesays how many engines flagged the file, withfile_path,file_md5,file_sha1and the report inurl. - Rootcheck's trojaned files:
category=trojan, with the file fromdata.fileorfull_log. Other rootcheck findings go to Alerts.
The rule's description is kept in description, and severity comes from rule.level as for
Alerts (0 to 3 counts as low).
Alerts: everything else.
| Field | From the alert |
|---|---|
app |
wazuh |
id |
id, the alert's own ID |
description |
rule.description |
severity |
from rule.level: 0 to 3 informational, 4 to 6 low, 7 to 9 medium, 10 to 12 high, 13 to 15 critical |
severity_id |
rule.level |
type |
rule.groups, joined with commas |
src |
data.srcip |
user |
data.dstuser, else data.srcuser, else the Windows target or subject user |
Anything not mapped stays in _raw, so you can still find it by text, for example
sourcetype=wazuh:alerts "Trojaned version".
Checking it works¶
Search sourcetype=wazuh:alerts over the last hour. To see what kinds of alerts arrive:
A line under the wazuh tag that is not a Wazuh alert is kept in Other with sourcetype
wazuh:alerts. If nothing arrives, check the Health page and Fluent Bit's log
(journalctl -u fluent-bit) on the manager; for the syslog route, the Syslog option on
Add data shows the messages arriving from the manager.