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.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Tutorials – Intrusion Protection

    No computer security is perfect, so make sure you've got a second line of protection.

  • Security Lessons

    Learn how to monitor and block attacks without lifting a finger.

  • Suricata

    Snort isn't the only free intrusion detection tool in the barnyard. We'll show you a powerful and promising alternative known as Suricata.

  • Intrusion Detection

    The Prelude security information management system receives both host- and network-based IDS messages and displays them in an easy web interface. We show you how to set it up.

  • Building a Rasp Pi IDS

    An intrusion detection system was once considered too complicated and too expensive for a home network, but nowadays you can use a Raspberry Pi and the Suricata IDS for real-time notice of an incoming attack.

comments powered by Disqus
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.

Learn More

News