def main(): api = TheHiveApi(url, api_key) cases = api.find_cases(range="all") cases = cases.json() workbook = xlsxwriter.Workbook(excel_path, {'strings_to_urls': False}) worksheet = workbook.add_worksheet() bold = workbook.add_format({"bold": True}) worksheet.write("A1", "TheHive ID", bold) worksheet.write("B1", "CaseID", bold) worksheet.write("C1", "Status", bold) worksheet.write("D1", "Title", bold) worksheet.write("E1", "Date", bold) worksheet.write("F1", "Owner", bold) worksheet.write("G1", "TLP", bold) worksheet.write("H1", "Tag", bold) row = 1 for item in cases: item_id = item["id"] if "id" in item.keys() else item["_id"] worksheet.write(row, 0, item_id) worksheet.write(row, 1, item["caseId"]) worksheet.write(row, 2, item["status"]) worksheet.write(row, 3, item["title"]) worksheet.write( row, 4, datetime.datetime.fromtimestamp( item["startDate"] / 1000).strftime("%Y-%m-%d %H:%M:%S"), ) worksheet.write(row, 5, item["owner"]) worksheet.write(row, 6, item["tlp"]) worksheet.write(row, 7, ",".join(item["tags"])) row += 1 worksheet2 = workbook.add_worksheet() worksheet2.write("A1", "TheHive ID") worksheet2.write("B1", "Observable DataType") worksheet2.write("C1", "Observable Value") worksheet2.write("D1", "IOC") row = 1 for item in cases: item_id = item["id"] if "id" in item.keys() else item["_id"] obs = api.get_case_observables(item_id, query=query, sort=["-startDate", "+ioc"], range="all") obs = obs.json() for ob in obs: worksheet2.write(row, 0, item["caseId"]) worksheet2.write(row, 1, ob["dataType"]) if ob["dataType"] != "file": worksheet2.write(row, 2, ob["data"]) else: worksheet2.write(row, 2, ",".join(ob["attachment"]["hashes"])) worksheet2.write(row, 3, True if ob["ioc"] == 1 else False) row += 1 workbook.close()
async def update_case_task(self, url, api_key, task_id, title=None, description=None, status=None, flag=None): self.logger.info(f'Updating task {task_id} in TheHive...') if not url.startswith("http"): url = f"http://{url}" api = TheHiveApi(url, api_key) task = CaseTask(**api.get_case_task(task_id).json()) task.id = task_id if title: task.title = title if description: task.description = description if status: task.status = status if flag is not None: task.flag = flag r = api.update_case_task(task) if r.status_code == 200: return r.json() else: raise IOError(r.text)
def __init__(self, filepath): self.api = TheHiveApi('http://THE_HIVE_IP:PORT', 'API_KEY') self.case_id = None self.osservable_data = [] self.filepath = filepath self.filetype = filepath.split(".")[-1] self.filename = os.path.basename(filepath)
def get_HTMLCaseTaskSummary(self, caseID): """ Get all tasks of a given incident, and calculate statistics of the task. Return them as HTML string. """ # get case tasks by th4py api = TheHiveApi(self.thehive_url, self.thehive_apikey) response = api.get_case_tasks(caseID) # create statistics t_total = 0 t_compl = 0 t_inpro = 0 t_waiti = 0 t_cance = 0 for t in response.json(): t_total += 1 if t["status"] == "Completed": t_compl += 1 if t["status"] == "InProgress": t_inpro += 1 if t["status"] == "Waiting": t_waiti += 1 if t["status"] == "Cancel": t_cance += 1 # in progress summary = ("Completed: {1}/{0}<br/>" "InProgress: {2}/{0}<br/>" "Waiting: {3}/{0}<br/>" "Canceled: {4}/{0}").format(t_total, t_compl, t_inpro, t_waiti, t_cance) return summary
def prepare_subject_observable(id, subject): hive_address = ''.join(settings.stored_hive_address[0]) hive_api = ''.join(settings.stored_api_key[0]) #Define the connection to thehive installation (including the generated API key). api = TheHiveApi(hive_address, hive_api, None, {'http': '', 'https': ''}) print(subject) print('Create subject observable') print('---------------------') domain = CaseObservable(dataType='subject', data=[subject], tlp=0, ioc=False, tags=['ExtractedSubject'], message='Subject Extracted') response = api.create_case_observable(id, domain) if response.status_code == 201: # print(json.dumps(response.json(), indent=4, sort_keys=True)) print( str(datetime.datetime.now()) + " Observable succesfully created.") elif response.status.code == 400: print( str(datetime.datetime.now()) + " Subject Observable already exists") else: print( str(datetime.datetime.now()) + " Error creating Subject Observables.") print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0)
def run(self, task_id, log): api = TheHiveApi(self.config['thehive_url'], self.config['thehive_api_key']) case_task_log = CaseTaskLog(message=log) response = api.create_task_log(task_id, case_task_log) return response.json()
def test_get_case(mock_get): thehive = TheHiveApi('http://127.0.0.1:9000', 'API_KEY') test_id = 'AV55EOIsPQ_zDQrlj4a9' test_json = { '_type': 'case', 'caseId': 5, 'createdAt': 1505269703195, 'createdBy': 'username', 'customFields': {}, 'description': 'test description', 'flag': False, 'id': test_id, 'metrics': {}, 'owner': 'username', 'severity': 2, 'startDate': 1505269703000, 'status': 'Open', 'tags': [], 'title': 'test case', 'tlp': 2, 'user': '******' } mock_response = mock.Mock() mock_response.json.return_value = test_json mock_response.status_code = 200 mock_get.return_value = mock_response case = thehive.case(test_id) assert mock_response.json.call_count == 1 assert case.id == test_id
def __init__(self): Responder.__init__(self) self.case_data_filter = [ "endDate", "startDate", "title", "createdAt", "caseId", "pap", "tlp", "severity", "owner", "createdBy", "updatedBy", "summary", "tags", "resolutionStatus", "impactStatus", "status", "customFields" ] self.case_observables_filter = [ "data", "dataType", "sighted", "tags", "createdAt", "createdBy", "pap", "tlp", "ioc", "startDate", "status" ] self.case_tasks_filter = [ "caseTasks", "updatedBy", "createdAt", "flag", "description", "title", "createdBy", "updatedAt", "order", "status", "group" ] self.api_key = self.get_param('config.api_key', None, 'Missing API-key') self.https_address = self.get_param('config.https_address', 'localhost') self.https_port = self.get_param('config.https_port', 9000, 'Missing thehive port') self.smtp_host = self.get_param('config.smtp_host', 'localhost') self.smtp_port = self.get_param('config.smtp_port', '25') self.mail_from = self.get_param('config.from', None, 'Missing sender email address') self.api = TheHiveApi( f"https://{self.https_address}:{self.https_port}", self.api_key)
def find_case_id(title, query, range, sort): hive_address = ''.join(settings.stored_hive_address[0]) hive_api = ''.join(settings.stored_api_key[0]) #Define the connection to thehive installation (including the generated API key). api = TheHiveApi(hive_address, hive_api, None, {'http': '', 'https': ''}) response = api.find_cases(query=query, range=range, sort=sort) if response.status_code == 200: test = json.dumps(response.json(), indent=4, sort_keys=True) resp = json.loads(test) try: full_case_id = resp[0]['id'] print( str(datetime.datetime.now()) + " Case: " + str(query) + " found. Extracted full case id number (" + str(full_case_id) + ").") return full_case_id except IndexError: print( str(datetime.datetime.now()) + " Case: " + str(query) + "has not been found.") else: # print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0)
def main(): api = TheHiveApi(url, api_key) session = requests.Session() session.headers.update({"Authorization": "Bearer {}".format(api_key)}) obs = api.get_case_observables(caseId, query={}, sort=["-startDate", "+ioc"], range="all") obs = obs.json() for ob in obs: r = session.get( '{}/api/case/artifact/{}/similar?range=all&sort=-startDate'.format( url, ob['id'])) data = r.json() if len(data) > 0: print(ob['data'], len(r.json()), 'results') titles = [] for case in data: #print(case) cases = api.find_cases(query=Id(case['_parent']), range="all") print("\t - {} [{}]".format(cases.json()[0]['title'], case['_parent'])) print()
def __init__(self): Responder.__init__(self) self.flow_master_controller = self.get_param('config.flow_master_controller', None, "Endpoint is Missing") self.thehive_instance = self.get_param('config.thehive_instance', 'localhost:9000') self.thehive_api_key = self.get_param('config.thehive_api_key', 'YOUR_KEY_HERE') self.api = TheHiveApi(self.thehive_instance,self.thehive_api_key) self.Cert_Path = self.get_param('config.Cert_Path')
def process_events(config, events): """ process events returned by cyrating """ thapi = TheHiveApi(config.get('url', None), config.get('key'), config.get('password', None), config.get('proxies')) for a in events: print("Working with " + a.get('name')) query = And(String("title:\"Reputation alert from Cyrating for \""), Child('case_artifact', And(Eq('data', a.get('name'))))) #query = String("title:\"Reputation alert from Cyrating for \"" + generate_title_from_event(a) + "\"") logging.debug('API TheHive - case: {}'.format(a.get('name'))) response = thapi.find_cases(query=query, range='all', sort=[]) logging.debug('API TheHive - Find case - status code: {}'.format( response.status_code)) if response.status_code > 299: logging.debug('API TheHive - raw error output: {}'.format( response.raw.read())) continue case = response.json() if len(case) == 0: print("Create new case") create_th_case(thapi, a) else: print("Previous cases found - updating") for c in case: print(" - " + c.get('id') + " (" + c.get('title') + ")") update_case(thapi, c, a)
async def get_item(self, apikey, url, field_type, cur_id): self.thehive = TheHiveApi(url, apikey) newstr = "" ret = "" if field_type.lower() == "alert": ret = self.thehive.get_alert(cur_id) elif field_type.lower() == "case": ret = self.thehive.get_case(cur_id) elif field_type.lower() == "case_observables": ret = self.thehive.get_case_observables(cur_id) elif field_type.lower() == "case_task": ret = self.thehive.get_case_task(cur_id) elif field_type.lower() == "case_tasks": ret = self.thehive.get_case_tasks(cur_id) elif field_type.lower() == "case_template": ret = self.thehive.get_case_tasks(cur_id) elif field_type.lower() == "linked_cases": ret = self.thehive.get_linked_cases(cur_id) elif field_type.lower() == "task_log": ret = self.thehive.get_task_log(cur_id) elif field_type.lower() == "task_logs": ret = self.thehive.get_task_logs(cur_id) else: return "%s is not implemented. See https://github.com/frikky/shuffle-apps for more info." % field_type newstr = str(ret.json()).replace("\'", "\"") newstr = newstr.replace("True", "true") newstr = newstr.replace("False", "false") return newstr
async def create_case_observable(self, case_id, url, api_key, data_type, data, description=None, tlp=0, is_ioc=False, is_sighted=False, tags=None): tags = tags if tags is not None else [] self.logger.info(f'Creating observable for {case_id} in TheHive...') if not url.startswith("http"): url = f"http://{url}" api = TheHiveApi(url, api_key) obs = CaseObservable(dataType=data_type, message=description, tlp=tlp, tags=tags, ioc=is_ioc, sighted=is_sighted, data=data) r = api.create_case_observable(case_id, obs) if r.status_code == 201: return r.json() else: raise IOError(r.text)
def __connect_thehive(self, url, apikey, organisation): if organisation: self.thehive = TheHiveApi( url, apikey, cert=False, organisation=organisation ) else: self.thehive = TheHiveApi(url, apikey, cert=False)
def hiveInit(): # Check if verifying cert if 'False' in hive_verifycert: api = TheHiveApi(hive_url, hive_key, cert=False) else: api = TheHiveApi(hive_url, hive_key, cert=True) return api
def add_task_log(full_task_id, body, file_array): hive_address = ''.join(settings.stored_hive_address[0]) hive_api = ''.join(settings.stored_api_key[0]) #Define the connection to thehive installation (including the generated API key). api = TheHiveApi(hive_address, hive_api, None, {'http': '', 'https': ''}) #Strip the message of any old replies---difficult as I have already made it a plain text file so all encoded stuff gone!. #string_list = re.findall(r"\w+\s+\w+[,]\s+\w+\s+\d+[,]\s+\d+\s+\w+\s+\d+[:]\d+\s+\w+.*", body) # regex for On Thu, Mar 24, 2011 at 3:51 PM #res = body.split(string_list[0]) # split on that match #print(res[0]) # get before string of the regex #print("So is this the split message?:",res[0]) #Later add on file=file_array tasklog = CaseTaskLog(message=body, file="") #Need to also add some observables to this response = api.create_task_log(full_task_id, tasklog) if response.status_code == 201: #print(json.dumps(response.json(), indent=4, sort_keys=True)) print(str(datetime.datetime.now()) + " Task Log succesfully created.") else: print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0)
def prepare_url_observable(id, url_array): hive_address = ''.join(settings.stored_hive_address[0]) hive_api = ''.join(settings.stored_api_key[0]) #We will need to run through the arrays to extract the values. #Define the connection to thehive installation (including the generated API key). api = TheHiveApi(hive_address, hive_api, None, {'http': '', 'https': ''}) for urladdress in url_array: print( str(datetime.datetime.now()) + " Creating url observable:" + urladdress) domain = CaseObservable(dataType='url', data=[urladdress], tlp=0, ioc=False, tags=['ExtractedUrls'], message='Urls Extracted') response = api.create_case_observable(id, domain) if response.status_code == 201: # print(json.dumps(response.json(), indent=4, sort_keys=True)) print( str(datetime.datetime.now()) + " Observable succesfully created.") elif response.status_code == 400: print( str(datetime.datetime.now()) + " URL Observable already exists") else: print( str(datetime.datetime.now()) + " Error creating URL Observables.") print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0)
async def get_item(self, apikey, url, field_type, cur_id): self.thehive = TheHiveApi(url, apikey, cert=False) newstr = "" ret = "" if field_type.lower() == "alert": ret = self.thehive.get_alert(cur_id + "?similarity=1") elif field_type.lower() == "case": ret = self.thehive.get_case(cur_id) elif field_type.lower() == "case_observables": ret = self.thehive.get_case_observables(cur_id) elif field_type.lower() == "case_task": ret = self.thehive.get_case_task(cur_id) elif field_type.lower() == "case_tasks": ret = self.thehive.get_case_tasks(cur_id) elif field_type.lower() == "case_template": ret = self.thehive.get_case_tasks(cur_id) elif field_type.lower() == "linked_cases": ret = self.thehive.get_linked_cases(cur_id) elif field_type.lower() == "task_log": ret = self.thehive.get_task_log(cur_id) elif field_type.lower() == "task_logs": ret = self.thehive.get_task_logs(cur_id) else: return ( "%s is not implemented. See https://github.com/frikky/shuffle-apps for more info." % field_type) return ret.text
async def update_case_observable(self, url, api_key, case_id, obs_id, description=None, tlp=0, is_ioc=False, is_sighted=False, tags=None, tags_mode=None): self.logger.info(f'Updating observable {obs_id} in case {case_id} in TheHive...') if not url.startswith("http"): url = f"http://{url}" api = TheHiveApi(url, api_key) obs_list = api.get_case_observables(case_id).json() obs_json = [obs for obs in obs_list if obs["id"] == obs_id][0] obs = CaseObservable(**obs_json) obs.id = obs_id if description: obs.description = description if tlp: obs.tlp = tlp if is_ioc is not None: obs.ioc = is_ioc if is_sighted is not None: obs.sighted = is_sighted if tags is not None: if tags_mode == "append": tags = obs.tags + tags obs.tags = tags r = api.update_case_observables(obs) if r.status_code == 200: return r.json() else: raise IOError(r.text)
async def create_case_task(self, case_id, url, api_key, data=None): self.logger.info(f'Creating task for {case_id} in TheHive...') if not url.startswith("http"): url = f"http://{url}" api = TheHiveApi(url, api_key) results = {} for item in data: try: title = item["title"] description = item["description"] startDate = time.time_ns() // 1000000 task = CaseTask(title=title, description=description, startDate=startDate) r = api.create_case_task(case_id, task) if r.status_code == 201: results[title] = r.json() else: raise IOError(r.text) except Exception as e: self.console_logger.info(f"Failed to create task with input {item} because: {e}") return results
async def create_alert(self, apikey, url, type, source, sourceref, title, description="", tlp=1, severity=1, tags=""): self.thehive = TheHiveApi(url, apikey) if tags: if ", " in tags: tags = tags.split(", ") elif "," in tags: tags = tags.split(",") else: tags = [] else: tags = [] # Wutface fix if not tlp: tlp = 1 if not severity: severity = 1 if isinstance(tlp, str): if not tlp.isdigit(): return "TLP needs to be a number from 0-2, not %s" % tlp tlp = int(tlp) if isinstance(severity, str): if not severity.isdigit(): return "Severity needs to be a number from 0-2, not %s" % tlp severity = int(severity) if tlp > 2 or tlp < 0: return "TLP needs to be a number from 0-2, not %d" % tlp if severity > 2 or severity < 0: return "Severity needs to be a number from 0-2, not %d" % tlp alert = thehive4py.models.Alert( title=title, tlp=tlp, severity=severity, tags=tags, description=description, type=type, source=source, sourceRef=sourceref, ) try: ret = self.thehive.create_alert(alert) return ret.text except requests.exceptions.ConnectionError as e: return "ConnectionError: %s" % e
def send_thehive_message(rule, message, asset, description): print("send_thehive_message:", rule, message, asset, description) thehive_url = Setting.objects.get(key="alerts.endpoint.thehive.url") thehive_apikey = Setting.objects.get(key="alerts.endpoint.thehive.apikey") alert_message = "[Alert][Rule={}]{}".format(rule.title, message) api = TheHiveApi(thehive_url.value, thehive_apikey.value) sourceRef = str(uuid.uuid4())[0:6] rule_severity = 0 if rule.severity == "Low": rule_severity = 1 elif rule.severity == "Medium": rule_severity = 2 elif rule.severity == "High": rule_severity = 3 tlp = 0 if asset.criticity == "low": tlp = 1 elif asset.criticity == "medium": tlp = 2 elif asset.criticity == "high": tlp = 3 if asset: artifacts = [AlertArtifact(dataType=asset.type, data=asset.value)] try: alert = Alert( title=alert_message, tlp=tlp, severity=rule_severity, tags=['src:PatrOwl'], description=description, type='external', source='patrowl', sourceRef=sourceRef, artifacts=artifacts) response = api.create_alert(alert) if response.status_code == 201: alert_id = response.json()['id'] # todo: track theHive alerts Event.objects.create( message="[Rule][send_thehive_message()] " "Alert sent to TheHive with message '{}' (alert id: {})".format(message, alert_id), type="DEBUG", severity="DEBUG" ) else: Event.objects.create( message="[Rule][send_thehive_message()] Unable to send " "alert to TheHive with message ='{}'".format(message), type="ERROR", severity="ERROR" ) except Exception: Event.objects.create( message="[Rule][send_thehive_message()] Unable to send alert " "to TheHive with message ='{}'".format(message), type="ERROR", severity="ERROR")
def __init__(self): self.customers = [] self.db_status = False if cfg.TheHive: self.hive = TheHiveApi("http://%s" % cfg.hiveip, cfg.hiveusername, cfg.hivepassword, {"http": "", "https": ""}) self.cortex_log_path = "log/cortex_analysis.log" self.cortex_listener = cortex_listen(self.cortex_log_path)
async def search_alerts(self, apikey, url, title_query): self.thehive = TheHiveApi(url, apikey) response = self.thehive.find_alerts(query=String("title:'%s'" % title_query), range='all', sort=[]) return response.text
async def search_cases(self, apikey, url, title_query): self.thehive = TheHiveApi(url, apikey, cert=False) response = self.thehive.find_cases(query=ContainsString( "title", title_query), range="all", sort=[]) return response.text
def run(self, alert_id, case_template=None): api = TheHiveApi(self.config['thehive_url'], self.config['thehive_api_key']) # api.promote_alert_to_case(alert_id, case_template) # wait for https://github.com/TheHive-Project/TheHive4py/pull/115 api.promote_alert_to_case(alert_id) return True
def run(self, job_id, log): api = TheHiveApi(self.config['thehive_url'], self.config['thehive_api_key']) task_id = self.action_service.get_value( name='thehive_job_{}'.format(job_id), local=False) response = api.create_task_log(task_id, log) return response.json()
def __init__(self): Responder.__init__(self) self.thehive_instance = self.get_param('config.thehive_instance', 'localhost:9000') self.thehive_api = self.get_param('config.thehive_api', 'YOUR_KEY_HERE') self.api = TheHiveApi(self.thehive_instance, self.thehive_api) self.tmpPath = self.get_param('config.tmp_file_location')
def __init__(self, url = None, username = None, password = None, apiKey = None, proxies={}, cert=True, organisation=None, version=None, sid = "", logger = None): self.logger = logger if version=="TheHive4": self.logger.debug("[TH25] TheHive version is 4.x") if sys.version_info[0] < 3: version = Version.THEHIVE_4 else: version = Version.THEHIVE_4.value elif version=="TheHive3": self.logger.debug("[TH26] TheHive version is 3.x") if sys.version_info[0] < 3: version = Version.THEHIVE_3 else: version = Version.THEHIVE_3.value else: self.logger.warning("[TH27] No valid version of TheHive was found for the given type: \""+str(version)+"\". Default will be used (TheHive 3)") if sys.version_info[0] < 3: version = Version.THEHIVE_3 else: version = Version.THEHIVE_3.value try : if sys.version_info[0] < 3: if apiKey is not None: TheHiveApi.__init__(self,url=str(url),principal=str(apiKey),password=None,proxies=proxies,cert=cert,organisation=organisation,version=version) elif password is not None: TheHiveApi.__init__(self,url=str(url),principal=username,password=password,proxies=proxies,cert=cert,organisation=organisation,version=version) else: self.logger.error("[TH30-ERROR] THE_HIVE_AUTHENTICATION - Password AND API Key are null values") exit(30) else: if apiKey is not None: super().__init__(url=str(url),principal=str(apiKey),password=None,proxies=proxies,cert=cert,organisation=organisation,version=version) elif password is not None: super().__init__(url=str(url),principal=username,password=password,proxies=proxies,cert=cert,organisation=organisation,version=version) else: self.logger.error("[TH31-ERROR] THE_HIVE_AUTHENTICATION - Password AND API Key are null values") exit(31) self.logger.debug("[TH35] TheHive instance is initialized") # Try to connect to the API by recovering some cases self.find_cases(query={}, range='all') if apiKey is not None: self.logger.debug("[TH40] TheHive API connection to (URL=\""+url+"\",API key=\""+apiKey+"\") is successful") elif password is not None: self.logger.debug("[TH41] TheHive API connection to (URL=\""+url+"\",Username=\""+username+"\",Password=\""+password+"\") is successful") except thehive4py.exceptions.TheHiveException as e: if "CERTIFICATE_VERIFY_FAILED" in str(e): self.logger.warning("[TH45] THE_HIVE_CERTIFICATE_FAILED - It seems that the certificate verification failed. Please check that the certificate authority is added to \""+str(certifi.where())+"\". Complete error: "+str(e)) sys.exit(45) else: self.logger.error("[TH46-GENERIC-ERROR] THE_HIVE_CONNECTION_ERROR - Error: "+str(e)) sys.exit(46) self.__sid = sid
class Cortex(object): def __init__(self): self.es = Elasticsearch(['127.0.0.1'], port=9200) self.api = Api('http://<CORTEX URL>', <CORTEX KEY>) self.hive_api = TheHiveApi('<HIVE URL>', <HIVE KEY>, cert=False) def parseArtifacts(self, cortexJobId, jobId): artifacts = self.api.jobs.get_artifacts(cortexJobId) if artifacts: caseId = self.es.search(index='the_hive_13', body={'query':{'match':{'objectId': jobId,}}})['hits']['hits'][0]['_source']['rootId'] for a in artifacts: ob = CaseObservable(dataType=a.dataType, data=a.data) self.hive_api.create_case_observable(caseId, ob) time.sleep(1)
print('Misp connected') except: print('Misp not connected') pymisp = False misp_event_url = '#' # The Hive # try: from thehive4py.api import TheHiveApi import thehive4py.exceptions from theHiveKEYS import the_hive_url, the_hive_key, the_hive_verifycert if the_hive_url == '': HiveApi = False hive_case_url = '#' print('The HIVE not connected') else: HiveApi = TheHiveApi(the_hive_url, the_hive_key, cert=the_hive_verifycert) hive_case_url = the_hive_url+'/index.html#/case/id_here/details' except: print('The HIVE not connected') HiveApi = False hive_case_url = '#' if HiveApi != False: try: HiveApi.get_alert(0) print('The Hive connected') except thehive4py.exceptions.AlertException: HiveApi = False print('The Hive not connected') # VARIABLES #
def __init__(self): self.es = Elasticsearch(['127.0.0.1'], port=9200) self.api = Api('http://<CORTEX URL>', <CORTEX KEY>) self.hive_api = TheHiveApi('<HIVE URL>', <HIVE KEY>, cert=False)
def submitTheHive(message): ''' Create a new case in TheHive based on the email Return 'TRUE' is successfully processed otherwise 'FALSE' ''' global log # Decode email msg = email.message_from_bytes(message) decode = email.header.decode_header(msg['From'])[0] if decode[1] is not None: fromField = decode[0].decode(decode[1]) else: fromField = str(decode[0]) decode = email.header.decode_header(msg['Subject'])[0] if decode[1] is not None: subjectField = decode[0].decode(decode[1]) else: subjectField = str(decode[0]) log.info("From: %s Subject: %s" % (fromField, subjectField)) attachments = [] observables = [] # Extract SMTP headers and search for observables parser = HeaderParser() headers = parser.parsestr(msg.as_string()) headers_string = '' i = 0 while i < len(headers.keys()): headers_string = headers_string + headers.keys()[i] + ': ' + headers.values()[i] + '\n' i+=1 # Temporary disabled # observables = searchObservables(headers_string, observables) body = '' for part in msg.walk(): if part.get_content_type() == "text/plain": try: body = part.get_payload(decode=True).decode() except UnicodeDecodeError: body = part.get_payload(decode=True).decode('ISO-8859-1') observables.extend(searchObservables(body, observables)) elif part.get_content_type() == "text/html": try: html = part.get_payload(decode=True).decode() except UnicodeDecodeError: html = part.get_payload(decode=True).decode('ISO-8859-1') observables.extend(searchObservables(html, observables)) else: # Extract MIME parts filename = part.get_filename() mimetype = part.get_content_type() if filename and mimetype: if mimetype in config['caseFiles'] or not config['caseFiles']: log.info("Found attachment: %s (%s)" % (filename, mimetype)) # Decode the attachment and save it in a temporary file charset = part.get_content_charset() if charset is None: charset = chardet.detect(bytes(part))['encoding'] # Get filename extension to not break TheHive analysers (see Github #11) fname, fextension = os.path.splitext(filename) fd, path = tempfile.mkstemp(prefix=slugify(fname) + "_", suffix=fextension) try: with os.fdopen(fd, 'w+b') as tmp: tmp.write(part.get_payload(decode=1)) attachments.append(path) except OSerror as e: log.error("Cannot dump attachment to %s: %s" % (path,e.errno)) return False # Cleanup observables (remove duplicates) new_observables = [] for o in observables: if not {'type': o['type'], 'value': o['value'] } in new_observables: # Is the observable whitelisted? if isWhitelisted(o['value']): log.debug('Skipping whitelisted observable: %s' % o['value']) else: new_observables.append({ 'type': o['type'], 'value': o['value'] }) log.debug('Found observable %s: %s' % (o['type'], o['value'])) else: log.info('Ignoring duplicate observable: %s' % o['value']) log.info("Removed duplicate observables: %d -> %d" % (len(observables), len(new_observables))) observables = new_observables api = TheHiveApi(config['thehiveURL'], config['thehiveUser'], config['thehivePassword'], {'http': '', 'https': ''}) # Search for interesting keywords in subjectField: log.debug("Searching for %s in '%s'" % (config['alertKeywords'], subjectField)) if re.match(config['alertKeywords'], subjectField, flags=0): # # Add observables found in the mail body # artifacts = [] if config['thehiveObservables'] and len(observables) > 0: for o in observables: artifacts.append(AlertArtifact(dataType=o['type'], data=o['value'])) # # Prepare tags - add alert keywords found to the list of tags # tags = list(config['alertTags']) match = re.findall(config['alertKeywords'], subjectField) for m in match: tags.append(m) # # Prepare the alert # sourceRef = str(uuid.uuid4())[0:6] alert = Alert(title=subjectField.replace('[ALERT]', ''), tlp = int(config['alertTLP']), tags = tags, description = body, type = 'external', source = fromField, sourceRef = sourceRef, artifacts = artifacts) # Create the Alert id = None response = api.create_alert(alert) if response.status_code == 201: log.info('Created alert %s' % response.json()['sourceRef']) else: log.error('Cannot create alert: %s (%s)' % (response.status_code, response.text)) return False else: # Prepare the sample case tasks = [] for task in config['caseTasks']: tasks.append(CaseTask(title=task)) # Prepare the custom fields customFields = CustomFieldHelper()\ .add_string('from', fromField)\ .add_string('attachment', str(attachments))\ .build() # If a case template is specified, use it instead of the tasks if len(config['caseTemplate']) > 0: case = Case(title=subjectField, tlp = int(config['caseTLP']), flag = False, tags = config['caseTags'], description = body, template = config['caseTemplate'], customFields = customFields) else: case = Case(title = subjectField, tlp = int(config['caseTLP']), flag = False, tags = config['caseTags'], description = body, tasks = tasks, customFields = customFields) # Create the case id = None response = api.create_case(case) if response.status_code == 201: newID = response.json()['id'] log.info('Created case %s' % response.json()['caseId']) if len(attachments) > 0: for path in attachments: observable = CaseObservable(dataType='file', data = [path], tlp = int(config['caseTLP']), ioc = False, tags = config['caseTags'], message = 'Found as email attachment' ) response = api.create_case_observable(newID, observable) if response.status_code == 201: log.info('Added observable %s to case ID %s' % (path, newID)) os.unlink(path) else: log.warning('Cannot add observable: %s - %s (%s)' % (path, response.status_code, response.text)) # # Add observables found in the mail body # if config['thehiveObservables'] and len(observables) > 0: for o in observables: observable = CaseObservable( dataType = o['type'], data = o['value'], tlp = int(config['caseTLP']), ioc = False, tags = config['caseTags'], message = 'Found in the email body' ) response = api.create_case_observable(newID, observable) if response.status_code == 201: log.info('Added observable %s: %s to case ID %s' % (o['type'], o['value'], newID)) else: log.warning('Cannot add observable %s: %s - %s (%s)' % (o['type'], o['value'], response.status_code, response.text)) else: log.error('Cannot create case: %s (%s)' % (response.status_code, response.text)) return False return True