MISP / MISP/PyMISP

MISP integration with WAZUH

Open
#857 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
491
Forks
290
Avg merge
2d 8h
Merged PRs (30d)
3

Description

Hi Community
I'm integrating MISP with WAZUH
I did all the necessary configuration on the files:
-Ossec.conf: on wazuh server
-misp.xml: new rule on the wazuh server
-custom-misp.py: on the integrations folder of the server
After testing a windows client (Dns query) I got the alert on wazuh server through Sysmon, unfortunately, there is no feedback from MISP
You find below my configuration for each file
your help would be much appreciated
Custom-misp.py
#!/var/ossec/framework/python/bin/python3

MISP API Integration

import sys
import os
from socket import socket, AF_UNIX, SOCK_DGRAM
from datetime import date, datetime, timedelta
import time
import requests
from requests.exceptions import ConnectionError
import json
import ipaddress
import hashlib
import re
pwd = os.path.dirname(os.path.dirname(os.path.realpath(file)))
socket_addr = '{0}/queue/sockets/queue'.format(pwd)
def send_event(msg, agent = None):
if not agent or agent["id"] == "000":
string = '1:misp:{0}'.format(json.dumps(msg))
else:
string = '1:[{0}] ({1}) {2}->misp:{3}'.format(agent["id"], agent["name"], agent["ip"] if "ip" in agent else "any", json.dumps(msg))
sock = socket(AF_UNIX, SOCK_DGRAM)
sock.connect(socket_addr)
sock.send(string.encode())
sock.close()
false = False

Read configuration parameters

alert_file = open(sys.argv[1])

Read the alert file

alert = json.loads(alert_file.read())
alert_file.close()

New Alert Output if MISP Alert or Error calling the API

alert_output = {}

MISP Server Base URL

misp_base_url = "https://172.16.1.101/attributes/restSearch/"

MISP Server API AUTH KEY

misp_api_auth_key = "*Your API Key"

API - HTTP Headers

misp_apicall_headers = {"Content-Type":"application/json", "Authorization":f"{misp_api_auth_key}", "Accept":"application/json"}

Extract Sysmon for Windows/Sysmon for Linux and Sysmon Event ID

event_source = alert["rule"]["groups"][0]
event_type = alert["rule"]["groups"][2]

Regex Pattern used based on SHA256 lenght (64 characters)

regex_file_hash = re.compile('\w{64}')
if event_source == 'windows':
if event_type == 'sysmon_event1':
try:
wazuh_event_param = regex_file_hash.search(alert["data"]["win"]["eventdata"]["hashes"]).group(0)
except IndexError:
sys.exit()
elif event_type == 'sysmon_event3' and alert["data"]["win"]["eventdata"]["destinationIsIpv6"] == 'false':
try:
dst_ip = alert["data"]["win"]["eventdata"]["destinationIp"]
if ipaddress.ip_address(dst_ip).is_global:
wazuh_event_param = dst_ip
else:
sys.exit()
except IndexError:
sys.exit()
elif event_type == 'sysmon_event3' and alert_output["data"]["win"]["eventdata"]["destinationIsIpv6"] == 'true':
sys.exit()
elif event_type == 'sysmon_event6':
try:
wazuh_event_param = regex_file_hash.search(alert["data"]["win"]["eventdata"]["hashes"]).group(0)
except IndexError:
sys.exit()
elif event_type == 'sysmon_event7':
try:
wazuh_event_param = regex_file_hash.search(alert["data"]["win"]["eventdata"]["hashes"]).group(0)
except IndexError:
sys.exit()
elif event_type == 'sysmon_event_15':
try:
wazuh_event_param = regex_file_hash.search(alert["data"]["win"]["eventdata"]["hashes"]).group(0)
except IndexError:
sys.exit()
elif event_type == 'sysmon_event_22':
try:
wazuh_event_param = alert["data"]["win"]["eventdata"]["queryName"]
except IndexError:
sys.exit()
elif event_type == 'sysmon_event_23':
try:
wazuh_event_param = regex_file_hash.search(alert["data"]["win"]["eventdata"]["hashes"]).group(0)
except IndexError:
sys.exit()
elif event_type == 'sysmon_event_24':
try:
wazuh_event_param = regex_file_hash.search(alert["data"]["win"]["eventdata"]["hashes"]).group(0)
except IndexError:
sys.exit()
elif event_type == 'sysmon_event_25':
try:
wazuh_event_param = regex_file_hash.search(alert["data"]["win"]["eventdata"]["hashes"]).group(0)
except IndexError:
sys.exit()
else:
sys.exit()
misp_search_value = "value:"f"{wazuh_event_param}"
misp_search_url = ''.join([misp_base_url, misp_search_value])
try:
misp_api_response = requests.get(misp_search_url, headers=misp_apicall_headers, verify=False)
except ConnectionError:
alert_output["misp"] = {}
alert_output["integration"] = "misp"
alert_output["misp"]["error"] = 'Connection Error to MISP API'
send_event(alert_output, alert["agent"])
else:
misp_api_response = misp_api_response.json()
# Check if response includes Attributes (IoCs)
if (misp_api_response["response"]["Attribute"]):
# Generate Alert Output from MISP Response
alert_output["misp"] = {}
alert_output["misp"]["source"] = {}
alert_output["misp"]["event_id"] = misp_api_response["response"]["Attribute"][0]["event_id"]
alert_output["misp"]["category"] = misp_api_response["response"]["Attribute"][0]["category"]
alert_output["misp"]["value"] = misp_api_response["response"]["Attribute"][0]["value"]
alert_output["misp"]["type"] = misp_api_response["response"]["Attribute"][0]["type"]
alert_output["misp"]["source"]["description"] = alert["rule"]["description"]
send_event(alert_output, alert["agent"])
elif event_source == 'linux':
if event_type == 'sysmon_event3' and alert["data"]["eventdata"]["destinationIsIpv6"] == 'false':
try:
dst_ip = alert["data"]["eventdata"]["DestinationIp"]
if ipaddress.ip_address(dst_ip).is_global:
wazuh_event_param = dst_ip
misp_search_value = "value:"f"{wazuh_event_param}"
misp_search_url = ''.join([misp_base_url, misp_search_value])
try:
misp_api_response = requests.get(misp_search_url, headers=misp_apicall_headers, verify=False)
except ConnectionError:
alert_output["misp"] = {}
alert_output["integration"] = "misp"
alert_output["misp"]["error"] = 'Connection Error to MISP API'
send_event(alert_output, alert["agent"])
else:
misp_api_response = misp_api_response.json()
# Check if response includes Attributes (IoCs)
if (misp_api_response["response"]["Attribute"]):
# Generate Alert Output from MISP Response
alert_output["misp"] = {}
alert_output["misp"]["event_id"] = misp_api_response["response"]["Attribute"][0]["event_id"]
alert_output["misp"]["category"] = misp_api_response["response"]["Attribute"][0]["category"]
alert_output["misp"]["value"] = misp_api_response["response"]["Attribute"][0]["value"]
alert_output["misp"]["type"] = misp_api_response["response"]["Attribute"][0]["type"]
send_event(alert_output, alert["agent"])
else:
sys.exit()
except IndexError:
sys.exit()
else:
sys.exit()
elif event_source == 'ossec' and event_type == "syscheck_entry_added":
try:
wazuh_event_param = alert["syscheck"]["sha256_after"]
except IndexError:
sys.exit()
misp_search_value = "value:"f"{wazuh_event_param}"
misp_search_url = ''.join([misp_base_url, misp_search_value])
try:
misp_api_response = requests.get(misp_search_url, headers=misp_apicall_headers, verify=false)
except ConnectionError:
alert_output["misp"] = {}
alert_output["integration"] = "misp"
alert_output["misp"]["error"] = 'Connection Error to MISP API'
send_event(alert_output, alert["agent"])
else:
misp_api_response = misp_api_response.json()
# Check if response includes Attributes (IoCs)
if (misp_api_response["response"]["Attribute"]):
# Generate Alert Output from MISP Response
alert_output["misp"] = {}
alert_output["misp"]["event_id"] = misp_api_response["response"]["Attribute"][0]["event_id"]
alert_output["misp"]["category"] = misp_api_response["response"]["Attribute"][0]["category"]
alert_output["misp"]["value"] = misp_api_response["response"]["Attribute"][0]["value"]
alert_output["misp"]["type"] = misp_api_response["response"]["Attribute"][0]["type"]
send_event(alert_output, alert["agent"])
else:
sys.exit()
Block added to ossec.config

custom-misp.py
sysmon_event1,sysmon_event3,sysmon_event6,sysmon_event7,sysmon_event_15,sysmon_event_22,syscheck
<alert_format>json</alert_format>

The file: MISP.XML


misp
misp
MISP Events
no_full_log


<if_sid>100620</if_sid>
.+
MISP - Error connecting to API
no_full_log
misp_error,


.+
MISP - IoC found in Threat Intel - Category: $(misp.category), Attribute: $(misp.value)
no_full_log
misp_alert,


image

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with custom-misp.py and trace the Windows Sysmon DNS alert through the MISP REST request and Wazuh socket output. Then compare the integration block in ossec.conf with the rules in misp.xml, reproduce the reported Windows client test, and confirm that a MISP response produces the expected Wazuh alert.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.