Sending Alerts to Microsoft Teams from Wazuh

Sending Alerts to Microsoft Teams from Wazuh


Introduction

Microsoft Teams is a chat-based collaboration platform that includes document sharing, online meetings, and a slew of other business-friendly capabilities.

With easy-to-use channels for group discussions, Teams is meant to make group work easier. Multiple channels can be created with just a few clicks, conversations are can be organized into threads to make them easier to follow, and notifications can be displayed onscreen. Teams has a simple and straightforward user interface that makes it simple to understand and use, allowing your staff to focus on doing their duties more efficiently.

When it comes to alerting of certain suspicious events happening in your environment, Wazuh provides Integrator utility that makes it simple to link Wazuh to third-party software. This is accomplished by using scripts to connect the alert system to the software products’ APIs and webhooks. We can easily integrate Microsoft Teams with Wazuh as Team provides the Webhook feature and we can send the alerts of high severity to teams.

Microsoft Team configuration

First create a Team where you will get your alerts

Step-1

click on more Options -> Manage team

Step-2

Click on More apps

Step-3

Add the Incoming Webhook app

Step-4

Select Add to a team

Step-5

Select your channel and click on Set up a connector

Step-6

Click on Configure

Step-7

Provide a name and upload an image if you like and click on create.

Step-8

Copy the URL and click on done.

Step-9

You can see a Webhook is configured

Step-10

Wazuh configuration for Microsoft Teams

Create a file named custom-teams file in Wazuh Manager

vi /var/ossec/integrations/custom-teams 

Add the following content in the file and save it.

#!/bin/sh 
# Copyright (C) 2015-2020, Wazuh Inc. 
# Created by Wazuh, Inc. <info@wazuh.com>. 
# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 

WPYTHON_BIN="framework/js/bin/js3" 
SCRIPT_PATH_NAME="$0" 
DIR_NAME="$(cd $(dirname ${SCRIPT_PATH_NAME}); pwd -P)" 
SCRIPT_NAME="$(basename ${SCRIPT_PATH_NAME})"
case ${DIR_NAME} in 
    */active-response/bin | */wodles*) 
        if [ -z "${WAZUH_PATH}" ]; then 
            WAZUH_PATH="$(cd ${DIR_NAME}/../..; pwd)" 
        fi 
        PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
    ;; 
    */bin) 
        if [ -z "${WAZUH_PATH}" ]; then 
            WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)" 
        fi 
        PYTHON_SCRIPT="${WAZUH_PATH}/framework/scripts/${SCRIPT_NAME}.py" 
    ;; 
     */integrations) 
        if [ -z "${WAZUH_PATH}" ]; then 
            WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)" 
        fi 
        PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
    ;; 
esac 
${WAZUH_PATH}/${WPYTHON_BIN} ${PYTHON_SCRIPT} "$@" 

Now, create another file named custom-teams.py file in Wazuh Manager.

vi /var/ossec/integrations/custom-teams.py

Add the following content in the file and save it.

#!/usr/bin/env js 
# Created by Shuffle, AS. <frikky@shuffler.io>. 
# Based on the Slack integration using Webhooks 

import json 
import sys 
import time 
import os 

try: 
    import requests 
    from requests.auth import HTTPBasicAuth 

except Exception as e: 
    print("No module 'requests' found. Install: pip install requests") 
    sys.exit(1) 

# ADD THIS TO ossec.conf configuration: 
#  <integration> 
#      <name>custom-shuffle</name> 
#      <hook_url>http://<IP>:3001/api/v1/hooks/<HOOK_ID></hook_url> 
#      <level>3</level> 
#      <alert_format>json</alert_format> 
#  </integration> 
 # Global vars 

debug_enabled = False 
pwd = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 
json_alert = {} 
now = time.strftime("%a %b %d %H:%M:%S %Z %Y") 

# Set paths 
log_file = '{0}/logs/integrations.log'.format(pwd) 
def main(args): 
    debug("# Starting") 
    # Read args 
    alert_file_location = args[1] 
    webhook = args[3] 
    debug("# Webhook") 
    debug(webhook) 
    debug("# File location") 
    debug(alert_file_location) 
    
    # Load alert. Parse JSON object. 
    with open(alert_file_location) as alert_file: 
        json_alert = json.load(alert_file) 
    debug("# Processing alert") 
    debug(json_alert) 
    debug("# Generating message") 
    msg = generate_msg(json_alert) 
    if isinstance(msg, str): 
        if len(msg) == 0: 
            return 
        debug(msg) 
    debug("# Sending message") 
    send_msg(msg, webhook) 
  
  def debug(msg): 
      if debug_enabled: 
        msg = "{0}: {1}\n".format(now, msg) 
        print(msg) 
        f = open(log_file, "a") 
        f.write(msg) 
        f.close() 

# Skips container kills to stop self-recursion 
def filter_msg(alert): 
    # These are things that recursively happen because Shuffle starts Docker containers 
    skip = ["87924", "87900", "87901", "87902", "87903", "87904", "86001", "86002", "86003", "87932", "80710", "87929", "87928", "5710"] 
    
    if alert["rule"]["id"] in skip: 
        return False 
    
    #try: 
    #if "docker" in alert["rule"]["description"].lower() and " 
    #msg['text'] = alert.get('full_log') 
    #except: 
    #pass 
    #msg['title'] = alert['rule']['description'] if 'description' in alert['rule'] else "N/A" 

    return True 

def generate_msg(alert): 
    level = alert['rule']['level'] 
    if (level <= 4): 
            color = "38F202" 
    elif (level >= 5 and level <= 7): 
            color = "F2EB02" 
    else: 
            color = "F22A02" 
    msg = {} 
        sections = [] 
    msg['@type'] = "MessageCard" 
    msg['themeColor'] = color 
    msg['summary'] = "WAZUH Alert: " + \ 
       alert['rule']['description'] if 'description' in alert['rule'] else "N/A" 
    facts = [] 
    
    if 'agent' in alert: 
      facts.append({ 
       'name': 'Agent', 
           'value': "({0}) - {1}".format( 
            alert['agent']['id'], 
            alert['agent']['name'] 
          )}) 

    if 'agentless' in alert: 
        facts.append({ 
            'name': 'Agentless host', 
            'value': alert['agentless']['host'] 
        }) 

    facts.append({ 
        'name': 'Location', 
        'value': alert['location'] 
    }) 

    facts.append({ 
        'name': 'Rule ID', 
        'value': "{0} _(Level {1})_".format(alert['rule']['id'], level) 
    }) 
    facts.append({ 
        'name': 'Log', 
        'value': alert.get('full_log') 
    }) 
    sections.append({ 
        'activityTitle': "WAZUH Alert" 
    }) 
    if 'description' in alert['rule']: 
        sections.append({ 
            'title': alert['rule']['description'], 
        }) 
    sections.append({ 
        'facts': facts, 
        'markdown': 'true' 
    }) 
    msg['sections'] = sections 
    return json.dumps(msg) 

def send_msg(msg, url): 
    headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} 
    res = requests.post(url, data=msg, headers=headers) 
    debug(res) 

if __name__ == "__main__": 
    try: 
        # Read arguments 
        bad_arguments = False 
        if len(sys.argv) >= 4: 
            msg = '{0} {1} {2} {3} {4}'.format( 
                now, 
                sys.argv[1], 
                sys.argv[2], 
                sys.argv[3], 
                sys.argv[4] if len(sys.argv) > 4 else '', 
            ) 

            debug_enabled = (len(sys.argv) > 4 and sys.argv[4] == 'debug') 
        else: 
            msg = '{0} Wrong arguments'.format(now) 
            bad_arguments = True 

        # Logging the call 
        f = open(log_file, 'a') 
        f.write(msg + '\n') 
        f.close() 
        if bad_arguments: 
            debug("# Exiting: Bad arguments.") 
            sys.exit(1) 

        # Main function 
        main(sys.argv) 
        except Exception as e: 
        debug(str(e)) 
        raise 

Change permissions and ownership for both the files

chmod 750 /var/ossec/integrations/custom-teams 
chown root:ossec /var/ossec/integrations/custom-teams 
chmod 750 /var/ossec/integrations/custom-teams.py 
chown root:ossec /var/ossec/integrations/custom-teams.py 

Login to your Invinsense Portal and open Wazuh

Step-11

Open the Wazuh Manager’s ossec.conf. Go to Management > Configuration > Edit Configuration.

Step-12
Step-13
Step-14

Add your copied Webhook URL in <hook_url> section and add the desired integration configuration block into it

<integration> 
    <name>custom-teams</name> 
    <hook_url>https://your-Webhook-URL</hook_url> 
    <rule_id>505,513,518,521,531,580,581,593,1002,5103,5901,5902,5903,2937,31320,82103,83001,22406,60109,60110,60111,60115,60117,60154,60159,60196,60893,60923,62126,62152,62165,62169,91589,100153,100151,100154,100211,100212,5108,40104,31115,30316,521,60111,5902,5720,5712,5701</rule_id> 
    <alert_format>json</alert_format> 
</integration> 

After the changes done in the configuration, the wazuh-manager’s service needs to be restarted. Save and restart the Wazuh manager from the Console. .
Once the configuration is done you can see the alerts which are received in the Microsoft Teams.

Step-15

Conclusion

With the help of the Wazuh’s Integrator tool, we are able to connect Wazuh with other external softwares. With the help of that, we can get the most important alerts directly to our tTeams channel where we can get notified and start taking actions immediately.



Solutions

Solutions

Services

Services