DEV Community

Nguyen Dong
Nguyen Dong

Posted on

Three ways a third-party Wazuh rules file breaks a 4.14.7 manager

This week we loaded a third-party Wazuh decoder and rules file, exactly as published, into a clean Wazuh 4.14.7 manager (the official wazuh/wazuh-manager:4.14.7 container). It had three separate problems. One stopped the manager. The other two left it running with rules that could never fire.

None of the three is exotic, so we rebuilt each one with made-up names (myapp) and measured it again on its own. Everything below is from those reruns.

The test line, a syslog line with a JSON body:

Nov 10 10:30:00 web01 myapp: {"event":"deny","user":"alice","action":"block"}
Enter fullscreen mode Exit fullscreen mode

1. <field name="action"> on a static field: the manager does not start

action is one of Wazuh's static fields, like srcip or dstuser. A rule that matches it with the dynamic-field syntax:

<rule id="100501" level="12">
  <if_sid>100500</if_sid>
  <field name="action">block</field>
  <description>myapp: request blocked for $(user)</description>
</rule>
Enter fullscreen mode Exit fullscreen mode

is rejected when the ruleset loads:

wazuh-analysisd: ERROR: Failure to read rule 100501. Field 'action' is static.
wazuh-analysisd: CRITICAL: (1220): Error loading the rules: 'etc/rules/myapp_rules.xml'.
Enter fullscreen mode Exit fullscreen mode

and wazuh-control status then reports wazuh-analysisd not running.... One wrong tag in one added file, and nothing gets analysed at all. The fix is the static-field tag:

<action>block</action>
Enter fullscreen mode Exit fullscreen mode

2. PCRE syntax without type="pcre2": the decoder extracts nothing

<decoder name="myapp-event">
  <parent>myapp</parent>
  <regex>"event":"deny".*"user":"([^"]+)".*"action":"(\w+)"</regex>
  <order>user,action</order>
</decoder>
Enter fullscreen mode Exit fullscreen mode

Wazuh's default regex engine (OS_Regex) is not PCRE. With this decoder the manager runs, logtest shows the myapp decoder matching, and no fields come out. The parent rule still fires (level 8), but the level 12 rule that needs action never does, and there is no error anywhere. Adding the type fixes it:

<regex type="pcre2">"event":"deny".*"user":"([^"]+)".*"action":"(\w+)"</regex>
Enter fullscreen mode Exit fullscreen mode

3. decoded_as pointing at the child decoder: the rule never matches

<rule id="100500" level="8">
  <decoded_as>myapp-event</decoded_as>
  <description>myapp: request denied for $(user)</description>
</rule>
Enter fullscreen mode Exit fullscreen mode

With the decoder fixed, logtest extracts action and the user, and reports the decoder name as myapp, the parent. A rule with decoded_as set to the child name matched nothing in our test. Use the parent name:

<decoded_as>myapp</decoded_as>
Enter fullscreen mode Exit fullscreen mode

With all three changed, the test line raised rule 100501 at level 12.

A smaller one we hit on the way

user in <order> is stored in the static field dstuser. The descriptions above use $(user), and with every other fix in place rule 100501 still came out as "myapp: request blocked for " with nothing after it; changing it to $(dstuser) gave "myapp: request blocked for alice".

Checking a rules file before it goes into /var/ossec/etc/rules

On a test manager (a throwaway container is enough), mount the files, then:

grep -E "ERROR|CRITICAL" /var/ossec/logs/ossec.log
echo '<one real log line>' | /var/ossec/bin/wazuh-logtest
Enter fullscreen mode Exit fullscreen mode

The first line catches case 1. For the second, check three things in the output: that the fields you expect are listed under the decoder, that the decoder name is the one your rule's decoded_as uses, and that the rule id you expect appears in phase 3. Cases 2 and 3 only show up there.

Where our tool fits, and where it doesn't

We make Detection Watch, which reads a manager's alerts and lists custom rules that never fired in the last seven days. Its one-command quick check would list rules like the ones in cases 2 and 3 as never fired. It does nothing for case 1: when analysisd does not start there are no alerts to read, and the manager log above is the place to look.

Quick check: https://vct.atkvn.com/detection-watch.html?src=devto-3ways#quick

All measurements: Wazuh 4.14.7 only. We have not repeated them on 4.14.10 or 5.0.

Top comments (0)