#!/usr/bin/env python3 # -*-coding:UTF-8 -* """ Importer Class ================ Import Content """ import os import sys import uuid from abc import ABC from thehive4py.api import TheHiveApi from thehive4py.models import Alert, AlertArtifact, Case, CaseObservable import thehive4py.exceptions from urllib3 import disable_warnings as urllib3_disable_warnings sys.path.append('../../configs/keys') sys.path.append(os.environ['AIL_BIN']) ################################# # Import Project packages ################################# from exporter.abstract_exporter import AbstractExporter from lib.ConfigLoader import ConfigLoader from lib.ail_core import get_ail_uuid from lib.objects.Items import Item # from lib.objects.abstract_object import AbstractObject config_loader = ConfigLoader() r_db = config_loader.get_db_conn("Kvrocks_DB") config_loader = None #### FUNCTIONS #### # --- FUNCTIONS --- # # MISPExporter -> return correct exporter by type ???? class TheHiveExporter(AbstractExporter, ABC): """TheHive Exporter :param url: URL of the Hive instance you want to connect to :param key: API key of the user you want to use :param ssl: can be True or False (to check or to not check the validity of the certificate. Or a CA_BUNDLE in case of self signed or other certificate (the concatenation of all the crt of the chain) """ def __init__(self, url='', key='', ssl=False): super().__init__() if url and key: self.url = url self.key = key self.ssl = ssl if self.ssl is False: urllib3_disable_warnings() elif url or key: raise Exception('Error: missing url or api key') else: try: from theHiveKEYS import the_hive_url, the_hive_key, the_hive_verifycert self.url = the_hive_url self.key = the_hive_key self.ssl = the_hive_verifycert if self.ssl is False: urllib3_disable_warnings() if self.url.endswith('/'): self.url = self.url[:-1] except ModuleNotFoundError: self.url = None self.key = None self.ssl = None def get_hive(self): return TheHiveApi(self.url, self.key, cert=self.ssl) # TODO ADD TIMEOUT # TODO return error def ping(self): try: self.get_hive().get_alert('0') return True except thehive4py.exceptions.AlertException: return False @staticmethod def sanitize_threat_level(threat_level): try: int(threat_level) if 1 <= threat_level <= 3: return threat_level else: return 2 except (TypeError, ValueError): return 2 @staticmethod def sanitize_tlp(tlp): try: int(tlp) if 0 <= tlp <= 3: return tlp else: return 2 except (TypeError, ValueError): return 2 @staticmethod def sanitize_analysis(analysis): try: int(analysis) if 0 <= analysis <= 2: return analysis else: return 0 except (TypeError, ValueError): return 0 def get_case_url(self, case_id): return f'{self.url}/cases/{case_id}/details' def create_alert(self, artifacts, source, description='AIL', source_ref=None, tags=None, tlp=3, type='ail'): if not source_ref: source_ref = str(uuid.uuid4())[0:6] if tags is None: tags = [] alert = Alert(title='AIL Leak', tlp=self.sanitize_tlp(tlp), tags=tags, description=description, type=type, source=source, sourceRef=source_ref, artifacts=artifacts) # Create the Alert alert_id = 0 try: req = self.get_hive().create_alert(alert) if req.status_code == 201: # print(json.dumps(req.json(), indent=4, sort_keys=True)) print('Alert Created') # print(req.json()) alert_id = req.json()['id'] else: # TODO LOGS print(f'ko: {req.status_code}/{req.text}') return -2 except Exception as e: print(e) print('hive connection error') return -1 return alert_id def create_case(self, observables, description=None, tags=None, title=None, threat_level=2, tlp=2): if tags is None: tags = [] case = Case(title=title, tlp=self.sanitize_tlp(tlp), severity=self.sanitize_threat_level(threat_level), flag=False, tags=tags, description=description) # Create Case thehive = self.get_hive() resp = thehive.create_case(case) if resp.status_code == 201: case_id = resp.json()['id'] for observable in observables: resp_o = thehive.create_case_observable(case_id, observable) if resp_o.status_code != 201: # TODO LOGS print(f'error observable creation: {resp_o.status_code}/{resp_o.text}') # print(case_id) # return HIVE_URL /thehive/cases/~37040/details return case_id else: # TODO LOGS print(f'ko: {resp.status_code}/{resp.text}') return None def __repr__(self): return f'<{self.__class__.__name__}(url={self.url})' class TheHiveExporterAlertTag(TheHiveExporter): """TheHiveExporterAlertTag TagTrigger :param url: URL of the Hive instance you want to connect to :param key: API key of the user you want to use :param ssl: can be True or False (to check or to not check the validity of the certificate. Or a CA_BUNDLE in case of self signed or other certificate (the concatenation of all the crt of the chain) """ def __init__(self, url='', key='', ssl=False): super().__init__(url=url, key=key, ssl=ssl) def export(self, item, tag): item_id = item.get_id() tags = list(item.get_tags()) # remove .gz from submitted path to TheHive because content is decompressed if item_id.endswith(".gz"): item_id = item_id[:-3] # add .txt to make it easier to open when downloaded from TheHive item_id = f'{item_id}.txt' description = f'AIL Leak, triggered by {tag}' artifacts = [ AlertArtifact(dataType='other', message='uuid-ail', data=(get_ail_uuid())), AlertArtifact(dataType='file', data=(item.get_raw_content(decompress=True), item_id), tags=tags) ] return self.create_alert(artifacts, description=description, source=item.get_source(), tags=tags) class TheHiveExporterItem(TheHiveExporter): """TheHiveExporter Item case :param url: URL of the Hive instance you want to connect to :param key: API key of the user you want to use :param ssl: can be True or False (to check or to not check the validity of the certificate. Or a CA_BUNDLE in case of self signed or other certificate (the concatenation of all the crt of the chain) """ def __init__(self, url='', key='', ssl=False): super().__init__(url=url, key=key, ssl=ssl) def export(self, item_id, description=None, title=None, threat_level=None, tlp=None): item = Item(item_id) date = item.get_date() date = f'{date[0:4]}-{date[4:6]}-{date[6:8]}' tags = item.get_tags() ail_uuid = get_ail_uuid() if not title: title = f'AIL Case {item.id}' if not description: description = f'AIL {ail_uuid} Case' observables = [ CaseObservable(dataType="other", data=[ail_uuid], message="uuid-ail"), CaseObservable(dataType="file", data=item.get_filename(), tags=tags), CaseObservable(dataType="other", data=[item.get_source()], message="source"), CaseObservable(dataType="other", data=[date], message="last-seen") ] case_id = self.create_case(observables, tags=tags, description=description, title=title, threat_level=threat_level, tlp=tlp) # SAVE CASE URL/ID ???? return case_id # if __name__ == '__main__':