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
- all custom integrations scripts names need to start with custom-
cp slack custom-discord cp slack.py custom-discord.py
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>
- The tag name in the line 354 is where we define the name of the script that will launch the python script.
- The tag hook is where you will need to place your webhook URL.
- In the line 356 I can control what will trigger the integration, in my case is any Wazuh alert that is equal or greater than 07.
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:
- /var/ossec/logs/ossec.log
- /var/ossec/logs/integration.log
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.