def create_hive_case(self, customer, data): create_hive_bool = self.get_hive_cases(customer, data) # Returns if case already merged. if not create_hive_bool: return False # Baseline for creating a case title = ("%s: %s - %s" % (customer.name, str(data["id"]), data["description"])) static_task = "Why did it happen? Check rule.", task_data = self.get_hive_task_data(data) tasks = [ CaseTask(title=static_task) ] if task_data: for item in task_data: tasks.append(CaseTask(title=item)) # Creates a case object case = Case(title=title, tlp=0, flag=False, tags=data["categories"], \ description=data["description"], tasks=tasks) # Creates the actual case based on prior info ret = self.hive.create_case(case) if ret.ok: # FIX, datatype is static self.add_observable_data(ret.json()["id"], create_hive_bool, \ "ip", data, data["categories"]) return True return False
def create_case_from_inc_name(api, incident): # Prepare the custom fields customFields = CustomFieldHelper() \ .add_string('category', incident["category"]) \ .add_string('type', incident["type"]) \ .build() # Словарь соответствия Severity в MP SIEM и The HIVE severity_dict = {'Low': 1, 'Medium': 2, 'High': 3} case = Case(title=incident["name"], tlp=3, flag=True, tags=['MP SIEM', 'Script'], description='', severity=severity_dict[incident["severity"]], customFields=customFields) # Create the CASE response = api.create_case(case) if response.status_code == 201: # print(json.dumps(response.json(), indent=4, sort_keys=True)) case_id = response.json()['id'] print_log("INFO: New Case **" + incident["name"] + "** in The Hive created") else: print_log('ERROR: {}/{}'.format(response.status_code, response.text)) sys.exit(0) return case_id
def run(self, params={}): client = self.connection.client self.logger.info("Input: %s", params) task = CaseTask( title=params.get("task").get("title", None), description=params.get("task").get("description", None), flag=params.get("task").get("flag", False), owner=params.get("task").get("owner", None), status=params.get("task").get("status", None), startDate=params.get("task").get("startDate", None), ) case = Case( title=params.get("title", None), tlp=params.get("tlp", 2), flag=params.get("flag", False), tags=params.get("tags", []), description=params.get("description", None), tasks=[task], customFields=params.get("customFields", None), ) try: new_case = client.create_case(case) new_case.raise_for_status() except requests.exceptions.HTTPError: self.logger.error(new_case.json()) raise except: self.logger.error("Failed to create case") raise return {"case": new_case.json()}
def run(self, params={}): client = self.connection.client self.logger.info('Input: %s', params) task = CaseTask(title=params.get('task').get('title', None), description=params.get('task').get( 'description', None), flag=params.get('task').get('flag', False), owner=params.get('task').get('owner', None), status=params.get('task').get('status', None), startDate=params.get('task').get('startDate', None)) case = Case(title=params.get('title', None), tlp=params.get('tlp', 2), flag=params.get('flag', False), tags=params.get('tags', []), description=params.get('description', None), tasks=[task], customFields=params.get('customFields', None)) try: new_case = client.create_case(case) new_case.raise_for_status() except requests.exceptions.HTTPError: self.logger.error(new_case.json()) raise except: self.logger.error('Failed to create case') raise return {'case': new_case.json()}
def save(self): site_id = self.validated_data['id'] site = Site.objects.get(pk=site_id) # Check if there is already a Case if DnsTwisted.objects.filter(domain_name=site.domain_name): dns_twisted = DnsTwisted.objects.get(domain_name=site.domain_name) if site.the_hive_case_id is None: site.the_hive_case_id = dns_twisted.the_hive_case_id # Save the case id in database Site.objects.filter(pk=site.pk).update(the_hive_case_id=dns_twisted.the_hive_case_id) # Test The Hive instance connection try: requests.get(settings.THE_HIVE_URL) except requests.exceptions.SSLError as e: print(str(timezone.now()) + " - ", e) raise AuthenticationFailed("SSL Error: " + settings.THE_HIVE_URL) except requests.exceptions.RequestException as e: print(str(timezone.now()) + " - ", e) raise NotFound("Not Found: " + settings.THE_HIVE_URL) hive_api = TheHiveApi(settings.THE_HIVE_URL, settings.THE_HIVE_KEY, cert=True) if site.the_hive_case_id is not None: # If the case already exist, then we update IOCs update_observables(hive_api, site) else: # If the case does not exist, then we create it # Prepare the case case = Case(title='Suspicious domain name ' + site.domain_name, owner=settings.THE_HIVE_CASE_ASSIGNEE, severity=2, tlp=2, pap=2, flag=False, tags=['Watcher', 'Impersonation', 'Malicious Domain', 'Typosquatting'], description='Suspicious domain name ' + site.domain_name) # Create the case print(str(timezone.now()) + " - " + 'Create Case') print('-----------------------------') response = hive_api.create_case(case) if response.status_code == 201: print(str(timezone.now()) + " - " + "OK") case_id = response.json()['id'] # Save the case id in database Site.objects.filter(pk=site.pk).update(the_hive_case_id=case_id) if DnsTwisted.objects.filter(domain_name=site.domain_name): DnsTwisted.objects.filter(domain_name=site.domain_name).update(the_hive_case_id=case_id) # Create all IOCs observables create_observables(hive_api, case_id, site) else: print(str(timezone.now()) + " - " + 'ko: {}/{}'.format(response.status_code, response.text)) data = {'detail': response.json()['type'] + ": " + response.json()['message']} raise serializers.ValidationError(data)
def Create_Case( titles, descriptions, tlps, templates='', case_tagg=['' ]): ## insert default template here incase nothing is specified global response ## global response variable print('Creating Case From Template') print('-----------------------------') case = Case(title=titles, description=descriptions, tlp=tlps, template=templates, tags=case_tagg) print(case.jsonify()) print('Creating Case') print('-----------------------------') response = api.create_case(case) if response.status_code == 201: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') id = response.json()['id'] print("Case Successfully Created") return id
def closeCase(self, caseid): self.logger.debug('%s.closeCase starts', __name__) #Create a Case object case = Case() case.id = caseid fields = ['status'] case.status = "Resolved" #Update the case self.updateCase(case, fields)
def craftCase(self, title, description): self.logger.info('%s.craftCase starts', __name__) case = Case(title=title, tlp=2, tags=['Synapse'], description=description, ) return case
def prepare_thehive_case(cls, incident: Incident) -> Case: return Case( title=cls._get_case_title(incident), description=cls._get_case_description(incident), severity=cls._get_case_severity(incident), tags=cls._prepare_case_tags(incident), startDate=cls._get_case_datetime(incident), metrics=cls._prepare_metrics(incident), customFields=cls.prepare_custom_fields(incident), template=cls._get_case_template_name(incident) )
def prepare_case_template(subject, indicatorlevel, emailbody, casetype, tag, templatename): 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': ''}) # Prepare the sample Case based on a Template print( str(datetime.datetime.now()) + " Preparing the case for " + casetype) case = Case( title=subject, tlp=indicatorlevel, tags=[tag], description=emailbody, template=templatename, # type=alerttype, # source='instance1', # sourceRef=sourceRef, # artifacts="") ) # Create the Case id = None ################################################# response = api.create_case(case) ################################################# if response.status_code == 201: # print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') id = response.json()['id'] simple_id = response.json()['caseId'] else: print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0) # Get all the details of the created case print( str(datetime.datetime.now()) + " Getting created case {}".format(id)) response = api.get_case(id) if response.status_code == requests.codes.ok: # print(json.dumps(response.json(), indent=4, sort_keys=True)) print( str(datetime.datetime.now()) + " Observable succesfully created.") else: print('ko: {}/{}'.format(response.status_code, response.text)) return id, simple_id, emailbody
def do_newcase(self, *_): '''Create a new case within TheHive''' print( "Let's create a new case! The next few steps will request some data from you." ) nc_title = input("Case Title: ") nc_description = input("Case Description: ") new_case = Case(title=nc_title, description=nc_description) api = config.get_api() resp = api.create_case(new_case) if resp.status_code == 201: print("Successfully created case {0}!".format(nc_title))
def hive_create_case(hive_tlp, threat_level, hive_description, hive_case_title, l_tags, path): ail_uuid = r_serv_db.get('ail:uuid') source = path.split('/')[-6:] source = '/'.join(source)[:-3] # get paste date var = path.split('/') last_seen = "{0}-{1}-{2}".format(var[-4], var[-3], var[-2]) case = Case(title=hive_case_title, tlp=hive_tlp, severity=threat_level, flag=False, tags=l_tags, description='hive_description') # Create the case id = None response = HiveApi.create_case(case) if response.status_code == 201: id = response.json()['id'] observ_sensor = CaseObservable(dataType="other", data=[ail_uuid], message="sensor") observ_file = CaseObservable(dataType="file", data=[path], tags=l_tags) observ_source = CaseObservable(dataType="other", data=[source], message="source") observ_last_seen = CaseObservable(dataType="other", data=[last_seen], message="last-seen") res = HiveApi.create_case_observable(id, observ_sensor) if res.status_code != 201: print('ko: {}/{}'.format(res.status_code, res.text)) res = HiveApi.create_case_observable(id, observ_source) if res.status_code != 201: print('ko: {}/{}'.format(res.status_code, res.text)) res = HiveApi.create_case_observable(id, observ_file) if res.status_code != 201: print('ko: {}/{}'.format(res.status_code, res.text)) res = HiveApi.create_case_observable(id, observ_last_seen) if res.status_code != 201: print('ko: {}/{}'.format(res.status_code, res.text)) r_serv_metadata.set('hive_cases:' + path, id) return hive_case_url.replace('id_here', id) else: print('ko: {}/{}'.format(response.status_code, response.text)) return False
def update_case_status(self, event): mi_caseid = event['case']['id'] try: hive_caseid = self.get_hive_case_id(mi_caseid) updated_case = Case() keys_to_del = updated_case.__dict__ print(keys_to_del) for key in list(keys_to_del): delattr(updated_case, key) updated_case.status = case_status_mappings[event['case'] ['status'].lower()] if updated_case.status != 'Resolved': pass else: updated_case.resolutionStatus = case_resolution_mappings[ event['case']['status'].lower()] updated_case.impactStatus = 'WithImpact' updated_case.id = hive_caseid response = self.api.update_case(updated_case) log.info("case updated status: %s", response.status_code) log.info("response body: %s", response.text) self.update_case_tasks(event) except Exception: log.error("An error occurred while updating a case : %s", mi_caseid, exc_info=True)
def do_newcase(self, arg): '''Create a new case within TheHive''' #Check if the config file exists first print( "Let's create a new case! The next few steps will request some data from you. Hit Enter to accept any defaults: " ) nc_title = input("Case Title: ") nc_description = input("Case Description: ") nc = Case(title=nc_title, description=nc_description) api = config.get_api() resp = api.create_case(nc) if resp.status_code == 201: print("Successfully created case {0}!".format(nc_title))
def __init__(self, event, tenant): # Case attributes user = event['user'] nature = event['nature'] case_name = event['case']['name'] case_id = event['case']['id'] case_url = event['case']['url'] case_tags = ['McAfee Investigator', case_id, nature] # Task attributes task_owner = tenant.hive_user # task_start_date = datetime.datetime.now().strftime("%d-%m-%Y %H:%M") task_start_date = int(time.time()) * 1000 task_description = "Autogenerated task to track MI case events" tasks = [ CaseTask(title='MI - analytics investigation', status='InProgress', owner=task_owner, startDate=task_start_date, description=task_description), CaseTask(title='MI - system events', status='InProgress', owner=task_owner, startDate=task_start_date, description=task_description), CaseTask(title='MI - user events', status='Waiting', description="Auto generated task to track MI user events") ] # Prepare the custom fields (values are searchable) customFields = CustomFieldHelper()\ .add_boolean('MI-autogenerated', True)\ .add_string('MI-caseid', case_id)\ .add_string('MI-user', user)\ .add_string('MI-nature', nature)\ .build() case = Case(title=case_name, tlp=0, flag=False, description="For additional info see " + self.get_case_ui_url(case_url), tags=case_tags, tasks=tasks, customFields=customFields) self.case = case
def update_case_priority(self, event): mi_caseid = event['case']['id'] try: hive_caseid = self.get_hive_case_id(mi_caseid) response_dict = self.api.get_case(hive_caseid).json() print(json.dumps(response_dict, indent=4, sort_keys=True)) new_severity = case_priority_mappings[event['case'] ['priority'].lower()] # updated_case = Case(**response_dict) updated_case = Case(severity=new_severity) keys_to_del = updated_case.__dict__ print(keys_to_del) for key in list(keys_to_del): delattr(updated_case, key) updated_case.severity = new_severity updated_case.id = hive_caseid response = self.api.update_case(updated_case) log.info("case updated status: {}".format(response.status_code)) log.info("response body: {}".format(response.text)) self.update_case_tasks(event) except Exception: log.error("An error occurred while updating a case : %s", mi_caseid, exc_info=True)
def main(): api = TheHiveApi(HiveWEB, HiveAPI) S1Management = Management(hostname=S1WEB, api_token=S1API) tod = datetime.datetime.now() d = datetime.timedelta(days=DAYS) filter = ThreatQueryFilter() filter.apply("createdAt", tod - d, op="gt") filter.apply("resolved", False, op="eq") threats = S1Management.threats.get(query_filter=filter) i = 0 while True: threat = threats.json["data"][i] string = searchCaseByDescription(api, threat["id"]) if string is None: threat_values = createKeys(threat) description = createCaseDescription(threat_values) case = Case( title=threat["description"], tlp=0, pap=0, severity=1, flag=False, tags=[ "Sentinel One", threat["classification"], threat["agentOsType"], ], description=description, tasks=[], status="Open", createdAt=threat["createdDate"], ) response = api.create_case(case) if response.status_code == 201: logging.info(json.dumps(response.json(), indent=4, sort_keys=True)) id = response.json()["id"] postUpdate(api, id, threat) else: logging.error("ko: {}/{}".format(response.status_code, response.text)) i += 1 if i == len(threats.json["data"]): cursor = threats.pagination["nextCursor"] if not cursor: break threats = S1Management.threats.get(cursor=cursor) i = 0
def create_case(self, title, tasks=None, tlp=TLP.AMBER, pap=PAP.AMBER, severity=HiveSeverity.MEDIUM, additional_fields=None, additional_tags=None, flag=False, description='N/A'): case_tags = self.case_tags.copy() if additional_tags is not None: for additional_tag in additional_tags: case_tags.append(additional_tag) custom_fields_helper = CustomFieldHelper() if additional_fields is not None: for field in additional_fields: custom_fields_helper.add_string(field['name'], field['value']) custom_fields = custom_fields_helper.build() new_tasks = list() if tasks is not None: for task in tasks: new_tasks.append(CaseTask(title=task)) hive_case = Case(title=title, tlp=tlp.value, pap=pap.value, description=description, tags=case_tags, severity=severity.value, flag=flag, customFields=custom_fields, tasks=new_tasks) response = self.api.create_case(hive_case) if response.status_code == 201: print('Caso Creada Exitosamente') print(json.dumps(response.json(), indent=4, sort_keys=True)) else: print('Error') print(response.text) return response.json()
def sendtoHIVE(title, description, domain): tasks = [ CaseTask(title='Tracking'), CaseTask(title='Communication'), CaseTask(title='Investigation', status='Waiting', flag=True) ] # Prepare the custom fields customFields = CustomFieldHelper()\ .add_boolean('booleanField', True)\ .add_string('businessImpact', 'HIGH')\ .add_date('occurDate', int(time.time())*1000)\ .add_number('cvss', 9)\ .build() case = Case(title=title, tlp=3, flag=True, tags=['wordpress', domain], description=description, tasks=tasks, customFields=customFields) # Create the case print('Create Case') print('-----------------------------') id = None response = api.create_case(case) if response.status_code == 201: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') id = response.json()['id'] else: print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0) # Get all the details of the created case print('Get created case {}'.format(id)) print('-----------------------------') response = api.get_case(id) if response.status_code == requests.codes.ok: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') else: print('ko: {}/{}'.format(response.status_code, response.text))
class THApi: 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 run_iocp(self): data = [] proc = subprocess.Popen(['iocp', '-i', self.filetype, self.filepath], stdout=subprocess.PIPE) for line in proc.stdout.readlines(): self.osservable_data.append( [x for x in line.strip().split(',') if line.strip() != '']) def create_osservables(self): for oss in self.osservable_data: domain = CaseObservable(dataType=exchange[oss[2]], tlp=1, ioc=True, tags=['thehive4py'], data=oss[3]) response = self.api.create_case_observable(self.case_id, domain) if response.status_code == 201: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') else: print('ko: {}/{}'.format(response.status_code, response.text)) print("adding OSSERVABLE", oss[2], "-", oss[3], "to", self.case_id) def create_case(self): case = Case(title='From TheHive4Py', tlp=3, flag=True, tags=['TheHive4Py', 'sample'], description=self.filename) response = self.api.create_case(case) if response.status_code == 201: self.case_id = response.json()['id'] else: self.case_id = None
def parse_hooks(self): logger.info('Start parsing webhooks for ELK automation') #Set the default action self.report_action = 'None' #if it is a new case if self.webhook.isImportedAlert(): logger.info('Registered the finishing steps of the creation of a new case') #Register case info self.caseid = self.webhook.data['details']['case'] self.tags = self.webhook.data['object']['tags'] self.description = self.webhook.data['object']['description'] #Enrich the case information with missing information from the alert if 'ELK' in self.webhook.data['object']['tags']: self.report_action = 'enrichCase' logger.info('Alert {} has been tagged as ELK and is just imported or following has been reenabled. Adding custom fields'.format(self.webhook.data['details']['case'])) # Enrich offense with information from the alert by posting the missing information through an API call #Create a Case object self.case = Case() #Add the case id to the object self.case.id = self.caseid logger.info('Updating case %s' % self.case.id) #Define which fields need to get updated fields = ['customFields'] #Retrieve all required attributes from the alert and add them as custom fields to the case customFields = CustomFieldHelper()\ .add_string('anomalyType', self.webhook.data['object']['type'])\ .add_string('source', self.webhook.data['object']['source'])\ .build() #Add custom fields to the case object self.case.customFields = customFields #Update the case response = self.TheHiveConnector.updateCase(self.case,fields) return report_action
def prepare_case(content): """ convert a Cyrating alert into a TheHive alert :param incident: Cyrating Alert :type incident: dict :type thumbnails: dict :return: Thehive alert :rtype: thehive4py.models Alerts """ case = Case(title=generate_title_from_event(content), tlp=1, pap=1, tags=generate_tags_from_event(content), severity=th_severity(content.get('severity', 1)), description=th_case_description(content), caseTemplate=TheHive['template']) return case
def main(api): i = 0 while i < (currentNum): check = True string = searchCaseByDescription(threats.json['data'][i]['id']) if string == None and check == True: threat = createKeys(threats.json['data'][i], i) parsed = createAlertDescription(threat, i) case = Case(title=threats.json['data'][i]['description'], tlp=0, pap=0, severity=1, flag=False, tags=[ 'Sentinel One', threats.json['data'][i]['classification'], threats.json['data'][i]['agentOsType'], ], description=parsed, tasks=[ CaseTask( title='Communication', description='Auto Imported Sentinel One Alert', owner='sentinelone', group='default', createdAt=time.time()) ], status='Open', user='******', createdAt=threats.json['data'][i]['createdDate']) response = api.create_case(case) postUpdate(searchCaseByDescription(threats.json['data'][i]['id']), i) if response.status_code == 201: logging.info( json.dumps(response.json(), indent=4, sort_keys=True)) logging.info('') id = response.json()['id'] else: print(check) logging.error('ko: {}/{}'.format(response.status_code, response.text)) i += 1
# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import unicode_literals import sys import json from thehive4py.api import TheHiveApi from thehive4py.models import Case, CaseObservable api = TheHiveApi('http://127.0.0.1:9000', '**YOUR_API_KEY**') print('Create case') print('-----------------------------') case = Case(title='From TheHive4Py based on the Phishing template', description='N/A', tlp=2, tags=['thehive4py']) print(case.jsonify()) response = api.create_case(case) if response.status_code == 201: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') id = response.json()['id'] else: print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0) print('Create domain observable') print('-----------------------------') domain = CaseObservable(dataType='filename',
# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import unicode_literals import sys import json from thehive4py.api import TheHiveApi from thehive4py.models import Case, CaseTemplate api = TheHiveApi('http://127.0.0.1:9000', '**YOUR_API_KEY**') print('Create case from template') print('-----------------------------') case = Case(title='From TheHive4Py based on the Phishing template', description='N/A', tlp=2, template='Phishing') print(case.jsonify()) print('Create Case') print('-----------------------------') response = api.create_case(case) if response.status_code == 201: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') id = response.json()['id'] else: print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0)
def submitTheHive(message): '''Create a new case in TheHive based on the email''' # Decode email msg = email.message_from_bytes(message) decode = email.header.decode_header(msg['From'])[0] fromField = str(decode[0]) decode = email.header.decode_header(msg['Subject'])[0] subjectField = str(decode[0]) if args.verbose: print("[INFO] From: %s Subject: %s" % (fromField, subjectField)) attachments = [] body = '' for part in msg.walk(): if part.get_content_type() == "text/plain": body = part.get_payload(decode=True).decode() 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']: print("[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'] fd, path = tempfile.mkstemp(prefix=slugify(filename) + "_") try: with os.fdopen(fd, 'w+b') as tmp: tmp.write(part.get_payload(decode=1)) attachments.append(path) except OSError as e: print("[ERROR] Cannot dump attachment to %s: %s" % (path, e.errno)) api = TheHiveApi(config['thehiveURL'], config['thehiveUser'], config['thehivePassword'], { 'http': '', 'https': '' }) if '[ALERT]' in subjectField: # Prepare the alert sourceRef = str(uuid.uuid4())[0:6] alert = Alert(title=subjectField.replace('[ALERT]', ''), tlp=int(config['alertTLP']), tags=config['alertTags'], description=body, type='external', source=fromField, sourceRef=sourceRef) # Create the Alert id = None response = api.create_alert(alert) if response.status_code == 201: if args.verbose: print('[INFO] Created alert %s' % response.json()['sourceRef']) else: print('[ERROR] Cannot create alert: %s (%s)' % (response.status_code, response.text)) sys.exit(0) 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() 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'] if args.verbose: print('[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='Created by imap2thehive.py') response = api.create_case_observable(newID, observable) if response.status_code == 201: if args.verbose: print('[INFO] Added observable %s to case ID %s' % (path, newID)) os.unlink(path) else: print('[ERROR] Cannot add observable: %s - %s (%s)' % (path, response.status_code, response.text)) sys.exit(0) else: print('[ERROR] Cannot create case: %s (%s)' % (response.status_code, response.text)) sys.exit(0) return
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'] fd, path = tempfile.mkstemp(prefix=slugify(filename) + "_") 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 if config['thehiveAuthMethod'] == 'APIKey': api = TheHiveApi(config['thehiveURL'], config['thehiveAPIKey'], None, { 'http': '', 'https': '' }) else: 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:
.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],
CaseTask(title='Recovery'), CaseTask(title='Lessons Learned', status='Waiting', flag=True) ] # Prepare the custom fields customFields = CustomFieldHelper()\ .add_boolean('booleanField', True)\ .add_string('businessImpact', 'HIGH')\ .add_date('occurDate', int(time.time())*1000)\ .add_number('cvss', 9)\ .build() case = Case(title='Account Compromise', tlp=3, flag=True, tags=['TheHive4Py', 'sample'], description='N/A', tasks=tasks, customFields=customFields) # Create the case print('Create Case') print('-----------------------------') id = None response = api.create_case(case) if response.status_code == 201: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') id = response.json()['id'] else: print('ko: {}/{}'.format(response.status_code, response.text))
# #Some sample tasks-response actions for posting in the case. Customize per your reqs. # #TODO: You can also utilize - thehive-playbook-creator - for dynamic task/playbook assignment using your QRadar Rule groups. tasks = [ CaseTask(title='PB:- Phase:Identification'), CaseTask(title='PB: - Phase:Remediation'), CaseTask(title='PB: - Phase:Lessons Learned', status='Waiting', flag=True) ] #Build TheHive Case with custom fields thehive_case = Case(title=offense_desc, tlp=tlp, flag=True, tags=['offense', 'qradar', offense_type_name], description=build_desc, customFields=custom_fields.fields, tasks=tasks) print('-------Posting Case with initial values--------') case_id = None try: resp = hive_api.create_case(thehive_case) if resp.status_code == 201: case_id = resp.json()['id'] case_num = resp.json()['caseId'] qr.post_offense_note(offense_id, offense_note.format(case_num)) sl.insert_record( case_table, 'id, case_id, status', '"{}","{}","{}"'.format(offense_id, case_id, 'Open'))