Difference between revisions of "Wazuh Custom Rule Creation"

From Notes_Wiki
 
Line 278: Line 278:


=== Example 3: Match srcip and hostname ===
=== Example 3: Match srcip and hostname ===
The '''<srcip>''' tag ensures that the rule is triggered only when the source IP address in the log exactly matches the value specified in log (e.g., a known attacker IP). If the source IP in the incoming log differs from the value provided, the rule will not be applied. This allows for more precise alerting by narrowing down rule activation to specific IP addresses associated with potential threats.
The alert will fire only if both the source IP and hostname match the specified values. If either the source IP differs or the hostname does not match, the custom rule will not apply and in such cases, the default alert will be triggered instead. This mechanism allows for more accurate and focused alerting by restricting rule execution to specific hosts and IP addresses linked to potential threats.


<pre>
<pre>

Latest revision as of 13:20, 6 June 2025

Home > Wazuh > Wazuh Custom Rule Creation

Wazuh Custom Rule Creation

In Wazuh, we analyze triggered alerts by reviewing fields such as rule.description, full log details, srcip, rule.level, and others. Additionally, we leverage threat intelligence platforms like VirusTotal, AbuseIPDB, and similar sources to investigate data points such as attacker IPs or file hash values. Based on this comprehensive analysis, we determine whether an alert represents a true positive or a false positive. Depending on the outcome, we either create custom rules or modify existing default rules by adjusting parameters like the rule level, ID, description, and other relevant settings.

In Wazuh, there are two types of rules:

  1. Default rules
  2. Custom rules

Default Rules

Wazuh’s default rules are pre-configured rules included with every Wazuh installation. These are located at:

/var/ossec/ruleset/rules/

These rules are designed to monitor a broad spectrum of security events and log sources, providing a solid foundation for detecting common security threats such as attacks, vulnerabilities, and suspicious activities.

Note: Modifying existing default rules is not recommended directly.

Creating Custom Rule by Modifing Existing Rules

Wazuh allows us to modify its built-in rules by copying them to:

/var/ossec/etc/rules/local_rules.xml

To override a rule, add the attribute overwrite="yes".

Sample Event Log

Jun 06 08:46:21 thehive sshd[2556]: Invalid user test from 10.9.8.16 port 39496

Let's use this example with Rule ID 5710: sshd: Attempt to login using a non-existent user.

Default Rule Definition

Below is the default rule definition triggered for rule ID 5710:

<group name="syslog,sshd,">
  <rule id="5710" level="5">
    <if_sid>5700</if_sid>
    <match>illegal user|invalid user</match>
    <description>sshd: Attempt to login using a non-existent user</description>
    <mitre>
      <id>T1110.001</id>
      <id>T1021.004</id>
    </mitre>
    <group>authentication_failed,gdpr_IV_35.7.d,...</group>
  </rule>
</group>

Example 1: Change Alert Level

Modifying the severity level of the existing rule for sshd: Attempt to login using a non-existent user (Rule ID 5710) from level 5 to level 10. The updated rule is shown below:


<group name="syslog,sshd,">
  <rule id="5710" level="10" overwrite="yes">
    <if_sid>5700</if_sid>
    <match>illegal user|invalid user</match>
    <description>sshd: Attempt to login using a non-existent user</description>
    <mitre>
      <id>T1110.001</id>
      <id>T1021.004</id>
    </mitre>
    <group>authentication_failed,gdpr_IV_35.7.d,...</group>
  </rule>
</group>

Example 2: Match by Hostname

We now include the <hostname> tag in the rule to ensure that alerts are triggered only when the hostname in the event log matches the specified value. If the hostname does not match, the rule will not activate, even if all other conditions in the event are met

<group name="syslog,sshd,">
  <rule id="5710" level="10" overwrite="yes">
    <if_sid>5700</if_sid>
    <match>illegal user|invalid user</match>
    <hostname>t-t</hostname>
    <description>sshd: Attempt to login using a non-existent user</description>
    <mitre>
      <id>T1110.001</id>
      <id>T1021.004</id>
    </mitre>
    <group>authentication_failed,gdpr_IV_35.7.d,...</group>    
  </rule>
</group>

Example 3: Match by Source IP

We now add the <srcip> tag to the rule to ensure that alerts are triggered only when the source IP address in the event log matches the specified value. If the source IP does not match, the rule will not trigger even if the rest of the event content meets the other conditions.

<group name="syslog,sshd,">
  <rule id="5710" level="10" overwrite="yes">
    <if_sid>5700</if_sid>
    <match>illegal user|invalid user</match>
    <srcip>10.9.8.16</srcip>
    <description>sshd: Attempt to login using a non-existent user</description>
    <mitre>
      <id>T1110.001</id>
      <id>T1021.004</id>
    </mitre>
    <group>authentication_failed,gdpr_IV_35.7.d,...</group>   
  </rule>
</group>

Custom Rules

In Wazuh, custom rules are used to define specific conditions or patterns that determine when an alert should be triggered. These rules enable users to customize security monitoring based on the unique needs of their environment. Unlike default rules, which come pre-configured with Wazuh, custom rules are user-defined and maintained to address specialized security requirements or to refine detection logic. Custom rules are written in the file located at:

 /var/ossec/rules/local_rules.xml

Use custom rule IDs (100000 to 120000) to avoid conflicts.

Basic Custom Rule Structure

Below is the basic structure of a custom rule with mandatory tags and in further examples below we add some other tags like <group>, <mitre> etc. for better classification and fine tuning the alert generation.

<group name="custom_name,">
  <rule id="100010" level="5">
    <if_sid>...</if_sid>
    <match>...</match>
    <description>...</description>
  </rule>
</group>

Testing Rules

Use the following binary to test log matches:

/var/ossec/bin/wazuh-logtest

Example Log:

Jun 05 09:48:16 shuffle sshd[6670]: '''Failed password for shuffle from 10.9.8.16 port 57868 ssh2'''

Run:

/var/ossec/bin/wazuh-logtest

Paste the log and observe the output.

Sample Output

Below is the output for the example log:

**Phase 1: Completed pre-decoding.
	full event: 'Jun 05 09:48:16 shuffle sshd[6670]: Failed password for shuffle from 10.9.8.16 port 57868 ssh2'
	timestamp: 'Jun 05 09:48:16'
	hostname: 'shuffle'
	program_name: 'sshd'

**Phase 2: Completed decoding.
	name: 'sshd'
	parent: 'sshd'
	dstuser: 'shuffle'
	srcip: '10.9.8.16'
	srcport: '57868'

**Phase 3: Completed filtering (rules).
	id: '5760'
	level: '5'
	description: 'sshd: authentication failed.'
	groups: '['syslog', 'sshd', 'authentication_failed']'
	firedtimes: '1'
	gdpr: '['IV_35.7.d', 'IV_32.2']'
	gpg13: '['7.1']'
	hipaa: '['164.312.b']'
	mail: 'False'
	mitre.id: '['T1110.001', 'T1021.004']'
	mitre.tactic: '['Credential Access', 'Lateral Movement']'
	mitre.technique: '['Password Guessing', 'SSH']'
	nist_800_53: '['AU.14', 'AC.7']'
	pci_dss: '['10.2.4', '10.2.5']'
	tsc: '['CC6.1', 'CC6.8', 'CC7.2', 'CC7.3']'
**Alert to be generated.

Triggered Rule

This is the default rule definition for the example log above:

<group name="syslog,sshd,">
  <rule id="5760" level="5">
    <if_sid>5700,5716</if_sid>
    <match>Failed password|Failed keyboard|authentication error</match>
    <description>sshd: authentication failed.</description>
    <mitre>
      <id>T1110.001</id>
      <id>T1021.004</id>
    </mitre>
    <group>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,</group>
  </rule>
</group>

Creating Custom Rules

Example 1: Basic Custom Rule

<group name="custom_rule,">
  <rule id="100002" level="3">
    <if_sid>5760</if_sid>
    <match>Failed password|Failed keyboard|authentication error</match>
    <description>custom rule for sshd authentication failed.</description>
  </rule>
</group>

Explanation:

  • <group> — Assigns a group name
  • <rule> — Custom ID and severity
  • <if_sid> — Triggers only if rule 5760 matches
  • <match> — String match
  • <description> — Rule purpose

wazuh-logtest Output

**Phase 1: Completed pre-decoding.
	full event: 'Jun 05 09:48:16 shuffle sshd[6670]: Failed password for shuffle from 10.9.8.16 port 57868 ssh2'
	timestamp: 'Jun 05 09:48:16'
	hostname: 'shuffle'
	program_name: 'sshd'

**Phase 2: Completed decoding.
	name: 'sshd'
	parent: 'sshd'
	dstuser: 'shuffle'
	srcip: '10.9.8.16'
	srcport: '57868'

**Phase 3: Completed filtering (rules).
  id: '100002'
  level: '3'
  description: 'custom rule for sshd authentication failed.'
  groups: '['custom_rule']'
  firedtimes: '1'
  mail: 'False'
**Alert to be generated.

Example 2: Match srcip

The below rule will only trigger an alert if both specified conditions the hostname and the source IP address are simultaneously met in the incoming log data. This means that even if the log contains the correct source IP but the hostname doesn't match (or vice versa), the rule will not activate. Both criteria must align exactly with the values defined in the rule for it to be evaluated as a match and generate an alert.

<group name="custom_rule">
  <rule id="100002" level="3">
    <if_sid>5760</if_sid>
    <match>Failed password|Failed keyboard|authentication error</match>
    <srcip>10.9.8.16</srcip>
    <description>Custom rule for SSHD authentication failures.</description>
    <group>authentication_failed,sshd</group>
    <mitre>
      <id>T1110.001</id>
      <id>T1021.004</id>
    </mitre>
  </rule>
</group>

Additional Tags

  • <group>: Classifies alert
  • <mitre>: Maps TTPs for threat intelligence
  • <srcip>: Only triggers if source IP matches

Example 3: Match srcip and hostname

The alert will fire only if both the source IP and hostname match the specified values. If either the source IP differs or the hostname does not match, the custom rule will not apply and in such cases, the default alert will be triggered instead. This mechanism allows for more accurate and focused alerting by restricting rule execution to specific hosts and IP addresses linked to potential threats.

<group name="custom_rule">
  <rule id="100002" level="3">
    <if_sid>5760</if_sid>
    <match>Failed password|Failed keyboard|authentication error</match>
    <srcip>10.9.8.16</srcip>
    <hostname>t-t</hostname>
    <description>Custom rule for SSHD authentication failures.</description>
    <group>authentication_failed,sshd</group>
    <mitre>
      <id>T1110.001</id>
      <id>T1021.004</id>
    </mitre>
  </rule>
</group>

Additional Tags

  • <srcip>: Triggers only if source IP matches
  • <hostname>: Triggers only if hostname matches

Example 4: Adding Multiple Rule ID's in a Custom Rule

To add multiple rule ID's in a custom rule, we give the rule ID's by separating them with a coma inside the <if_sid> tag. For this example I have taken three example rule IDs, they are:

Logon Failure - Unknown user or bad password - 60122
syslog: User missed the password more than one time - 2502
PAM: User login failed. - 5503

If any of the three rules (60122, 2502, or 5503) trigger, this custom rule will also trigger. We can chage the rule level based on our priority. Below is the example custom rule defination:

<group name="custom_rule">
  <rule id="100030" level="10">
    <if_sid>60122,2502,5503</if_sid>
    <description>Custom alert for multiple types of failed login attempts</description>
    <group>authentication_failed,login_attempts</group>
    <mitre>
      <id>T1110.001</id>
    </mitre>
  </rule>
</group>