Thehive4 and wazuh integration Indexerror

197 views
Skip to first unread message

Johny Novent

unread,
Aug 31, 2023, 3:42:29 PM8/31/23
to wa...@googlegroups.com
Hello everyone 

I'm trying to integrate Wazuh and Thehive4

I'm using Wazuh version 4.4.5 and Thehive 4.1.24

I'm using the post of wazuh about this integration


#!/var/ossec/framework/python/bin/python3
import json
import sys
import os
import re
import logging
import uuid
from thehive4py.api import TheHiveApi
from thehive4py.models import Alert, AlertArtifact

#start user config

# Global vars

#threshold for wazuh rules level
lvl_threshold=0
#threshold for suricata rules level
suricata_lvl_threshold=3

debug_enabled = False
#info about created alert
info_enabled = True

#end user config

# Set paths
pwd = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
log_file = '{0}/logs/integrations.log'.format(pwd)
logger = logging.getLogger(__name__)
#set logging level
logger.setLevel(logging.WARNING)
if info_enabled:
    logger.setLevel(logging.INFO)
if debug_enabled:
    logger.setLevel(logging.DEBUG)
# create the logging file handler
fh = logging.FileHandler(log_file)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)



def main(args):
    logger.debug('#start main')
    logger.debug('#get alert file location')
    alert_file_location = args[1]
    logger.debug('#get TheHive url')
    thive = args[3]
    logger.debug('#get TheHive api key')
    thive_api_key = args[2]
    thive_api = TheHiveApi(thive, thive_api_key )
    logger.debug('#open alert file')
    w_alert = json.load(open(alert_file_location))
    logger.debug('#alert data')
    logger.debug(str(w_alert))
    logger.debug('#gen json to dot-key-text')
    alt = pr(w_alert,'',[])
    logger.debug('#formatting description')
    format_alt = md_format(alt)
    logger.debug('#search artifacts')
    artifacts_dict = artifact_detect(format_alt)
    alert = generate_alert(format_alt, artifacts_dict, w_alert)
    logger.debug('#threshold filtering')
    if w_alert['rule']['groups']==['ids','suricata']:
        #checking the existence of the data.alert.severity field
        if 'data' in w_alert.keys():
            if 'alert' in w_alert['data']:
                #checking the level of the source event
                if int(w_alert['data']['alert']['severity'])<=suricata_lvl_threshold:
                    send_alert(alert, thive_api)
    elif int(w_alert['rule']['level'])>=lvl_threshold:
        #if the event is different from suricata AND suricata-event-type: alert check lvl_threshold
        send_alert(alert, thive_api)


def pr(data,prefix, alt):
    for key,value in data.items():
        if hasattr(value,'keys'):
            pr(value,prefix+'.'+str(key),alt=alt)
        else:
            alt.append((prefix+'.'+str(key)+'|||'+str(value)))
    return alt



def md_format(alt,format_alt=''):
    md_title_dict = {}
    #sorted with first key
    for now in alt:
        now = now[1:]
        #fix first key last symbol
        dot = now.split('|||')[0].find('.')
        if dot==-1:
            md_title_dict[now.split('|||')[0]] =[now]
        else:
            if now[0:dot] in md_title_dict.keys():
                (md_title_dict[now[0:dot]]).append(now)
            else:
                md_title_dict[now[0:dot]]=[now]
    for now in md_title_dict.keys():
        format_alt+='### '+now.capitalize()+'\n'+'| key | val |\n| ------ | ------ |\n'
        for let in md_title_dict[now]:
            key,val = let.split('|||')[0],let.split('|||')[1]
            format_alt+='| **' + key + '** | ' + val + ' |\n'
    return format_alt


def artifact_detect(format_alt):
    artifacts_dict = {}
    artifacts_dict['ip'] = re.findall(r'\d+\.\d+\.\d+\.\d+',format_alt)
    artifacts_dict['url'] =  re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',format_alt)
    artifacts_dict['domain'] = []
    for now in artifacts_dict['url']: artifacts_dict['domain'].append(now.split('//')[1].split('/')[0])
    return artifacts_dict


def generate_alert(format_alt, artifacts_dict,w_alert):
    #generate alert sourceRef
    sourceRef = str(uuid.uuid4())[0:6]
    artifacts = []
    if 'agent' in w_alert.keys():
        if 'ip' not in w_alert['agent'].keys():
            w_alert['agent']['ip']='no agent ip'
    else:
        w_alert['agent'] = {'id':'no agent id', 'name':'no agent name'}

    for key,value in artifacts_dict.items():
        for val in value:
            artifacts.append(AlertArtifact(dataType=key, data=val))
    alert = Alert(title=w_alert['rule']['description'],
              tlp=2,
              tags=['wazuh', 
              'rule='+w_alert['rule']['id'], 
              'agent_name='+w_alert['agent']['name'],
              'agent_id='+w_alert['agent']['id'],
              'agent_ip='+w_alert['agent']['ip'],],
              description=format_alt ,
              type='wazuh_alert',
              source='wazuh',
              sourceRef=sourceRef,
              artifacts=artifacts,)
    return alert




def send_alert(alert, thive_api):
    response = thive_api.create_alert(alert)
    if response.status_code == 201:
        logger.info('Create TheHive alert: '+ str(response.json()['id']))
    else:
        logger.error('Error create TheHive alert: {}/{}'.format(response.status_code, response.text))



if __name__ == "__main__":

    try:
       logger.debug('debug mode') # if debug enabled       
       # Main function
       main(sys.argv)

    except Exception:
       logger.exception('EGOR')


I've installed thehive4py 1.8.1 

image.png

image.png

I changed the user and group accordingly 

chmod 755 /var/ossec/integrations/custom-w2thive.py
chmod 755 /var/ossec/integrations/custom-w2thive
chown root:wazuh /var/ossec/integrations/custom-w2thive.py
chown root:wazuh /var/ossec/integrations/custom-w2thive

image.png

I've created my API key user in Thehive and put it in the block in ossec.conf

<integration>
<name>custom-w2thive</name>
<hook_url>http://TheHive_Server_IP:9000</hook_url>
<api_key>My API KEY FROM THEHIVE</api_key>
<alert_format>json</alert_format>
</integration>

I restarted the wazuh-manager several times and thehive server too

but not successfully when I'm in my thehive account nothing appears 

image.png

I've found the following error in /var/ossec/logs/integrations.log

image.png

It looks like an error with sys module and Index error 

If someone can help me or someone it worked the script please help 

Regards 

Johny



Jorge Eduardo Molas

unread,
Aug 31, 2023, 4:02:41 PM8/31/23
to Wazuh | Mailing List
Hi Johny. Thanks for using Wazuh. 
I'll take a look at your case, I'll be back soon.
Greetings

Johny Novent

unread,
Aug 31, 2023, 10:34:58 PM8/31/23
to Wazuh | Mailing List
Thank you Jorge Eduardo for your time and support 

I'll be waiting for your answer  

Regards 

Johny

Johny Novent

unread,
Aug 31, 2023, 10:49:35 PM8/31/23
to Wazuh | Mailing List
Recently I found the following errors with the logs paths 

When I check the logs for any errors or changes, I see the same error in the paths

/var/ossec/logs/ossec.log


1.jpg


In the path

tail -f /var/ossec/logs/integrations.log

2.jpg


I think that the error is caused for this

when I try to run the code with python3 the script custom-w2thive.py

3.jpg

It can't find the module thehive4py ......but why ??


The module was installed or no ??

when I run the following command thehive4py is installed

# /var/ossec/framework/python/bin/pip3 install thehive4py==1.8.1


4.jpg


I have this in my packages and this is my python3


# python3 --version

Python 3.6.8


------

I can't see thehive4py in pip3 list


# pip3 list

DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.

asn1crypto (0.24.0)

cffi (1.11.5)

chardet (3.0.4)

configobj (5.0.6)

cryptography (2.3)

dbus-python (1.2.4)

decorator (4.2.1)

ethtool (0.14)

file-magic (0.3.0)

gpg (1.10.0)

idna (2.5)

iniparse (0.4)

isc (2.0)

jmespath (0.9.0)

netifaces (0.10.6)

nftables (0.1)

pciutils (2.3.6)

perf (0.1)

pip (9.0.3)

ply (3.9)

pycairo (1.16.3)

pycparser (2.14)

pygobject (3.28.3)

pyinotify (0.9.6)

pyOpenSSL (18.0.0)

PySocks (1.6.8)

python-dateutil (2.6.1)

python-dmidecode (3.12.2)

python-linux-procfs (0.6)

pyudev (0.21.0)

PyYAML (3.12)

requests (2.20.0)

rhnlib (2.8.6)

rpm (4.14.2)

schedutils (0.6)

selinux (2.9)

sepolicy (1.1)

setools (4.2.2)

setroubleshoot (1.1)

setuptools (39.2.0)

six (1.11.0)

slip (0.6.4)

slip.dbus (0.6.4)

sos (3.8)

SSSDConfig (2.2.3)

subscription-manager (1.28.32)

syspurpose (1.28.32)

systemd-python (234)

urllib3 (1.24.2)


I hope you can help me with this


Regards


Johny


Jorge Eduardo Molas

unread,
Sep 1, 2023, 11:37:23 AM9/1/23
to Wazuh | Mailing List
Hi there!
I apologize for the delay. I understand that you have already identified an issue with the Python library. In order to troubleshoot, we need to verify a few points.

First, please note that the blog has been tested on Wazuh 4.2.5 and TheHive version 4.1.18.

Second, we need to know what type of installation Wazuh uses - Kubernetes, Docker, Virtual Machine (OVA), or Server (and what OS?).

Third, it's possible that you haven't adequately verified the installation of thehive4py-1.8.1 if you've been using Python installed on your own host. To properly verify it, you'll need to use the embedded Python in Wazuh, located at /var/ossec/framework/python/bin. Use the command "./pip3 list" to verify.

I look forward to your comments!
Greetings

Johny Novent

unread,
Sep 1, 2023, 8:50:13 PM9/1/23
to Wazuh | Mailing List
Hello Jorge 

1. Yeah I note that in wazuh post they used Thehive 4.1 and Wazuh 4.2 

I'm using thehive 4.1.24 , Wazuh 4.4.5 

2. I'm using one server with Wazuh manager, it was installed offline with RPM packages, Thehive was installed in other server but It is reachable

3. When I run the command 

It seems that the module is installed 

# /var/ossec/framework/python/bin/pip3 list

Package                  Version
------------------------ ---------
aiohttp                  3.8.1
aiohttp-cache            2.2.0
aiohttp-cors             0.7.0
aiohttp-jinja2           1.4.2
aioredis                 1.3.1
aiosignal                1.2.0
api                      4.4.5
asn1crypto               1.3.0
async-timeout            4.0.2
attrs                    20.3.0
azure-common             1.1.25
azure-storage-blob       2.1.0
azure-storage-common     2.1.0
boto3                    1.17.85
botocore                 1.20.85
cachetools               4.1.0
certifi                  2022.12.7
cffi                     1.14.4
chardet                  3.0.4
charset-normalizer       2.0.4
click                    8.1.3
clickclick               20.10.2
connexion                2.6.0
cryptography             3.3.2
Cython                   0.29.21
defusedxml               0.6.0
docker                   4.2.0
docker-pycreds           0.4.0
docutils                 0.15.2
ecdsa                    0.16.1
envparse                 0.2.0
Flask                    2.2.5
frozenlist               1.2.0
future                   0.18.3
google-api-core          1.30.0
google-auth              1.28.0
google-cloud-core        1.7.1
google-cloud-pubsub      2.7.1
google-cloud-storage     1.39.0
google-crc32c            1.1.2
google-resumable-media   1.3.1
googleapis-common-protos 1.51.0
grpc-google-iam-v1       0.12.3
grpcio                   1.38.1
hiredis                  1.1.0
idna                     2.9
importlib-metadata       3.10.1
inflection               0.3.1
itsdangerous             2.0.0
Jinja2                   3.0.0
jmespath                 0.9.5
jsonschema               2.6.0
libcst                   0.3.20
MarkupSafe               2.1.2
more-itertools           8.2.0
multidict                5.1.0
mypy-extensions          0.4.3
numpy                    1.21.6
openapi-spec-validator   0.2.6
packaging                20.9
pathlib                  1.0.1
pip                      23.0.1
proto-plus               1.19.0
protobuf                 3.19.6
psutil                   5.8.0
pyarrow                  8.0.0
pyasn1                   0.4.8
pyasn1-modules           0.2.8
pycparser                2.20
pyparsing                2.4.7
python-dateutil          2.8.1
python-jose              3.1.0
python-json-logger       2.0.2
python-magic             0.4.27
pytz                     2020.1
PyYAML                   5.4.1
requests                 2.25.1
rsa                      4.7.2
s3transfer               0.4.2
secure                   0.2.1
setuptools               65.5.1
six                      1.14.0
SQLAlchemy               1.3.11
tabulate                 0.8.9
thehive4py               1.8.1
typing-extensions        3.10.0.2
typing-inspect           0.7.1
urllib3                  1.26.5
uvloop                   0.15.2
wazuh                    4.4.5
websocket-client         0.57.0
Werkzeug                 2.2.3
xmltodict                0.12.0
yarl                     1.6.3
zipp                     3.3.2

[notice] A new release of pip is available: 23.0.1 -> 23.2.1
[notice] To update, run: /var/ossec/framework/python/bin/python3.9 -m pip install --upgrade pip


I tried to run this commands in a debug_mode = true 

And I create one file with json format called alert.json and test the script 

# /var/ossec/framework/python/bin/python3 /var/ossec/integrations/custom-w2thive.py /var/ossec/integrations/alert.json testkey testurl

I got this errors

1.jpg

This is maybe the format of my alert, because this is caused for the key "rule"

this is my alert in json 

3.jpg

I add "_source"  here in the script custom-w2thive.py


2.jpg

When I add this to the code pass this part and go to another error 

4.jpg

Now I change "testkey" and "testurl" with "api key thehive" and "http://10.xxx.xx.xx:9000/api/alert"

5.jpg

Here I dont know why I cant get create the alert ????

Regards 

Johny

Jorge Eduardo Molas

unread,
Sep 6, 2023, 2:44:43 PM9/6/23
to Wazuh | Mailing List
Sorry for my delay John! Woow, your debug looks fantastic.  
Regarding your last screenshot, it's possible that the path is incorrectly setted. Figure out in the message it says "/api/alert/api/alert"

In the configuration, you may only need to set "http://10.xxx.xx.xx:9000" instead of a full path.
I look forward to hearing your comments!
Reply all
Reply to author
Forward
0 new messages