diff --git a/bin/DB_KVROCKS_MIGRATION.py b/bin/DB_KVROCKS_MIGRATION.py index 61bcb3cf..19f152fb 100755 --- a/bin/DB_KVROCKS_MIGRATION.py +++ b/bin/DB_KVROCKS_MIGRATION.py @@ -564,7 +564,7 @@ def domain_migration(): for history in get_domain_history_by_port(domain_type, dom, port): epoch = history['epoch'] # DOMAIN DOWN - if not history.get('status'): # domain DOWN + if not history.get('status'): # domain DOWN domain.add_history(epoch) print(f'DOWN {epoch}') # DOMAIN UP @@ -585,6 +585,7 @@ def domain_migration(): #print() + # TODO REMOVE INVALID DOMAINS for domain_type in ['onion', 'regular']: for date in Date.get_date_range_today('20190101'): for dom in get_domain_down_by_date(domain_type, date): @@ -601,7 +602,7 @@ def domain_migration(): domain.update_daterange(last_check) if last_origin: domain.set_last_origin(last_origin) - domain.add_history(None, None, date=date) + domain.add_history(0, None, date=date) ############################### @@ -871,12 +872,12 @@ if __name__ == '__main__': #core_migration() #user_migration() #tags_migration() - items_migration() - #crawler_migration() - # domain_migration() # TO TEST ########################### + # items_migration() + # crawler_migration() + domain_migration() # TO TEST ########################### # decodeds_migration() # screenshots_migration() - # subtypes_obj_migration() + subtypes_obj_migration() # ail_2_ail_migration() # trackers_migration() # investigations_migration() diff --git a/bin/export/AILObjects.py b/bin/export/AILObjects.py deleted file mode 100755 index f2af699b..00000000 --- a/bin/export/AILObjects.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:UTF-8 -* - -import os -import sys -import uuid - -sys.path.append(os.environ['AIL_BIN']) -from lib.objects import ail_objects -from lib import ConfigLoader - -config_loader = ConfigLoader.ConfigLoader() -r_serv_objects = config_loader.get_redis_conn("ARDB_Objects") -config_loader = None - -def create_map_obj_uuid_golbal_id(obj_uuid, global_id): - r_serv_objects.sadd('all_object:uuid', obj_uuid) - r_serv_objects.sadd('all_object:global_id', global_id) - r_serv_objects.sadd('object:map:uuid_id:{}'.format(obj_uuid), global_id) - r_serv_objects.sadd('object:map:id_uuid:{}'.format(global_id), obj_uuid) - -def create_map_obj_event_uuid(event_uuid, global_id): - r_serv_objects.sadd('export:all_object:event_uuid', event_uuid) - r_serv_objects.sadd('export:all_object:global_id', global_id) - r_serv_objects.sadd('object:map:event_id:{}'.format(event_uuid), global_id) - r_serv_objects.sadd('object:map:id_event:{}'.format(global_id), event_uuid) - -# def get_user_list_of_obj_to_export(user_id, add_uuid=False): -# objs_to_export = [] -# res = r_serv_objects.hgetall('user:all_objs_to_export:{}'.format(user_id)) -# for global_id in res: -# dict_obj = Correlate_object.get_global_id_from_id(global_id) -# dict_obj['lvl'] = int(res[global_id]) -# if add_uuid: -# obj_dict['uuid'] = str(uuid.uuid4()) -# objs_to_export.append(dict_obj) -# return objs_to_export - -def add_user_object_to_export(user_id, obj_type, obj_id, lvl, obj_subtype=None): - ## TODO: check if user exist - # # TODO: check if valid object - # # TODO: check lvl - global_id = ail_objects.get_obj_global_id(obj_type, obj_subtype, obj_id) - return r_serv_objects.hset('user:all_objs_to_export:{}'.format(user_id), global_id, lvl) - -def delete_user_object_to_export(user_id, obj_type, obj_id, obj_subtype=None): - ## TODO: check if user exist - global_id = ail_objects.get_obj_global_id(obj_type, obj_subtype, obj_id) - r_serv_objects.hdel('user:all_objs_to_export:{}'.format(user_id), global_id) - -def delete_all_user_object_to_export(user_id): - ## TODO: check if user exist - r_serv_objects.delete('user:all_objs_to_export:{}'.format(user_id)) diff --git a/bin/export/Export.py b/bin/export/Export.py index faa79859..c76e641c 100755 --- a/bin/export/Export.py +++ b/bin/export/Export.py @@ -3,53 +3,172 @@ import os import sys -from uuid import uuid4 +import uuid sys.path.append(os.environ['AIL_BIN']) -from lib import ConfigLoader - -sys.path.append('../../configs/keys') -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 == '': - is_hive_connected = False - else: - is_hive_connected = TheHiveApi(the_hive_url, the_hive_key, cert=the_hive_verifycert) -except: - is_hive_connected = False -if is_hive_connected != False: - try: - is_hive_connected.get_alert(0) - is_hive_connected = True - except thehive4py.exceptions.AlertException: - is_hive_connected = False +################################## +# Import Project packages +################################## +from lib.ConfigLoader import ConfigLoader +from lib.objects.Items import Item +from lib.ail_core import get_ail_uuid +from lib.Investigations import Investigation +from lib.objects import ail_objects ## LOAD CONFIG ## -config_loader = ConfigLoader.ConfigLoader() -r_serv_cache = config_loader.get_redis_conn("Redis_Cache") -r_serv_db = config_loader.get_redis_conn("ARDB_DB") -r_serv_metadata = config_loader.get_redis_conn("ARDB_Metadata") +config_loader = ConfigLoader() +r_cache = config_loader.get_redis_conn("Redis_Cache") +r_db = config_loader.get_db_conn("Kvrocks_DB") + +r_serv_db = config_loader.get_redis_conn("ARDB_DB") ###################################### +r_serv_metadata = config_loader.get_redis_conn("ARDB_Metadata") ###################################### config_loader = None ## -- ## -def load_tags_to_export_in_cache(): - all_exports = ['misp', 'thehive'] - for export_target in all_exports: - # save solo tags in cache - all_tags_to_export = Tag.get_list_of_solo_tags_to_export_by_type() - if len(all_tags_to_export) > 1: - r_serv_cache.sadd('to_export:solo_tags:{}'.format(export_target), *all_tags_to_export) - elif all_tags_to_export: - r_serv_cache.sadd('to_export:solo_tags:{}'.format(export_target), all_tags_to_export[0]) +sys.path.append('../../configs/keys') +################################## +# Import Keys +################################## +from thehive4py.api import TheHiveApi +from thehive4py.models import Alert, AlertArtifact, Case, CaseObservable +import thehive4py.exceptions - # save combinaison of tags in cache - pass +from pymisp import MISPEvent, MISPObject, PyMISP -def is_hive_connected(): # # TODO: REFRACTOR, put in cache (with retry) - return is_hive_connected +################################## +# THE HIVE +################################## +HIVE_CLIENT = None +try: + from theHiveKEYS import the_hive_url, the_hive_key, the_hive_verifycert + + HIVE_URL = the_hive_url + HIVE_KEY = the_hive_key + HIVE_VERIFY_CERT = the_hive_verifycert +except: + HIVE_URL = None + HIVE_KEY = None + HIVE_VERIFY_CERT = None + + +def get_hive_client(): + global HIVE_CLIENT + try: + HIVE_CLIENT = TheHiveApi(HIVE_URL, HIVE_KEY, cert=HIVE_VERIFY_CERT) + except: + HIVE_CLIENT = None + return HIVE_CLIENT + + +def is_hive_connected(): + try: + # print(hive_client.health()) + HIVE_CLIENT.get_alert(0) + return True + except thehive4py.exceptions.AlertException: + return False + + +HIVE_CLIENT = get_hive_client() + + +def create_thehive_alert(item_id, tag_trigger): + item = Item(item_id) + meta = item.get_meta() + # TheHive expects a file + content = item.get_raw_content(decompress=True) + + # remove .gz from submitted path to TheHive because we've decompressed it + if item_id.endswith(".gz"): + item_id = item_id[:-3] + # add .txt it's easier to open when downloaded from TheHive + item_id = f'{item_id}.txt' + + artifacts = [ + AlertArtifact(dataType='other', message='uuid-ail', data=(get_ail_uuid())), + AlertArtifact(dataType='file', data=(content, item_id), tags=meta['tags']) + ] + + # Prepare the sample Alert + sourceRef = str(uuid.uuid4())[0:6] + alert = Alert(title='AIL Leak', + tlp=3, + tags=meta['tags'], + description='AIL Leak, triggered by {}'.format(tag_trigger), + type='ail', + source=meta['source'], # Use item ID ? + sourceRef=sourceRef, + artifacts=artifacts) + + # Create the Alert + alert_id = None + try: + response = HIVE_CLIENT.create_alert(alert) + if response.status_code == 201: + # print(json.dumps(response.json(), indent=4, sort_keys=True)) + print('Alert Created') + print(response.json()) + alert_id = response.json()['id'] + else: + print(f'ko: {response.status_code}/{response.text}') + return 0 + except: + print('hive connection error') + print(alert_id) + + +# TODO SAVE CASE URL ???????????????????????? +def create_thehive_case(item_id, title=None, tlp=2, threat_level=2, description=None): + item = Item(item_id) + ail_uuid = get_ail_uuid() + + if not title: + title = f'AIL Case {item.id}' + if not description: + description = f'AIL {ail_uuid} Case' + date = item.get_date() + date = f'{date[0:4]}-{date[4:6]}-{date[6:8]}' + tags = item.get_tags(r_list=True) + + case = Case(title=title, + tlp=tlp, + severity=threat_level, + flag=False, + tags=tags, + description=description) + + # Create Case + response = get_hive_client().create_case(case) + if response.status_code == 201: + case_id = response.json()['id'] + + observables = [ + CaseObservable(dataType="other", data=[ail_uuid], message="uuid-ail"), + CaseObservable(dataType="file", data=item.get_filename(), tags=tags), + CaseObservable(dataType="other", data=[item.get_source()], message="source"), + CaseObservable(dataType="other", data=[date], message="last-seen") + ] + + for observable in observables: + resp = HIVE_CLIENT.create_case_observable(case_id, observable) + if resp.status_code != 201: + print(f'error observable creation: {resp.status_code}/{resp.text}') + # print(case_id) + # return HIVE_URL /thehive/cases/~37040/details + return case_id + + # r_serv_metadata.set('hive_cases:'+path, id) + else: + print(f'ko: {response.status_code}/{response.text}') + return None + + +def get_case_url(case_id): + return f'{HIVE_URL}/cases/{case_id}/details' + + +# TODO def get_item_hive_cases(item_id): hive_case = r_serv_metadata.get('hive_cases:{}'.format(item_id)) if hive_case: @@ -57,6 +176,150 @@ def get_item_hive_cases(item_id): return hive_case +################################## +# MISP +################################## + +try: + from mispKEYS import misp_url, misp_key, misp_verifycert + + MISP_URL = misp_url + MISP_KEY = misp_key + MISP_VERIFYCERT = misp_verifycert + if MISP_URL.endswith('/'): + MISP_URL = MISP_URL[:-1] +except: + MISP_URL = None + MISP_KEY = None + MISP_VERIFYCERT = None + + +def get_misp_client(): + return PyMISP(misp_url, misp_key, misp_verifycert) + + +# # TODO: return error +def ping_misp(): + try: + PyMISP(misp_url, misp_key, misp_verifycert) + return True + except Exception as e: + print(e) + return False + + +def sanitize_misp_event_distribution(distribution): + try: + int(distribution) + if 0 <= distribution <= 3: + return distribution + else: + return 0 + except: + return 0 + + +def sanitize_misp_event_threat_level(threat_level): + try: + int(threat_level) + if 1 <= threat_level <= 4: + return threat_level + else: + return 4 + except: + return 4 + + +def sanitize_misp_event_analysis(analysis): + try: + int(analysis) + if 0 <= analysis <= 2: + return analysis + else: + return 0 + except: + return 0 + +def create_misp_event(objs, event_uuid=None, date=None, distribution=0, threat_level_id=4, publish=False, analysis=0, + info=None, tags=None, export=False): + if tags is None: + tags = [] + event = MISPEvent() + if not event_uuid: + event_uuid = str(uuid.uuid4()) + event.uuid = event_uuid + if date: + event.date = date + if not info: + info = 'AIL framework export' + event.info = info + if publish: + event.publish() + for tag in tags: + event.add_tag(tag) + event.distribution = sanitize_misp_event_distribution(distribution) + event.threat_level_id = sanitize_misp_event_threat_level(threat_level_id) + event.analysis = sanitize_misp_event_analysis(analysis) + + misp_objects = ail_objects.get_misp_objects(objs) + for obj in misp_objects: + event.add_object(obj) + + # print(event.to_json()) + + if export: + misp = get_misp_client() + misp_event = misp.add_event(event) + # TODO: handle error + + misp_event['url'] = f'{MISP_URL}/events/view/{misp_event["Event"]["uuid"]}' + return misp_event + else: + return {'uuid': event['uuid'], 'event': event.to_json()} + +def create_investigation_misp_event(investigation_uuid): + investigation = Investigation(investigation_uuid) + objs = ail_objects.get_objects(investigation.get_objects()) + + event = create_misp_event(objs, + # event_uuid=investigation.get_uuid(separator=True), # TODO EDIT EXISTING EVENT ???? + date=investigation.get_date(), + distribution=0, + threat_level_id=investigation.get_threat_level(), + analysis=investigation.get_analysis(), + info=investigation.get_info(), + tags=investigation.get_tags(), + export=True) + url = event['url'] + if url: + investigation.add_misp_events(url) + return url + +def get_user_misp_objects_to_export(user_id): + objs = [] + objects = r_db.hgetall(f'user:obj:misp:export:{user_id}') + for obj in objects: + obj_type, obj_subtype, obj_id = obj.split(':', 2) + lvl = objects[obj] + try: + lvl = int(lvl) + except: + lvl = 0 + objs.append({'type': obj_type, 'subtype': obj_subtype, 'id': obj_id, 'lvl': lvl}) + return objs + +def add_user_misp_object_to_export(user_id, obj_type, obj_subtype, obj_id, lvl=0): + if not obj_subtype: + obj_subtype = '' + r_db.hset(f'user:obj:misp:export:{user_id}', f'{obj_type}:{obj_subtype}:{obj_id}', lvl) + +def delete_user_misp_object_to_export(user_id, obj_type, obj_subtype, obj_id): + r_db.hdel(f'user:obj:misp:export:{user_id}', f'{obj_type}:{obj_subtype}:{obj_id}') + +def delete_user_misp_objects_to_export(user_id): + r_db.delete(f'user:obj:misp:export:{user_id}') + + ########################################################### # # set default # if r_serv_db.get('hive:auto-alerts') is None: @@ -64,3 +327,11 @@ def get_item_hive_cases(item_id): # # if r_serv_db.get('misp:auto-events') is None: # r_serv_db.set('misp:auto-events', 0) + +# if __name__ == '__main__': +# from lib.objects.Cves import Cve +# create_misp_event([Item('crawled/2020/09/14/circl.lu0f4976a4-dda4-4189-ba11-6618c4a8c951'), +# Cve('CVE-2020-16856'), Cve('CVE-2014-6585'), Cve('CVE-2015-0383'), +# Cve('CVE-2015-0410')]) + +# create_investigation_misp_event('c6bbf8fa9ead4cc698eaeb07835cca5d) diff --git a/bin/export/MispExport.py b/bin/export/MispExport.py deleted file mode 100755 index 56f0501c..00000000 --- a/bin/export/MispExport.py +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/env python3 -# -*-coding:UTF-8 -* - -import os -import io -import sys -import uuid - -sys.path.append(os.environ['AIL_BIN']) -from lib.objects import ail_objects - -from export import AILObjects - - -from lib.Investigations import Investigation - -# # TODO: # FIXME: REFACTOR ME => use UI/Global config -sys.path.append('../../configs/keys') -try: - from mispKEYS import misp_url, misp_key, misp_verifycert -except: - misp_url = '' - misp_key = '' - misp_verifycert = False - -# MISP -from pymisp import MISPEvent, MISPObject, PyMISP - -def is_valid_obj_to_export(obj_type, obj_subtype, obj_id): - if not ail_objects.is_valid_object_type(obj_type): - return False - if not ail_objects.is_valid_object_subtype(obj_type, obj_subtype): - return False - if not ail_objects.exists_obj(obj_type, obj_subtype, obj_id): - return False - return True - -def sanitize_obj_export_lvl(lvl): - try: - lvl = int(lvl) - except: - lvl = 0 - return lvl - -def get_export_filename(json_content): - return 'ail_export_{}.json'.format(json_content.uuid) - -def create_in_memory_file(json_content): - return io.BytesIO(json_content.encode()) - -def add_relation_ship_to_create(set_relationship, dict_obj, dict_new_obj): - global_id = ail_objects.get_obj_global_id(dict_obj['type'], dict_obj.get('subtype', ''), dict_obj['id']) - global_id_new = ail_objects.get_obj_global_id(dict_new_obj['type'], dict_new_obj.get('subtype', ''), dict_new_obj['id']) - if global_id > global_id_new: - res = (global_id, global_id_new) - else: - res = (global_id_new, global_id) - set_relationship.add( res ) - -# # TODO: add action by obj type -# ex => Domain -def add_obj_to_create(all_obj_to_export, set_relationship, dict_obj): - all_obj_to_export.add(ail_objects.get_obj_global_id(dict_obj['type'], dict_obj.get('subtype', ''), dict_obj['id'])) - -def add_obj_to_create_by_lvl(all_obj_to_export, set_relationship, dict_obj, lvl): - # # TODO: filter by export mode or filter on all global ? - if lvl >= 0: - add_obj_to_create(all_obj_to_export, add_obj_to_create, dict_obj) - - if lvl > 0: - lvl = lvl - 1 - - # # TODO: filter by correlation types - obj_correlations = ail_objects.get_obj_correlations(dict_obj['type'], dict_obj.get('subtype', ''), dict_obj['id']) - for obj_type in obj_correlations: - dict_new_obj = {'type': obj_type} - if obj_type=='pgp' or obj_type=='cryptocurrency' or obj_type=='username': - for subtype in obj_correlations[obj_type]: - dict_new_obj['subtype'] = subtype - for obj_id in obj_correlations[obj_type][subtype]: - dict_new_obj['id'] = obj_id - add_obj_to_create_by_lvl(all_obj_to_export, set_relationship, dict_new_obj, lvl) - add_relation_ship_to_create(set_relationship, dict_obj, dict_new_obj) - - else: - for obj_id in obj_correlations[obj_type]: - dict_new_obj['id'] = obj_id - add_obj_to_create_by_lvl(all_obj_to_export, set_relationship, dict_new_obj, lvl) - add_relation_ship_to_create(set_relationship, dict_obj, dict_new_obj) - - - add_obj_to_create_by_lvl(all_obj_to_export, set_relationship, dict_obj, lvl) - - -def create_list_of_objs_to_export(l_obj, r_type='json'): - all_obj_to_export = set() - set_relationship = set() - for obj in l_obj: - add_obj_to_create_by_lvl(all_obj_to_export, set_relationship, obj, obj.get('lvl', 1)) - - # create MISP objects - dict_misp_obj = create_all_misp_obj(all_obj_to_export, set_relationship) - - # create object relationships - for obj_global_id_1, obj_global_id_2 in set_relationship: - dict_relationship = get_relationship_between_global_obj(obj_global_id_1, obj_global_id_2) - if dict_relationship: - obj_src = dict_misp_obj[dict_relationship['src']] - obj_dest = dict_misp_obj[dict_relationship['dest']] - obj_src.add_reference(obj_dest.uuid, dict_relationship['relation'], 'add a comment') - - event = MISPEvent() - event.info = 'AIL framework export' - event.uuid = str(uuid.uuid4()) - for obj_global_id in dict_misp_obj: - misp_obj = dict_misp_obj[obj_global_id] - AILObjects.create_map_obj_event_uuid(event.uuid, obj_global_id) - AILObjects.create_map_obj_uuid_golbal_id(event.uuid, obj_global_id) - if misp_obj: - # add object to event - event.add_object(dict_misp_obj[obj_global_id]) - - return event - -# TODO REFACTOR ME -def create_all_misp_obj(all_obj_to_export, set_relationship): - dict_misp_obj = {} - for obj_global_id in all_obj_to_export: - obj_type, obj_id = obj_global_id.split(':', 1) - dict_misp_obj[obj_global_id] = create_misp_obj(obj_type, obj_id) - return dict_misp_obj - -# TODO REFACTOR ME -def create_misp_obj(obj_type, obj_id): - if obj_type in ['cryptocurrency', 'pgp', 'username']: - obj_subtype, obj_id = obj_id.split(':', 1) - else: - obj_subtype = '' - misp_obj = ail_objects.get_misp_object(obj_type, obj_subtype, obj_id) - return misp_obj - - -def get_relationship_between_global_obj(obj_global_id_1, obj_global_id_2): - obj_type_1 = obj_global_id_1.split(':', 1)[0] - obj_type_2 = obj_global_id_2.split(':', 1)[0] - type_tuple = [obj_type_1, obj_type_2] - - if 'image' in type_tuple: # or screenshot ## TODO: - if obj_type_1 == 'image': - src = obj_global_id_1 - dest = obj_global_id_2 - else: - src = obj_global_id_2 - dest = obj_global_id_1 - return {'relation': 'screenshot-of', 'src': src, 'dest': dest} - elif 'decoded' in type_tuple: - if obj_type_1 == 'decoded': - src = obj_global_id_1 - dest = obj_global_id_2 - else: - src = obj_global_id_2 - dest = obj_global_id_1 - return {'relation': 'included-in', 'src': src, 'dest': dest} - elif 'pgp' in type_tuple: - if obj_type_1 == 'pgp': - src = obj_global_id_1 - dest = obj_global_id_2 - else: - src = obj_global_id_2 - dest = obj_global_id_1 - return {'relation': 'extracted-from', 'src': src, 'dest': dest} - elif 'cryptocurrency': - if obj_type_1 == 'cryptocurrency': - src = obj_global_id_1 - dest = obj_global_id_2 - else: - src = obj_global_id_2 - dest = obj_global_id_1 - return {'relation': 'extracted-from', 'src': src, 'dest': dest} - elif 'domain' in type_tuple: - if 'item' in type_tuple: - if obj_type_1 == 'item': - src = obj_global_id_1 - dest = obj_global_id_2 - else: - src = obj_global_id_2 - dest = obj_global_id_1 - return {'relation': 'extracted-from', 'src': src, 'dest': dest} # replave by crawled-from - elif 'item' in type_tuple: - if 'domain' in type_tuple: - if obj_type_1 == 'item': - src = obj_global_id_1 - dest = obj_global_id_2 - else: - src = obj_global_id_2 - dest = obj_global_id_1 - return {'relation': 'extracted-from', 'src': src, 'dest': dest} # replave by crawled-from - return None - -def sanitize_event_distribution(distribution): - try: - int(distribution) - if (0 <= distribution <= 3): - return distribution - else: - return 0 - except: - return 0 - -def sanitize_event_threat_level_id(threat_level_id): - try: - int(threat_level_id) - if (1 <= threat_level_id <= 4): - return threat_level_id - else: - return 4 - except: - return 4 - -def sanitize_event_analysis(analysis): - try: - int(analysis) - if (0 <= analysis <= 2): - return analysis - else: - return 0 - except: - return 0 - -# # TODO: return error -def ping_misp(): - try: - PyMISP(misp_url, misp_key, misp_verifycert) - return True - except Exception as e: - print(e) - return False - -def create_misp_event(event, distribution=0, threat_level_id=4, publish=False, analysis=0, event_info=None): - if event_info: - event.info = event_info - event.distribution = sanitize_event_distribution(distribution) - event.threat_level_id = sanitize_event_threat_level_id(threat_level_id) - event.analysis = sanitize_event_analysis(analysis) - if publish: - event.publish() - - # # TODO: handle multiple MISP instance - misp = PyMISP(misp_url, misp_key, misp_verifycert) - #print(event.to_json()) - - misp_event = misp.add_event(event) - #print(misp_event) - # # TODO: handle error - event_metadata = extract_event_metadata(misp_event) - return event_metadata - -def extract_event_metadata(event): - event_metadata = {} - event_metadata['uuid'] = event['Event']['uuid'] - event_metadata['id'] = event['Event']['id'] - if misp_url[-1] == '/': - event_metadata['url'] = misp_url + 'events/view/' + str(event_metadata['id']) - else: - event_metadata['url'] = misp_url + '/events/view/' + str(event_metadata['id']) - return event_metadata - -###### -# -# EXPORT LVL DEFINITION: (== Correl PARTIAL Only add core item Correlation -# LVL 1 => DETAILED Also add correlated_items correlation -###### - -# # TODO: # create object relationships -def create_investigation_event(investigation_uuid): - investigation = Investigation(investigation_uuid) - - event = MISPEvent() - event.info = investigation.get_info() - event.uuid = investigation.get_uuid(separator=True) - event.date = investigation.get_date() - event.analysis = investigation.get_analysis() - event.threat_level_id = investigation.get_threat_level() - - event.distribution = 0 - - # tags - for tag in investigation.get_tags(): - event.add_tag(tag) - # objects - investigation_objs = investigation.get_objects() - for obj in investigation_objs: - # if subtype -> obj_id = 'subtype:type' - if obj['subtype']: - obj_id = f"{obj['subtype']}:{obj['id']}" - else: - obj_id = obj['id'] - misp_obj = create_misp_obj(obj['type'], obj_id) - if misp_obj: - event.add_object(misp_obj) - - # if publish: - # event.publish() - - # print(event.to_json()) - misp = PyMISP(misp_url, misp_key, misp_verifycert) - if misp.event_exists(event.uuid): - misp_event = misp.update_event(event) - else: - misp_event = misp.add_event(event) - - # # TODO: handle error - event_metadata = extract_event_metadata(misp_event) - if event_metadata.get('uuid'): - if misp_url[-1] == '/': - url = misp_url[:-1] - else: - url = misp_url - investigation.add_misp_events(url) - return event_metadata - -# if __name__ == '__main__': - - # l_obj = [{'id': 'bfd5f1d89e55b10a8b122a9d7ce31667ec1d086a', 'type': 'decoded', 'lvl': 2}] - # create_list_of_objs_to_export(l_obj) - - #print(event.to_json()) diff --git a/bin/export/MispImport.py b/bin/export/MispImport.py index a2043164..a1c73509 100755 --- a/bin/export/MispImport.py +++ b/bin/export/MispImport.py @@ -13,8 +13,6 @@ from lib.objects import ail_objects from lib.objects import Items -from export import AILObjects - # MISP from pymisp import MISPEvent, MISPObject, PyMISP @@ -218,10 +216,6 @@ def create_obj_relationships(map_uuid_global_id, misp_obj): # TODO CREATE OBJ RELATIONSHIP -def create_map_all_obj_uuid_golbal_id(map_uuid_global_id): - for obj_uuid in map_uuid_global_id: - AILObjects.create_map_obj_uuid_golbal_id(obj_uuid, map_uuid_global_id[obj_uuid]) - def import_objs_from_file(filepath): map_uuid_global_id = {} @@ -237,7 +231,6 @@ def import_objs_from_file(filepath): for misp_obj in event_to_import.objects: create_obj_relationships(map_uuid_global_id, misp_obj) - create_map_all_obj_uuid_golbal_id(map_uuid_global_id) return map_uuid_global_id diff --git a/bin/import/ail_json_importer/Ail_feeder_urlextract.py b/bin/import/ail_json_importer/Ail_feeder_urlextract.py index 54bd0cb3..9bd4cbbd 100755 --- a/bin/import/ail_json_importer/Ail_feeder_urlextract.py +++ b/bin/import/ail_json_importer/Ail_feeder_urlextract.py @@ -12,12 +12,16 @@ import sys import datetime import uuid -sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) -import item_basic - sys.path.append(os.path.join(os.environ['AIL_BIN'], 'import', 'ail_json_importer')) from Default_json import Default_json +sys.path.append(os.environ['AIL_BIN']) +################################## +# Import Project packages +################################## +from lib.objects.Items import Item + + class Ail_feeder_urlextract(Default_json): """urlextract Feeder functions""" @@ -46,13 +50,14 @@ class Ail_feeder_urlextract(Default_json): # # TODO: def process_json_meta(self, process, item_id): - ''' + """ Process JSON meta filed. - ''' + """ json_meta = self.get_json_meta() + parent_id = str(json_meta['parent:twitter:tweet_id']) # TODO SEARCH IN CACHE !!! + item = Item(item_id) + item.set_parent(parent_id) # # TODO: change me - parent_type = 'twitter_id' - - parent_id = str(json_meta['parent:twitter:tweet_id']) - item_basic.add_item_parent_by_parent_id(parent_type, parent_id, item_id) + # parent_type = 'twitter_id' + # item_basic.add_item_parent_by_parent_id(parent_type, parent_id, item_id) diff --git a/bin/lib/Investigations.py b/bin/lib/Investigations.py index fe3d3d38..5600b6a4 100755 --- a/bin/lib/Investigations.py +++ b/bin/lib/Investigations.py @@ -200,8 +200,8 @@ class Investigation(object): else: raise UpdateInvestigationError(f'Invalid analysis: {analysis}') - def add_misp_events(self, misp_url): - r_tracking.sadd(f'investigations:misp:{self.uuid}', misp_url) + def add_misp_events(self, event_uuid): + r_tracking.sadd(f'investigations:misp:{self.uuid}', event_uuid) def set_tags(self, tags): # delete previous tags diff --git a/bin/lib/ail_core.py b/bin/lib/ail_core.py index 50c48dc2..923d16f0 100755 --- a/bin/lib/ail_core.py +++ b/bin/lib/ail_core.py @@ -12,13 +12,13 @@ sys.path.append(os.environ['AIL_BIN']) from lib.ConfigLoader import ConfigLoader config_loader = ConfigLoader() - +r_serv_db = config_loader.get_db_conn("Kvrocks_DB") config_loader = None -AIL_OBJECTS = {'cve', 'cryptocurrency', 'decoded', 'domain', 'item', 'pgp', 'screenshot', 'username'} +AIL_OBJECTS = sorted({'cve', 'cryptocurrency', 'decoded', 'domain', 'item', 'pgp', 'screenshot', 'username'}) def get_ail_uuid(): - pass + return r_serv_db.get('ail:uuid') #### AIL OBJECTS #### @@ -33,11 +33,21 @@ def get_object_all_subtypes(obj_type): if obj_type == 'username': return ['telegram', 'twitter', 'jabber'] +def get_all_objects_with_subtypes_tuple(): + str_objs = [] + for obj_type in get_all_objects(): + subtypes = get_object_all_subtypes(obj_type) + if subtypes: + for subtype in subtypes: + str_objs.append((obj_type, subtype)) + else: + str_objs.append((obj_type, '')) + return str_objs + ##-- AIL OBJECTS --## def paginate_iterator(iter_elems, nb_obj=50, page=1): - dict_page = {} - dict_page['nb_all_elem'] = len(iter_elems) + dict_page = {'nb_all_elem': len(iter_elems)} nb_pages = dict_page['nb_all_elem'] / nb_obj if not nb_pages.is_integer(): nb_pages = int(nb_pages)+1 diff --git a/bin/lib/data_retention_engine.py b/bin/lib/data_retention_engine.py index 7bf7a5c8..e1b27dc1 100755 --- a/bin/lib/data_retention_engine.py +++ b/bin/lib/data_retention_engine.py @@ -96,4 +96,3 @@ def update_obj_date(date, obj_type, subtype=''): if __name__ == '__main__': print(r_obj.hgetall(f'date:first')) print(r_obj.hgetall(f'date:last')) - diff --git a/bin/lib/objects/Domains.py b/bin/lib/objects/Domains.py index 97d73b46..062a1d12 100755 --- a/bin/lib/objects/Domains.py +++ b/bin/lib/objects/Domains.py @@ -420,11 +420,15 @@ class Domain(AbstractObject): def add_history(self, epoch, root_item=None, date=None): if not date: date = time.strftime('%Y%m%d', time.gmtime(epoch)) - try: - root_item = int(root_item) + if not root_item: + root_item = int(epoch) status = False - except (ValueError, TypeError): - status = True + else: + try: + root_item = int(root_item) + status = False + except (ValueError, TypeError): + status = True update_obj_date(date, 'domain', self.domain_type) # UP diff --git a/bin/lib/objects/Items.py b/bin/lib/objects/Items.py index 7df47275..b72aada9 100755 --- a/bin/lib/objects/Items.py +++ b/bin/lib/objects/Items.py @@ -88,10 +88,13 @@ class Item(AbstractObject): else: return item_basic.get_item_content(self.id) - def get_raw_content(self): + def get_raw_content(self, decompress=False): filepath = self.get_filename() - with open(filepath, 'rb') as f: - raw_content = BytesIO(f.read()) + if decompress: + raw_content = BytesIO(self.get_content(binary=True)) + else: + with open(filepath, 'rb') as f: + raw_content = BytesIO(f.read()) return raw_content def get_gzip_content(self, b64=False): diff --git a/bin/lib/objects/Usernames.py b/bin/lib/objects/Usernames.py index 68a58428..1e0783f0 100755 --- a/bin/lib/objects/Usernames.py +++ b/bin/lib/objects/Usernames.py @@ -18,7 +18,7 @@ from lib.ConfigLoader import ConfigLoader from lib.objects.abstract_subtype_object import AbstractSubtypeObject, get_all_id config_loader = ConfigLoader() - +baseurl = config_loader.get_config_str("Notifications", "ail_domain") config_loader = None diff --git a/bin/lib/objects/abstract_object.py b/bin/lib/objects/abstract_object.py index 0b8b78ee..7408ba67 100755 --- a/bin/lib/objects/abstract_object.py +++ b/bin/lib/objects/abstract_object.py @@ -243,6 +243,14 @@ class AbstractObject(ABC): """ return is_obj_correlated(self.type, self.subtype, self.id, type2, subtype2, id2) + def are_correlated(self, object2): + """ + Check if an object is correlated with another Object + :type object2 AbstractObject + """ + return is_obj_correlated(self.type, self.subtype, self.id, + object2.get_type(), object2.get_subtype(r_str=True), object2.get_id()) + def delete_correlation(self, type2, subtype2, id2): """ Get object correlations diff --git a/bin/lib/objects/ail_objects.py b/bin/lib/objects/ail_objects.py index db5c0abe..88737034 100755 --- a/bin/lib/objects/ail_objects.py +++ b/bin/lib/objects/ail_objects.py @@ -4,15 +4,12 @@ import os import sys -from abc import ABC -from flask import url_for - sys.path.append(os.environ['AIL_BIN']) ################################## # Import Project packages ################################## from lib.ConfigLoader import ConfigLoader -from lib.ail_core import get_all_objects +from lib.ail_core import get_all_objects, get_object_all_subtypes, get_all_objects_with_subtypes_tuple from lib import correlations_engine from lib import btc_ail from lib import Tag @@ -26,26 +23,18 @@ from lib.objects import Pgps from lib.objects.Screenshots import Screenshot from lib.objects import Usernames - config_loader = ConfigLoader() config_loader = None -class AILObjects(object): ## ?????????????????????? - initial = 0 - ongoing = 1 - completed = 2 + + def is_valid_object_type(obj_type): return obj_type in get_all_objects() def is_valid_object_subtype(obj_type, subtype): - if obj_type == 'cryptocurrency': - return subtype in CryptoCurrencies.get_all_subtypes() - elif obj_type == 'pgp': - return subtype in Pgps.get_all_subtypes() - elif obj_type == 'username': - return subtype in CryptoCurrencies.get_all_subtypes() + return subtype in get_object_all_subtypes(obj_type) def sanitize_objs_types(objs): l_types = [] @@ -56,6 +45,7 @@ def sanitize_objs_types(objs): l_types = get_all_objects() return l_types + def get_object(obj_type, subtype, id): if obj_type == 'item': return Item(id) @@ -74,6 +64,25 @@ def get_object(obj_type, subtype, id): elif obj_type == 'username': return Usernames.Username(id, subtype) +def get_objects(objects): + objs = set() + for obj in objects: + if isinstance(obj, dict): + obj_type = obj['type'] + obj_subtype = obj['subtype'] + obj_id = obj['id'] + if 'lvl' in obj: + correl_objs = get_obj_correlations_objs(obj_type, obj_subtype, obj_id, lvl=obj['lvl']) + objs = objs.union(correl_objs) + else: + obj_type, obj_subtype, obj_id = obj + objs.add((obj_type, obj_subtype, obj_id)) + ail_objects = [] + for obj in objs: + ail_objects.append(get_object(obj[0], obj[1], obj[2])) + return ail_objects + + def exists_obj(obj_type, subtype, obj_id): obj = get_object(obj_type, subtype, obj_id) if obj: @@ -81,35 +90,44 @@ def exists_obj(obj_type, subtype, obj_id): else: return False + def get_obj_global_id(obj_type, subtype, obj_id): obj = get_object(obj_type, subtype, obj_id) return obj.get_global_id() + def get_obj_from_global_id(global_id): obj = global_id.split(':', 3) return get_object(obj[0], obj[1], obj[2]) + def get_object_link(obj_type, subtype, id, flask_context=False): obj = get_object(obj_type, subtype, id) return obj.get_link(flask_context=flask_context) + def get_object_svg(obj_type, subtype, id): obj = get_object(obj_type, subtype, id) return obj.get_svg_icon() + ## TAGS ## def get_obj_tags(obj_type, subtype, id): obj = get_object(obj_type, subtype, id) return obj.get_tags() + def add_obj_tag(obj_type, subtype, id, tag): obj = get_object(obj_type, subtype, id) obj.add_tag(tag) + def add_obj_tags(obj_type, subtype, id, tags): obj = get_object(obj_type, subtype, id) for tag in tags: obj.add_tag(tag) + + # -TAGS- # def get_object_meta(obj_type, subtype, id, options=[], flask_context=False): @@ -119,6 +137,7 @@ def get_object_meta(obj_type, subtype, id, options=[], flask_context=False): meta['link'] = obj.get_link(flask_context=flask_context) return meta + def get_objects_meta(objs, options=[], flask_context=False): metas = [] for obj_dict in objs: @@ -126,13 +145,15 @@ def get_objects_meta(objs, options=[], flask_context=False): flask_context=flask_context)) return metas + def get_object_card_meta(obj_type, subtype, id, related_btc=False): obj = get_object(obj_type, subtype, id) meta = obj.get_meta() meta['icon'] = obj.get_svg_icon() if subtype or obj_type == 'cve': meta['sparkline'] = obj.get_sparkline() - meta['cve_search'] = obj.get_cve_search() + if obj_type == 'cve': + meta['cve_search'] = obj.get_cve_search() if subtype == 'bitcoin' and related_btc: meta["related_btc"] = btc_ail.get_bitcoin_info(obj.id) if obj.get_type() == 'decoded': @@ -143,6 +164,7 @@ def get_object_card_meta(obj_type, subtype, id, related_btc=False): meta["add_tags_modal"] = Tag.get_modal_add_tags(obj.id, obj.get_type(), obj.get_subtype(r_str=True)) return meta + def get_ui_obj_tag_table_keys(obj_type): ''' Warning: use only in flask (dynamic templates) @@ -150,15 +172,58 @@ def get_ui_obj_tag_table_keys(obj_type): if obj_type == "domain": return ['id', 'first_seen', 'last_check', 'status'] # # TODO: add root screenshot + +# # # # MISP OBJECTS # # # # + # # TODO: CHECK IF object already have an UUID def get_misp_object(obj_type, subtype, id): obj = get_object(obj_type, subtype, id) return obj.get_misp_object() + +def get_misp_objects(objs): + misp_objects = {} + for obj in objs: + misp_objects[obj] = obj.get_misp_object() + for relation in get_objects_relationships(objs): + obj_src = misp_objects[relation['src']] + obj_dest = misp_objects[relation['dest']] + # print(relation['src'].get_id(), relation['dest'].get_id()) + obj_src.add_reference(obj_dest.uuid, relation['relationship'], 'ail correlation') + return misp_objects.values() + # get misp relationship -def get_objects_relationship(obj_1, obj2): - relationship = {} - obj_types = (obj_1.get_type(), obj2.get_type()) +def get_objects_relationships(objs): + relation = [] + if len(objs) == 2: + if objs[0].are_correlated(objs[1]): + relationship = get_objects_relationship(objs[0], objs[1]) + if relationship: + relation.append(relationship) + else: + iterator = objs.copy() # [obj1, obj2, obj3, obj4] + for obj in objs[:-1]: # [obj1, obj2, obj3] + iterator.pop(0) # [obj2, obj3, obj4] obj1 correlation already checked + for obj2 in iterator: + # CHECK CORRELATION obj - > obj2 + if obj.are_correlated(obj2): + relationship = get_objects_relationship(obj, obj2) + if relationship: + relation.append(relationship) + return relation + +def get_relationship_src_dest(src_type, obj1, obj2): + if obj1.get_type() == src_type: + src = obj1 + dest = obj2 + else: + src = obj2 + dest = obj1 + return src, dest + +# get misp relationship +def get_objects_relationship(obj1, obj2): + obj_types = (obj1.get_type(), obj2.get_type()) ############################################################## # if ['cryptocurrency', 'pgp', 'username', 'decoded', 'screenshot']: @@ -166,63 +231,79 @@ def get_objects_relationship(obj_1, obj2): # relationship[relation] = ############################################################## if 'cryptocurrency' in obj_types: - relationship['relation'] = 'extracted-from' - if obj_1.get_type() == 'cryptocurrency': - relationship['src'] = obj_1.get_id() - relationship['dest'] = obj2.get_id() - else: - relationship['src'] = obj2.get_id() - relationship['dest'] = obj_1.get_id() - + relationship = 'extracted-from' + src, dest = get_relationship_src_dest('cryptocurrency', obj1, obj2) + elif 'cve' in obj_types: + relationship = 'extracted-from' + src, dest = get_relationship_src_dest('cve', obj1, obj2) elif 'pgp' in obj_types: - relationship['relation'] = 'extracted-from' - + relationship = 'extracted-from' + src, dest = get_relationship_src_dest('pgp', obj1, obj2) elif 'username' in obj_types: - relationship['relation'] = 'extracted-from' - + relationship = 'extracted-from' + src, dest = get_relationship_src_dest('username', obj1, obj2) elif 'decoded' in obj_types: - relationship['relation'] = 'included-in' - + relationship = 'included-in' + src, dest = get_relationship_src_dest('decoded', obj1, obj2) elif 'screenshot' in obj_types: - relationship['relation'] = 'screenshot-of' - + relationship = 'screenshot-of' + src, dest = get_relationship_src_dest('screenshot', obj1, obj2) elif 'domain' in obj_types: - relationship['relation'] = 'extracted-from' - + relationship = 'extracted-from' + src, dest = get_relationship_src_dest('domain', obj1, obj2) # default else: - pass + relationship = None + src = None + dest = None + if not relationship: + return {} + else: + return {'src': src, 'dest': dest, 'relationship': relationship} + +# - - - MISP OBJECTS - - - # - return relationship def api_sanitize_object_type(obj_type): if not is_valid_object_type(obj_type): return {'status': 'error', 'reason': 'Incorrect object type'}, 400 -def get_obj_correlations(obj_type, subtype, id): - obj = get_object(obj_type, subtype, id) + +def get_obj_correlations(obj_type, subtype, obj_id): + obj = get_object(obj_type, subtype, obj_id) return obj.get_correlations() -################################################################################ -# DATA RETENTION -# # TODO: TO ADD ?????????????????????? -# def get_first_objects_date(): -# return r_object.zrange('objs:first_date', 0, -1) -# -# def get_first_object_date(obj_type, subtype): -# return r_object.zscore('objs:first_date', f'{obj_type}:{subtype}') -# -# def set_first_object_date(obj_type, subtype, date): -# return r_object.zadd('objs:first_date', f'{obj_type}:{subtype}', date) +def _get_obj_correlations_objs(objs, obj_type, subtype, obj_id, lvl=0): + if lvl > 0 and (obj_type, subtype, obj_id) not in objs: # Avoid looking for the same correlation + objs.add((obj_type, subtype, obj_id)) + lvl = lvl - 1 + obj = get_object(obj_type, subtype, obj_id) + correlations = obj.get_correlations() + # print('--------------------------') + # print( obj_id, correlations) + # print(lvl) + # print('--------------------------') + for obj2_type in correlations: + for str_obj in correlations[obj2_type]: + obj2_subtype, obj2_id = str_obj.split(':', 1) + _get_obj_correlations_objs(objs, obj2_type, obj2_subtype, obj2_id, lvl=lvl) + # print(len(objs)) + objs.add((obj_type, subtype, obj_id)) + return objs +def get_obj_correlations_objs(obj_type, subtype, obj_id, lvl=0): + objs = set() + _get_obj_correlations_objs(objs, obj_type, subtype, obj_id, lvl=lvl) + return objs ################################################################################ ################################################################################ ################################################################################ -def delete_obj(obj_type, subtype, id): - object = get_object(obj_type, subtype, id) - return object.delete() +def delete_obj(obj_type, subtype, obj_id): + obj = get_object(obj_type, subtype, obj_id) + return obj.delete() + ################################################################################ ################################################################################ @@ -236,11 +317,12 @@ def create_correlation_graph_links(links_set): links.append({"source": link[0], "target": link[1]}) return links + def create_correlation_graph_nodes(nodes_set, obj_str_id, flask_context=True): graph_nodes_list = [] for node_id in nodes_set: obj_type, subtype, obj_id = node_id.split(';', 2) - dict_node = {"id": node_id} + dict_node = {'id': node_id} dict_node['style'] = get_object_svg(obj_type, subtype, obj_id) # # TODO: # FIXME: in UI @@ -258,11 +340,27 @@ def create_correlation_graph_nodes(nodes_set, obj_str_id, flask_context=True): graph_nodes_list.append(dict_node) return graph_nodes_list -def get_correlations_graph_node(obj_type, subtype, obj_id, filter_types=[], max_nodes=300, level=1, flask_context=False): - obj_str_id, nodes, links = correlations_engine.get_correlations_graph_nodes_links(obj_type, subtype, obj_id, filter_types=filter_types, max_nodes=max_nodes, level=level, flask_context=flask_context) - return {"nodes": create_correlation_graph_nodes(nodes, obj_str_id, flask_context=flask_context), "links": create_correlation_graph_links(links)} - +def get_correlations_graph_node(obj_type, subtype, obj_id, filter_types=[], max_nodes=300, level=1, + flask_context=False): + obj_str_id, nodes, links = correlations_engine.get_correlations_graph_nodes_links(obj_type, subtype, obj_id, + filter_types=filter_types, + max_nodes=max_nodes, level=level, + flask_context=flask_context) + return {"nodes": create_correlation_graph_nodes(nodes, obj_str_id, flask_context=flask_context), + "links": create_correlation_graph_links(links)} ############### + + +# if __name__ == '__main__': + # r = get_objects([{'lvl': 1, 'type': 'item', 'subtype': '', 'id': 'crawled/2020/09/14/circl.lu0f4976a4-dda4-4189-ba11-6618c4a8c951'}]) + # r = get_misp_objects([Item('crawled/2020/09/14/circl.lu0f4976a4-dda4-4189-ba11-6618c4a8c951'), + # Cve('CVE-2020-16856'), Cve('CVE-2014-6585'), Cve('CVE-2015-0383'), + # Cve('CVE-2015-0410')]) + # print() + # print(r) + + # res = get_obj_correlations_objs('username', 'telegram', 'corona', lvl=100) + # print(res) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 0361a083..ef308825 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ d4-pyclient>=0.1.6 thehive4py # Core -redis==3.0.0 +redis>4.4.0 python-magic>0.4.15 yara-python>4.0.2 diff --git a/var/www/blueprints/crawler_splash.py b/var/www/blueprints/crawler_splash.py index 7cdbab4e..698c57ce 100644 --- a/var/www/blueprints/crawler_splash.py +++ b/var/www/blueprints/crawler_splash.py @@ -34,7 +34,7 @@ from lib import Tag from packages import Date -#import Config_DB +# import Config_DB bootstrap_label = Flask_config.bootstrap_label # ============ BLUEPRINT ============ diff --git a/var/www/blueprints/import_export.py b/var/www/blueprints/import_export.py index 6dac8d0d..1eb58be6 100644 --- a/var/www/blueprints/import_export.py +++ b/var/www/blueprints/import_export.py @@ -4,17 +4,16 @@ ''' Blueprint Flask: MISP format import export ''' - +import io import os import sys import uuid import json -from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, send_file +from flask import render_template, jsonify, request, Blueprint, redirect, url_for, Response, send_file, abort from flask_login import login_required, current_user, login_user, logout_user sys.path.append('modules') -import Flask_config # Import Role_Manager from Role_Manager import login_admin, login_analyst, login_read_only @@ -23,20 +22,21 @@ sys.path.append(os.environ['AIL_BIN']) ################################## # Import Project packages ################################## -from export import MispExport -from export import MispImport -from export import AILObjects ####################### # # # # ########################## ## # #################################### - +from export import Export from lib.objects import ail_objects +from export import MispImport # TODO REMOVE ME + +# TODO REMOVE ME # ============ BLUEPRINT ============ -import_export = Blueprint('import_export', __name__, template_folder=os.path.join(os.environ['AIL_FLASK'], 'templates/import_export')) +import_export = Blueprint('import_export', __name__, + template_folder=os.path.join(os.environ['AIL_FLASK'], 'templates/import_export')) + # ============ VARIABLES ============ - # ============ FUNCTIONS ============ @@ -47,6 +47,7 @@ import_export = Blueprint('import_export', __name__, template_folder=os.path.joi def import_object(): return render_template("import_object.html") +# TODO @import_export.route("/import_export/import_file", methods=['POST']) @login_required @login_analyst @@ -79,137 +80,129 @@ def import_object_file(): return render_template("import_object.html", all_imported_obj=all_imported_obj, error=error) -@import_export.route('/import_export/export') + +@import_export.route("/objects/misp/export", methods=['GET']) @login_required @login_analyst -def export_object(): +def objects_misp_export(): user_id = current_user.get_id() + object_types = ail_objects.get_all_objects_with_subtypes_tuple() + to_export = Export.get_user_misp_objects_to_export(user_id) + return render_template("export_object.html", object_types=object_types, to_export=to_export) - # get user saved obj to export - l_obj_to_export = AILObjects.get_user_list_of_obj_to_export(user_id) - return render_template("export_object.html", l_obj_to_export=l_obj_to_export) - -@import_export.route("/import_export/export_file", methods=['POST']) +@import_export.route("/objects/misp/export/post", methods=['POST']) @login_required @login_analyst -def export_object_file(): +def objects_misp_export_post(): user_id = current_user.get_id() - l_obj_to_export = [] - l_obj_invalid = [] - - export_to_misp = False - dict_misp_event_export = {} - # Get new added Object + new_export = [] + user_lvl_export = {} for obj_tuple in list(request.form): + # GET NEW LEVEL + if obj_tuple[0] == '{': + obj_j = obj_tuple.replace("'", "\"") + obj_dict = json.loads(obj_j) # TODO sanitize + lvl = int(request.form.getlist(obj_tuple)[0]) + user_lvl_export[f"{obj_dict['type']}:{obj_dict['subtype']}:{obj_dict['id']}"] = lvl + l_input = request.form.getlist(obj_tuple) if len(l_input) == 3: - obj_type = l_input[0] - obj_id = l_input[1] - lvl = l_input[2] - lvl = MispExport.sanitize_obj_export_lvl(lvl) + if l_input[0] != 'Object type...': + new_type, new_subtype = l_input[0].split(':', 1) + if not new_subtype: + new_subtype = '' + new_export.append({'type': new_type, 'subtype': new_subtype, 'id': l_input[1], 'lvl': l_input[2]}) - obj_subtype = obj_type.split(';') - if len(obj_subtype) == 2: - obj_type = obj_subtype[0] - obj_subtype = obj_subtype[1] - else: - obj_subtype = None - - obj_dict = {'id': obj_id, 'type': obj_type, 'lvl': lvl} - if obj_subtype: - obj_dict['subtype'] = obj_subtype - - if MispExport.is_valid_obj_to_export(obj_type, obj_subtype, obj_id): - l_obj_to_export.append(obj_dict) - AILObjects.add_user_object_to_export(user_id, obj_dict['type'], obj_dict['id'], obj_dict['lvl'], obj_subtype=obj_dict.get('subtype', None)) - else: - if obj_id: - l_obj_invalid.append(obj_dict) + objects = [] + invalid_obj = [] + for obj in new_export: + if not ail_objects.exists_obj(obj['type'], obj['subtype'], obj['id']): + invalid_obj.append(obj) else: - dict_misp_event_export[str(obj_tuple)] = request.form.get(obj_tuple) - - # print(dict_misp_event_export) - - if dict_misp_event_export.get('export_to_misp', None): - export_to_misp = True - else: - dict_misp_event_export = None - - if l_obj_invalid: - # get user saved obj to export # # TODO: # performance - l_obj_to_export = AILObjects.get_user_list_of_obj_to_export(user_id) - - for obj_dict in l_obj_invalid: # set uuid input - obj_dict['uuid'] = str(uuid.uuid4()) - subtype = obj_dict.get('subtype', None) - if subtype: - obj_dict['type'] = f'{obj_dict["type"]};{subtype}' - - return render_template("export_object.html", l_obj_to_export=l_obj_to_export, - l_obj_invalid=l_obj_invalid, dict_misp_event_export=dict_misp_event_export) - else: - if export_to_misp and MispExport.ping_misp(): - event = MispExport.create_list_of_objs_to_export(l_obj_to_export, r_type='event') - - event_metadata = MispExport.create_misp_event(event, distribution=dict_misp_event_export.get('export_to_misp', None), - threat_level_id=dict_misp_event_export.get('misp_threat_level_id', None), - publish=dict_misp_event_export.get('misp_publish', None), - analysis=dict_misp_event_export.get('misp_event_analysis', None), - event_info=dict_misp_event_export.get('misp_event_info', None)) - - AILObjects.delete_all_user_object_to_export(user_id) - return render_template("export_object.html", l_obj_to_export=l_obj_to_export, - event_metadata=event_metadata, - l_obj_invalid=[], dict_misp_event_export=[]) + objects.append(obj) + for obj in Export.get_user_misp_objects_to_export(user_id): + if not ail_objects.exists_obj(obj['type'], obj['subtype'], obj['id']): + invalid_obj.append(obj) else: - # get user saved obj to export # # TODO: # performance - json_export = MispExport.create_list_of_objs_to_export(l_obj_to_export) - export_filename = MispExport.get_export_filename(json_export) - json_export = MispExport.create_in_memory_file(json_export.to_json()) - AILObjects.delete_all_user_object_to_export(user_id) - return send_file(json_export, as_attachment=True, attachment_filename=export_filename) + str_id = f"{obj['type']}:{obj['subtype']}:{obj['id']}" + if str_id in user_lvl_export: + obj['lvl'] = user_lvl_export[str_id] + objects.append(obj) + + if invalid_obj: + object_types = ail_objects.get_all_objects_with_subtypes_tuple() + return render_template("export_object.html", object_types=object_types, + to_export=objects, l_obj_invalid=invalid_obj) + + export = request.form.get('export_to_misp', False) + distribution = request.form.get('misp_event_distribution') + threat_level_id = request.form.get('threat_level_id') + analysis = request.form.get('misp_event_analysis') + info = request.form.get('misp_event_info') + publish = request.form.get('misp_event_info', False) + + objs = ail_objects.get_objects(objects) + event = Export.create_misp_event(objs, distribution=distribution, threat_level_id=threat_level_id, + analysis=analysis, info=info, export=export, publish=publish) + + Export.delete_user_misp_objects_to_export(user_id) + + if not export: + return send_file(io.BytesIO(event['event'].encode()), as_attachment=True, + download_name=f'ail_export_{event["uuid"]}.json') + else: + object_types = ail_objects.get_all_objects_with_subtypes_tuple() + return render_template("export_object.html", object_types=object_types, + misp_url=event['url']) -@import_export.route("/import_export/add_object_id_to_export", methods=['GET']) +@import_export.route("/objects/misp/export/add", methods=['GET']) @login_required @login_analyst def add_object_id_to_export(): user_id = current_user.get_id() - user_id = current_user.get_id() - obj_type = request.args.get('obj_type') - obj_id = request.args.get('obj_id') - obj_subtype = request.args.get('obj_subtype') - obj_lvl = request.args.get('obj_lvl') - AILObjects.add_user_object_to_export(user_id, obj_type, obj_id, obj_lvl, obj_subtype=obj_subtype) + obj_type = request.args.get('type') + obj_id = request.args.get('id') + obj_subtype = request.args.get('subtype') + obj_lvl = request.args.get('lvl') + + try: + obj_lvl = int(obj_lvl) + except: + obj_lvl = 0 + + if not ail_objects.exists_obj(obj_type, obj_subtype, obj_id): + abort(404) + Export.add_user_misp_object_to_export(user_id, obj_type, obj_subtype, obj_id, lvl=obj_lvl) # redirect - return redirect(url_for('import_export.export_object')) + return redirect(url_for('import_export.objects_misp_export')) + + +@import_export.route("/objects/misp/export/delete", methods=['GET']) +@login_required +@login_analyst +def delete_object_id_to_export(): + user_id = current_user.get_id() + obj_type = request.args.get('type') + obj_id = request.args.get('id') + obj_subtype = request.args.get('subtype') + + Export.delete_user_misp_object_to_export(user_id, obj_type, obj_subtype, obj_id) + return jsonify(success=True) + @import_export.route("/import_export/investigation", methods=['GET']) @login_required @login_analyst def export_investigation(): investigation_uuid = request.args.get("uuid") - - if MispExport.ping_misp(): - event_metadata = MispExport.create_investigation_event(investigation_uuid) + if Export.ping_misp(): + event = Export.create_investigation_misp_event(investigation_uuid) + print(event) else: - return Response(json.dumps({"error": "Can't reach MISP Instance"}, indent=2, sort_keys=True), mimetype='application/json'), 400 - + return Response(json.dumps({"error": "Can't reach MISP Instance"}, indent=2, sort_keys=True), + mimetype='application/json'), 400 return redirect(url_for('investigations_b.show_investigation', uuid=investigation_uuid)) - - -# @import_export.route("/import_export/delete_object_id_to_export", methods=['GET']) -# @login_required -# @login_analyst -# def delete_object_id_to_export(): -# user_id = current_user.get_id() -# obj_type = request.args.get('obj_type') -# obj_id = request.args.get('obj_id') -# obj_subtype = request.args.get('obj_subtype') -# obj_lvl = request.args.get('obj_lvl') -# AILObjects.delete_user_object_to_export(user_id, object_type, object_id, obj_lvl, obj_subtype=obj_subtype) -# # redirect -# return 'ok' diff --git a/var/www/modules/PasteSubmit/Flask_PasteSubmit.py b/var/www/modules/PasteSubmit/Flask_PasteSubmit.py index 43a4216b..1dd0c470 100644 --- a/var/www/modules/PasteSubmit/Flask_PasteSubmit.py +++ b/var/www/modules/PasteSubmit/Flask_PasteSubmit.py @@ -1,16 +1,15 @@ #!/usr/bin/env python3 # -*-coding:UTF-8 -* -''' - Flask functions and routes for the trending modules page -''' +""" + Flask functions and routes for the Item Submit modules page +""" ################################## # Import External packages ################################## import re import os import sys -import json import string import datetime import unicodedata @@ -20,7 +19,7 @@ from io import BytesIO from functools import wraps # Flask -from flask import Flask, render_template, jsonify, request, Blueprint, url_for, redirect, abort +from flask import render_template, jsonify, request, Blueprint, url_for, redirect, abort from Role_Manager import login_admin, login_analyst from flask_login import login_required @@ -28,56 +27,39 @@ from flask_login import login_required ################################## # Import Project packages ################################## +from export import Export from lib import Tag from lib.objects.Items import Item from packages import Import_helper -from pytaxonomies import Taxonomies +from pytaxonomies import Taxonomies # TODO REMOVE ME -try: - from pymisp.mispevent import MISPObject - flag_misp = True -except: - flag_misp = False -try: - from thehive4py.models import Case, CaseTask, CustomFieldHelper, CaseObservable - flag_hive = True -except: - flag_hive = False # ============ VARIABLES ============ import Flask_config app = Flask_config.app baseUrl = Flask_config.baseUrl -r_serv_metadata = Flask_config.r_serv_metadata -r_serv_db = Flask_config.r_serv_db -r_serv_log_submit = Flask_config.r_serv_log_submit + + + +r_serv_metadata = Flask_config.r_serv_metadata # TODO REMOVE ME +r_serv_db = Flask_config.r_serv_db # TODO REMOVE ME +r_serv_log_submit = Flask_config.r_serv_log_submit # TODO REMOVE ME logger = Flask_config.redis_logger -pymisp = Flask_config.pymisp -if pymisp is False: - flag_misp = False - -HiveApi = Flask_config.HiveApi -if HiveApi is False: - flag_hive = False - -PasteSubmit = Blueprint('PasteSubmit', __name__, template_folder='templates') valid_filename_chars = "-_ %s%s" % (string.ascii_letters, string.digits) UPLOAD_FOLDER = Flask_config.UPLOAD_FOLDER -misp_event_url = Flask_config.misp_event_url -hive_case_url = Flask_config.hive_case_url - text_max_size = int(Flask_config.SUBMIT_PASTE_TEXT_MAX_SIZE) / (1000*1000) file_max_size = int(Flask_config.SUBMIT_PASTE_FILE_MAX_SIZE) / (1000*1000*1000) allowed_extensions = ", ". join(Flask_config.SUBMIT_PASTE_FILE_ALLOWED_EXTENSIONS) +PasteSubmit = Blueprint('PasteSubmit', __name__, template_folder='templates') # ============ Validators ============ def limit_content_length(): @@ -117,133 +99,6 @@ def clean_filename(filename, whitelist=valid_filename_chars, replace=' '): # keep only whitelisted chars return ''.join(c for c in cleaned_filename if c in whitelist) -def date_to_str(date): - return "{0}-{1}-{2}".format(date.year, date.month, date.day) - -def misp_create_event(distribution, threat_level_id, analysis, info, l_tags, publish, path): - - item = Item(path) - source = item.get_source() - ail_uuid = r_serv_db.get('ail:uuid') - pseudofile = BytesIO(item.get_content(binary=True)) - - temp = item.get_duplicates() - - # beautifier - if not temp: - temp = '' - - p_duplicate_number = len(temp) if len(temp) >= 0 else 0 - - to_ret = "" - for dup in temp[:10]: - dup = dup.replace('\'','\"').replace('(','[').replace(')',']') - dup = json.loads(dup) - algo = dup[0] - path = dup[1].split('/')[-6:] - path = '/'.join(path)[:-3] # -3 removes .gz - if algo == 'tlsh': - perc = 100 - int(dup[2]) - else: - perc = dup[2] - to_ret += "{}: {} [{}%]\n".format(path, algo, perc) - p_duplicate = to_ret - - today = datetime.date.today() - # [0-3] - if publish == 'True': - published = True - else: - published = False - org_id = None - orgc_id = None - sharing_group_id = None - date = today - event = pymisp.new_event(distribution, threat_level_id, - analysis, info, date, - published, orgc_id, org_id, sharing_group_id) - eventUuid = event['Event']['uuid'] - eventid = event['Event']['id'] - - r_serv_metadata.set('misp_events:'+path, eventid) - - # add tags - for tag in l_tags: - pymisp.tag(eventUuid, tag) - - # create attributes - obj_name = 'ail-leak' - leak_obj = MISPObject(obj_name) - leak_obj.add_attribute('sensor', value=ail_uuid, type="text") - leak_obj.add_attribute('origin', value=source, type='text') - leak_obj.add_attribute('last-seen', value=date_to_str(item.get_date()), type='datetime') - leak_obj.add_attribute('raw-data', value=source, data=pseudofile, type="attachment") - - if p_duplicate_number > 0: - leak_obj.add_attribute('duplicate', value=p_duplicate, type='text') - leak_obj.add_attribute('duplicate_number', value=p_duplicate_number, type='counter') - - try: - templateID = [x['ObjectTemplate']['id'] for x in pymisp.get_object_templates_list()['response'] if x['ObjectTemplate']['name'] == obj_name][0] - except IndexError: - valid_types = ", ".join([x['ObjectTemplate']['name'] for x in pymisp.get_object_templates_list()]) - print (f"Template for type {obj_name} not found! Valid types are: {valid_types}") - return False - r = pymisp.add_object(eventid, templateID, leak_obj) - if 'errors' in r: - print(r) - return False - else: - event_url = misp_event_url + eventid - return event_url - -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 item 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: - logger.info(f'ko sensor: {res.status_code}/{res.text}') - res = HiveApi.create_case_observable(id, observ_source) - if res.status_code != 201: - logger.info(f'ko source: {res.status_code}/{res.text}') - res = HiveApi.create_case_observable(id, observ_file) - if res.status_code != 201: - logger.info(f'ko file: {res.status_code}/{res.text}') - res = HiveApi.create_case_observable(id, observ_last_seen) - if res.status_code != 201: - logger.info(f'ko last_seen: {res.status_code}/{res.text}') - - r_serv_metadata.set('hive_cases:'+path, id) - - return hive_case_url.replace('id_here', id) - else: - logger.info(f'ko: {response.status_code}/{response.text}') - return False - # ============= ROUTES ============== @PasteSubmit.route("/PasteSubmit/", methods=['GET']) @@ -462,50 +317,31 @@ def submit_status(): else: return 'INVALID UUID' - -@PasteSubmit.route("/PasteSubmit/create_misp_event", methods=['POST']) -@login_required -@login_analyst -def create_misp_event(): - - distribution = int(request.form['misp_data[Event][distribution]']) - threat_level_id = int(request.form['misp_data[Event][threat_level_id]']) - analysis = int(request.form['misp_data[Event][analysis]']) - info = request.form['misp_data[Event][info]'] - path = request.form['paste'] - publish = request.form.get('misp_publish') - - #verify input - if (0 <= distribution <= 3) and (1 <= threat_level_id <= 4) and (0 <= analysis <= 2): - - l_tags = list(r_serv_metadata.smembers('tag:'+path)) - event = misp_create_event(distribution, threat_level_id, analysis, info, l_tags, publish, path) - - if event != False: - return redirect(event) - else: - return 'error, event creation' - return 'error0' - +# TODO MOVE ME IN import_export blueprint @PasteSubmit.route("/PasteSubmit/create_hive_case", methods=['POST']) @login_required @login_analyst def create_hive_case(): - hive_tlp = int(request.form['hive_tlp']) - threat_level = int(request.form['threat_level_hive']) - hive_description = request.form['hive_description'] - hive_case_title = request.form['hive_case_title'] - path = os.environ['AIL_HOME'] + "/PASTES/"+ request.form['paste'] + tlp = request.form['hive_tlp'] + if tlp: + tlp = int(tlp) + else: + tlp = 2 + threat_level = request.form['threat_level_hive'] + if threat_level: + threat_level = int(threat_level) + else: + threat_level = 2 + description = request.form['hive_description'] + title = request.form['hive_case_title'] + item_id = request.form['obj_id'] - #verify input - if (0 <= hive_tlp <= 3) and (1 <= threat_level <= 4): + if (0 <= tlp <= 3) and (1 <= threat_level <= 4): - l_tags = list(r_serv_metadata.smembers('tag:'+path)) - case = hive_create_case(hive_tlp, threat_level, hive_description, hive_case_title, l_tags, path) - - if case != False: - return redirect(case) + case_id = Export.create_thehive_case(item_id, title=title, tlp=tlp, threat_level=threat_level, description=description) + if case_id: + return redirect(get_case_url(case_id)) else: return 'error' diff --git a/var/www/modules/hashDecoded/Flask_hashDecoded.py b/var/www/modules/hashDecoded/Flask_hashDecoded.py index e2fba72e..42ed7e3e 100644 --- a/var/www/modules/hashDecoded/Flask_hashDecoded.py +++ b/var/www/modules/hashDecoded/Flask_hashDecoded.py @@ -131,7 +131,7 @@ def get_all_types_id(correlation_type): def get_key_id_metadata(obj_type, subtype, obj_id): obj = ail_objects.get_object_meta(obj_type, subtype, obj_id) - return obj._get_meta() + return obj def list_sparkline_type_id_values(date_range_sparkline, correlation_type, type_id, key_id): sparklines_value = [] diff --git a/var/www/modules/hashDecoded/templates/DaysCorrelation.html b/var/www/modules/hashDecoded/templates/DaysCorrelation.html index 8f8dd2e9..a2c84607 100644 --- a/var/www/modules/hashDecoded/templates/DaysCorrelation.html +++ b/var/www/modules/hashDecoded/templates/DaysCorrelation.html @@ -171,7 +171,7 @@ {% for key_id in all_metadata %}   {{ all_metadata[key_id]['type_id'] }} - {{ key_id }} + {{ key_id }} {{ all_metadata[key_id]['first_seen'] }} {{ all_metadata[key_id]['last_seen'] }} {{ all_metadata[key_id]['nb_seen'] }} diff --git a/var/www/modules/hashDecoded/templates/hashDecoded.html b/var/www/modules/hashDecoded/templates/hashDecoded.html index c7a25abe..117cf940 100644 --- a/var/www/modules/hashDecoded/templates/hashDecoded.html +++ b/var/www/modules/hashDecoded/templates/hashDecoded.html @@ -158,7 +158,7 @@ {% for b64 in l_64 %}   {{ b64[1] }} - {{ b64[2] }} + {{ b64[2] }} {{ b64[5] }} {{ b64[6] }} {{ b64[3] }} diff --git a/var/www/templates/import_export/block_add_user_object_to_export.html b/var/www/templates/import_export/block_add_user_object_to_export.html index e05d8580..d91ecc7a 100644 --- a/var/www/templates/import_export/block_add_user_object_to_export.html +++ b/var/www/templates/import_export/block_add_user_object_to_export.html @@ -1,4 +1,4 @@ - + Add to Export diff --git a/var/www/templates/import_export/block_add_user_object_to_export_small.html b/var/www/templates/import_export/block_add_user_object_to_export_small.html index b1c9cb74..f7202ea5 100644 --- a/var/www/templates/import_export/block_add_user_object_to_export_small.html +++ b/var/www/templates/import_export/block_add_user_object_to_export_small.html @@ -1,6 +1,6 @@
- +
diff --git a/var/www/templates/import_export/block_to_export_input.html b/var/www/templates/import_export/block_to_export_input.html index 4ae91129..cae7d4f5 100644 --- a/var/www/templates/import_export/block_to_export_input.html +++ b/var/www/templates/import_export/block_to_export_input.html @@ -1,38 +1,21 @@
- + - + - +
{%if obj_type=="Object type..."%}     Please select an object type. {%else%} -              Unknow or Invalid ID. +              Unknown or Invalid ID. {%endif%}
diff --git a/var/www/templates/import_export/export_object.html b/var/www/templates/import_export/export_object.html index b055cdb5..fe2d36a3 100644 --- a/var/www/templates/import_export/export_object.html +++ b/var/www/templates/import_export/export_object.html @@ -34,7 +34,7 @@
-
+
@@ -47,36 +47,30 @@
-
-
-
-
- - +
+
+
+
+ + + - -
- {% for obj_dict in l_obj_to_export %} - {% with obj_type=obj_dict['type'], obj_subtype=obj_dict.get('subtype', None), obj_id=obj_dict['id'], obj_lvl=obj_dict['lvl'], input_uuid=obj_dict, obj_error=False%} + +
+ + {% for obj_dict in to_export %} + {% with obj_type=obj_dict['type'], obj_subtype=obj_dict['subtype'], obj_id=obj_dict['id'], obj_lvl=obj_dict['lvl'], input_uuid=obj_dict, obj_error=False%} {% include 'import_export/block_to_export_input.html' %} {% endwith %} {% endfor %} @@ -84,7 +78,7 @@
{% for obj_dict in l_obj_invalid %} - {% with obj_type=obj_dict['type'], obj_subtype=obj_dict.get('subtype', None), obj_id=obj_dict['id'], obj_lvl=obj_dict['lvl'], input_uuid=obj_dict['uuid'], obj_error=True%} + {% with obj_type=obj_dict['type'], obj_subtype=obj_dict.get('subtype', None), obj_id=obj_dict['id'], obj_lvl=obj_dict['lvl'], input_uuid=obj_dict, obj_error=True%} {% include 'import_export/block_to_export_input.html' %} {% endwith %} {% endfor %} @@ -119,10 +113,10 @@
- {% if event_metadata %} + {% if misp_url %} MISP Event Created: - - {{ event_metadata['url'] }} + + {{ misp_url }} {% endif %} @@ -155,7 +149,17 @@ function toggle_sidebar(){ } var input_1 = '
' + + {% for object_type in object_types %} + '' + + {% endfor %} + '
'; var minusButton = ''; @@ -163,13 +167,15 @@ var minusButton = ' - {{misp_url}}/events/view/{{metadata['uuid'][:8]}}-{{metadata['uuid'][8:12]}}-{{metadata['uuid'][12:16]}}-{{metadata['uuid'][16:20]}}-{{metadata['uuid'][20:]}}
+ + {{ misp_url }}
{% endfor %} {% endif %} diff --git a/var/www/templates/modals/create_hive_case.html b/var/www/templates/modals/create_hive_case.html index be56389e..17e25c0c 100644 --- a/var/www/templates/modals/create_hive_case.html +++ b/var/www/templates/modals/create_hive_case.html @@ -1,120 +1,54 @@