Skip to the content.

Versão em Portugês

Integrating Wazuh with Discord

The Motive

In the future, I want to monitor my home network with Wazuh and Suricata working together. I also want an easy way to see the alerts that are generated by Wazuh.

I could use the Wazuh integrations that are ready, like Slack, but Discord is an App that I use daily and is perfect to use as an example on how to build a custom integration with Wazuh.

It’s possible to create a custom-integration to send alerts to practically any place that has a webhook or any other form of receiving data via POST requests. Like Microsoft Teams, for example.

The Ambient

I’m assuming that you already have Wazuh installed and working. I’m working with a “All in one” installation in my kali VM, you can follow with any Linux distribution you like. If you are working with Wazuh distributed in clusters, you will have to replicate this entire configuration on all the node managers that you want the integration to work.

Creating a Webhook

The first thing you need to do is create a discord webhook on your server chat

- Open your server settings
- On "Integrations", click on "webhooks" to generate one
- Save the webhook link for now

Creating The Integration

change directory into the Wazuh integrations folder.

You should see the default integrations scritps.

cd /var/ossec/integrations 

As you can see, that are two slack scritps, one is in bash and the other is in python, the reason for that is that the bash one will work like a launcher for the python script.

Copy both of them and name it to custom-discord

The Slack’s scripts were made by the Wazuh team to integrate with Slack via webhook, we can modify them to work with Discord webhook instead. Practically, the only modification needed for that to work is going to be the in the custom-discord.py generate_msg() function.

Before we continue, I think it’s good to understand how an integration is triggered and how you can control what types of alerts will trigger it.

Open the configuration file of the Wazuh manager, ossec.conf

vim /var/ossec/etc/ossec.conf

This block of xml is what activates the integration, you will need to insert this on the configuration file of the Wazuh manager, ossec.conf. You can insert in any place you like, just be careful to not put in the middle of another configuration block.

  <integration>
    <name>custom-discord</name>
    <hook_url>https://discord.com/api/webhooks/hook</hook_url>
    <level>7</level>
    <alert_format>json</alert_format>
  </integration>

You can use the following options to trigger the alert:

<group>suricata,sysmon</group> Only the rules of the group suricata and sysmon will trigger the integration.
<level>12</level> Only rules greate or equal to 12 will trigger.
<rule_id>1299,1300</rule_id> Only this rules will trigger.

Customizing The Script

After activating the integration, the next step would be customizing the custom-discord.py script.

Open the script with your favorite text editor, in the line 76 you can replace the generate_msg() function with the bellow function.

This function will take an Wazuh alert as an argument and because the alerts are coming in json format, we just need to fill the values of the keys in the dictionary and then send the payload to Discord.

When I build this function, I used Birdie0 repository to help me understand how discord webhooks worked.

If you want to modify the contents of the alert, you will need to modify the fields in the payload

I recommend that you check out Birdie repository birdie0.github.io/discord-webhooks-guide/index.html and explore to see if you will like something different for your alert.

A good tool to help you with that is Postman https://www.postman.com/

def generate_msg(alert):
	#save the rule level
    level = alert['rule']['level']
    #compare rules level to set colors of the alert
    if (level <= 4):
    	#green
        color = "3731970"
    elif (level >= 5 and level <= 12):
        #yellow
        color = "15919874"
    else:
        #red
        color = "15870466"

    if 'agentless' in alert:
        agent_ = 'agentless'
    else:
        agent_ = alert['agent']['name']
    #data that the webhook will receive and use to display the alert in discord chat
    payload = json.dumps({
      "embeds": [
        {
          "title": "Wazuh Alert - Rule {}".format(alert['rule']['id']),
          "color": "{}".format(color),
          "description": "{}".format(alert['rule']['description']),
          "fields": [
            {
              "name": "Agent",
              "value": "{}".format(agent_),
              "inline": True
            },
            {
              "name": "Location",
              "value": "{}".format(alert['location']),
              "inline": True
            },
            {
            "name": "Rule Level",
            "value": "{}".format(alert['rule']['level']),
            "inline": True
            }
          ]
        }
      ]
    })

    return payload

This is the alert format:

I also like to change the debug() function, so I can control more freely when to save debug logs.

The default path for the integrations log file is.

/var/ossec/logs/integrations.log

You can control if you want logs or not with the variable deb

def debug(msg):
        # debug log
        deb = True
        if deb == True:
            msg = "{0}: {1}\n".format(now, msg)
            print(msg)
            f = open(log_file, "a")
            f.write(msg)
            f.close()

You will need to chance the scripts permissions and owners:

chmod 750 custom-*
chown root:wazuh custom-*

You will need the requests library.

pip3 install requests

Creating A Custom Rule

Everything should be ready now, but before we restart the Wazuh manager to activate the integration, I like to create a custom rule that I can manually trigger to test the integration.

Create a file in /var/log named test.log

touch /var/log/test.log

Open the ossec.conf file again and navigate to the bottom, you should see a lot of localfile blocks, they indicate a path to a file that Wazuh will collect logs from.

Insert this block:

  <localfile>
    <location>/var/log/test.log</location>
    <log_format>syslog</log_format>
  </localfile>

Next, create a custom rule, you will need to open the file designed for that, local_rules.xml.

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

Insert this rule:

  <rule id="119999" level="12">
    <regex>^test$</regex>
    <description>Test rule to configure integration</description>
  </rule>

Now every time that you will echo the word test in /var/log/test.log the rule should trigger. To test that we can use the Binary that is exclusively for that, wazuh-logtest

Run the binary and type the word test, you should see your rule getting triggered.

/var/ossec/bin/wazuh-logtest

Restart the manager and trigger the alert, you should receive the alert on your Discord channel.

/var/ossec/bin/wazuh-control restart
echo -e "test" /var/log/test.log

The alert in Discord:

Debugging

If you encounter problems, the files to look at are:

You can make the integrator daemon more verbose, for that execute with the flag -d or -dd

/var/ossec/bin/wazuh-integratord  -d

After that, the logs related to the integration should be more verbose in ossec.log, you should see the entire flow of execution of the integration.

Conclusion

First I would like to offer my thanks to Alexandre Borges @ale_sp_brazil for incentivizing me to start writing this blog. You should definitely check his blog exploitreversing.com

When I first needed to create a custom integration, I did not find much material talking about it, I hope that this can help someone.

Top