,

Custom Alert Rules in Wazuh

Custom Alert Rules in Wazuh

Task 1 Introduction

Wazuh

is an open-source security detection tool that works on top of the ELK stack (Elasticsearch, Logstash, and Kibana) and is designed to identify threats using its alert rule system. This system uses rules to search for potential security threats or issues in logs from various sources, such as operating system logs, application logs, endpoint security logs, etc.

Out of the box, Wazuh has a comprehensive set of pre-configured rules. While these rules cover a wide range of potential security issues, there are still scenarios or risks unique to an organization that these rules may not cover. To compensate for this, organizations can create custom alert rules, which is the focus of this room.

Learning objectives:

  • Learn how important data is extracted from logs using Decoders.
  • Learn how alerts are triggered using Rules.
  • Learn how to add new rules to extend detection capabilities.
  • Learn how to simulate a real-world attack to test existing rules.

Room Prerequisites

  • Knowledge and experience with Wazuh — If you need an overview of its features, visit the Wazuh room.
  • Familiarity with regular expressions — Wazuh decoders and rules rely heavily on regular expressions, so brush up by checking out the Regular Expressions room.
  • Knowledge of Sysmon — We’ll use Sysmon logs as an example for this room.

Task 2 Decoders

  • One of Wazuh’s many features is that it can ingest logs from different sources and generate alerts based on their contents
  • But various logs can have varied data types and structures
  • To manage this Wazuh uses Decoders that use regex to extract only the needed data for later use

Understanding Decoders —

  • Considering Sysmon ( System Monitor ) tool logs as an example
  • There is a pre-existing decoder for this listed in the windows+decoders.xml file on, can also be downloaded from task files

<decoder name=”Sysmon-EventID#1_new”>
<parent>windows</parent>
<type>windows</type>
<prematch>INFORMATION\\(1\\)\\.+Hashes</prematch>
<regex>Microsoft-Windows-Sysmon/Operational: \\S+\\((\\d+)\\)</regex>
<order>id</order>
</decoder>

Breaking down the parts of the decoder block above:

  • Decoder name- The name of this decoder. ( Note multiple decoder blocks can have the same name; this should be pictured as if they are being grouped together )
  • Parent- The name of the parent decoder. The parent decoder is processed before the children decoders
  • Prematch- Uses regular expressions to look for a match. If this succeeds, it will process the “regex” option below
  • Regex- Uses regular expressions to extract data. Any string in between a non-escaped open and closed parenthesis is extracted
  • Order- Contains a list of names to which the extracted data will be stored
  • The log entry above shows an example event a Wazuh agent installed in a windows machine sent
  • It describes an event where the user ran a PowerShell script named test.ps1 from his system using poweshell.exe executable initiated by the Explorer process ( C”\Windows\explorer.exe )
  • The above log entry has lots of data in it and it is the work of the decoder to extract them
  • Once this log entry is ingested all appropriate decoder blocks will kick into action where they will check the prematch option
  • The decoder block above will check if any strings match the regular expression “INFORMATION\(1\)\.+Hashes”
  • First, the regex will look for the INFORMATION string.
  • Followed by an escaped open parenthesis \\(
  • Followed by a number 1
  • Followed by an escaped close parenthesis \\)
  • And then any number of characters \\.+
  • Until it reaches the Hashes string

Q 1. Looking at the Sysmon Log, what will the value of sysmon.commandLine be?

Answer: “C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe” “-file” “C:\Users\Alberto\Desktop\test.ps1”

Q 2. What would the extracted value be if the regex is set to “User: (\.) \s”?

Answer: WIN-P57C9KN929H\Alberto

Task 3 Rules

  • Rules contain defined conditions to detect specific events or malicious activities using the extracted data from decoders
  • An alert is generated when an event matches a rule
  • The rules defined in the sysmon_rules.xml file will be discussed below

Understanding Rules

Here is an example of an alert rule that looks for the “svchost.exe” string in the “sysmon.image” field:

sysmon_rules.xml<rule id=”184666″ level=”12″><if_group>sysmon_event1</if_group><field name=”sysmon.image”>svchost.exe</field><description>Sysmon – Suspicious Process – svchost.exe</description><mitre><id>T1055</id></mitre><group>pci_dss_10.6.1,pci_dss_11.4,…</group></rule>

  • A rule block has multiple options
  • rule-id — The unique identity of the rule
  • rule level — The classification of levels from 0–15 indicating the level of severity as listed by Wazuh
  • if_group — Specifies the group name that triggers this rule when that group has matched
  • field name — The name of the field extracted from the decoder. The value in this field is matched using regex
  • group — Contains a list of groups or categories that the rule belongs to. It can be used for organizing and filtering rules

Testing the Rule

Go back to the “Ruleset Test” page. Paste the exact log entry we used in the previous task. The result should be the same, but this time, we will focus on Phase 3 of the output.

Ruleset Test Output**Phase 3: Completed filtering (rules).
id: 184665
level: –
description: Sysmon – Event 1
groups: [“sysmon”,”sysmon_event1″]
firedtimes: 1
gdpr: “-“
gpg13: “-“
hipaa: “-“
mail: “-“
mitre.id: “-“
mitre.technique: “-“
nist_800_53: “-“
pci_dss: “-“
tsc: “-“

Phase 3 shows what information an alert would contain when a rule is triggered, like “id”, “level”, “description”, etc.

Right now, the output shows that the triggered rule ID is 184665. This is not the rule block that we examined above, which has the ID of 184666. The reason for this is that 184666 is looking for “svchost.exe” in the “sysmon.image” field option. For this rule to trigger, we need to change “C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe” to “C:\WINDOWS\system32\svchost.exe”, as shown below:

Sysmon LogMar 29 13:36:36 WinEvtLog: Microsoft-Windows-Sysmon/Operational: INFORMATION(1): Microsoft-Windows-Sysmon: SYSTEM: NT AUTHORITY: WIN-P57C9KN929H: Process Create: UtcTime: 2017-03-29 11:36:36.964 ProcessGuid: {DB577E3B-9C44-58DB-0000-0010B0983A00} ProcessId: 3784 Image: C:\\WINDOWS\\system32\\svchost.exe CommandLine: “C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe” “-file” “C:\\Users\\Alberto\\Desktop\\test.ps1” CurrentDirectory: C:\\Users\\Alberto\\Desktop\\ User: WIN-P57C9KN929H\\Alberto LogonGuid: {DB577E3B-89E5-58DB-0000-0020CB290500} LogonId: 0x529cb TerminalSessionId: 1 IntegrityLevel: Medium Hashes: MD5=92F44E405DB16AC55D97E3BFE3B132FA,SHA256=6C05E11399B7E3C8ED31BAE72014CF249C144A8F4A2C54A758EB2E6FAD47AEC7 ParentProcessGuid: {DB577E3B-89E6-58DB-0000-0010FA3B0500} ParentProcessId: 2308 ParentImage: C:\\Windows\\explorer.exe ParentCommandLine: C:\\Windows\\Explorer.EXE

When this is done, press the “Test” button again to run the Ruleset Test. The output should now be different, especially in Phase 3:

Ruleset Test Output**Phase 3: Completed filtering (rules).
id: 184666
level: 12
description: Sysmon – Suspicious Process – svchost.exe
groups: [“sysmon”,”sysmon_process-anomalies”]
firedtimes: 1
gdpr: [“IV_35.7.d”]
gpg13: “-“
hipaa: [“164.312.b”]
mail: true
mitre.id: {“id”:[“T1055″],”tactic”:[“Defense Evasion”,”Privilege Escalation”],”technique”:[“Process Injection”]}
mitre.technique: {“id”:[“T1055″],”tactic”:[“Defense Evasion”,”Privilege Escalation”],”technique”:[“Process Injection”]}
nist_800_53: [“AU.6″,”SI.4”]
pci_dss: [“10.6.1″,”11.4”]
tsc: [“CC7.2″,”CC7.3″,”CC6.1″,”CC6.8”]
**Alert to be generated.

Because our rule now matches the log, the triggered Rule is now 184666. There is now also more information on the output thanks to the mitre and group options in the rule block.

Q 3. From the Ruleset Test results, what is the <mitre> ID of rule id 184666?

Answer: T1055

Q 4. According to the Wazuh documentation, what is the description of the rule with a classification level of 12?

Answer: High Importance Level

Q 5. In the Ruleset Test page, change the value of “sysmon.image” to “taskhost.exe’, and press the “Test” button again. What is the ID of the rule that will get triggered?

Answer: 184736

URL — https://github.com/wazuh/wazuh/blob/master/ruleset/rules/0330-sysmon_rules.xml

Task 4 Rule Order

  • In Wazuh rules are processed based on several factors determining rule order
  • One factor that will be discussed that is relevant to making custom rules is the “if” condition prerequisites
  • if_group option in the previous task, but there other “if” condition prerequisites like the if_side option shown below:

sysmon_rules.xml
<rule id=”184667″ level=”0″>
<if_sid>184666</if_sid>
<field name=”sysmon.parentImage”>\\\\services.exe</field>
<description>Sysmon – Legitimate Parent Image – svchost.exe</description>
</rule>

• if_sid — Specifies the ID of another rule that triggers this rule. In this example, the rule is triggered if an event with the ID of 184666 has been triggered.

These “if” condition prerequisites are considered the “parent” that must be evaluated first. Because of this parent-child relationship, it is essential to note that Wazuh Rules are triggered from a top-to-down manner. When rules are processed, the condition prerequisites are checked, and the rule order is updated.

Testing the Rule Order

Go back to the “Ruleset Test” page. Paste the exact log entry we used in the previous task. We want to trigger Rule ID 184667, so our Sysmon log entry should have the value of “sysmon.parentImage” changed to C:\\\\Windows\\\\services.exe.

The log entry should now look like the one below:

Sysmon LogMar 29 13:36:36 WinEvtLog: Microsoft-Windows-Sysmon/Operational: INFORMATION(1): Microsoft-Windows-Sysmon: SYSTEM: NT AUTHORITY: WIN-P57C9KN929H: Process Create: UtcTime: 2017-03-29 11:36:36.964 ProcessGuid: {DB577E3B-9C44-58DB-0000-0010B0983A00} ProcessId: 3784 Image: C:\\WINDOWS\\system32\\svchost.exe CommandLine: “C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe” “-file” “C:\\Users\\Alberto\\Desktop\\test.ps1” CurrentDirectory: C:\\Users\\Alberto\\Desktop\\ User: WIN-P57C9KN929H\\Alberto LogonGuid: {DB577E3B-89E5-58DB-0000-0020CB290500} LogonId: 0x529cb TerminalSessionId: 1 IntegrityLevel: Medium Hashes: MD5=92F44E405DB16AC55D97E3BFE3B132FA,SHA256=6C05E11399B7E3C8ED31BAE72014CF249C144A8F4A2C54A758EB2E6FAD47AEC7 ParentProcessGuid: {DB577E3B-89E6-58DB-0000-0010FA3B0500} ParentProcessId: 2308 ParentImage: C:\\Windows\\services.exe ParentCommandLine: C:\\Windows\\Explorer.EXE

Pressing the “Test” button would then output the following:

Ruleset Test Output**Phase 3: Completed filtering (rules).
id: 184667
level: –
description: Sysmon – Legitimate Parent Image – svchost.exe
groups: [“sysmon”,”sysmon_process-anomalies”]
firedtimes: 1
gdpr: “-“
gpg13: “-“
hipaa: “-“
mail: “-“
mitre.id: “-“
mitre.technique: “-“
nist_800_53: “-“
pci_dss: “-“
tsc: “-“

We can see that the triggered rule is 184667, which is what we expected. What is not shown in the output, however, is that before 184667 was triggered, Wazuh first checked if_sid and found that Rule ID184666 was a prerequisite. Before rule ID 184666, Wazuh then saw that it has if_group set to sysmon_event1, which is associated with Rule ID 184665. This goes on and on until all the chains of prerequisites are satisfied.

Q 6. In the sysmon_rules.xml file, what is the Rule ID of the parent of 184717?

Answer: 184716

Task 5 Custom Rules

As mentioned before, the pre-existing rules are comprehensive. However, it cannot cover all use cases, especially for all organizations with unique needs and requirements.

There are several reasons why we want to have custom rules:

  • You want to enhance the detection capabilities of Wazuh.
  • You are integrating a not-so-well-known security solution.
  • You use an old version of a security solution with an older log format.
  • You recently learned of a new attack and want to create a specific detection rule.
  • You want to fine-tune a rule.

In this task the auitd_rules.xml will be used, URL: https://github.com/wazuh/wazuh/blob/master/ruleset/rules/0365-auditd_rules.xml

Auditd Logtype=SYSCALL msg=audit(1479982525.380:50): arch=c000003e syscall=2 success=yes exit=3 a0=7ffedc40d83b a1=941 a2=1b6 a3=7ffedc40cce0 items=2 ppid=432 pid=3333 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm=”touch” exe=”/bin/touch” key=”audit-wazuh-w” type=CWD msg=audit(1479982525.380:50): cwd=”/var/log/audit” type=PATH msg=audit(1479982525.380:50): item=0 name=”/var/log/audit/tmp_directory1/” inode=399849 dev=ca:02 mode=040755 ouid=0 ogid=0 rdev=00:00 nametype=PARENT type=PATH msg=audit(1479982525.380:50): item=1 name=”/var/log/audit/tmp_directory1/malware.py” inode=399852 dev=ca:02 mode=0100644 ouid=0 ogid=0 rdev=00:00 nametype=CREATE type=PROCTITLE msg=audit(1479982525.380:50): proctitle=746F756368002F7661722F6C6F672F61756469742F746D705F6469726563746F7279312F6D616C776172652E7079

The log describes an event wherein a touch command (probably as root user) was used to create a new file called malware.py in the /var/log/audit/tmp_directory1/ directory. The command was successful, and the log was generated based on an audit rule with the key “audit-wazuh-w”.

When Wazuh ingests the above log, the pre-existing rule below will get triggered because of the value of <match>:

auditd_rules.xml<rule id=”80790″ level=”3″><if_group>audit_watch_write</if_group><match>type=CREATE</match><description>Audit: Created: $(audit.file.name)</description><group>audit_watch_write,audit_watch_create,gdpr_II_5.1.f,gdpr_IV_30.1.g,</group></rule>

Adding Local Rules

For this exercise, let’s create a custom rule that will override the above rule so we have more control over the information we display.

To do this, you need to do the following:

  1. Connect to the server using SSH at 10.10.177.121 and use thm for the username and TryHackMe! the password. The credentials and connection details are listed in Task 1 of this room.
  2. Use the sudo su command to become the root user.
  3. Open the file /var/ossec/etc/rules/local_rules.xml using your favourite editor.
  4. Paste the following text at the end of the file:

local_rules.xml<group name=”audit,”><rule id=”100002″ level=”3″><if_sid>80790</if_sid><field name=”audit.cwd”>downloads|tmp|temp</field><description>Audit: $(audit.exe) created a file with filename $(audit.file.name) the folder $(audit.directory.name).</description><group>audit_watch_write,</group></rule></group>

The rule above will get triggered if a file is created in the downloads, tmp, or temp folders. Let’s break this down so we can better understand:

  • group name=”audit,” We are setting this to the same value as the grouped rules in audit_rules.xml.
  • rule id=”100002″ — Each custom rule needs to have a unique ID. Custom IDs start from 100001 onwards. Since there is already an existing example rule that uses 100001, we are going to use 100002.
  • level=”3″ — We are setting this to 3 (Successful/Authorized events) because a file created in these folders isn’t necessarily malicious.
  • if_sid — We set the parent to rule ID 80790 because we want that rule to be processed before this one.
  • field name=”audit.directory.name The string here is matched using regex. In this case, we are looking for tmp, temp, or downloads matches. This value is compared to the audit.cwd variable fetched by the auditd decoder.
  • description The description that will appear on the alert. Variables can be used here using the format $(variable.name).
  • group — Used for grouping this specific alert. We just took the same value from rule 80790.

Save the file and run the code below to restart wazuh-manager so it can load the new custom rules:

Bashsystemctl restart wazuh-manager

Go back to the Wazuh dashboard, access the “Ruleset Test” page and paste the sample auditd log entry found above. If all goes well, you should see the following “Phase 3” output:

Ruleset Test Output**Phase 3: Completed filtering (rules).
id: ‘100002’
level: ‘3’
description: ‘Audit: /bin/touch created a file with filename /var/log/audit/tmp_directory1/malware.py the folder /var/log/audit.’
groups: ‘[“audit”,”audit_watch_write”]’
firedtimes: ‘1’
mail: ‘false’

From the results above, we can see that the custom rules that we created triggered an alert successfully.

Q 7. What is the regex field name used in the local_rules.xml?

Answer: audit.cwd

Step 1: SSH into the machine with the given credentials and elevate privileges to root using the sudo su command

Editing the file in nano —

Q 8. Looking at the log, what is the current working directory (CWD) from where the command was executed?

Answer: /var/log/audit

Running the sample log in the rule test against the newly added rule in the local_rules.xml file

Task 6 Fine-Tuning

You can fine-tune the custom rule by adding more child rules, each focusing on specific related data from the logs. For example, you can use the values decoded by auditd decoder, as shown in the Phase 2 results of the previous test.

Ruleset Test Output**Phase 2: Completed decoding.
name: ‘auditd’
parent: ‘auditd’
audit.arch: ‘c000003e’
audit.auid: ‘0’
audit.command: ‘touch’
audit.cwd: ‘/var/log/audit’
audit.directory.inode: ‘399849’
audit.directory.mode: ‘040755’
audit.directory.name: ‘/var/temp/downloads/tmp_directory1/’
audit.egid: ‘0’
audit.euid: ‘0’
audit.exe: ‘/bin/touch’
audit.exit: ‘3’
audit.file.inode: ‘399852’
audit.file.mode: ‘0100644’
audit.file.name: ‘/var/log/audit/tmp_directory1/malware.py’
….

We can use the above data to make our detection rules as broad or as specific as needed. The following is an expanded version of local_rules.xml that incorporates more of the log’s data.

local_rules.xml<group name=”audit,”><rule id=”100002″ level=”3″><if_sid>80790</if_sid><field name=”audit.directory.name”>downloads|tmp|temp</field><description>Audit: $(audit.exe) created a file with filename $(audit.file.name) in the folder $(audit.directory.name).</description><group>audit_watch_write,</group></rule><rule id=”100003″ level=”12″><if_sid>100002</if_sid><field name=”audit.file.name”>.py|.sh|.elf|.php</field><description>Audit: $(audit.exe) created a file with a suspicious file extension: $(audit.file.name) in the folder $(audit.directory.name).</description><group>audit_watch_write,</group></rule><rule id=”100004″ level=”6″><if_sid>100002</if_sid><field name=”audit.success”>no</field><description>>Audit: $(audit.exe) created a file with filename $(audit.file.name) but failed</description><group>audit_watch_write,</group></rule><rule id=”100005″ level=”12″><if_sid>100003</if_sid><field name=”audit.file.name”>>malware|shell|dropper|linpeas</field><description>Audit: $(audit.exe) created a file with suspicious file name: $(audit.file.name) in the folder $(audit.directory.name).</description><group>audit_watch_write,</group></rule><rule id=”100006″ level=”0″><if_sid>100005</if_sid><field name=”audit.file.name”>malware-checker.py</field><description>False positive. “malware-checker.py” is used by our red team for testing. This is just a temporary exception.</description><group>audit_watch_write,</group></rule></group>

You can test these rules by updating thelocal_rules.xml file and checking the output on the Ruleset Test Page.

Q 9. If the filename in the logs is “test.php”, what rule ID will be triggered?

Answer: 100003<rule id=”100003″ level=”12″>
<if_sid>100002</if_sid>
<field name=”audit.file.name”>.py|.sh|.elf|.php</field>
<description>Audit: $(audit.exe) created a file with a suspicious file extension: $(audit.file.name) in the folder $(audit.directory.name).</description>
<group>audit_watch_write,</group>
</rule>

Q 10. If the filename in the logs is “malware-checker.sh”, what is the rule classification level in the generated alert?

Answer: 12

Leave a Reply

Your email address will not be published. Required fields are marked *