Wazuh 4.14 Detection Rules - Syntax and Logic

Wazuh rules define the threat detection logic: which events are security-relevant, what severity level to assign, and what metadata to attach to the alert. Each rule is described in XML and contains trigger conditions, a description, and a classification. This guide provides a detailed look at rule syntax, the severity level system, composite rules, and testing tools.

XML Rule Structure

Every rule is enclosed in a <rule> element within a <group> container:

<group name="syslog,sshd,">
  <rule id="100001" level="5">
    <decoded_as>sshd</decoded_as>
    <match>Failed password</match>
    <description>SSH authentication failure.</description>
    <mitre>
      <id>T1110</id>
    </mitre>
    <group>authentication_failed,pci_dss_10.2.4,</group>
  </rule>
</group>

Rule Element Attributes

AttributeRequiredDescription
idYesUnique numeric identifier (1-999999)
levelYesAlert severity level (0-15)
frequencyNoNumber of matches required to trigger
timeframeNoTime window in seconds for frequency
ignoreNoSuppression duration for repeated alerts (seconds)
maxsizeNoMaximum event size
noalertNoIf 1, the rule triggers without generating an alert
overwriteNoIf yes, overwrites the rule with the same id

Trigger Condition Elements

Content Matching

match - searches for a substring or pattern in the log body:

<match>Failed password</match>

Supports negate="yes" (inversion) and type (osmatch, osregex, pcre2) attributes:

<match type="pcre2" negate="yes">successful|accepted</match>

regex - searches using a regular expression:

<regex>Failed password for (\S+) from (\S+)</regex>

decoded_as - triggers when the event matches a specific decoder:

<decoded_as>sshd</decoded_as>

category - triggers by decoder category:

<category>firewall</category>

Extracted Field Matching

field - checks the value of a field extracted by a decoder:

<field name="log_type">error</field>

srcip / dstip - matches source or destination IP (supports CIDR notation):

<srcip>192.168.1.0/24</srcip>
<srcip negate="yes">10.0.0.0/8</srcip>

srcport / dstport - source or destination port:

<dstport>22</dstport>

user - username:

<user>root</user>

hostname - source hostname:

<hostname>web-server-01</hostname>

program_name - program name from the syslog header:

<program_name>sshd</program_name>

action - action extracted by the decoder:

<action>blocked</action>

status - event status:

<status>403</status>

url - URL from the event:

<url type="pcre2">/admin|/wp-login\.php</url>

protocol - transport protocol:

<protocol>TCP</protocol>

Time Filters

time - time-of-day range (format hh:mm-hh:mm):

<time>22:00-06:00</time>

weekday - day of the week:

<weekday>weekend</weekday>

Metadata and Description

description - human-readable rule description (required):

<description>Multiple SSH authentication failures from same source.</description>

info - supplementary information:

<info type="link">https://attack.mitre.org/techniques/T1110/</info>
<info type="text">Possible brute force attack detected.</info>

group - tags for grouping and filtering (comma-separated, trailing comma required):

<group>authentication_failed,brute_force,pci_dss_10.2.4,</group>

mitre - MITRE ATT&CK technique mapping:

<mitre>
  <id>T1110</id>
  <id>T1078</id>
</mitre>

options - additional behavioral flags:

<options>no_log</options>
<options>alert_by_email</options>

Rule Classification Levels (0-15)

Wazuh uses 16 severity levels. Assigning the correct level is critical for alert prioritization.

LevelTitleDescription
0IgnoredEvent is ignored, no alert generated. Used to suppress false positives
2System low priority notificationStatus messages with no security significance
3Successful/Authorized eventsLegitimate actions such as successful logins or firewall permits
4System low priority errorConfiguration issues, minor system problems
5User generated errorAuthentication errors (failed login, wrong password)
6Low relevance attackIneffective attacks, frequent IDS triggers with no real threat
7Bad word matchingEvents containing suspicious keywords but lacking clear classification
8First time seenAction performed for the first time (first login, new process)
9Error from invalid sourceActions from unknown or suspicious sources
10Multiple user generated errorsRepeated authentication failures (possible brute-force attack)
11Integrity checking warningBinary modifications, rootkit detection
12High importance eventCritical system warnings, application-level attacks
13Unusual error (high importance)Patterns matching common attack methodologies
14High importance security eventCorrelation-driven alerts, probable attacks
15Severe attackConfirmed attack, immediate response required. No chance of false positives

Rules at level 12 and above trigger real-time notifications (when alert integrations are configured).

Rule Ordering and Overwriting

Load Order

Wazuh loads rules in the following order:

  1. Default rules from /var/ossec/ruleset/rules/ (in alphabetical file order)
  2. Custom rules from /var/ossec/etc/rules/ (including local_rules.xml)

Custom rules are processed after default rules and can override them.

Overwriting Default Rules

To modify the behavior of a default rule, use the overwrite attribute:

<!-- Overwrite default rule 5710 (change the level) -->
<rule id="5710" level="10" overwrite="yes">
  <decoded_as>sshd</decoded_as>
  <match>illegal user|invalid user</match>
  <description>SSH: attempt to login using a non-existent user.</description>
  <mitre>
    <id>T1110.001</id>
  </mitre>
  <group>authentication_failed,pci_dss_10.2.4,</group>
</rule>

An overwritten rule must contain the complete definition, not just the changed fields.

Suppressing False Positives

To suppress a false positive, create a child rule with level 0:

<rule id="100100" level="0">
  <if_sid>5710</if_sid>
  <srcip>10.0.0.50</srcip>
  <description>Suppress SSH invalid user alert from monitoring system.</description>
</rule>

Composite Rules (Correlation)

Composite rules detect patterns based on event sequences or frequencies.

Parent Rule Linkage (if_sid)

if_sid - the rule triggers only if the specified rule has already fired:

<rule id="100010" level="10">
  <if_sid>5710</if_sid>
  <same_source_ip />
  <description>Multiple SSH invalid user attempts from same source.</description>
</rule>

if_group - triggers on group membership:

<rule id="100011" level="8">
  <if_group>authentication_failed</if_group>
  <match>root</match>
  <description>Authentication failure for root account.</description>
</rule>

if_level - triggers based on the level of a preceding event:

<rule id="100012" level="12">
  <if_level>10</if_level>
  <same_source_ip />
  <description>High severity event followed by another from same source.</description>
</rule>

Frequency Rules (frequency + timeframe)

if_matched_sid - triggers when the specified rule fires frequency times within timeframe seconds:

<rule id="100020" level="10" frequency="5" timeframe="120">
  <if_matched_sid>5710</if_matched_sid>
  <same_source_ip />
  <description>SSH brute force: 5 invalid user attempts in 2 minutes.</description>
  <mitre>
    <id>T1110.001</id>
  </mitre>
  <group>brute_force,pci_dss_11.4,</group>
</rule>

if_matched_group - same concept, but by rule group:

<rule id="100021" level="10" frequency="8" timeframe="300">
  <if_matched_group>authentication_failed</if_matched_group>
  <same_source_ip />
  <description>Multiple authentication failures from same IP in 5 minutes.</description>
</rule>

Field Correlation Elements

ElementDescription
<same_source_ip />Source IP matches across correlated events
<different_source_ip />Source IP differs
<same_dst_ip />Destination IP matches
<different_dst_ip />Destination IP differs
<same_user />Username matches
<different_user />Username differs
<same_id />Identifier matches
<same_location />Log source matches
<same_protocol />Protocol matches
<different_protocol />Protocol differs

CDB Lists (Constant Database)

CDB lists enable field value lookups against external reference tables (IP lists, IoCs, allowed processes).

List Format

A list file contains key:value pairs (the value is optional):

192.168.1.100:known_scanner
10.0.0.50:monitoring_system
172.16.0.0/12:

Usage in Rules

<rule id="100030" level="12">
  <if_sid>5710</if_sid>
  <list field="srcip" lookup="address_match_key">etc/lists/malicious-ips</list>
  <description>SSH login attempt from known malicious IP.</description>
</rule>

Lookup types:

TypeDescription
match_keyExact key match
not_match_keyKey is absent from the list
address_match_keyIP address match (with CIDR support)
not_address_match_keyIP address is absent from the list
match_key_valueKey and value match

Registering Lists

Lists must be registered in ossec.conf:

<ruleset>
  <list>etc/lists/malicious-ips</list>
</ruleset>

After adding or modifying a list, reload the manager:

/var/ossec/bin/wazuh-control reload

Default Ruleset Overview

Default Wazuh rules are organized by category into separate files.

FileCategoryExample Rules
0015-ossec_rules.xmlWazuh internalAgent status, manager errors
0095-sshd_rules.xmlSSHAuthentication, brute force, invalid user
0100-syslog_rules.xmlSyslogLinux system events
0200-attack_rules.xmlAttacksCommon attack detection
0210-pam_rules.xmlPAMPAM authentication
0230-postfix_rules.xmlMailPostfix mail server
0240-apache_rules.xmlApacheApache web server
0250-nginx_rules.xmlNginxNginx web server
0350-amazon_rules.xmlAWSCloudTrail, GuardDuty
0470-windows_rules.xmlWindowsWindows Event Log
0575-win-firewall_rules.xmlWindows FirewallWindows Defender Firewall
0620-win-security_rules.xmlWindows SecurityWindows security auditing
0800-sysmon_rules.xmlSysmonWindows process monitoring
0840-docker_rules.xmlDockerContainer events

A complete listing of rule files is available in /var/ossec/ruleset/rules/.

MITRE ATT&CK Mapping

Wazuh supports mapping rules to MITRE ATT&CK techniques and tactics, enabling ATT&CK matrix coverage visualization in the Dashboard.

<rule id="100050" level="12">
  <if_sid>5710</if_sid>
  <frequency>10</frequency>
  <timeframe>60</timeframe>
  <same_source_ip />
  <description>SSH brute force attack detected.</description>
  <mitre>
    <id>T1110.001</id>  <!-- Brute Force: Password Guessing -->
  </mitre>
</rule>

Technique identifiers must be verified against the official MITRE ATT&CK matrix .

Compliance Standard Groups

Rules may include tags that map to regulatory standards:

<group>pci_dss_10.2.4,gdpr_IV_32.2,hipaa_164.312.b,nist_800_53_AU.14,tsc_CC6.1,</group>

Testing Rules with wazuh-logtest

The wazuh-logtest utility enables interactive rule testing.

Interactive Mode

/var/ossec/bin/wazuh-logtest

Enter a log line and receive the analysis result:

Type one log per line

Mar  5 10:15:01 server sshd[12345]: Failed password for invalid user admin from 192.168.1.100 port 22 ssh2

**Phase 1: Completed pre-decoding.
       full event: 'Mar  5 10:15:01 server sshd[12345]: Failed password for invalid user admin from 192.168.1.100 port 22 ssh2'
       timestamp: 'Mar  5 10:15:01'
       hostname: 'server'
       program_name: 'sshd'

**Phase 2: Completed decoding.
       name: 'sshd'
       parent: 'sshd'
       srcip: '192.168.1.100'
       srcport: '22'
       srcuser: 'admin'

**Phase 3: Completed filtering (rules).
       id: '5710'
       level: '5'
       description: 'sshd: Attempt to login using a non-existent user.'
       groups: '['syslog', 'sshd', 'invalid_login', 'authentication_failed']'

Batch Mode

To test a set of logs from a file:

cat test-logs.txt | /var/ossec/bin/wazuh-logtest -q

Verifying a Specific Rule

To confirm that a specific rule triggers on a specific log, use the -U flag:

echo "test log line" | /var/ossec/bin/wazuh-logtest -U 100001:5:sshd

The command returns exit code 0 if the rule with id=100001, level=5, and decoder sshd fired.

Verbose Output

For debugging, use the -v flag:

/var/ossec/bin/wazuh-logtest -v

Rule ID Ranges

When creating custom rules, use identifiers in the 100000-999999 range to avoid conflicts with default rules.

RangePurpose
100000-109999General security detections
110000-119999Application-specific rules
120000-129999AI/ML pipeline monitoring
147000-147999File integrity and YARA
191000-191999Privilege escalation

Rule Authoring Checklist

When creating a new rule, verify that all items are addressed:

  • Rule identifier (id) is within the correct range
  • Level (level) matches the event severity
  • Description (description) is clear and actionable
  • MITRE ATT&CK mapping (mitre/id) is specified and verified
  • The decoder extracts the required fields before the rule fires
  • The rule has been tested with wazuh-logtest
  • No catastrophic backtracking risk in regular expressions
  • Group tags (group) are populated and end with a comma

Related Sections

Last updated on