def create_the_hive_alert(source, path, tag): tags = list(r_serv_metadata.smembers('tag:'+path)) artifacts = [ AlertArtifact( dataType='uuid-ail', data=r_serv_db.get('ail:uuid') ), AlertArtifact( dataType='file', data=path, tags=tags ) ] l_tags = tag.split(',') # Prepare the sample Alert sourceRef = str(uuid.uuid4())[0:6] alert = Alert(title='AIL Leak', tlp=3, tags=l_tags, description='infoleak', type='ail', source=source, sourceRef=sourceRef, artifacts=artifacts) # Create the Alert id = None try: response = HiveApi.create_alert(alert) if response.status_code == 201: #print(json.dumps(response.json(), indent=4, sort_keys=True)) print('Alert Created') print('') id = response.json()['id'] else: print('ko: {}/{}'.format(response.status_code, response.text)) return 0 except: print('hive connection error')
def artifactsCrafter(notification): artifacts = [] # device artifact message = \ '- **Private IP** : {private_ip}\n'\ '- **Public IP** : {public_ip}\n'\ '- **Agent OS** : {agent_os}\n'\ '- **Agent OS Revision** : {os_revision}\n'\ '- **Agent Version** : {agent_version}\n'\ '- **Machine Type** : {machine_type}\n'\ '- **Last Logged In Username** : {last_user}\n'\ .format( private_ip=notification['agentDetectionInfo']['agentIpV4'], public_ip=notification['agentDetectionInfo']['externalIp'], agent_os=notification['agentDetectionInfo']['agentOsName'], os_revision=notification['agentDetectionInfo']['agentOsRevision'], agent_version=notification['agentDetectionInfo']['agentVersion'], machine_type=notification['agentRealtimeInfo']['agentMachineType'], last_user=notification['agentDetectionInfo']['agentLastLoggedInUserName']) artifacts.append(AlertArtifact( dataType='hostname', data=str(notification['agentRealtimeInfo']['agentComputerName']), message=message, ignoreSimilarity=False, tags=[notification['id']])) # threat artifact hash = "" if notification['threatInfo']['sha256'] != None: hash = notification['threatInfo']['sha256'] elif notification['threatInfo']['sha1'] != None: hash = notification['threatInfo']['sha1'] elif notification['threatInfo']['md5'] != None: hash = notification['threatInfo']['md5'] else: return artifacts message = \ '- **Threat Name** : {threat_name}\n'\ '- **Threat Path** : {threat_path}\n'\ '- **File Size** : {file_size}\n'\ '- **File Extension** : {file_ext}\n'\ '- **File Extension Type** : {file_ext_type}\n'\ '- **Classification** : {classification}\n'\ '- **Publisher Name** : {publisher}\n'\ .format( threat_name=notification['threatInfo']['threatName'], threat_path=notification['threatInfo']['filePath'], file_size=size(int(notification['threatInfo']['fileSize'])), file_ext=notification['threatInfo']['fileExtension'], file_ext_type=notification['threatInfo']['fileExtensionType'], classification=notification['threatInfo']['classification'], publisher=notification['threatInfo']['publisherName']) artifacts.append(AlertArtifact( dataType='hash', data=hash, message=message, tags=[notification['id']])) return artifacts
def craftAlertArtifact(self, artifacts_dict): """Takes a dict of artifacts and returns a list of AlertArtifact objects""" self.logger.info('%s.craftAlertArtifact starts', __name__) artifacts = [] for dataType in artifacts_dict: data = artifacts_dict[dataType] if type(data) == list: for elmt in data: artifacts.append(AlertArtifact(dataType=dataType, data=elmt)) else: artifacts.append(AlertArtifact(dataType=dataType, data=data)) return artifacts
def artifactsCrafter(alert_data): alert_id = alert_data.get('investigationId', "") artifacts = [] emails = [] usernames = [] hostnames = [] users = alert_data.get('actors', {}).get('users', []) assets = alert_data.get('actors', {}).get('assets', []) if len(users) > 0: for user in users: emails.append([user.get('name', ""), user.get('emails', [])]) usernames.append( [user.get('name', ""), user.get('distinguishedName', "")]) if len(assets) > 0: for asset in assets: hostnames.append([ asset.get('hostname', ""), asset.get('fqdn', ""), asset.get('shortname', "") ]) for email in emails: for mail in email[1]: artifacts.append( AlertArtifact(dataType="mail", data=mail, message="", tags=[alert_id, email[0]])) for username in usernames: artifacts.append( AlertArtifact(dataType="username", data=username[0], message=username[1], tags=[alert_id, username[0]])) for hostname in hostnames: artifacts.append( AlertArtifact(dataType="hostname", data=hostname[0], message="{}\n\n{}".format(hostname[1], hostname[2]), tags=[alert_id])) return artifacts
def build_observables(observables): """ Convert DS observables into TheHive observables :param observables: observables from DS :type observables: dict :return: AlertArtifact :rtype: thehive4py.models AlertArtifact """ artefacts = [] if observables.get('total', 0) > 0: for ioc in observables.get('content'): a = AlertArtifact( data=ioc.get('value'), dataType=th_dataType(ioc.get('type')), message="Observable from DigitalShadows. \ Source: {}".format(ioc.get('source')), tlp=2, tags=["src:DigitalShadows"] ) artefacts.append(a) return artefacts
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_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 alert(self, matches): connection_details = self.rule['hive_connection'] api = TheHiveApi( '{hive_host}:{hive_port}'.format(**connection_details), connection_details.get('hive_apikey',''), proxies=connection_details.get('hive_proxies', {'http': '', 'https': ''}), cert=connection_details.get('hive_verify', False)) for match in matches: context = {'rule': self.rule, 'match': match} artifacts = [] for mapping in self.rule.get('hive_observable_data_mapping', []): for observable_type, match_data_key in mapping.iteritems(): try: match_data_keys = re.findall(r'\{match\[([^\]]*)\]', match_data_key) if all([True for k in match_data_keys if k in context['match']]): artifacts.append(AlertArtifact(dataType=observable_type, data=match_data_key.format(**context))) except KeyError: raise KeyError('\nformat string\n{}\nmatch data\n{}'.format(match_data_key, context)) alert_config = { 'artifacts': artifacts, 'sourceRef': str(uuid.uuid4())[0:6], 'title': '{rule[name]}'.format(**context) } alert_config.update(self.rule.get('hive_alert_config', {})) for alert_config_field, alert_config_value in alert_config.iteritems(): if alert_config_field == 'customFields': custom_fields = CustomFieldHelper() for cf_key, cf_value in alert_config_value.iteritems(): try: func = getattr(custom_fields, 'add_{}'.format(cf_value['type'])) except AttributeError: raise Exception('unsupported custom field type {}'.format(cf_value['type'])) value = cf_value['value'].format(**context) func(cf_key, value) alert_config[alert_config_field] = custom_fields.build() elif isinstance(alert_config_value, basestring): alert_config[alert_config_field] = alert_config_value.format(**context) elif isinstance(alert_config_value, (list, tuple)): formatted_list = [] for element in alert_config_value: try: formatted_list.append(element.format(**context)) except: formatted_list.append(element) alert_config[alert_config_field] = formatted_list alert = Alert(**alert_config) response = api.create_alert(alert) if response.status_code != 201: raise Exception('alert not successfully created in TheHive\n{}'.format(response.text))
def craftAlertArtifact(self, **attributes): """From a collection of attributes, create an Alert Artifact""" from thehive4py.models import AlertArtifact alertArtifact = AlertArtifact(dataType=attributes["dataType"], message=attributes["message"], data=attributes["data"]) return alertArtifact
def craftAlertArtifact(self, **attributes): self.logger.info('%s.craftAlertArtifact starts', __name__) alertArtifact = AlertArtifact(dataType=attributes["dataType"], message=attributes["message"], data=attributes["data"], tags=attributes['tags']) return alertArtifact
def create_alarm(self, title, source_ref=None, description='N/A', alert_type='external', source='LogRhythm', iocs=None, additional_fields=None, additional_tags=None, tlp=TLP.AMBER, pap=PAP.AMBER, severity=HiveSeverity.MEDIUM): if source_ref is None: source_ref = str(uuid.uuid4())[0:6] alert_tags = self.alert_tags.copy() if additional_tags is not None: for additional_tag in additional_tags: alert_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() artifacts = list() if iocs is not None: for ioc in iocs: artifacts.append( AlertArtifact(dataType=ioc['type'].value, data=ioc['value'])) hive_alert = Alert(title=title, tlp=tlp.value, tags=alert_tags, description=description, type=alert_type, source=source, sourceRef=source_ref, pap=pap.value, artifacts=artifacts, customFields=custom_fields, severity=severity.value) response = self.api.create_alert(hive_alert) if response.status_code == 201: print('Alerta Creada Exitosamente') print(json.dumps(response.json(), indent=4, sort_keys=True)) else: print('Error') print(response.text) return response.json()
def artifactCrafter(notification, theHiveConnector, alert_tags): threat_cause_found = False artifacts = list() # device hostname artifacts.append( AlertArtifact(dataType='hostname', data=str(notification['deviceInfo']['deviceName']), message=str("{}\n\n{}".format( notification['deviceInfo']['email'], notification['deviceInfo']['deviceId'])), tags=[notification['threatInfo']['incidentId']])) # threat indicators (processes) for indicator in notification['_info']['threat_indicators']: alert_tags.extend(indicator['ttps']) tags = indicator['ttps'] tags.append(str(notification['threatInfo']['incidentId'])) if indicator['sha256'] == notification['_info'][ 'threat_cause_actor_sha256']: tags.append("THREAT CAUSE") threat_cause_found = True artifacts.append( AlertArtifact(dataType='hash', data=str(indicator['sha256']), message=str(indicator['process_name']), tags=tags)) # threat cause, sometimes not in _info.threat_indicators for whatever reason if not threat_cause_found: artifacts.append( AlertArtifact( dataType='hash', data=str(notification['_info']['threat_cause_actor_sha256']), message=str(notification['_info']['threat_cause_actor_name']), tags=[ "THREAT CAUSE", str(notification['threatInfo']['incidentId']) ])) return artifacts
def run(self): """ Add a hash to the specified Elasticsearch index if some artifacts have been submitted and the hash does not already exist """ Responder.run(self) data = self.get_data() artifacts = self.get_param('data.artifacts') rule_title = self.get_param('data.title', default='no data') suppressing_username = self.get_param('data.createdBy', default='no data') if not artifacts: # If there are no artifacts we have no data to generate a hash self.error('No artifacts submitted') observables = [] # The jsonify method provides a list of predictably sorted JSON strings which we then sort in order to make # sure that the we generate the same hash that will be read from the database by HashSuppressorEnhancement for artifact in artifacts: observables.append(AlertArtifact(dataType=artifact.get('dataType'), data=artifact.get('data'))) observable_hash_string = u'|'.join(sorted([observable.jsonify() for observable in observables])) observable_hash = hashlib.md5(observable_hash_string.encode('utf-8')).hexdigest() class AlertHash(Document): alert_hash = Keyword() date_suppressed = Date() rule_title = Keyword() suppressing_username = Keyword() class Index: name = self.es_index # This is required because the commented registration below does not work connections.create_connection(**self.es_kwargs) alert_hashes = Index(self.es_index) # alert_hashes.document(AlertHash) # Registering a Document to the Index does not work for some reason if not alert_hashes.exists(): alert_hashes.create() results = AlertHash.search().filter('term', alert_hash=observable_hash).execute(ignore_cache=True) if not results: # Don't save the same hash multiple times alert_hash = AlertHash( alert_hash=observable_hash, date_suppressed=datetime.datetime.now(), rule_title=rule_title, suppressing_username=suppressing_username ) alert_hash.save() message = 'MD5 hash [{}] added to Elasticsearch database [{}:{}] index [{}]'.format( observable_hash, self.es_host, self.es_port, self.es_index) else: message = 'MD5 hash [{}] already existed in the Elasticsearch database [{}:{}] index [{}]'.format( observable_hash, self.es_host, self.es_port, self.es_index) self.report({'message': message})
def create_the_hive_alert(source, item_id, tag): # # TODO: check items status (processed by all modules) # # TODO: add item metadata: decoded content, link to auto crawled content, pgp correlation, cryptocurrency correlation... # # # TODO: description, add AIL link:show items ? tags = list(r_serv_metadata.smembers('tag:{}'.format(item_id))) artifacts = [ AlertArtifact(dataType='uuid-ail', data=r_serv_db.get('ail:uuid')), AlertArtifact(dataType='file', data=item_basic.get_item_filepath(item_id), tags=tags) ] # Prepare the sample Alert sourceRef = str(uuid.uuid4())[0:6] alert = Alert(title='AIL Leak', tlp=3, tags=tags, description='AIL Leak, triggered by {}'.format(tag), type='ail', source=source, sourceRef=sourceRef, artifacts=artifacts) # Create the Alert id = None try: response = HiveApi.create_alert(alert) if response.status_code == 201: #print(json.dumps(response.json(), indent=4, sort_keys=True)) print('Alert Created') print('') id = response.json()['id'] else: print('ko: {}/{}'.format(response.status_code, response.text)) return 0 except: print('hive connection error')
def create_artifacts(self, match): artifacts = [] context = {'rule': self.rule, 'match': match} for mapping in self.rule.get('hive_observable_data_mapping', []): for observable_type, match_data_key in mapping.items(): try: artifacts.append( AlertArtifact(dataType=observable_type, data=match_data_key.format(**context))) except KeyError as e: print( ('format string {} fail cause no key {} in {}'.format( e, match_data_key, context))) return artifacts
def build_observables_from_databreach(observables): """ Convert DS observables into TheHive observables :param observables: observables from DS :type observables: dict :return: AlertArtifact :rtype: thehive4py.models AlertArtifact """ artefacts = [] if observables.get('total', 0) > 0: for ioc in observables.get('content'): a = AlertArtifact( data=ioc.get('username'), dataType="mail" if bool( re.search( r"^[A-Za-z0-9\.\+\-\_]+\@[\w\d\-\_\.]+\.[a-zA-Z]{2,3}$", ioc.get('username'))) else "other", message=databreach_message(ioc), tlp=2, tags=["src:DigitalShadows", "databreach"]) artefacts.append(a) leakfile = '/tmp/leak.csv' leakfd = open(leakfile, 'w') leakfd.write(databreach_list(observables.get('content'))) leakfd.close() artefacts.append( AlertArtifact(dataType="file", data=leakfile, message="List of records from DigitalShadows", tlp=2, tags=["src:DigitalShadows", "databreach"])) return artefacts
def add_alert_artefact(artefacts, dataType, data, tags, tlp): """ :type artefacts: array :type dataType: string :type data: string :type tags: array :type tlp: int :rtype: array """ return artefacts.append( AlertArtifact(tags=tags, dataType=dataType, data=data, message="From CrowdStrike", tlp=tlp))
def alert(self, matches): connection_details = self.rule['hive_connection'] api = TheHiveApi( '{hive_host}:{hive_port}'.format(**connection_details), '{hive_username}'.format(**connection_details), '{hive_password}'.format(**connection_details), connection_details.get('hive_proxies', {'http': '', 'https': ''})) for match in matches: context = {'rule': self.rule, 'match': match} artifacts = [] for mapping in self.rule.get('hive_observable_data_mapping', []): for observable_type, match_data_key in mapping.iteritems(): try: artifacts.append(AlertArtifact(dataType=observable_type, data=match_data_key.format(**context))) except KeyError: raise KeyError('\nformat string\n{}\nmatch data\n{}'.format(match_data_key, context)) alert_config = { 'artifacts': artifacts, 'sourceRef': str(uuid.uuid4())[0:6], 'title': '{rule[index]}_{rule[name]}'.format(**context) } alert_config.update(self.rule.get('hive_alert_config', {})) for alert_config_field, alert_config_value in alert_config.iteritems(): if isinstance(alert_config_value, basestring): alert_config[alert_config_field] = alert_config_value.format(**context) elif isinstance(alert_config_value, (list, tuple)): formatted_list = [] for element in alert_config_value: try: formatted_list.append(element.format(**context)) except: formatted_list.append(element) alert_config[alert_config_field] = formatted_list alert = Alert(**alert_config) response = api.create_alert(alert) if response.status_code != 201: raise Exception('alert not successfully created in TheHive\n{}'.format(response.text))
def _create_artifacts(rule, match): context = {'rule': rule, 'match': match} artifacts = [] for mapping in rule.get('hive_observable_data_mapping', []): for observable_type, match_data_key in mapping.items(): try: match_data_keys = re.findall(r'\{match\[([^\]]*)\]', match_data_key) rule_data_keys = re.findall(r'\{rule\[([^\]]*)\]', match_data_key) data_keys = match_data_keys + rule_data_keys context_keys = list(context['match'].keys()) + list(context['rule'].keys()) if all([True if k in context_keys else False for k in data_keys]): artifacts.append(AlertArtifact(dataType=observable_type, data=match_data_key.format(**context))) except KeyError as e: print('format string failed for key {}\nformat string\n{}\ncontext\n{}'.format( e, match_data_key, context)) return artifacts
def add_alert_artifact(artifacts, data_type, data, tags, tlp): """ :param artifacts: array :param data_type: string :param data: string :param tags: array :param tlp: int :return: array :rtype: array """ if data is not None: return artifacts.append(AlertArtifact(tags=tags, dataType=data_type, data=str(data), message="From Zerofox", tlp=tlp) )
def build_observables(observables, device_id): """ Convert CrowdStrike behaviors into TheHive observables :param observables: behaviors from CrowdStrike :type observables: dict :return: AlertArtifact :rtype: thehive4py.models AlertArtifact """ observables = flatten_dict(observables) artefacts = [] for observable_key, observable_value in observables.items(): # print(observable_key, 'corresponds to', observable_value) a = AlertArtifact(data=observable_value, dataType=th_datatype(observable_value), message="Observable from CrowdStrike. \ Device ID: {}".format(device_id), tlp=2, tags=["src:CrowdStrike"]) return a
def build_observables(observables): """ Convert FE observables into TheHive observables :param observables: observables from FE :type observables: dict :return: AlertArtifact :rtype: thehive4py.models AlertArtifact """ artefacts = [] if len(observables) > 0: for ioc in observables: a = AlertArtifact(data=ioc[0], dataType=ioc[1], message="Observable from FireEye.", tlp=2, tags=["src:FireEye"]) artefacts.append(a) return artefacts
def createHiveAlert(esid): search = getHits(esid) #Hive Stuff #es_url = parser.get('es', 'es_url') hive_url = parser.get('hive', 'hive_url') hive_key = parser.get('hive', 'hive_key') hive_verifycert = parser.get('hive', 'hive_verifycert') tlp = int(parser.get('hive', 'hive_tlp')) # 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) #if hits > 0: for result in search['hits']['hits']: # Get initial details message = result['_source']['message'] description = str(message) sourceRef = str(uuid.uuid4())[0:6] tags=["SecurityOnion"] artifacts=[] id = None host = str(result['_index']).split(":")[0] index = str(result['_index']).split(":")[1] event_type = result['_source']['event_type'] if 'source_ip' in result['_source']: src = str(result['_source']['source_ip']) if 'destination_ip' in result['_source']: dst = str(result['_source']['destination_ip']) #if 'source_port' in result['_source']: # srcport = result['_source']['source_port'] #if 'destination_port' in result['_source']: # dstport = result['_source']['destination_port'] # NIDS Alerts if 'snort' in event_type: alert = result['_source']['alert'] category = result['_source']['category'] sensor = result['_source']['interface'] tags.append("nids") tags.append(category) title=alert # Add artifacts artifacts.append(AlertArtifact(dataType='ip', data=src)) artifacts.append(AlertArtifact(dataType='ip', data=dst)) artifacts.append(AlertArtifact(dataType='other', data=sensor)) # Bro logs elif 'bro' in event_type: _map_key_type ={ "conn": "Connection", "dhcp": "DHCP", "dnp3": "DNP3", "dns": "DNS", "files": "Files", "ftp": "FTP", "http": "HTTP", "intel": "Intel", "irc": "IRC", "kerberos": "Kerberos", "modbus": "Modbus", "mysql": "MySQL", "ntlm": "NTLM", "pe": "PE", "radius": "RADIUS", "rdp": "RDP", "rfb": "RFB", "sip" : "SIP", "smb": "SMB", "smtp": "SMTP", "snmp": "SNMP", "ssh": "SSH", "ssl": "SSL", "syslog": "Syslog", "weird": "Weird", "x509": "X509" } def map_key_type(indicator_type): ''' Maps a key type to use in the request URL. ''' return _map_key_type.get(indicator_type) bro_tag = event_type.strip('bro_') bro_tag_title = map_key_type(bro_tag) title= str('New Bro ' + bro_tag_title + ' record!') if 'source_ip' in result['_source']: artifacts.append(AlertArtifact(dataType='ip', data=src)) if 'destination_ip' in result['_source']: artifacts.append(AlertArtifact(dataType='ip', data=dst)) if 'sensor_name' in result['_source']: sensor = str(result['_source']['sensor_name']) artifacts.append(AlertArtifact(dataType='other', data=sensor)) if 'uid' in result['_source']: uid = str(result['_source']['uid']) title= str('New Bro ' + bro_tag_title + ' record! - ' + uid) artifacts.append(AlertArtifact(dataType='other', data=uid)) if 'fuid' in result['_source']: fuid = str(result['_source']['fuid']) title= str('New Bro ' + bro_tag_title + ' record! - ' + fuid) artifacts.append(AlertArtifact(dataType='other', data=fuid)) if 'id' in result['_source']: fuid = str(result['_source']['id']) title= str('New Bro ' + bro_tag_title + ' record! - ' + fuid) artifacts.append(AlertArtifact(dataType='other', data=fuid)) tags.append('bro') tags.append(bro_tag) # Wazuh/OSSEC logs elif 'ossec' in event_type: agent_name = result['_source']['agent']['name'] if 'description' in result['_source']: ossec_desc = result['_source']['description'] else: ossec_desc = result['_source']['full_log'] if 'ip' in result['_source']['agent']: agent_ip = result['_source']['agent']['ip'] artifacts.append(AlertArtifact(dataType='ip', data=agent_ip)) artifacts.append(AlertArtifact(dataType='other', data=agent_name)) else: artifacts.append(AlertArtifact(dataType='other', data=agent_name)) title= ossec_desc tags.append("wazuh") elif 'sysmon' in event_type: if 'ossec' in result['_source']['tags']: agent_name = result['_source']['agent']['name'] agent_ip = result['_source']['agent']['ip'] ossec_desc = result['_source']['full_log'] artifacts.append(AlertArtifact(dataType='ip', data=agent_ip)) artifacts.append(AlertArtifact(dataType='other', data=agent_name)) title= "New Sysmon Event! - " + agent_name tags.append("wazuh") else: title = "New " + event_type + " Event From Security Onion" # Build alert hivealert = Alert( title= title, tlp=tlp, tags=tags, description=description, type='external', source='SecurityOnion', sourceRef=sourceRef, artifacts=artifacts ) # Send it off response = api.create_alert(hivealert) if response.status_code == 201: print(json.dumps(response.json(), indent=4, sort_keys=True)) print('') id = response.json()['id'] # If running standalone / eval tell ES that we sent the alert #es_type = 'doc' #es_index = index #es_headers = {'Content-Type' : 'application/json'} #es_data = '{"script" : {"source": "ctx._source.tags.add(params.tag)","lang": "painless","params" : {"tag" : "Sent to TheHive"}}}' #update_es_event = requests.post(es_url + '/' + es_index + '/' + es_type + '/' + esid + '/_update', headers=es_headers, data=es_data) #print(update_es_event.content) else: print('ko: {}/{}'.format(response.status_code, response.text)) sys.exit(0)
def getSentinelAlertArtifacts(data): artifacts = [] #every elemnt defines a column element columns_list = data["tables"][0]["columns"] #every element is a list that contains all elements of one specific alerts row_list = data["tables"][0]["rows"] #dictionary to map columnames to indices in a rowlist column_index = {} index = 0 for c in columns_list: column_index[c["name"]] = index index += 1 for row in row_list: if row[column_index["Entities"]] != "": entities_json = json.loads(row[column_index["Entities"]]) for artifact in entities_json: if artifact['Type'] == "ip": address = artifact.get('Address') if address: artifacts.append( AlertArtifact(dataType='ip', data=artifact['Address'])) else: logging.info("Unknown ip entity: " + json.dumps( entities_json, indent=4, sort_keys=True)) elif artifact['Type'] == "host": hostname = artifact.get('HostName') azureID = artifact.get('AzureID') if hostname: artifacts.append( AlertArtifact(dataType='host', data=artifact['HostName'])) elif azureID: artifacts.append( AlertArtifact(dataType='host', data=artifact['AzureID'])) else: logging.info("Unknown host entity: " + json.dumps( entities_json, indent=4, sort_keys=True)) elif artifact['Type'] == "account": name = artifact.get('Name') aadUserId = artifact.get('AadUserId') if name: artifacts.append( AlertArtifact(dataType='account', data=artifact['Name'])) elif aadUserId: artifacts.append( AlertArtifact(dataType='account', data=artifact['AadUserId'])) else: logging.info("Unknown account entity: " + json.dumps( entities_json, indent=4, sort_keys=True)) elif artifact['Type'] == "file": name = artifact.get('Name') if name: artifacts.append( AlertArtifact(dataType='filename', data=artifact['Name'])) else: logging.info("Unknown file entity: " + json.dumps( entities_json, indent=4, sort_keys=True)) elif artifact['Type'] == "filehash": value = artifact.get('Value') if value: artifacts.append( AlertArtifact(dataType='hash', data=artifact['Value'])) else: logging.info("Unknown filehash entity: " + json.dumps( entities_json, indent=4, sort_keys=True)) elif artifact['Type'] == "process": commandline = artifact.get('CommandLine') if commandline: artifacts.append( AlertArtifact(dataType='filename', data=artifact['CommandLine'])) else: logging.info("Unknown process entity: " + json.dumps( entities_json, indent=4, sort_keys=True)) else: logging.info( "Unknown entity: " + json.dumps(entities_json, indent=4, sort_keys=True)) return artifacts
def connectEws(): report = dict() report['success'] = bool() clients = None with open('/opt/Synapse/conf/mailboxes.json') as f: clients = json.load(f) mailboxes = clients['mailboxes'] cfg = getConf() theHiveConnector = TheHiveConnector(cfg) for mailbox in mailboxes: ewsConnector = EwsConnector(username=mailbox['username'], password=mailbox['password'], auth_type=mailbox['auth_type'], server=mailbox['server'], smtp_address=mailbox['smtp_address']) unread = ewsConnector.scan(mailbox['folder_name']) for msg in unread: #type(msg) #<class 'exchangelib.folders.Message'> conversationId = msg.conversation_id.id origin_mail = msg.attachments[0].item fullBody = getEmailBody(msg) alertTitle = "{}; {}".format( msg.subject, ''.join( [i if ord(i) < 128 else '' for i in origin_mail.subject])) alertDescription = ('```\n' + 'Alert created by Synapse\n' + 'conversation_id: "' + str(msg.conversation_id.id) + '"\n\n' + 'Original mail:\n\n' + fullBody[3:]) # rapporteur reporter = str(msg.sender.email_address).lower() # expéditeur sender = str(origin_mail.sender.email_address).lower() # date de réception originale et en-tant que spam rcv_date_timestamp = origin_mail.datetime_received.timestamp( ) * 1000 # date de signalement à la boîte support rpt_date_timestamp = msg.datetime_received.timestamp() * 1000 customFields = CustomFieldHelper()\ .add_string('reporter', reporter)\ .add_string('sender', sender)\ .add_date('receivedDate', rcv_date_timestamp)\ .add_date('reportedDate', rpt_date_timestamp)\ .add_string('client', mailbox['name'])\ .build() file_paths = [] artifacts = [] artifacts.append( AlertArtifact(dataType='mail', data=reporter, ignoreSimilarity=True, tags=['Synapse'])) artifacts.append( AlertArtifact(dataType='mail', data=sender, message="Original sender of the e-mail", tags=['Synapse', 'Sender'])) artifacts.append( AlertArtifact(dataType='mail_subject', data=str(origin_mail.subject), message="Original subject of the e-mail", tags=['Synapse'])) attachedFiles = getFileAttachments(msg) for attached in attachedFiles: artifacts.append( AlertArtifact(dataType='file', data=[attached['path']], tags=['Attachment', 'Synapse'])) file_paths.append(attached['path']) alert = Alert(title=alertTitle, description=alertDescription, severity=2, date=rcv_date_timestamp, tags=[], tlp=2, status="New", type="Phishing", source="BAL Phishing", sourceRef="{}-{}".format( mailbox['short_name'], str(uuid.uuid4())[24:].upper()), artifacts=artifacts, caseTemplate="Suspicious Email Case", customFields=customFields) theHiveConnector.createAlert(alert) ewsConnector.markAsRead(msg) logger.info("Cleaning temp files ...") for temp_file in file_paths: try: os.remove(temp_file) except OSError as errRm: logger.error("'{}' could not be removed.{}".format( temp_file, errRm)) report['success'] = True return report
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:
def build_alert(detection, id): """ Convert CrowdStrike Falcon alert into TheHive Alerts :param detection: Detection from CrowdStrike Alert :type detection: dict :param observables: observables from CrowdStrike Alert :type observables: dict :return: TheHive alert :rtype: thehive4py.models Alerts """ meta = detection['data']['meta'] resources = detection['data']['resources'][0] status = detection['status'] behaviors = resources['behaviors'][0] device = resources['device'] detection_title = '{} {} {} {}'.format( 'CROWDSTRIKE ALERT - ', resources.get('max_severity_displayname'), 'Severity', behaviors['scenario'].replace("_", " ")) tlp = 2 artifacts = [ AlertArtifact(dataType='filename', data=behaviors.get('filename'), message="File name of the triggering process"), AlertArtifact(dataType='hash', data=behaviors.get('sha256'), tags=['sha256'], message="SHA256 of the triggering process", ioc=True), AlertArtifact(dataType='other', data=behaviors.get('user_name'), tags=['target-user'], message="The user's name", tlp=3), AlertArtifact(dataType='other', data=behaviors.get('user_id'), message="Users SID in Windows", tlp=3), AlertArtifact(dataType='hash', data=behaviors.get('md5'), tags=['md5'], message="MD5 of the triggering process", ioc=True), AlertArtifact(dataType='other', data=behaviors.get('cmdline'), message="Command Line of the triggering process"), AlertArtifact(dataType='other', data=behaviors.get('ioc_source'), message="Source that triggered an IOC detection"), AlertArtifact(dataType=th_datatype(behaviors.get('ioc_type')), data=behaviors.get('ioc_value'), message="ioc_value", ioc=True), AlertArtifact(dataType='other', data=device.get('hostname'), tags=['target-machine'], message="Device hostname"), AlertArtifact(dataType='ip', data=device.get('local_ip'), tags=['host-ip'], message="Hosts local ip.", tlp=3), AlertArtifact(dataType='ip', data=device.get('external_ip'), tags=['external-ip'], message="Hosts external ip.") ] a = Alert( title='{} {} {}'.format(detection_title, 'on', device.get('hostname')), tlp=2, severity=th_severity(resources.get('max_severity_displayname')), type="FalconHost Alert", tags=[ "CrowdStrike:Scenario={}".format(behaviors['scenario'].replace( "_", " ").title()), "CrowdStrike:Max Confidence={}".format( resources.get('max_confidence')), "CrowdStrike:Max Severity={}".format( resources.get('max_severity')), device.get('machine_domain'), device.get('hostname'), device.get('local_ip'), behaviors.get('user_name'), behaviors.get('tactic'), behaviors.get('technique') ], caseTemplate=TheHive['template'], source="CrowdStrike", sourceRef=id, artifacts=artifacts, # Switch description to named parameters? description="{0} {1} {2} {3} {4} {5} {6}".format( "#### **" + detection_title + 'on ' + device.get('hostname') + "**", "\n\n --- \n", "#### **SUMMARY**\n\n", "{0} {1} {2} {3} {4} {5} {6} {7}".format( "- **SCENARIO: **" + behaviors.get('scenario') + "\n", "- **SEVERITY: **" + resources.get('max_severity_displayname') + "\n", "- **DETECT TIME: **" + behaviors.get('timestamp') + "\n", "- **HOST: **" + device.get('hostname') + "\n", "- **HOST IP: **" + device.get('local_ip') + "\n", "- **USERNAME: **" + behaviors.get('user_name') + "\n", "- **TACTIC: **" + behaviors.get('tactic') + "\n", "- **TECHNIQUE: **" + behaviors.get('technique') + "\n", ), "\n\n --- \n", "#### **DETECTION DETAILS**\n\n", "{0} {1} {2}".format( "```\n", json.dumps(detection, indent=4, sort_keys=True), "\n```", ), )) return a
def createHiveAlert(esid): search = getHits(esid) #Hive Stuff #es_url = parser.get('es', 'es_url') hive_url = parser.get('hive', 'hive_url') api = hiveInit() tlp = int(parser.get('hive', 'hive_tlp')) for result in search['hits']['hits']: # Get initial details message = result['_source']['message'] es_id = result['_id'] description = str(message) sourceRef = str(uuid.uuid4())[0:6] tags = ["SecurityOnion"] artifacts = [] id = None host = str(result['_index']).split(":")[0] index = str(result['_index']).split(":")[1] event_type = result['_source']['event_type'] if 'source_ip' in result['_source']: src = str(result['_source']['source_ip']) if 'destination_ip' in result['_source']: dst = str(result['_source']['destination_ip']) if 'source_port' in result['_source']: srcport = str(result['_source']['source_port']) if 'destination_port' in result['_source']: dstport = str(result['_source']['destination_port']) # NIDS Alerts if 'ids' in event_type: alert = result['_source']['alert'] sid = str(result['_source']['sid']) category = result['_source']['category'] sensor = result['_source']['sensor_name'] masterip = str(es_url.split("//")[1].split(":")[0]) tags.append("nids") tags.append(category) title = alert print(alert) sys.stdout.flush() # Add artifacts artifacts.append(AlertArtifact(dataType='ip', data=src)) artifacts.append(AlertArtifact(dataType='ip', data=dst)) artifacts.append(AlertArtifact(dataType='other', data=sensor)) description = "`NIDS Dashboard:` \n\n <https://" + masterip + "/kibana/app/kibana#/dashboard/ed6f7e20-e060-11e9-8f0c-2ddbf5ed9290?_g=(refreshInterval:(display:Off,pause:!f,value:0),time:(from:now-24h,mode:quick,to:now))&_a=(columns:!(_source),index:'*:logstash-*',interval:auto,query:(query_string:(analyze_wildcard:!t,query:'sid:" + sid + "')),sort:!('@timestamp',desc))> \n\n `IPs: `" + src + ":" + srcport + "-->" + dst + ":" + dstport + "\n\n `Signature:`" + alert + "\n\n `PCAP:` " + "https://" + masterip + "/kibana/app//sensoroni/securityonion/joblookup?redirectUrl=/sensoroni/&esid=" + es_id # Bro logs elif 'bro' in event_type: _map_key_type = { "conn": "Connection", "dhcp": "DHCP", "dnp3": "DNP3", "dns": "DNS", "files": "Files", "ftp": "FTP", "http": "HTTP", "intel": "Intel", "irc": "IRC", "kerberos": "Kerberos", "modbus": "Modbus", "mysql": "MySQL", "ntlm": "NTLM", "pe": "PE", "radius": "RADIUS", "rdp": "RDP", "rfb": "RFB", "sip": "SIP", "smb": "SMB", "smtp": "SMTP", "snmp": "SNMP", "ssh": "SSH", "ssl": "SSL", "syslog": "Syslog", "weird": "Weird", "x509": "X509" } def map_key_type(indicator_type): ''' Maps a key type to use in the request URL. ''' return _map_key_type.get(indicator_type) bro_tag = event_type.strip('bro_') bro_tag_title = map_key_type(bro_tag) title = str('New Bro ' + bro_tag_title + ' record!') if 'source_ip' in result['_source']: artifacts.append(AlertArtifact(dataType='ip', data=src)) if 'destination_ip' in result['_source']: artifacts.append(AlertArtifact(dataType='ip', data=dst)) if 'sensor_name' in result['_source']: sensor = str(result['_source']['sensor_name']) artifacts.append(AlertArtifact(dataType='other', data=sensor)) if 'uid' in result['_source']: uid = str(result['_source']['uid']) title = str('New Bro ' + bro_tag_title + ' record! - ' + uid) artifacts.append(AlertArtifact(dataType='other', data=uid)) if 'fuid' in result['_source']: fuid = str(result['_source']['fuid']) title = str('New Bro ' + bro_tag_title + ' record! - ' + fuid) artifacts.append(AlertArtifact(dataType='other', data=fuid)) if 'id' in result['_source']: fuid = str(result['_source']['id']) title = str('New Bro ' + bro_tag_title + ' record! - ' + fuid) artifacts.append(AlertArtifact(dataType='other', data=fuid)) tags.append('bro') tags.append(bro_tag) # Wazuh/OSSEC logs elif 'ossec' in event_type: agent_name = result['_source']['agent']['name'] if 'description' in result['_source']: ossec_desc = result['_source']['description'] else: ossec_desc = result['_source']['full_log'] if 'ip' in result['_source']['agent']: agent_ip = result['_source']['agent']['ip'] artifacts.append(AlertArtifact(dataType='ip', data=agent_ip)) artifacts.append( AlertArtifact(dataType='other', data=agent_name)) else: artifacts.append( AlertArtifact(dataType='other', data=agent_name)) title = ossec_desc tags.append("wazuh") elif 'sysmon' in event_type: if 'ossec' in result['_source']['tags']: agent_name = result['_source']['agent']['name'] agent_ip = result['_source']['agent']['ip'] ossec_desc = result['_source']['full_log'] artifacts.append(AlertArtifact(dataType='ip', data=agent_ip)) artifacts.append( AlertArtifact(dataType='other', data=agent_name)) tags.append("wazuh") elif 'beat' in result['_source']['tags']: agent_name = str(result['_source']['beat']['hostname']) if 'beat_host' in result['_source']: os_name = str(result['_source']['beat_host']['os']['name']) artifacts.append( AlertArtifact(dataType='other', data=os_name)) if 'source_hostname' in result['_source']: source_hostname = str(result['_source']['source_hostname']) artifacts.append( AlertArtifact(dataType='fqdn', data=source_hostname)) if 'source_ip' in result['_source']: source_ip = str(result['_source']['source_ip']) artifacts.append( AlertArtifact(dataType='ip', data=source_ip)) if 'destination_ip' in result['_source']: destination_ip = str(result['_source']['destination_ip']) artifacts.append( AlertArtifact(dataType='ip', data=destination_ip)) if 'image_path' in result['_source']: image_path = str(result['_source']['image_path']) artifacts.append( AlertArtifact(dataType='filename', data=image_path)) if 'Hashes' in result['_source']['event_data']: hashes = result['_source']['event_data']['Hashes'] for hash in hashes.split(','): if hash.startswith('MD5') or hash.startswith('SHA256'): artifacts.append( AlertArtifact(dataType='hash', data=hash.split('=')[1])) tags.append("beats") else: agent_name = '' title = "New Sysmon Event! - " + agent_name else: title = "New " + event_type + " Event From Security Onion" form = DefaultForm() artifact_string = jsonpickle.encode(artifacts) return render_template('hive.html', title=title, tlp=tlp, tags=tags, description=description, artifact_string=artifact_string, sourceRef=sourceRef, form=form)
def createGRRFlow(esid, flow_name): search = getHits(esid) tlp = int(parser.get('hive', 'hive_tlp')) # Check if verifying cert if 'False' in hive_verifycert: hiveapi = TheHiveApi(hive_url, hive_key, cert=False) else: hiveapi = TheHiveApi(hive_url, hive_key, cert=True) grr_url = parser.get('grr', 'grr_url') grr_user = parser.get('grr', 'grr_user') grr_pass = parser.get('grr', 'grr_pass') grrapi = api.InitHttp(api_endpoint=grr_url, auth=(grr_user, grr_pass)) base64string = '%s:%s' % (grr_user, grr_pass) base64string = base64.b64encode(bytes(base64string, "utf-8")) authheader = "Basic %s" % base64string index_response = requests.get(grr_url, auth=HTTPBasicAuth(grr_user, grr_pass)) csrf_token = index_response.cookies.get("csrftoken") headers = { "Authorization": authheader, "x-csrftoken": csrf_token, "x-requested-with": "XMLHttpRequest" } cookies = {"csrftoken": csrf_token} for result in search['hits']['hits']: result = result['_source'] message = result['message'] description = str(message) info = description if 'source_ip' in result: source_ip = result['source_ip'] if 'destination_ip' in result: destination_ip = result['destination_ip'] for ip in source_ip, destination_ip: search_result = grrapi.SearchClients(ip) grr_result = {} client_id = '' for client in search_result: # Get client id client_id = client.client_id client_last_seen_at = client.data.last_seen_at grr_result[client_id] = client_last_seen_at #flow_name = "ListProcesses" if client_id is None: pass # Process flow and get flow id flow_id = listProcessFlow(client_id, grr_url, headers, cookies, grr_user, grr_pass) # Get status status = checkFlowStatus(client_id, grr_url, flow_id, headers, cookies, grr_user, grr_pass) # Keep checking to see if complete while status != "terminated": time.sleep(15) print( "Flow not yet completed..watiing 15 secs before attempting to check status again..." ) status = checkFlowStatus(client_id, grr_url, flow_id, headers, cookies, grr_user, grr_pass) # If terminated, run the download if status == "terminated": downloadFlowResults(client_id, grr_url, flow_id, headers, cookies, grr_user, grr_pass) #print("Done!") # Run flow via API client #flow_obj = grrapi.Client(client_id) #flow_obj.CreateFlow(name=flow_name) title = "Test Alert with GRR Flow" description = str(message) sourceRef = str(uuid.uuid4())[0:6] tags = ["SecurityOnion", "GRR"] artifacts = [] id = None filepath = "/tmp/soctopus/" + client_id + ".zip" artifacts.append( AlertArtifact(dataType='file', data=str(filepath))) # Build alert hivealert = Alert(title=title, tlp=tlp, tags=tags, description=description, type='external', source='SecurityOnion', sourceRef=sourceRef, artifacts=artifacts) # Send it off response = hiveapi.create_alert(hivealert) if client_id: # Redirect to GRR instance return redirect(grr_url + '/#/clients/' + client_id + '/flows') else: return "No matches found for source or destination ip"
def create_alert(): # Get request JSON content = request.get_json() # Configure logging logging.basicConfig( filename=app.config['LOG_FILE'], filemode='a', format='%(asctime)s - graylog2thehive - %(levelname)s - %(message)s', level=logging.INFO) logging.info(json.dumps(content)) # Configure API api = TheHiveApi(app.config['HIVE_URL'], app.config['API_KEY']) # Configure artifacts artifacts = [] # Configure tags tags = ['graylog'] # Build description body and tags list description = 'Alert Condition: \n' + content['check_result'][ 'triggered_condition']['title'] + '\n\nMatching messages:\n\n' tags = ['graylog'] for message in content['check_result']['matching_messages']: description = description + "\n\n---\n\n**Source:** " + message[ 'source'] + "\n\n**Log URL:** " + app.config[ 'GRAYLOG_URL'] + "/messages/" + message[ 'index'] + "/" + message['id'] + "\n\n" message_flattened = flatten_dict(message) for key in message_flattened.keys(): if key != "message" and key != "source": description = description + "\n**" + key + ":** " + json.dumps( message_flattened[key], ensure_ascii=False) + "\n" # Use any IPs, hashes, URLs, filenames, etc here in place of src_ip and dst_ip to include them as artifacts/observables in your alert if key == "cmd_url2": artifacts.append( AlertArtifact(dataType='url', tags=[key], data=message_flattened[key])) if key == "dest_ip": artifacts.append( AlertArtifact(dataType='ip', tags=[key], data=message_flattened[key])) if key == "MD5" or key == "SHA256": artifacts.append( AlertArtifact(dataType='hash', tags=[key], data=message_flattened[key])) description = description + '\n\n**Raw Message:** \n\n```\n' + json.dumps( message) + '\n```\n---\n' # Prepare alert sourceRef = str(uuid.uuid4())[0:6] alert = Alert(title="Graylog Alert: " + content['stream']['title'] + " - " + content['check_result']['result_description'], tlp=2, tags=tags, description=content['check_result']['result_description'], type='external', source='graylog', artifacts=artifacts, sourceRef=sourceRef) # Create the alert print('Create Alert') print('-----------------------------') id = None response = api.create_alert(alert) if response.status_code == 201: logging.info(json.dumps(response.json(), indent=4, sort_keys=True)) 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) return content['check_result']['result_description']