Integrated security with Wazuh
Wazuh Integration
An important benefit of Wazuh is the ability to integrate it with other tools. One powerful partner is TheHive [2], an OpenSource platform that is a great aid to the incident response process. TheHive, which was created to facilitate the work of SOC or CSIRT analysts, has REST APIs that make it possible to integrate with various security solutions in order to collect security events and alerts for further investigation and case tracking. In TheHive, you work on cases. When Wazuh reports an alert, a case will automatically be created in TheHive. An analyst can then assign a task to himself and work on it. To set up Wazuh to work with TheHive, start by creating a new organization on TheHive web interface. In Test Organization, create a new user with organization administrator privileges. Make sure the user has permission to manage the organization, including creating new users, managing cases, and setting up alerts. Create a password for this user so that you can log in to view the dashboard and manage cases. Click on New password beside the user account and enter the desired password.
Integration with Wazuh is possible with the help of TheHive REST API. You'll need to create a user with analyst privileges on TheHive who can create alerts via the API. Then generate the API key for the user.
Wazuh Manager Configuration
To use the Wazuh configuration manager, start by installing TheHive Python module:
sudo /var/ossec/framework/python/ bin/pip3 install thehive4py==1.8.1
Wazuh has prepared a ready-made Python script that will automatically perform the initial installation. Paste the script in /var/ossec/integrations/custom-w2thive.py. The lvl_threshold variable in the script indicates the minimum alert level that will be forwarded to TheHive. The variable can be customized so that only relevant alerts are forwarded to TheHive (Listing 1).
Listing 1
Forwarding Relevant Threats
001 #!/var/ossec/framework/python/bin/python3
002 import json.
003 import sys
004 import os
005 import re
006 import logging
007 import uuid
008 from thehive4py.api import TheHiveApi
009 from thehive4py.models import Alert, AlertArtifact
010
011 #start user config
012
013 # Global vars
014
015 #threshold for wazuh rules level
016 lvl_threshold=0
017 #threshold for suricata rules level
018 suricata_lvl_threshold=3
019
020 debug_enabled = False
021 #info about created alert
022 info_enabled = True
023
024 #end user config
025
026 # Set paths
027 pwd = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
028 log_file = '{0}/logs/integrations.log'.format(pwd)
029 logger = logging.getLogger(__name__)
030 #set logging level
031 logger.setLevel(logging.WARNING)
032 if info_enabled:
033 logger.setLevel(logging.INFO)
034 if debug_enabled:
035 logger.setLevel(logging.DEBUG)
036 # create the logging file handler
037 fh = logging.FileHandler(log_file)
038 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
039 fh.setFormatter(formatter)
040 logger.addHandler(fh)
041
042
043
044 def main(args):
045 logger.debug('#start main')
046 logger.debug('#get alert file location')
047 alert_file_location = args[1]
048 logger.debug('#get TheHive url')
049 thive = args[3]
050 logger.debug('#get TheHive api key')
051 thive_api_key = args[2]
052 thive_api = TheHiveApi(thive, thive_api_key )
053 logger.debug('#open alert file')
054 w_alert = json.load(open(alert_file_location))
055 logger.debug('#alert data')
056 logger.debug(str(w_alert))
057 logger.debug('#gen json to dot-key-text')
058 alt = pr(w_alert,'',[])
059 logger.debug('#formatting description')
060 format_alt = md_format(alt)
061 logger.debug('#search artifacts')
062 artifacts_dict = artifact_detect(format_alt)
063 alert = generate_alert(format_alt, artifacts_dict, w_alert)
064 logger.debug('#threshold filtering')
065 if w_alert['rule']['groups']==['ids','suricata']:
066 #checking the existence of the data.alert.severity field
067 if 'data' in w_alert.keys():
068 if 'alert' in w_alert['data']:
069 #checking the level of the source event
070 if int(w_alert['data']['alert']['severity'])<=suricata_lvl_threshold:
071 send_alert(alert, thive_api)
072 elif int(w_alert['rule']['level'])>=lvl_threshold:
073 #if the event is different from suricata AND suricata-event-type: alert check lvl_threshold
074 send_alert(alert, thive_api)
075
076
077 def pr(data,prefix, alt):
078 for key,value in data.items():
079 if hasattr(value,'keys'):
080 pr(value,prefix+'.'+str(key),alt=alt)
081 else:
082 alt.append((prefix+'.'+str(key)+'|||'+str(value)))
083 return alt
084
085
086
087 def md_format(alt,format_alt=''):
088 md_title_dict = {}
089 #sorted with first key
090 for now in alt:
091 now = now[1:]
092 #fix first key last symbol
093 dot = now.split('|||')[0].find('.')
094 if dot==-1:
095 md_title_dict[now.split('|||')[0]] =[now]
096 else:
097 if now[0:dot] in md_title_dict.keys():
098 (md_title_dict[now[0:dot]]).append(now)
099 else:
100 md_title_dict[now[0:dot]]=[now]
101 for now in md_title_dict.keys():
102 format_alt+='### '+now.capitalize()+'\n'+'| key | val |\n| ------ | ------ |\n'
103 for let in md_title_dict[now]:
104 key,val = let.split('|||')[0],let.split('|||')[1]
105 format_alt+='| **' + key + '** | ' + val + ' |\n'
106 return format_alt
107
108
109 def artifact_detect(format_alt):
110 artifacts_dict = {}
111 artifacts_dict['ip'] = re.findall(r'\d+\.\d+\.\d+\.\d+',format_alt)
112 artifacts_dict['url'] = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F] \
113 [0-9a-fA-F]))+',format_alt)
114 artifacts_dict['domain'] = []
115 for now in artifacts_dict['url']: artifacts_dict['domain'].append(now.split('//')[1].split('/')[0])
116 return artifacts_dict
117
118
119 def generate_alert(format_alt, artifacts_dict,w_alert):
120 #generate alert sourceRef
121 sourceRef = str(uuid.uuid4())[0:6]
122 artifacts = []
123 if 'agent' in w_alert.keys():
124 if 'ip' not in w_alert['agent'].keys():
125 w_alert['agent']['ip']='no agent ip'
126 else:
127 w_alert['agent'] = {'id':'no agent id', 'name':'no agent name'}
128
129 for key,value in artifacts_dict.items():
130 for val in value:
131 artifacts.append(AlertArtifact(dataType=key, data=val))
132 alert = Alert(title=w_alert['rule']['description'],
133 tlp=2,
134 tags=['wazuh',
135 'rule='+w_alert['rule']['id'],
136 'agent_name='+w_alert['agent']['name'],
137 'agent_id='+w_alert['agent']['id'],
138 'agent_ip='+w_alert['agent']['ip'],],
139 description=format_alt ,
140 type='wazuh_alert',
141 source='wazuh',
142 sourceRef=sourceRef,
143 artifacts=artifacts,)
144 return alert
145
146
147
148
149 def send_alert(alert, thive_api):
150 response = thive_api.create_alert(alert)
151 if response.status_code == 201:
152 logger.info('Create TheHive alert: '+ str(response.json()['id']))
153 else:
154 logger.error('Error create TheHive alert: {}/{}'.format(response.status_code, response.text))
155
156
157
158 if __name__ == "__main__":
159
160 try:
161 logger.debug('debug mode') # if debug enabled
162 # Main function
163 main(sys.argv)
164
165 except Exception:
166 logger.exception('EGOR')
Wazuh has prepared a special Bash script that executes the script in Listing 1. I create the bash script as /var/ossec/integrations/custom-w2thive (Listing 2).
Listing 2
Bash Script
01 #!/bin/sh
02 # Copyright (C) 2015-2020, Wazuh Inc.
03 # Created by Wazuh, Inc. <info@wazuh.com>.
04 # This program is free software; you can redistribute it and/or modify it under the terms of GP>
05
06 WPYTHON_BIN="framework/python/bin/python3"
07
08 SCRIPT_PATH_NAME="$0"
09
10 DIR_NAME="$(cd $(dirname ${SCRIPT_PATH_NAME}); pwd -P)"
11 SCRIPT_NAME="$(basename ${SCRIPT_PATH_NAME})"
12
13 case ${DIR_NAME} in
14 */active-response/bin | */wodles*)
15 if [ -z "${WAZUH_PATH}" ]; then
16 WAZUH_PATH="$(cd ${DIR_NAME}/../..; pwd)"
17 fi
18
19 PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
20 ;;
21 */bin)
22 if [ -z "${WAZUH_PATH}" ]; then
23 WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
24 fi
25
26 PYTHON_SCRIPT="${WAZUH_PATH}/framework/scripts/${SCRIPT_NAME}.py"
27 ;;
28 */integrations)
29 if [ -z "${WAZUH_PATH}" ]; then
30 WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
31 fi
32
33 PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
34 ;;
35 esac
36
37 ${WAZUH_PATH}/${WPYTHON_BIN} ${PYTHON_SCRIPT} $@
Change the file permissions and the ownership of the scripts to ensure that Wazuh has the necessary permissions:
sudo chmod 755 /var/ossec/integrations/custom-w2thive.py sudo chmod 755 /var/ossec/integrations/custom-w2thive sudo chown root:ossec /var/ossec/integrations/custom-w2thive.py sudo chown root:ossec /var/ossec/integrations/custom-w2thive
To allow Wazuh to run the integration script, add the lines in Listing 3 to the manager configuration file located at /var/ossec/etc/ossec.conf. Provide the IP address for TheHive server along with the API key that was generated earlier.
Listing 3
Add to ossec.conf
<ossec_config>
?
<integration>
<name>custom-w2thive</name>
<hook_url>http://TheHive_Server_IP:9000</hook_url>
<api_key>RWw/Ii0yE6l+Nnd3nv3o3Uz+5UuHQYTM</api_key>
<alert_format>json</alert_format>
</integration>
?
</ossec_config>
Restart the manager to apply the changes:
sudo systemctl restart wazuh-manager
ClamAV
ClamAV [3] is an open source anti-malware toolkit designed for various use cases such as endpoint security, web scanning, and email scanning. ClamAV can provide real-time protection at endpoints.
To collect ClamAV logs from Linux endpoints, remove the # comment tag before the LogSyslog true statement in /etc/clamav/clamd.conf. Logs collected by ClamAV should then be visible in the Wazuh console.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Linux Now Runs Most Windows Games
The latest data shows that nearly 90 percent of Windows games can be played on Linux.
-
Fedora 43 Has Finally Landed
The Fedora Linux developers have announced their latest release, Fedora 43.
-
KDE Unleashes Plasma 6.5
The Plasma 6.5 desktop environment is now available with new features, improvements, and the usual bug fixes.
-
Xubuntu Site Possibly Hacked
It appears that the Xubuntu site was hacked and briefly served up a malicious ZIP file from its download page.
-
LMDE 7 Now Available
Linux Mint Debian Edition, version 7, has been officially released and is based on upstream Debian.
-
Linux Kernel 6.16 Reaches EOL
Linux kernel 6.16 has reached its end of life, which means you'll need to upgrade to the next stable release, Linux kernel 6.17.
-
Amazon Ditches Android for a Linux-Based OS
Amazon has migrated from Android to the Linux-based Vega OS for its Fire TV.
-
Cairo Dock 3.6 Now Available for More Compositors
If you're a fan of third-party desktop docks, then the latest release of Cairo Dock with Wayland support is for you.
-
System76 Unleashes Pop!_OS 24.04 Beta
System76's first beta of Pop!_OS 24.04 is an impressive feat.
-
Linux Kernel 6.17 is Available
Linus Torvalds has announced that the latest kernel has been released with plenty of core improvements and even more hardware support.

