Decoding Wazuh Security Alerts: Unveiling the Mystery Behind Uncertainty

With OpenAI custom integration

ยท

8 min read

Introduction

Despite implementing robust security measures, it is not uncommon to encounter odd security alerts that leave us questioning their true significance.

Sometimes, in the middle of a constant stream of notifications, we can find ourselves struggling with the strange nature of these alerts. Often delivered through monitoring systems, these messages notify us of potential security breaches, vulnerabilities, or suspicious activities. However, decoding their meaning and accurately assessing the level of risk they pose can be a challenging task.
Also, not all security alerts are created equal. Sometimes, the language used in security alerts can be confusing or misleading, making it difficult for security analysts to understand what the alert is actually about and what they need to do to take appropriate measures.

Yes, an incomprehensible alert is an alert that never existed...

Deal with it GIF - Find on GIFER

In the face of these uncertainties, it becomes crucial to dig deeper into the alerts' intricacies and gain a clear understanding of their implications.
This knowledge empowers us to make informed decisions, respond effectively, and take appropriate actions to mitigate potential risks.

The Panacea for a SIEM

What if a SIEM could go beyond mere alerting and actively guide organizations on how to respond to security alerts?

This intriguing concept introduces the notion of an "intelligent" SIEM, one that not only detects threats but also assists security teams by providing actionable guidance and recommendations for incident response.
Imagine a SIEM that can analyze the characteristics of an alert, cross-reference it with historical data and threat intelligence feeds, and then generate comprehensive response playbooks tailored to the specific context of the incident...

Internet Wow GIF - Internet Wow Science - Discover & Share GIFs | Mind  blown, Jon cryer, Gif

This SIEM would effectively become a virtual security advisor, helping organizations make more informed and timely decisions during critical moments.

However, while the concept of a SIEM guiding incident response holds tremendous promise, it also raises important questions and considerations:

  • How can organizations ensure the accuracy and reliability of the SIEM's recommendations?

  • What measures need to be in place to protect against potential biases or errors in the guidance provided?

  • Furthermore, how can the intelligent SIEM strike a balance between automation and human decision-making, recognizing that certain situations may require human judgment and expertise?

Leveraging ChatGPT's Knowledge

While ChatGPT's training data only extends until September 2021, it still possesses a wealth of knowledge and insights on security-related topics. It can offer guidance on fundamental security practices, explain common attack vectors, and provide advice on incident response strategies.

By leveraging the available knowledge within the model, analysts can gain a solid foundation in security principles and tactics that are relevant beyond 2021. It may not be aware of specific vulnerabilities, exploits, or security developments that have emerged since then. Therefore, it's crucial to complement the guidance provided by ChatGPT with up-to-date information from trusted sources, such as industry-specific security blogs, threat intelligence reports, and security advisories released by software vendors and cybersecurity organizations.

Needless to say, rather than relying solely on ChatGPT's responses, it's advisable to use it as a tool to augment your own knowledge and decision-making process.

This article aims to shed light on the challenges associated with comprehending security alerts and offers an alternative for deciphering their hidden meanings taking advantage of the benefits of AI.

I'm only scratching the surface, and this is not intended as a scholarly investigation of AI usage within a SIEM, just a brief exploration of the subject.

Whether you are an InfoSec beginner or an experienced one, using a custom Wazuh's ChatGPT integration, can equip you with the necessary guidance to navigate the security alerts world more confidently.

Enough intro. Let's get to it! ๐Ÿš€

ChatGPT integration configuration

One of the key strengths I value regarding any security monitoring platform (Especially on Wazuh) lies in its ability to easily integrate with external services and sources, making it an invaluable asset for any security-conscious organization.

Step 1

We need to create a rule that detects failed SSH authentication attempts. The rule (5760) triggers an alert when it matches events from the following sources:

  • sshd - Failed SSH authentication attempts

  • auth.log - Failed SSH authentication attempts.

This allows us to distinguish malicious insiders and those attempting to gain access from outside the network.

Open the Wazuh manager local rules file /var/ossec/etc/rules/local_rules.xml and add the below block:

<!-- User Failed Authentication from Public IPv4 -->
<group name="local,syslog,sshd,">
 <rule id="100004" level="10">
    <if_sid>5760</if_sid>
    <match type="pcre2">\.+</match>
    <description>sshd: Authentication failed from a public IP address > $(srcip).</description>
    <group>authentication_failed,pci_dss_10.2.4,pci_dss_10.2.5,</group>
  </rule>
</group>

The <match></match> block of the rule specifies that we want to perform a REGEX to capture the whole event log.

Step 2

The below Python script takes the log event text and sends it to the ChatGPT API endpoint to get guidance on how to respond.

#!/var/ossec/framework/python/bin/python3
# Copyright (C) 2015-2022, Wazuh Inc.
# ChatGPT Integration template by @WhatDoesKmean

import json
import sys
import time
import os
from socket import socket, AF_UNIX, SOCK_DGRAM

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

# 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)
socket_addr = '{0}/queue/sockets/queue'.format(pwd)

def main(args):
    debug("# Starting")
    # Read args
    alert_file_location = args[1]
    apikey = args[2]
    debug("# API Key")
    debug(apikey)
    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)

    # Request chatgpt info
    msg = request_chatgpt_info(json_alert,apikey)
    # If positive match, send event to Wazuh Manager
    if msg:
        send_event(msg, json_alert["agent"])

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


def collect(data):
  full_log = data['full_log']
  choices = data['content']
  return full_log, choices


def in_database(data, full_log):
  result = data['full_log']
  if result == 0:
    return False
  return True


def query_api(full_log, apikey):
  # Calling ChatGPT API Endpoint
  headers = {
        'Authorization': 'Bearer ' + apikey,
        'Content-Type': 'application/json',
    }

  json_data = {
        'model': 'gpt-3.5-turbo',
        'messages': [
            {
                'role': 'user',
                'content': 'Regarding this log message, what are the next steps to take? ' + full_log,
            },
        ],
    }

  response = requests.post('https://api.openai.com/v1/chat/completions', headers=headers, json=json_data)

  if response.status_code == 200:
      full_log = {"full_log": full_log}
      new_json = {}
      new_json = response.json()["choices"][0]["message"]
      new_json.update(full_log)
      json_response = new_json

      data = json_response
      return data
  else:
      alert_output = {}
      alert_output["chatgpt"] = {}
      alert_output["integration"] = "custom-chatgpt"
      json_response = response.json()
      debug("# Error: The chatgpt encountered an error")
      alert_output["chatgpt"]["error"] = response.status_code
      alert_output["chatgpt"]["description"] = json_response["errors"][0]["detail"]
      send_event(alert_output)
      exit(0)


def request_chatgpt_info(alert, apikey):
    alert_output = {}

    # Request info using chatgpt API
    data = query_api(alert["full_log"], apikey)

    # Create alert
    alert_output["chatgpt"] = {}
    alert_output["integration"] = "custom-chatgpt"
    alert_output["chatgpt"]["found"] = 0
    alert_output["chatgpt"]["source"] = {}
    alert_output["chatgpt"]["source"]["alert_id"] = alert["id"]
    alert_output["chatgpt"]["source"]["rule"] = alert["rule"]["id"]
    alert_output["chatgpt"]["source"]["description"] = alert["rule"]["description"]
    alert_output["chatgpt"]["source"]["full_log"] = alert["full_log"]

    full_log = alert["full_log"]

    # Check if chatgpt has any info about the full_log
    if in_database(data, full_log):
      alert_output["chatgpt"]["found"] = 1
    # Info about the IP found in chatgpt
    if alert_output["chatgpt"]["found"] == 1:
        full_log, choices = collect(data)

        # Populate JSON Output object with chatgpt request
        alert_output["chatgpt"]["full_log"] = full_log
        alert_output["chatgpt"]["choices"] = choices

        debug(alert_output)

    return(alert_output)


def send_event(msg, agent = None):
    if not agent or agent["id"] == "000":
        string = '1:chatgpt:{0}'.format(json.dumps(msg))
    else:
        string = '1:[{0}] ({1}) {2}->chatgpt:{3}'.format(agent["id"], agent["name"], agent["ip"] if "ip" in agent else "any", json.dumps(msg))

    debug(string)
    sock = socket(AF_UNIX, SOCK_DGRAM)
    sock.connect(socket_addr)
    sock.send(string.encode())
    sock.close()


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(str(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

This script will be saved in the /var/ossec/integrations/ path of the Wazuh Manager as custom-chatgpt_response.py

The file execution permissions can be changed by the chmod command. Also, don't forget to use the chown command to change the file ownership as well.

In my case:
chmod 750 /var/ossec/integrations/custom-chatgpt_response.py
chown root:wazuh /var/ossec/integrations/custom-chatgpt_response.py

Step 3

Now it's time to update the Wazuh manager configuration file /var/ossec/etc/ossec.conf using the integration block below:

<!-- ChatGPT Integration -->
  <integration>
    <name>custom-chatgpt_response.py</name>
    <hook_url>https://api.openai.com/v1/chat/completions</hook_url>
    <api_key>YOUR-OWN-API-KEY</api_key>
    <level>10</level>
    <rule_id>100004</rule_id>
    <alert_format>json</alert_format>
  </integration>

This instructs the Wazuh Manager to call the ChatGPT API endpoint anytime our rule id (100004), is triggered. You need to replace the <api_key> block with your own.
Register for a free API key at platform.openai.com/signup.

Step 4

We need to capture the response sent back to the Wazuh Manager so we can observe the information gathered by our ChatGPT integration.

Open the Wazuh Manager local rules file at /var/ossec/etc/rules/local_rules.xml and add the block below:

<group name="local,syslog,sshd,">
  <rule id="100007" level="10">
    <field name="chatgpt.full_log">\.+</field>
    <description>$(chatgpt.full_log) >> โ†“ SEE NEXT STEPS TO TAKE โ†“</description>
    <group>authentication_failed,pci_dss_10.2.4,pci_dss_10.2.5,</group>
  </rule>
</group>

In my case, I used the $(chatgpt.full_log) field as a reference description. But I believe using the $(chatgpt.source.alert_id) field instead, makes more sense.

Lastly, restart the Wazuh Manager.

Conclusion

The idea of a SIEM that not only alerts but also guides organizations on how to respond to security alerts represents a significant leap forward in cybersecurity capabilities.
By harnessing the power of machine learning, and contextual awareness, an intelligent SIEM has the potential to transform incident response processes, empower security teams, and fortify organizations against emerging threats.
As cybersecurity continues to evolve, embracing the concept of a SIEM as a virtual security advisor may become an essential strategy for staying resilient in the face of an ever-changing threat landscape.

Now, you know! ๐Ÿ˜‰

ย