mirror of https://github.com/CIRCL/AIL-framework
				
				
				
			DB migration
							parent
							
								
									2f8a5a333a
								
							
						
					
					
						commit
						9c1bfb7073
					
				|  | @ -6,6 +6,7 @@ | |||
| """ | ||||
| import os | ||||
| import sys | ||||
| import time | ||||
| 
 | ||||
| import importlib.util | ||||
| 
 | ||||
|  | @ -15,13 +16,23 @@ sys.path.append(os.environ['AIL_BIN']) | |||
| ################################## | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
| from lib import Users | ||||
| from lib.objects import Decodeds | ||||
| from lib.objects import Domains | ||||
| from lib.objects import Items | ||||
| from lib.objects.CryptoCurrencies import CryptoCurrency | ||||
| from lib.objects.Pgps import Pgp | ||||
| from lib.objects.Screenshots import Screenshot, get_all_screenshots | ||||
| from lib.objects.Usernames import Username | ||||
| 
 | ||||
| # # # # CONFIGS # # # # | ||||
| config_loader = ConfigLoader() | ||||
| r_kvrocks = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_kvrocks = config_loader.get_db_conn("Kvrocks_DB") | ||||
| 
 | ||||
| r_serv_db = config_loader.get_redis_conn("ARDB_DB") | ||||
| r_serv_tracker = config_loader.get_redis_conn("ARDB_Tracker") | ||||
| r_serv_tags = config_loader.get_redis_conn("ARDB_Tags") | ||||
| r_crawler = config_loader.get_redis_conn("ARDB_Onion") | ||||
| r_serv_metadata = config_loader.get_redis_conn("ARDB_Metadata") | ||||
| config_loader = None | ||||
| # # - - CONFIGS - - # # | ||||
| 
 | ||||
|  | @ -32,6 +43,13 @@ spec.loader.exec_module(old_ail_2_ail) | |||
| 
 | ||||
| old_ail_2_ail.r_serv_sync = r_serv_db | ||||
| 
 | ||||
| from packages import Tag | ||||
| spec = importlib.util.find_spec('Tag') | ||||
| old_Tag = importlib.util.module_from_spec(spec) | ||||
| spec.loader.exec_module(old_Tag) | ||||
| 
 | ||||
| old_Tag.r_serv_tags = r_serv_tags | ||||
| 
 | ||||
| from lib import Tracker | ||||
| spec = importlib.util.find_spec('Tracker') | ||||
| old_Tracker = importlib.util.module_from_spec(spec) | ||||
|  | @ -46,6 +64,12 @@ spec.loader.exec_module(old_Investigations) | |||
| 
 | ||||
| old_Investigations.r_tracking = r_serv_tracker | ||||
| 
 | ||||
| from lib import crawlers | ||||
| spec = importlib.util.find_spec('crawlers') | ||||
| old_crawlers = importlib.util.module_from_spec(spec) | ||||
| spec.loader.exec_module(old_crawlers) | ||||
| 
 | ||||
| old_crawlers.r_serv_onion = r_crawler | ||||
| 
 | ||||
| # # TODO: desable features - credentials - stats ? - sentiment analysis | ||||
| 
 | ||||
|  | @ -53,6 +77,13 @@ old_Investigations.r_tracking = r_serv_tracker | |||
| 
 | ||||
| # /!\ ISSUE WITH FILE DUPLICATES => NEED TO BE REFACTORED | ||||
| 
 | ||||
| 
 | ||||
| def get_item_date(item_id): | ||||
|     dirs = item_id.split('/') | ||||
|     return f'{dirs[-4]}{dirs[-3]}{dirs[-2]}' | ||||
| 
 | ||||
| ################################################################ | ||||
| 
 | ||||
| def core_migration(): | ||||
|     print('CORE MIGRATION...') | ||||
| 
 | ||||
|  | @ -81,6 +112,12 @@ def core_migration(): | |||
|     r_kvrocks.hset('d4:passivedns', 'enabled', bool(d4_enabled)) | ||||
|     r_kvrocks.hset('d4:passivedns', 'update_time', d4_update_time) | ||||
| 
 | ||||
|     # Crawler Manager | ||||
|     manager_url = old_crawlers.get_splash_manager_url() | ||||
|     manager_api_key = old_crawlers.get_splash_api_key() | ||||
|     crawlers.save_splash_manager_url_api(manager_url, manager_api_key) | ||||
|     crawlers.reload_splash_and_proxies_list() | ||||
| 
 | ||||
|     # ail:misp | ||||
|     # ail:thehive | ||||
|     # hive:auto-alerts | ||||
|  | @ -91,9 +128,6 @@ def core_migration(): | |||
| 
 | ||||
| 
 | ||||
|     # # TODO: TO CHECK | ||||
|     # config:all_global_section + | ||||
|     # config:global:crawler + | ||||
|     # mess_not_saved_export | ||||
| 
 | ||||
| 
 | ||||
| # # # # # # # # # # # # # # # # | ||||
|  | @ -215,26 +249,361 @@ def item_submit_migration(): | |||
|     pass | ||||
| 
 | ||||
| # /!\ KEY COLISION | ||||
| # # TODO: change db | ||||
| # # TODO: change db -> olds modules + blueprints | ||||
| # # TODO: HANDLE LOCAL TAGS | ||||
| # # TODO: HANDLE LOCAL TAGS | ||||
| # # TODO: HANDLE LOCAL TAGS | ||||
| # # TODO: HANDLE LOCAL TAGS | ||||
| # # TODO: HANDLE LOCAL TAGS | ||||
| def tags_migration(): | ||||
|      | ||||
| 
 | ||||
|     # HANDLE LOCAL TAGS | ||||
| 
 | ||||
|     print(old_Tag.get_all_tags()) | ||||
| 
 | ||||
| 
 | ||||
|     # | ||||
|     #   /!\ OBJECTS TAGS ISSUE /!\ | ||||
|     #          -> only one layer | ||||
|     # | ||||
|     #   issue with subtypes + between objects with same ID | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| # # TODO: MIGRATE item_basic.add_map_obj_id_item_id ?????????????????????? | ||||
| ############################### | ||||
| #                             # | ||||
| #       ITEMS MIGRATION       # | ||||
| #                             # | ||||
| ############################### | ||||
| 
 | ||||
| def get_item_father(item_id): | ||||
|     return r_serv_metadata.hget(f'paste_metadata:{item_id}', 'father') | ||||
| 
 | ||||
| def items_migration(): | ||||
|     pass | ||||
|     print('ITEMS MIGRATION...') | ||||
|     # MIGRATE IMPORTED URLEXTRACT Father | ||||
|     for item_id in Items.get_items_by_source('urlextract'): | ||||
|         father_id = get_item_father(item_id) | ||||
|         if father_id: | ||||
|             item = Items.Item(item_id) | ||||
|             item.set_father(father_id) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # TODO: migrate cookies | ||||
| # TODO: migrate auto crawlers | ||||
| 
 | ||||
| ############################### | ||||
| #                             # | ||||
| #     CRAWLERS MIGRATION      # | ||||
| #                             # | ||||
| ############################### | ||||
| 
 | ||||
| # Retun last crawled domains by type | ||||
| #   domain;epoch | ||||
| def get_last_crawled_domains(domain_type): | ||||
|     return r_crawler.lrange(f'last_{domain_type}', 0 ,-1) | ||||
| 
 | ||||
| def crawler_migration(): | ||||
|     print('CRAWLER MIGRATION...') | ||||
| 
 | ||||
|     pass | ||||
|     # for domain_type in ['onion', 'regular']: | ||||
|     #     for row in get_last_crawled_domains(domain_type): | ||||
|     #         dom_row, epoch = row.rsplit(';', 1) | ||||
|     #         domain, port = dom_row.rsplit(':', 1) | ||||
|     #         print(domain, port, epoch) | ||||
|     #         #crawlers.add_last_crawled_domain(domain_type, domain, port, epoch) | ||||
| 
 | ||||
|     for cookiejar_uuid in old_crawlers.get_all_cookiejar(): | ||||
|         meta = old_crawlers.get_cookiejar_metadata(cookiejar_uuid, level=True) | ||||
|         #print(meta) | ||||
|         #crawlers.create_cookiejar(meta['user_id'], level=meta['level'], description=meta['description'], cookiejar_uuid=cookiejar_uuid) | ||||
|         #_set_cookiejar_date(meta['date']) | ||||
| 
 | ||||
|         for meta_cookie, cookie_uuid in old_crawlers.get_cookiejar_cookies_list(cookiejar_uuid, add_cookie_uuid=True): | ||||
|             print(cookie_uuid) | ||||
|             #crawlers.add_cookie_to_cookiejar(cookiejar_uuid, meta_cookie, cookie_uuid=cookie_uuid) | ||||
| 
 | ||||
|     # TODO: auto crawler -> to Fix / change | ||||
| 
 | ||||
| 
 | ||||
|     # TODO: crawlers queues | ||||
| 
 | ||||
| ############################### | ||||
| #                             # | ||||
| #      DOMAINS MIGRATION      # | ||||
| #                             # | ||||
| ############################### | ||||
| 
 | ||||
| # # TODO: DOMAIN DOWN -> start onion_down:20190101 | ||||
| 
 | ||||
| # Start -> 2019-01-01 | ||||
| 
 | ||||
| # BY TYPE - FIRST DATE DOWN / UP | ||||
| 
 | ||||
| def get_item_link(item_id): | ||||
|     return r_serv_metadata.hget(f'paste_metadata:{item_id}', 'real_link') | ||||
| 
 | ||||
| def get_item_father(item_id): | ||||
|     return r_serv_metadata.hget(f'paste_metadata:{item_id}', 'father') | ||||
| 
 | ||||
| def get_item_children(item_id): | ||||
|     return r_serv_metadata.smembers(f'paste_children:{item_id}') | ||||
| 
 | ||||
| def get_domains_up_by_type(domain_type): | ||||
|     return r_crawler.smembers(f'full_{domain_type}_up') | ||||
| 
 | ||||
| def get_domain_first_seen(domain_type, domain): | ||||
|     return r_crawler.hget(f'{domain_type}_metadata:{domain}', 'first_seen') | ||||
| 
 | ||||
| def get_domain_last_check(domain_type, domain): | ||||
|     return r_crawler.hget(f'{domain_type}_metadata:{domain}', 'last_check') | ||||
| 
 | ||||
| def get_domain_last_origin(domain_type, domain): | ||||
|     return r_crawler.hget(f'{domain_type}_metadata:{domain}', 'paste_parent') | ||||
| 
 | ||||
| def get_domain_ports(domain_type, domain): | ||||
|     l_ports = r_crawler.hget(f'{domain_type}_metadata:{domain}', 'ports') | ||||
|     if l_ports: | ||||
|         return l_ports.split(";") | ||||
|     return [] | ||||
| 
 | ||||
| def get_domain_languages(dom): | ||||
|     return r_crawler.smembers(f'domain:language:{dom}') | ||||
| 
 | ||||
| def is_crawled_item(domain, item_id): | ||||
|     domain_lenght = len(domain) | ||||
|     if len(item_id) > (domain_lenght+48): | ||||
|         if item_id[-36-domain_lenght:-36] == domain: | ||||
|             return True | ||||
|     return False | ||||
| 
 | ||||
| def get_crawled_items(domain, root_id): | ||||
|     crawled_items = get_crawled_items_children(domain, root_id) | ||||
|     crawled_items.append(root_id) | ||||
|     return crawled_items | ||||
| 
 | ||||
| def get_crawled_items_children(domain, root_id): | ||||
|     crawled_items = [] | ||||
|     for item_id in get_item_children(root_id): | ||||
|         if is_crawled_item(domain, item_id): | ||||
|             crawled_items.append(item_id) | ||||
|             crawled_items.extend(get_crawled_items_children(domain, item_id)) | ||||
|     return crawled_items | ||||
| 
 | ||||
| def get_domain_history_by_port(domain_type, domain, port): | ||||
|     history_tuple = r_crawler.zrange(f'crawler_history_{domain_type}:{domain}:{port}', 0, -1, withscores=True) | ||||
|     history = [] | ||||
|     for root_id, epoch in history_tuple: | ||||
|         dict_history = {} | ||||
|         epoch = int(epoch) # force int | ||||
|         dict_history["epoch"] = epoch | ||||
|         try: | ||||
|             int(root_id) | ||||
|             dict_history['status'] = False | ||||
|         except ValueError: | ||||
|             dict_history['status'] = True | ||||
|             dict_history['root'] = root_id | ||||
|         history.append(dict_history) | ||||
|     return history | ||||
| 
 | ||||
| def domain_migration(): | ||||
|     pass | ||||
|     print('Domains MIGRATION...') | ||||
| 
 | ||||
| # # TODO: refractor keys | ||||
| def correlations_migration(): | ||||
|     pass | ||||
|     for domain_type in ['onion', 'regular']: | ||||
|         for dom in get_domains_up_by_type(domain_type): | ||||
| 
 | ||||
|             ports = get_domain_ports(domain_type, dom) | ||||
|             first_seen = get_domain_first_seen(domain_type, dom) | ||||
|             last_check = get_domain_last_check(domain_type, dom) | ||||
|             last_origin = get_domain_last_origin(domain_type, dom) | ||||
|             languages = get_domain_languages(dom) | ||||
| 
 | ||||
|             domain = Domains.Domain(dom) | ||||
|             # domain.update_daterange(first_seen) | ||||
|             # domain.update_daterange(last_check) | ||||
|             # domain._set_ports(ports) | ||||
|             # if last_origin: | ||||
|             #     domain.set_last_origin(last_origin) | ||||
|             for language in languages: | ||||
|                 print(language) | ||||
|             #     domain.add_language(language) | ||||
|             #print('------------------') | ||||
|             #print('------------------') | ||||
|             #print('------------------') | ||||
|             #print('------------------') | ||||
|             #print('------------------') | ||||
|             print(dom) | ||||
|             #print(first_seen) | ||||
|             #print(last_check) | ||||
|             #print(ports) | ||||
| 
 | ||||
|             # # TODO: FIXME filter invalid hostname | ||||
| 
 | ||||
| 
 | ||||
|              # CREATE DOMAIN HISTORY | ||||
|             for port in ports: | ||||
|                 for history in get_domain_history_by_port(domain_type, dom, port): | ||||
|                     epoch = history['epoch'] | ||||
|                     # DOMAIN DOWN | ||||
|                     if not history.get('status'): # domain DOWN | ||||
|                         # domain.add_history(epoch, port) | ||||
|                         print(f'DOWN {epoch}') | ||||
|                     # DOMAIN UP | ||||
|                     else: | ||||
|                         root_id = history.get('root') | ||||
|                         if root_id: | ||||
|                             # domain.add_history(epoch, port, root_item=root_id) | ||||
|                             #print(f'UP {root_id}') | ||||
|                             crawled_items = get_crawled_items(dom, root_id) | ||||
|                             for item_id in crawled_items: | ||||
|                                 url = get_item_link(item_id) | ||||
|                                 item_father = get_item_father(item_id) | ||||
|                                 if item_father and url: | ||||
|                                     #print(f'{url}    {item_id}') | ||||
|                                     pass | ||||
|                                     # domain.add_crawled_item(url, port, item_id, item_father) | ||||
| 
 | ||||
| 
 | ||||
|                     #print() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ############################### | ||||
| #                             # | ||||
| #      DECODEDS MIGRATION     # | ||||
| #                             # | ||||
| ############################### | ||||
| def get_estimated_type(decoded_id): | ||||
|     return r_serv_metadata.hget(f'metadata_hash:{decoded_id}', 'estimated_type') | ||||
| 
 | ||||
| def get_decoded_items_list_by_decoder(decoder_type, decoded_id): ################### | ||||
|     #return r_serv_metadata.zrange('nb_seen_hash:{}'.format(sha1_string), 0, -1) | ||||
|     return r_serv_metadata.zrange(f'{decoder_type}_hash:{decoded_id}', 0, -1) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| def decodeds_migration(): | ||||
|     print('Decoded MIGRATION...') | ||||
|     decoder_names = ['base64', 'binary', 'hexadecimal'] | ||||
| 
 | ||||
|     Decodeds._delete_old_json_descriptor() | ||||
|     for decoded_id in Decodeds.get_all_decodeds(): | ||||
|         mimetype = get_estimated_type(decoded_id) | ||||
|         # ignore invalid object | ||||
|         if mimetype is None: | ||||
|             continue | ||||
|         print() | ||||
|         print(decoded_id) | ||||
| 
 | ||||
|         decoded = Decodeds.Decoded(decoded_id) | ||||
|         filepath = decoded.get_filepath(mimetype=mimetype) | ||||
|         decoded._save_meta(filepath, mimetype) | ||||
| 
 | ||||
|         for decoder_type in decoder_names: | ||||
|             for item_id in get_decoded_items_list_by_decoder(decoder_type, decoded_id): | ||||
|                 print(item_id, decoder_type) | ||||
|                 date = get_item_date(item_id) | ||||
|             #for decoder_type in : | ||||
| 
 | ||||
|                 decoded.add(decoder_type, date, item_id, mimetype) | ||||
| 
 | ||||
| ############################### | ||||
| #                             # | ||||
| #    SCREENSHOTS MIGRATION    # | ||||
| #                             # | ||||
| ############################### | ||||
| 
 | ||||
| # old correlation | ||||
| def get_screenshot_items_list(screenshot_id): ######################### # TODO: DELETE SOLO SCREENSHOTS | ||||
|     print(f'screenshot:{screenshot_id}') | ||||
|     return r_crawler.smembers(f'screenshot:{screenshot_id}') | ||||
| # old correlation | ||||
| def get_screenshot_domain(screenshot_id): | ||||
|     return r_crawler.smembers(f'screenshot_domain:{screenshot_id}') | ||||
| 
 | ||||
| # Tags + Correlations | ||||
| # # TODO: save orphelin screenshot ????? | ||||
| def screenshots_migration(): | ||||
|     print('SCREENSHOTS MIGRATION...') | ||||
|     screenshots = get_all_screenshots() | ||||
|     #screenshots = ['5fcc292ea8a699aa7a9ce93a704b78b8f493620ccdb2a5cebacb1069a4327211'] | ||||
|     for screenshot_id in screenshots: | ||||
|         print(screenshot_id) | ||||
| 
 | ||||
|         screenshot = Screenshot(screenshot_id) | ||||
| 
 | ||||
|         tags = old_Tag.get_obj_tag(screenshot_id) ################## # TODO: | ||||
|         if tags: | ||||
|             print(screenshot_id) | ||||
|             print(tags) | ||||
| 
 | ||||
|         # Correlations | ||||
|         for item_id in get_screenshot_items_list(screenshot_id): | ||||
|             print(item_id) | ||||
|             screenshot.add_correlation('item', '', item_id) | ||||
|         for domain_id in get_screenshot_domain(screenshot_id): | ||||
|             print(domain_id) | ||||
|             screenshot.add_correlation('domain', '', domain_id) | ||||
| 
 | ||||
| ############################### | ||||
| #                             # | ||||
| #      SUBTYPES MIGRATION     # | ||||
| #                             # | ||||
| ############################### | ||||
| 
 | ||||
| def get_item_correlation_obj(obj_type, subtype, obj_id): | ||||
|     return r_serv_metadata.smembers(f'set_{obj_type}_{subtype}:{obj_id}') | ||||
| 
 | ||||
| def get_obj_subtype_first_seen(obj_type, subtype, obj_id): | ||||
|     return r_serv_metadata.hget(f'{obj_type}_metadata_{subtype}:{obj_id}', 'first_seen') | ||||
| 
 | ||||
| def get_obj_subtype_last_seen(obj_type, subtype, obj_id): | ||||
|     return r_serv_metadata.hget(f'{obj_type}_metadata_{subtype}:{obj_id}', 'last_seen') | ||||
| 
 | ||||
| def get_all_subtype_id(obj_type, subtype): | ||||
|     print(f'{obj_type}_all:{subtype}') | ||||
|     print(r_serv_metadata.zrange(f'{obj_type}_all:{subtype}', 0, -1)) | ||||
|     return r_serv_metadata.zrange(f'{obj_type}_all:{subtype}', 0, -1) | ||||
| 
 | ||||
| def get_subtype_object(obj_type, subtype, obj_id): | ||||
|     if obj_type == 'cryptocurrency': | ||||
|         return CryptoCurrency(obj_id, subtype) | ||||
|     elif obj_type == 'pgpdump': | ||||
|         return Pgp(obj_id, subtype) | ||||
|     elif obj_type == 'username': | ||||
|         return Username(obj_id, subtype) | ||||
| 
 | ||||
| def migrate_subtype_obj(Obj, obj_type, subtype, obj_id): | ||||
|     first_seen = get_obj_subtype_first_seen(obj_type, subtype, obj_id) | ||||
|     last_seen = get_obj_subtype_last_seen(obj_type, subtype, obj_id) | ||||
| 
 | ||||
|     # dates | ||||
|     for item_id in get_item_correlation_obj(obj_type, subtype, obj_id): | ||||
|         date = get_item_date(item_id) | ||||
|         Obj.add(date, item_id) | ||||
| 
 | ||||
| dict_obj_subtypes = {'cryptocurrency': ['bitcoin', 'bitcoin-cash', 'dash', 'ethereum', 'litecoin', 'monero', 'zcash'], | ||||
|                     'pgpdump': ['key', 'mail', 'name'], | ||||
|                     'username': ['telegram', 'twitter', 'jabber']} | ||||
| 
 | ||||
| def subtypes_obj_migration(): | ||||
|     print('SUBPTYPE MIGRATION...') | ||||
| 
 | ||||
|     for obj_type in dict_obj_subtypes: | ||||
|         print(f'{obj_type} MIGRATION...') | ||||
|         for subtype in dict_obj_subtypes[obj_type]: | ||||
|             for obj_id in get_all_subtype_id(obj_type, subtype): | ||||
|                 Obj = get_subtype_object(obj_type, subtype, obj_id) | ||||
|                 migrate_subtype_obj(Obj, obj_type, subtype, obj_id) | ||||
| 
 | ||||
| # # # # # # # # # # # # # # # # | ||||
| #       STATISTICS | ||||
|  | @ -246,10 +615,16 @@ def statistics_migration(): | |||
| 
 | ||||
| if __name__ == '__main__': | ||||
| 
 | ||||
|     core_migration() | ||||
|     user_migration() | ||||
|     #core_migration() | ||||
|     #user_migration() | ||||
|     #items_migration() | ||||
|     #crawler_migration() | ||||
|     #domain_migration() | ||||
|     #decodeds_migration() | ||||
|     #screenshots_migration() | ||||
|     #subtypes_obj_migration() | ||||
|     #ail_2_ail_migration() | ||||
|     trackers_migration() | ||||
|     #trackers_migration() | ||||
|     #investigations_migration() | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -295,7 +295,7 @@ function shutting_down_redis_servers { | |||
|     redis_dir=${AIL_HOME}/redis/src | ||||
|     for port in "${array[@]}"; | ||||
|         do | ||||
|             bash -c "${redis_dir}/redis-cli -p ${port} SHUTDOWN" | ||||
|             bash -c "${redis_dir}/redis-cli -p ${port} -a ail SHUTDOWN" | ||||
|             sleep 0.1 | ||||
|         done | ||||
| } | ||||
|  | @ -324,7 +324,7 @@ function checking_redis_servers { | |||
|     for port in "${array[@]}"; | ||||
|         do | ||||
|             sleep 0.2 | ||||
|             bash -c "${redis_dir}/redis-cli -p ${port} PING | grep "PONG" &> /dev/null" | ||||
|             bash -c "${redis_dir}/redis-cli -p ${port} -a ail PING | grep "PONG" &> /dev/null" | ||||
|             if [ ! $? == 0 ]; then | ||||
|                 echo -e "${RED}\t${port} ${db_name} not ready${DEFAULT}" | ||||
|                 flag_db=1 | ||||
|  | @ -512,6 +512,20 @@ function killall { | |||
|     fi | ||||
| } | ||||
| 
 | ||||
| function _set_kvrocks_namespace() { | ||||
|   bash -c "${redis_dir}/redis-cli -p ${port} -a ail namespace add $1 $2" | ||||
| } | ||||
| 
 | ||||
| function set_kvrocks_namespaces() { | ||||
|   if checking_kvrocks; then | ||||
|     _set_kvrocks_namespace "cor"  "ail_correls" | ||||
|     _set_kvrocks_namespace "obj"  "ail_objs" | ||||
|     _set_kvrocks_namespace "tag"  "ail_tags" | ||||
|   else | ||||
|     echo -e $RED"\t* Error: Please launch Kvrocks server"$DEFAULT | ||||
|   fi | ||||
| } | ||||
| 
 | ||||
| function update() { | ||||
|     bin_dir=${AIL_HOME}/bin | ||||
| 
 | ||||
|  | @ -672,6 +686,8 @@ while [ "$1" != "" ]; do | |||
|         -lkv | --launchKVORCKSVerify )  launch_kvrocks; | ||||
|                                         wait_until_kvrocks_is_ready; | ||||
|                                         ;; | ||||
|         --set_kvrocks_namespaces )      set_kvrocks_namespaces; | ||||
|                                         ;; | ||||
|         -k | --killAll )                killall; | ||||
|                                         ;; | ||||
|         -ks | --killscript )            killscript; | ||||
|  |  | |||
|  | @ -26,8 +26,8 @@ import Tag | |||
| 
 | ||||
| config_loader = ConfigLoader.ConfigLoader() | ||||
| r_cache = config_loader.get_redis_conn("Redis_Cache") | ||||
| r_serv_db = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_sync = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_db = config_loader.get_db_conn("Kvrocks_DB") | ||||
| r_serv_sync = config_loader.get_db_conn("Kvrocks_DB") | ||||
| config_loader = None | ||||
| 
 | ||||
| WEBSOCKETS_CLOSE_CODES = { | ||||
|  |  | |||
|  | @ -8,14 +8,15 @@ Receiver Jabber Json Items | |||
| 
 | ||||
| """ | ||||
| import os | ||||
| import json | ||||
| import sys | ||||
| import time | ||||
| import datetime | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) | ||||
| import item_basic | ||||
| import Username | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| ################################## | ||||
| # Import Project packages | ||||
| ################################## | ||||
| from lib import item_basic | ||||
| from lib.objects.Usernames import Username | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'import', 'ail_json_importer')) | ||||
| from Default_json import Default_json | ||||
|  | @ -45,6 +46,9 @@ class Ail_feeder_jabber(Default_json): | |||
|         to = str(self.json_item['meta']['jabber:to']) | ||||
|         fr = str(self.json_item['meta']['jabber:from']) | ||||
|         item_date = item_basic.get_item_date(item_id) | ||||
|         Username.save_item_correlation('jabber', to, item_id, item_date) | ||||
|         Username.save_item_correlation('jabber', fr, item_id, item_date) | ||||
|         return None | ||||
| 
 | ||||
|         user_to = Username(to, 'jabber') | ||||
|         user_fr = Username(fr, 'jabber') | ||||
|         user_to.add(date, item_id) | ||||
|         user_fr.add(date, item_id) | ||||
|         return None | ||||
|  |  | |||
|  | @ -8,13 +8,15 @@ Recieve Json Items (example: Twitter feeder) | |||
| 
 | ||||
| """ | ||||
| import os | ||||
| import json | ||||
| import sys | ||||
| import datetime | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) | ||||
| import item_basic | ||||
| import Username | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| ################################## | ||||
| # Import Project packages | ||||
| ################################## | ||||
| from lib import item_basic | ||||
| from lib.objects.Usernames import Username | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'import', 'ail_json_importer')) | ||||
| from Default_json import Default_json | ||||
|  | @ -46,14 +48,14 @@ class Ail_feeder_telegram(Default_json): | |||
|         telegram_id = f'{channel_id}_{message_id}' | ||||
|         item_basic.add_map_obj_id_item_id(telegram_id, item_id, 'telegram_id') | ||||
|         #print(self.json_item['meta']) | ||||
|         username = None | ||||
|         user = None | ||||
|         if self.json_item['meta'].get('user'): | ||||
|             username = str(self.json_item['meta']['user']) | ||||
|             user = str(self.json_item['meta']['user']) | ||||
|         else: | ||||
|             if self.json_item['meta'].get('channel'): | ||||
|                 username = str(self.json_item['meta']['channel']['username']) | ||||
|         if username: | ||||
|             #print(username) | ||||
|                 user = str(self.json_item['meta']['channel']['username']) | ||||
|         if user: | ||||
|             item_date = item_basic.get_item_date(item_id) | ||||
|             Username.save_item_correlation('telegram', username, item_id, item_date) | ||||
|             username = Username(user, 'telegram') | ||||
|             username.add(date, item_id) | ||||
|         return None | ||||
|  |  | |||
|  | @ -8,13 +8,15 @@ Recieve Json Items (example: Twitter feeder) | |||
| 
 | ||||
| """ | ||||
| import os | ||||
| import json | ||||
| import sys | ||||
| import datetime | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) | ||||
| import item_basic | ||||
| import Username | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| ################################## | ||||
| # Import Project packages | ||||
| ################################## | ||||
| from lib import item_basic | ||||
| from lib.objects.Usernames import Username | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'import', 'ail_json_importer')) | ||||
| from Default_json import Default_json | ||||
|  | @ -39,9 +41,12 @@ class Ail_feeder_twitter(Default_json): | |||
|         ''' | ||||
|         Process JSON meta filed. | ||||
|         ''' | ||||
|         twitter_id = str(self.json_item['meta']['twitter:tweet_id']) | ||||
|         item_basic.add_map_obj_id_item_id(twitter_id, item_id, 'twitter_id') | ||||
|         username = str(self.json_item['meta']['twitter:id']) | ||||
|         item_date = item_basic.get_item_date(item_id) | ||||
|         Username.save_item_correlation('twitter', username, item_id, item_date) | ||||
|         tweet_id = str(self.json_item['meta']['twitter:tweet_id']) | ||||
|         item_basic.add_map_obj_id_item_id(tweet_id, item_id, 'twitter_id') | ||||
| 
 | ||||
|         date = item_basic.get_item_date(item_id) | ||||
|         user = str(self.json_item['meta']['twitter:id']) | ||||
|         username = Username(user, 'twitter') | ||||
|         username.add(date, item_id) | ||||
| 
 | ||||
|         return None | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ Recieve Json Items (example: Twitter feeder) | |||
| 
 | ||||
| """ | ||||
| import os | ||||
| import json | ||||
| import sys | ||||
| import datetime | ||||
| import uuid | ||||
|  |  | |||
|  | @ -41,6 +41,12 @@ class ConfigLoader(object): | |||
|                                   db=self.cfg.getint(redis_name, "db"), | ||||
|                                   decode_responses=decode_responses ) | ||||
| 
 | ||||
|     def get_db_conn(self, db_name, decode_responses=True): ## TODO: verify redis name | ||||
|         return redis.StrictRedis( host=self.cfg.get(db_name, "host"), | ||||
|                                   port=self.cfg.getint(db_name, "port"), | ||||
|                                   password=self.cfg.get(db_name, "password"), | ||||
|                                   decode_responses=decode_responses ) | ||||
| 
 | ||||
|     def get_files_directory(self, key_name): | ||||
|         directory_path = self.cfg.get('Directories', key_name) | ||||
|         # full path | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ sys.path.append(os.environ['AIL_BIN']) | |||
| from lib.ConfigLoader import ConfigLoader | ||||
| 
 | ||||
| config_loader = ConfigLoader() | ||||
| r_serv_db = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_db = config_loader.get_db_conn("Kvrocks_DB") | ||||
| MIN_ITEM_SIZE = float(config_loader.get_config_str('Modules_Duplicates', 'min_paste_size')) # # TODO: RENAME ME | ||||
| config_loader = None | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/')) | |||
| import Tag | ||||
| 
 | ||||
| config_loader = ConfigLoader.ConfigLoader() | ||||
| r_tracking = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_tracking = config_loader.get_db_conn("Kvrocks_DB") | ||||
| config_loader = None | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -146,7 +146,7 @@ def save_domain_relationship(obj_id, domain): | |||
| 
 | ||||
| def delete_domain_relationship(obj_id, domain): | ||||
|     r_serv_onion.srem('domain_screenshot:{}'.format(domain), obj_id) | ||||
|     r_serv_onion.sadd('screenshot_domain:{}'.format(obj_id), domain) | ||||
|     r_serv_onion.srem('screenshot_domain:{}'.format(obj_id), domain) | ||||
| 
 | ||||
| def save_obj_relationship(obj_id, obj2_type, obj2_id): | ||||
|     if obj2_type == 'domain': | ||||
|  |  | |||
|  | @ -25,8 +25,8 @@ import item_basic | |||
| config_loader = ConfigLoader.ConfigLoader() | ||||
| r_cache = config_loader.get_redis_conn("Redis_Cache") | ||||
| 
 | ||||
| r_serv_db = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_tracker = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_db = config_loader.get_db_conn("Kvrocks_DB") | ||||
| r_serv_tracker = config_loader.get_db_conn("Kvrocks_DB") | ||||
| 
 | ||||
| items_dir = config_loader.get_config_str("Directories", "pastes") | ||||
| if items_dir[-1] == '/': | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ from lib.ConfigLoader import ConfigLoader | |||
| # Config | ||||
| config_loader = ConfigLoader() | ||||
| #r_serv_db = config_loader.get_redis_conn("ARDB_DB") | ||||
| r_serv_db = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_db = config_loader.get_db_conn("Kvrocks_DB") | ||||
| config_loader = None | ||||
| 
 | ||||
| regex_password = r'^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z]).{10,100}$' | ||||
|  |  | |||
|  | @ -0,0 +1,723 @@ | |||
| #!/usr/bin/env python3 | ||||
| # -*-coding:UTF-8 -* | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| import redis | ||||
| 
 | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| ################################## | ||||
| # Import Project packages | ||||
| ################################## | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
| 
 | ||||
| config_loader = ConfigLoader() | ||||
| r_metadata = config_loader.get_db_conn("Kvrocks_Correlations") | ||||
| config_loader = None | ||||
| 
 | ||||
| ################################## | ||||
| # CORRELATION MIGRATION | ||||
| ################################## | ||||
| # | ||||
| #   MIGRATE TO KVROCKS + Rename correlation Keys | ||||
| #                           => Add support for correlations between subtypes | ||||
| #                           => Common correlation engine for each objects | ||||
| # | ||||
| #   Objects Iterations: -screenshot | ||||
| #                       -decoded | ||||
| #                       -subtypes | ||||
| #                       -domains | ||||
| # | ||||
| #   /!\ Handle reinsertion /!\ | ||||
| # | ||||
| # | ||||
| #   CORRELATION DB ????? => purge if needed | ||||
| # | ||||
| # | ||||
| # | ||||
| # | ||||
| # | ||||
| ################################## | ||||
| # CORRELATION MIGRATION | ||||
| ################################## | ||||
| 
 | ||||
| CORRELATION_TYPES_BY_OBJ = { | ||||
|     "cryptocurrency" : ["domain", "item"], | ||||
|     "decoded" : ["domain", "item"], | ||||
|     "domain": ["cryptocurrency", "decoded", "item", "pgp", "username", "screenshot"], | ||||
|     "item": ["cryptocurrency", "decoded", "domain", "pgp", "username", "screenshot"], | ||||
|     "pgp" : ["domain", "item"], | ||||
|     "username" : ["domain", "item"], | ||||
|     "screenshot" : ["domain", "item"], | ||||
| } | ||||
| 
 | ||||
| def get_obj_correl_types(obj_type): | ||||
|     return CORRELATION_TYPES_BY_OBJ.get(obj_type) | ||||
| 
 | ||||
| def sanityze_obj_correl_types(obj_type, correl_types): | ||||
|     obj_correl_types = get_obj_correl_types(obj_type) | ||||
|     if correl_types: | ||||
|         correl_types = set(correl_types).intersection(obj_correl_types) | ||||
|     if not correl_types: | ||||
|         correl_types = obj_correl_types | ||||
|     return correl_types | ||||
| 
 | ||||
| def get_nb_correlation_by_correl_type(obj_type, subtype, obj_id, correl_type): | ||||
|     return r_metadata.scard(f'correlation:obj:{obj_type}:{subtype}:{correl_type}:{obj_id}') | ||||
| 
 | ||||
| def get_nb_correlations(obj_type, subtype, obj_id, filter_types=[]): | ||||
|     if subtype is None: | ||||
|         subtype = '' | ||||
|     nb_correlations = 0 | ||||
|     filter_types = sanityze_obj_correl_types(obj_type, filter_types) | ||||
|     for correl_type in filter_types: | ||||
|         obj_correlations += get_nb_correlation_by_correl_type(obj_type, subtype, obj_id, correl_type) | ||||
|     return obj_correlations | ||||
| 
 | ||||
| def get_correlation_by_correl_type(obj_type, subtype, obj_id, correl_type): | ||||
|     return r_metadata.smembers(f'correlation:obj:{obj_type}:{subtype}:{correl_type}:{obj_id}') | ||||
| 
 | ||||
| def get_correlations(obj_type, subtype, obj_id, filter_types=[]): | ||||
|     if subtype is None: | ||||
|         subtype = '' | ||||
|     obj_correlations = {} | ||||
|     filter_types = sanityze_obj_correl_types(obj_type, filter_types) | ||||
|     for correl_type in filter_types: | ||||
|         obj_correlations[correl_type] = get_correlation_by_correl_type(obj_type, subtype, obj_id, correl_type) | ||||
|     return obj_correlations | ||||
| 
 | ||||
| def exists_obj_correlation(obj_type, subtype, obj_id, obj2_type): | ||||
|     if subtype is None: | ||||
|         subtype = '' | ||||
|     return r_metadata.exists(f'correlation:obj:{obj_type}:{subtype}:{obj2_type}:{obj_id}') | ||||
| 
 | ||||
| def is_obj_correlated(obj_type, subtype, obj_id, obj2_type, subtype2, obj2_id): | ||||
|     if subtype is None: | ||||
|         subtype = '' | ||||
|     if subtype2 is None: | ||||
|         subtype2 = '' | ||||
|     return r_metadata.sismember(f'correlation:obj:{obj_type}:{subtype}:{obj2_type}:{obj_id}', '{subtype2}:{obj2_id}') | ||||
| 
 | ||||
| def add_obj_correlation(obj1_type, subtype1, obj1_id, obj2_type, subtype2, obj2_id): | ||||
|     print(obj1_type, subtype1, obj1_id, obj2_type, subtype2, obj2_id) | ||||
|     if subtype1 is None: | ||||
|         subtype1 = '' | ||||
|     if subtype2 is None: | ||||
|         subtype2 = '' | ||||
|     r_metadata.sadd(f'correlation:obj:{obj1_type}:{subtype1}:{obj2_type}:{obj1_id}', f'{subtype2}:{obj2_id}') | ||||
|     r_metadata.sadd(f'correlation:obj:{obj2_type}:{subtype2}:{obj1_type}:{obj2_id}', f'{subtype1}:{obj1_id}') | ||||
| 
 | ||||
| 
 | ||||
| def delete_obj_correlation(obj1_type, subtype1, obj1_id, obj2_type, subtype2, obj2_id): | ||||
|     if subtype1 is None: | ||||
|         subtype1 = '' | ||||
|     if subtype2 is None: | ||||
|         subtype2 = '' | ||||
|     r_metadata.srem(f'correlation:obj:{obj1_type}:{subtype}:{obj2_type}:{obj_id}', f'{subtype2}:{obj2_id}') | ||||
|     r_metadata.srem(f'correlation:obj:{obj2_type}:{subtype2}:{obj1_type}:{obj2_id}', f'{subtype}:{obj_id}') | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # # TODO: CORRELATION GRAPH | ||||
| 
 | ||||
| 
 | ||||
| def get_obj_str_id(obj_type, subtype, obj_id): ################ REPLACE BY : ????????????????????????? | ||||
|     if subtype is None: | ||||
|         subtype = '' | ||||
|     return f'{obj_type};{subtype};{obj_id}' | ||||
| 
 | ||||
| def get_correlations_graph_nodes_links(obj_type, subtype, obj_id, filter_types=[], max_nodes=300, level=1, flask_context=False): | ||||
|     links = set() | ||||
|     nodes = set() | ||||
| 
 | ||||
|     obj_str_id = get_obj_str_id(obj_type, subtype, obj_id) | ||||
| 
 | ||||
|     _get_correlations_graph_node(links, nodes, obj_type, subtype, obj_id, level, max_nodes, filter_types=[], previous_str_obj='') | ||||
|     return obj_str_id, nodes, links | ||||
| 
 | ||||
| 
 | ||||
| def _get_correlations_graph_node(links, nodes, obj_type, subtype, obj_id, level, max_nodes, filter_types=[], previous_str_obj=''): | ||||
|     obj_str_id = get_obj_str_id(obj_type, subtype, obj_id) | ||||
|     nodes.add(obj_str_id) | ||||
| 
 | ||||
|     obj_correlations = get_correlations(obj_type, subtype, obj_id, filter_types=[]) | ||||
|     print(obj_correlations) | ||||
|     for correl_type in obj_correlations: | ||||
|         for str_obj in obj_correlations[correl_type]: | ||||
|             subtype2, obj2_id = str_obj.split(':', 1) | ||||
|             obj2_str_id = get_obj_str_id(correl_type, subtype2, obj2_id) | ||||
| 
 | ||||
|             if obj2_str_id == previous_str_obj: | ||||
|                 continue | ||||
| 
 | ||||
|             if len(nodes) > max_nodes: | ||||
|                 break | ||||
|             nodes.add(obj2_str_id) | ||||
|             links.add((obj_str_id, obj2_str_id)) | ||||
| 
 | ||||
|             if level > 0: | ||||
|                 next_level = level - 1 | ||||
|                 _get_correlations_graph_node(links, nodes, correl_type, subtype2, obj2_id, next_level, max_nodes, filter_types=filter_types, previous_str_obj=obj_str_id) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ########################################################## | ||||
| ########################################################## | ||||
| ########################################################## | ||||
| ########################################################## | ||||
| ########################################################## | ||||
| ########################################################## | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # get_correlations_fcts = { | ||||
| #     "cryptocurrency" : ["domain", "item"], | ||||
| #     "decoded" : ["domain", "item"], | ||||
| #     "domain": ["cryptocurrency", "decoded", "item", "pgp", "username", "screenshot"], | ||||
| #     "item": ["cryptocurrency", "decoded", "domain", "pgp", "username", "screenshot"], | ||||
| #     "pgp" : ["domain", "item"], | ||||
| #     "username" : ["domain", "item"], | ||||
| #     "screenshot" :{ | ||||
| #         "domain": get_correl_screenshot_domain, | ||||
| #         "item": get_correl_screenshot_item, | ||||
| #          }, | ||||
| #     } | ||||
| # } | ||||
| # | ||||
| # def build_lsets_obj_types(obj1_type, obj_types): | ||||
| #     return [set(obj1_type, x) for x in subtypes_obj] | ||||
| # | ||||
| # ########################## | ||||
| # subtypes_obj = ['cryptocurrency', 'pgp', 'username'] | ||||
| # lsets_subtypes_obj_domain = build_lsets_obj_types('domain', subtypes_obj) | ||||
| # lsets_subtypes_obj_item = build_lsets_obj_types('item', subtypes_obj) | ||||
| # ########################## | ||||
| 
 | ||||
| # TODO HANDLE CRAWLED ITEMS | ||||
| def add_correlation(obj1_type, obj1_subtype, obj1_id, obj2_type, obj2_subtype, obj2_id): | ||||
|     set_type = set(ob1_type, ob2_type) | ||||
| 
 | ||||
|     # domain - subtypes objs | ||||
|     if set_type in lsets_subtypes_obj_domain: | ||||
|         if ob1_type == 'domain': | ||||
|             domain = obj1_id | ||||
|             obj_type = obj2_type | ||||
|             obj_subtype = obj2_subtype | ||||
|             obj_id = obj2_id | ||||
|         else: | ||||
|             domain = obj2_id | ||||
|             obj_type = obj1_type | ||||
|             obj_subtype = obj1_subtype | ||||
|             obj_id = obj1_id | ||||
|         r_metadata.sadd(f'domain_{obj_type}_{obj_subtype}:{domain}', obj_id) | ||||
|         r_metadata.sadd(f'set_domain_{obj_type}_{obj_subtype}:{obj_id}', domain) | ||||
| 
 | ||||
|     # TODO HANDLE CRAWLED ITEMS | ||||
|     # item - subtypes objs | ||||
|     elif set_type in lsets_subtypes_obj_item: | ||||
|         if ob1_type == 'item': | ||||
|             item_id = obj1_id | ||||
|             obj_type = obj2_type | ||||
|             obj_subtype = obj2_subtype | ||||
|             obj_id = obj2_id | ||||
|         else: | ||||
|             item_id = obj2_id | ||||
|             obj_type = obj1_type | ||||
|             obj_subtype = obj1_subtype | ||||
|             obj_id = obj1_id | ||||
|         r_metadata.sadd(f'set_{obj_type}_{obj_subtype}:{obj_id}', item_id) | ||||
|         r_metadata.sadd(f'item_{obj_type}_{obj_subtype}:{item_id}', obj_id) | ||||
| 
 | ||||
|     # domain - decoded | ||||
|     elif set_type == set('domain', 'decoded'): | ||||
|         if ob1_type == 'decoded': | ||||
|             decoded_id = ob1_id | ||||
|             domain = obj2_id | ||||
|         else: | ||||
|             decoded_id = obj2_id | ||||
|             domain = ob1_id | ||||
|         r_metadata.sadd(f'hash_domain:{domain}', decoded_id) # domain - hash map | ||||
|         r_metadata.sadd(f'domain_hash:{decoded_id}', domain) # hash - domain map | ||||
| 
 | ||||
|     # item - decoded | ||||
|     elif set_type == set('item', 'decoded'): | ||||
|         if ob1_type == 'decoded': | ||||
|             decoded_id = ob1_id | ||||
|             item_id = obj2_id | ||||
|         else: | ||||
|             decoded_id = obj2_id | ||||
|             item_id = ob1_id | ||||
| 
 | ||||
|         ############################################################ | ||||
| 
 | ||||
| 
 | ||||
|     # domain - screenshot | ||||
|     elif set_type == set('domain', 'screenshot'): | ||||
|         if ob1_type == 'screenshot': | ||||
|             screenshot_id = ob1_id | ||||
|             domain = obj2_id | ||||
|         else: | ||||
|             screenshot_id = obj2_id | ||||
|             domain = ob1_id | ||||
|         r_crawler.sadd(f'domain_screenshot:{domain}', screenshot_id) | ||||
|         r_crawler.sadd(f'screenshot_domain:{screenshot_id}', domain) | ||||
| 
 | ||||
|     # item - screenshot | ||||
|     elif set_type == set('item', 'screenshot'): | ||||
|         if ob1_type == 'screenshot': | ||||
|             screenshot_id = ob1_id | ||||
|             item_id = obj2_id | ||||
|         else: | ||||
|             screenshot_id = obj2_id | ||||
|             item_id = ob1_id | ||||
|         r_metadata.hset(f'paste_metadata:{item_id}', 'screenshot', screenshot_id) | ||||
|         r_crawler.sadd(f'screenshot:{screenshot_id}', item_id) | ||||
| 
 | ||||
|     # domain - item | ||||
|     elif set_type == set('domain', 'item'): | ||||
|         if ob1_type == 'item': | ||||
|             item_id = ob1_id | ||||
|             domain = obj2_id | ||||
|         else: | ||||
|             item_id = obj2_id | ||||
|             domain = ob1_id | ||||
| 
 | ||||
|     ############################################################ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # TODO ADD COMPLETE DELETE | ||||
| # TODO: Handle items crawled | ||||
| def delete_correlation(obj1_type, obj1_subtype, obj1_id, obj2_type, obj2_subtype, obj2_id): | ||||
|     set_type = set(ob1_type, ob2_type) | ||||
| 
 | ||||
|     # domain - subtypes objs | ||||
|     if set_type in lsets_subtypes_obj_domain: | ||||
|         if ob1_type == 'domain': | ||||
|             domain = obj1_id | ||||
|             obj_type = obj2_type | ||||
|             obj_subtype = obj2_subtype | ||||
|             obj_id = obj2_id | ||||
|         else: | ||||
|             domain = obj2_id | ||||
|             obj_type = obj1_type | ||||
|             obj_subtype = obj1_subtype | ||||
|             obj_id = obj1_id | ||||
|         r_metadata.srem(f'domain_{obj_type}_{obj_subtype}:{domain}', obj_id) | ||||
|         r_metadata.srem(f'set_domain_{obj_type}_{obj_subtype}:{obj_id}', domain) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     # TODO ADD COMPLETE DELETE | ||||
|     # item - subtypes objs | ||||
|     elif set_type in lsets_subtypes_obj_item: | ||||
|         if ob1_type == 'item': | ||||
|             item_id = obj1_id | ||||
|             obj_type = obj2_type | ||||
|             obj_subtype = obj2_subtype | ||||
|             obj_id = obj2_id | ||||
|         else: | ||||
|             item_id = obj2_id | ||||
|             obj_type = obj1_type | ||||
|             obj_subtype = obj1_subtype | ||||
|             obj_id = obj1_id | ||||
|         # TODO ADD COMPLETE DELETE | ||||
|         r_metadata.srem(f'set_{obj_type}_{subtype}:{obj_id}', item_id) | ||||
|         r_metadata.srem(f'item_{obj_type}_{subtype}:{item_id}', obj_id) | ||||
|         # TODO ADD COMPLETE DELETE | ||||
| 
 | ||||
|     # domain - decoded | ||||
|     elif set_type == set('domain', 'decoded'): | ||||
|         if ob1_type == 'decoded': | ||||
|             decoded_id = ob1_id | ||||
|             domain = obj2_id | ||||
|         else: | ||||
|             decoded_id = obj2_id | ||||
|             domain = ob1_id | ||||
|         r_metadata.srem(f'hash_domain:{domain}', decoded_id) | ||||
|         r_metadata.srem(f'domain_hash:{decoded_id}', domain) | ||||
| 
 | ||||
|     # item - decoded | ||||
|     elif set_type == set('item', 'decoded'): | ||||
|         if ob1_type == 'decoded': | ||||
|             decoded_id = ob1_id | ||||
|             item_id = obj2_id | ||||
|         else: | ||||
|             decoded_id = obj2_id | ||||
|             item_id = ob1_id | ||||
| 
 | ||||
|             #################################################################### | ||||
| 
 | ||||
| 
 | ||||
|     # domain - screenshot | ||||
|     elif set_type == set('domain', 'screenshot'): | ||||
|         if ob1_type == 'screenshot': | ||||
|             screenshot_id = ob1_id | ||||
|             domain = obj2_id | ||||
|         else: | ||||
|             screenshot_id = obj2_id | ||||
|             domain = ob1_id | ||||
|         r_crawler.srem(f'domain_screenshot:{domain}', screenshot_id) | ||||
|         r_crawler.srem(f'screenshot_domain:{screenshot_id}', domain) | ||||
| 
 | ||||
|     # item - screenshot | ||||
|     elif set_type == set('item', 'screenshot'): | ||||
|         if ob1_type == 'screenshot': | ||||
|             screenshot_id = ob1_id | ||||
|             item_id = obj2_id | ||||
|         else: | ||||
|             screenshot_id = obj2_id | ||||
|             item_id = ob1_id | ||||
|         r_metadata.hdel(f'paste_metadata:{item_id}', 'screenshot', screenshot_id) | ||||
|         r_crawler.srem(f'screenshot:{screenshot_id}', item_id) | ||||
| 
 | ||||
|     # domain - item | ||||
| 
 | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| 
 | ||||
| ## Subtypes - Cryptocurrency Pgp Username ## | ||||
| 
 | ||||
| def get_correl_subtypes_obj_domain(obj_type, obj_subtype, obj_id): | ||||
|     r_serv_metadata.smembers(f'set_domain_{obj_type}_{obj_subtype}:{obj_id}') | ||||
| 
 | ||||
| def get_correl_subtypes_obj_item(): | ||||
|     pass | ||||
| 
 | ||||
| def delete_subtype_domain_correlation(domain, obj_type, subtype, obj_id): | ||||
|     r_metadata.srem(f'domain_{obj_type}_{subtype}:{domain}', obj_id) | ||||
|     r_metadata.srem(f'set_domain_{obj_type}_{subtype}:{obj_id}', domain) | ||||
| 
 | ||||
| # TODO ADD COMPLETE DELETE | ||||
| def delete_subtype_item_correlation(obj_type, subtype, obj_id, item_id, item_date): | ||||
|     #self.update_correlation_daterange(subtype, obj_id, item_date) update daterange ! # # TODO: | ||||
|     r_metadata.srem(f'set_{obj_type}_{subtype}:{obj_id}', item_id) | ||||
|     r_metadata.srem(f'item_{obj_type}_{subtype}:{item_id}', obj_id) | ||||
| 
 | ||||
|     # # TODO: FIXME HANDLE SUB Objects Metadata # WARNING: | ||||
|     # res = r_serv_metadata.hincrby('{}:{}:{}'.format(self.correlation_name, subtype, item_date), obj_id, -1) | ||||
|     # if int(res) < 0: # remove last | ||||
|     #     r_serv_metadata.hdel('{}:{}:{}'.format(self.correlation_name, subtype, item_date), obj_id) | ||||
|     # | ||||
|     # res = r_serv_metadata.zscore('{}_all:{}'.format(self.correlation_name, subtype), obj_id) | ||||
|     # if int(res) > 0: | ||||
|     #     r_serv_metadata.zincrby('{}_all:{}'.format(self.correlation_name, subtype), obj_id, -1) | ||||
| 
 | ||||
| ## Screenshot ## | ||||
| 
 | ||||
| ##-- Screenshot - Domain --## | ||||
| def add_correl_screenshot_domain(screenshot_id, domain): | ||||
|     r_crawler.sadd(f'domain_screenshot:{domain}', screenshot_id) | ||||
|     r_crawler.sadd(f'screenshot_domain:{screenshot_id}', domain) | ||||
| 
 | ||||
| def get_correl_screenshot_domain(screenshot_id): | ||||
|     return r_crawler.smembers(f'screenshot_domain:{screenshot_id}') | ||||
| 
 | ||||
| # def delete_correl_screenshot_domain(screenshot_id, domain): | ||||
| #     r_crawler.srem(f'domain_screenshot:{domain}', screenshot_id) | ||||
| #     r_crawler.srem(f'screenshot_domain:{screenshot_id}', domain) | ||||
| 
 | ||||
| ##-- Screenshot - Item --## | ||||
| def add_correl_screenshot_item(screenshot_id, item_id): | ||||
|     r_metadata.hset(f'paste_metadata:{item_id}', 'screenshot', screenshot_id) | ||||
|     r_crawler.sadd(f'screenshot:{screenshot_id}', item_id) | ||||
| 
 | ||||
| def get_correl_screenshot_item(screenshot_id): | ||||
|     r_crawler.smembers(f'screenshot:{screenshot_id}') | ||||
| 
 | ||||
| # def delete_correl_screenshot_item(screenshot_id, item_id): | ||||
| #     r_metadata.hdel(f'paste_metadata:{item_id}', 'screenshot', screenshot_id) | ||||
| #     r_crawler.srem(f'screenshot:{screenshot_id}', item_id) | ||||
| 
 | ||||
| ##    --     ## | ||||
| 
 | ||||
| 
 | ||||
| def get_correl_item_screenshot(item_id): | ||||
|     res = r_metadata.hget(f'paste_metadata:{item_id}', 'screenshot') | ||||
|     if res: | ||||
|         return set(res) | ||||
|     else: | ||||
|         return set() | ||||
| 
 | ||||
| ## Domain ## | ||||
| 
 | ||||
| def get_correl_domain_subtypes_obj(domain_id, obj_type, obj_subtype): | ||||
|     return r_serv_metadata.smembers(f'domain_{obj_type}_{obj_subtype}:{domain_id}') | ||||
| 
 | ||||
| ##   --   ## | ||||
| 
 | ||||
| ## Item ## | ||||
| 
 | ||||
| def get_correl_item_subtypes_obj(): | ||||
|     pass | ||||
| 
 | ||||
| ##   --   ## war game stinger - stranger thing | ||||
| 
 | ||||
| 
 | ||||
| def _get_object_correlations(obj_type, obj_subtype, obj_id, filter_types=[]): # # TODO: , filter_subtypes=[] | ||||
|     obj_relationships = get_obj_relationships(obj_type) | ||||
|     correlations = [] | ||||
|     for correlation_fct in obj_relationship_fcts[obj_type]: | ||||
|         correlations | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| def get_object_correlations(filter_types, filter_subtypes, lvl=0): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #################################################################### | ||||
| #################################################################### | ||||
| #################################################################### | ||||
| #################################################################### | ||||
| #################################################################### | ||||
| #################################################################### | ||||
| 
 | ||||
| def get_object_correlation(object_type, value, correlation_names=None, correlation_objects=None, requested_correl_type=None): | ||||
|     if object_type == 'domain': | ||||
|         return Domain.get_domain_all_correlation(value, correlation_names=correlation_names) | ||||
|     elif object_type == 'paste' or object_type == 'item': | ||||
|         return Item.get_item_all_correlation(value, correlation_names=correlation_names) | ||||
|     elif object_type == 'decoded': | ||||
|         return Decoded.get_decoded_correlated_object(value, correlation_objects=correlation_objects) | ||||
|     elif object_type == 'pgp': | ||||
|         return Pgp.pgp.get_correlation_all_object(requested_correl_type, value, correlation_objects=correlation_objects) | ||||
|     elif object_type == 'cryptocurrency': | ||||
|         return Cryptocurrency.cryptocurrency.get_correlation_all_object(requested_correl_type, value, correlation_objects=correlation_objects) | ||||
|     elif object_type == 'username': | ||||
|         return Username.correlation.get_correlation_all_object(requested_correl_type, value, correlation_objects=correlation_objects) | ||||
|     elif object_type == 'screenshot' or object_type == 'image': | ||||
|         return Screenshot.get_screenshot_correlated_object(value, correlation_objects=correlation_objects) | ||||
|     return {} | ||||
| 
 | ||||
| def get_obj_tag_table_keys(object_type): | ||||
|     ''' | ||||
|     Warning: use only in flask (dynamic templates) | ||||
|     ''' | ||||
|     if object_type=="domain": | ||||
|         return ['id', 'first_seen', 'last_check', 'status'] # # TODO: add root screenshot | ||||
| 
 | ||||
| def create_obj_relationship(obj1_type, obj1_id, obj2_type, obj2_id, obj1_subtype=None, obj2_subtype=None): | ||||
|     if obj1_type == 'domain': | ||||
|         pass | ||||
|     elif obj1_type == 'item': | ||||
|         pass # son/father + duplicate + domain | ||||
|     elif obj1_type == 'pgp': | ||||
|         Pgp.pgp.save_obj_relationship(obj1_subtype, obj1_id, obj2_type, obj2_id) | ||||
|     elif obj1_type == 'cryptocurrency': | ||||
|         Cryptocurrency.cryptocurrency.save_obj_relationship(obj1_subtype, obj1_type, obj2_type, obj2_id) | ||||
|     elif obj1_type == 'decoded': | ||||
|         Decoded.save_obj_relationship(obj1_id, obj2_type, obj2_id) | ||||
|     elif obj1_type == 'image': | ||||
|         Screenshot.save_obj_relationship(obj1_id, obj2_type, obj2_id) | ||||
| 
 | ||||
| def delete_obj_relationship(obj1_type, obj1_id, obj2_type, obj2_id, obj1_subtype=None, obj2_subtype=None): | ||||
|     if obj1_type == 'domain': | ||||
|         pass | ||||
|     elif obj1_type == 'item': | ||||
|         pass # son/father + duplicate + domain | ||||
|     elif obj1_type == 'pgp': | ||||
|         Pgp.pgp.delete_obj_relationship(obj1_subtype, obj1_id, obj2_type, obj2_id) | ||||
|     elif obj1_type == 'cryptocurrency': | ||||
|         Cryptocurrency.cryptocurrency.delete_obj_relationship(obj1_subtype, obj1_type, obj2_type, obj2_id) | ||||
|     elif obj1_type == 'decoded': | ||||
|         Decoded.delete_obj_relationship(obj1_id, obj2_type, obj2_id) | ||||
|     elif obj1_type == 'image': | ||||
|         Screenshot.delete_obj_relationship(obj1_id, obj2_type, obj2_id) | ||||
| 
 | ||||
| def create_graph_links(links_set): | ||||
|     graph_links_list = [] | ||||
|     for link in links_set: | ||||
|         graph_links_list.append({"source": link[0], "target": link[1]}) | ||||
|     return graph_links_list | ||||
| 
 | ||||
| def create_graph_nodes(nodes_set, root_node_id, flask_context=True): | ||||
|     graph_nodes_list = [] | ||||
|     for node_id in nodes_set: | ||||
|         correlation_name, correlation_type, value = node_id.split(';', 3) | ||||
|         dict_node = {"id": node_id} | ||||
|         dict_node['style'] = get_correlation_node_icon(correlation_name, correlation_type, value) | ||||
|         dict_node['text'] = value | ||||
|         if node_id == root_node_id: | ||||
|             dict_node["style"]["node_color"] = 'orange' | ||||
|             dict_node["style"]["node_radius"] = 7 | ||||
|         dict_node['url'] = get_item_url(correlation_name, value, correlation_type, flask_context=flask_context) | ||||
|         graph_nodes_list.append(dict_node) | ||||
|     return graph_nodes_list | ||||
| 
 | ||||
| def create_node_id(correlation_name, value, correlation_type=''): | ||||
|     if correlation_type is None: | ||||
|         correlation_type = '' | ||||
|     return '{};{};{}'.format(correlation_name, correlation_type, value) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # # TODO: filter by correlation type => bitcoin, mail, ... | ||||
| def get_graph_node_object_correlation(object_type, root_value, mode, correlation_names, correlation_objects, max_nodes=300, requested_correl_type=None, flask_context=True): | ||||
|     links = set() | ||||
|     nodes = set() | ||||
| 
 | ||||
|     root_node_id = create_node_id(object_type, root_value, requested_correl_type) | ||||
|     nodes.add(root_node_id) | ||||
| 
 | ||||
|     root_correlation = get_object_correlation(object_type, root_value, correlation_names, correlation_objects, requested_correl_type=requested_correl_type) | ||||
|     for correl in root_correlation: | ||||
|         if correl in ('pgp', 'cryptocurrency', 'username'): | ||||
|             for correl_type in root_correlation[correl]: | ||||
|                 for correl_val in root_correlation[correl][correl_type]: | ||||
| 
 | ||||
|                     # add correlation | ||||
|                     correl_node_id = create_node_id(correl, correl_val, correl_type) | ||||
| 
 | ||||
|                     if mode=="union": | ||||
|                         if len(nodes) > max_nodes: | ||||
|                             break | ||||
|                         nodes.add(correl_node_id) | ||||
|                         links.add((root_node_id, correl_node_id)) | ||||
| 
 | ||||
|                     # get second correlation | ||||
|                     res = get_object_correlation(correl, correl_val, correlation_names, correlation_objects, requested_correl_type=correl_type) | ||||
|                     if res: | ||||
|                         for corr_obj in res: | ||||
|                             for correl_key_val in res[corr_obj]: | ||||
|                                 #filter root value | ||||
|                                 if correl_key_val == root_value: | ||||
|                                     continue | ||||
| 
 | ||||
|                                 if len(nodes) > max_nodes: | ||||
|                                     break | ||||
|                                 new_corel_1 = create_node_id(corr_obj, correl_key_val) | ||||
|                                 new_corel_2 = create_node_id(correl, correl_val, correl_type) | ||||
|                                 nodes.add(new_corel_1) | ||||
|                                 nodes.add(new_corel_2) | ||||
|                                 links.add((new_corel_1, new_corel_2)) | ||||
| 
 | ||||
|                                 if mode=="inter": | ||||
|                                     nodes.add(correl_node_id) | ||||
|                                     links.add((root_node_id, correl_node_id)) | ||||
|         if correl in ('decoded', 'screenshot', 'domain', 'paste'): | ||||
|             for correl_val in root_correlation[correl]: | ||||
| 
 | ||||
|                 correl_node_id = create_node_id(correl, correl_val) | ||||
|                 if mode=="union": | ||||
|                     if len(nodes) > max_nodes: | ||||
|                         break | ||||
|                     nodes.add(correl_node_id) | ||||
|                     links.add((root_node_id, correl_node_id)) | ||||
| 
 | ||||
|                 res = get_object_correlation(correl, correl_val, correlation_names, correlation_objects) | ||||
|                 if res: | ||||
|                     for corr_obj in res: | ||||
|                         if corr_obj in ('decoded', 'domain', 'paste', 'screenshot'): | ||||
|                             for correl_key_val in res[corr_obj]: | ||||
|                                 #filter root value | ||||
|                                 if correl_key_val == root_value: | ||||
|                                     continue | ||||
| 
 | ||||
|                                 if len(nodes) > max_nodes: | ||||
|                                     break | ||||
|                                 new_corel_1 = create_node_id(corr_obj, correl_key_val) | ||||
|                                 new_corel_2 = create_node_id(correl, correl_val) | ||||
|                                 nodes.add(new_corel_1) | ||||
|                                 nodes.add(new_corel_2) | ||||
|                                 links.add((new_corel_1, new_corel_2)) | ||||
| 
 | ||||
|                                 if mode=="inter": | ||||
|                                     nodes.add(correl_node_id) | ||||
|                                     links.add((root_node_id, correl_node_id)) | ||||
| 
 | ||||
|                         if corr_obj in ('pgp', 'cryptocurrency', 'username'): | ||||
|                             for correl_key_type in res[corr_obj]: | ||||
|                                 for correl_key_val in res[corr_obj][correl_key_type]: | ||||
|                                     #filter root value | ||||
|                                     if correl_key_val == root_value: | ||||
|                                         continue | ||||
| 
 | ||||
|                                     if len(nodes) > max_nodes: | ||||
|                                         break | ||||
|                                     new_corel_1 = create_node_id(corr_obj, correl_key_val, correl_key_type) | ||||
|                                     new_corel_2 = create_node_id(correl, correl_val) | ||||
|                                     nodes.add(new_corel_1) | ||||
|                                     nodes.add(new_corel_2) | ||||
|                                     links.add((new_corel_1, new_corel_2)) | ||||
| 
 | ||||
|                                     if mode=="inter": | ||||
|                                         nodes.add(correl_node_id) | ||||
|                                         links.add((root_node_id, correl_node_id)) | ||||
| 
 | ||||
| 
 | ||||
|     return {"nodes": create_graph_nodes(nodes, root_node_id, flask_context=flask_context), "links": create_graph_links(links)} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #######################################################################################3 | ||||
|  | @ -168,7 +168,7 @@ def load_crawler_cookies(cookiejar_uuid, domain, crawler_type='regular'): | |||
| ################################################################################ | ||||
| 
 | ||||
| def get_all_cookiejar(): | ||||
|     r_serv_onion.smembers('cookiejar:all') | ||||
|     return r_serv_onion.smembers('cookiejar:all') | ||||
| 
 | ||||
| def get_global_cookiejar(): | ||||
|     res = r_serv_onion.smembers('cookiejar:global') | ||||
|  | @ -185,19 +185,24 @@ def get_user_cookiejar(user_id): | |||
| def exist_cookiejar(cookiejar_uuid): | ||||
|     return r_serv_onion.exists('cookiejar_metadata:{}'.format(cookiejar_uuid)) | ||||
| 
 | ||||
| def create_cookiejar(user_id, level=1, description=None): | ||||
|     cookiejar_uuid = str(uuid.uuid4()) | ||||
| def _set_cookiejar_date(date): | ||||
|     r_serv_onion.hset(f'cookiejar_metadata:{cookiejar_uuid}', 'date', date) | ||||
| 
 | ||||
| # # TODO: sanitize cookie_uuid | ||||
| def create_cookiejar(user_id, level=1, description=None, cookiejar_uuid=None): | ||||
|     if not cookiejar_uuid: | ||||
|         cookiejar_uuid = str(uuid.uuid4()) | ||||
| 
 | ||||
|     r_serv_onion.sadd('cookiejar:all', cookiejar_uuid) | ||||
|     if level==0: | ||||
|         r_serv_onion.sadd('cookiejar:user:{}'.format(user_id), cookiejar_uuid) | ||||
|         r_serv_onion.sadd(f'cookiejar:user:{user_id}', cookiejar_uuid) | ||||
|     else: | ||||
|         r_serv_onion.sadd('cookiejar:global', cookiejar_uuid) | ||||
|     # metadata | ||||
|     r_serv_onion.hset('cookiejar_metadata:{}'.format(cookiejar_uuid), 'user_id', user_id) | ||||
|     r_serv_onion.hset('cookiejar_metadata:{}'.format(cookiejar_uuid), 'level', level) | ||||
|     r_serv_onion.hset('cookiejar_metadata:{}'.format(cookiejar_uuid), 'description', description) | ||||
|     r_serv_onion.hset('cookiejar_metadata:{}'.format(cookiejar_uuid), 'date', datetime.now().strftime("%Y%m%d")) | ||||
|     r_serv_onion.hset(f'cookiejar_metadata:{cookiejar_uuid}', 'user_id', user_id) | ||||
|     r_serv_onion.hset(f'cookiejar_metadata:{cookiejar_uuid}', 'level', level) | ||||
|     r_serv_onion.hset(f'cookiejar_metadata:{cookiejar_uuid}', 'description', description) | ||||
|     _set_cookiejar_date(datetime.now().strftime("%Y%m%d")) | ||||
| 
 | ||||
|     # if json_cookies: | ||||
|     #     json_cookies = json.loads(json_cookies) # # TODO: catch Exception | ||||
|  | @ -259,7 +264,7 @@ def get_cookiejar_metadata(cookiejar_uuid, level=False): | |||
|         dict_cookiejar['date'] = get_cookiejar_date(cookiejar_uuid) | ||||
|         dict_cookiejar['user_id'] = get_cookiejar_owner(cookiejar_uuid) | ||||
|         if level: | ||||
|             dict_cookiejar['level'] = get_cookies_level(cookiejar_uuid) | ||||
|             dict_cookiejar['level'] = get_cookiejar_level(cookiejar_uuid) | ||||
|     return dict_cookiejar | ||||
| 
 | ||||
| def get_cookiejar_metadata_by_iterator(iter_cookiejar_uuid): | ||||
|  | @ -311,10 +316,12 @@ def get_cookie_dict(cookie_uuid): | |||
|     return cookie_dict | ||||
| 
 | ||||
| # name, value, path=None, httpOnly=None, secure=None, domain=None, text=None | ||||
| def add_cookie_to_cookiejar(cookiejar_uuid, cookie_dict): | ||||
|     cookie_uuid = generate_uuid() | ||||
|     r_serv_onion.sadd('cookiejar:{}:cookies:uuid'.format(cookiejar_uuid), cookie_uuid) | ||||
|     r_serv_onion.sadd('cookies:map:cookiejar:{}'.format(cookie_uuid), cookiejar_uuid) | ||||
| def add_cookie_to_cookiejar(cookiejar_uuid, cookie_dict, cookie_uuid=None): | ||||
|     # # TODO: sanitize cookie_uuid | ||||
|     if not cookie_uuid: | ||||
|         cookie_uuid = generate_uuid() | ||||
|     r_serv_onion.sadd(f'cookiejar:{cookiejar_uuid}:cookies:uuid', cookie_uuid) | ||||
|     r_serv_onion.sadd(f'cookies:map:cookiejar:{cookie_uuid}', cookiejar_uuid) | ||||
| 
 | ||||
|     set_cookie_value(cookie_uuid, 'name', cookie_dict['name']) | ||||
|     set_cookie_value(cookie_uuid, 'value', cookie_dict['value']) | ||||
|  | @ -631,7 +638,6 @@ def add_auto_crawler_in_queue(domain, domain_type, port, epoch, delta, message): | |||
| 
 | ||||
| def update_auto_crawler_queue(): | ||||
|     current_epoch = int(time.time()) | ||||
|     current_epoch = 1631096842 | ||||
|     # check if current_epoch > domain_next_epoch | ||||
|     l_queue = r_serv_onion.zrangebyscore('crawler_auto_queue', 0, current_epoch) | ||||
|     for elem in l_queue: | ||||
|  | @ -715,6 +721,73 @@ def send_url_to_crawl_in_queue(crawler_mode, crawler_type, url): | |||
| 
 | ||||
| #### #### | ||||
| #### CRAWLER TASK API #### | ||||
| 
 | ||||
| def api_add_crawler_task(json_dict): | ||||
|     user_id = None ############################################### | ||||
|     user_agent = data.get('user_agent', None) | ||||
|     url = json_dict.get('url', '') | ||||
|     if not is_valid_uuid_v4(investigation_uuid): | ||||
|         return {"status": "error", "reason": f"Invalid Investigation uuid: {investigation_uuid}"}, 400 | ||||
| 
 | ||||
|     screenshot = json_dict.get('screenshot', True) #### | ||||
|     screenshot = screenshot == True | ||||
|     har = json_dict.get('screenshot', True) #### | ||||
|     har = har == True | ||||
| 
 | ||||
|     depth_limit = data.get('depth_limit', 1) | ||||
|     try: | ||||
|         depth_limit = int(depth_limit) | ||||
|         if depth_limit < 0: | ||||
|             depth_limit = 0 | ||||
|     except ValueError: | ||||
|         return ({'error':'invalid depth limit'}, 400) | ||||
| 
 | ||||
|     max_pages = data.get('max_pages', 100) | ||||
|     if max_pages: | ||||
|         try: | ||||
|             max_pages = int(max_pages) | ||||
|             if max_pages < 1: | ||||
|                 max_pages = 1 | ||||
|         except ValueError: | ||||
|             return ({'error':'invalid max_pages limit'}, 400) | ||||
| 
 | ||||
|     auto_crawler = data.get('auto_crawler', False) | ||||
|     auto_crawler = auto_crawler == True | ||||
|     crawler_delta = data.get('crawler_delta', 3600) | ||||
|     if auto_crawler: | ||||
|         try: | ||||
|             crawler_delta = int(crawler_delta) | ||||
|             if crawler_delta < 0: | ||||
|                 return ({'error':'invalid delta between two pass of the crawler'}, 400) | ||||
|         except ValueError: | ||||
|             return ({'error':'invalid delta between two pass of the crawler'}, 400) | ||||
| 
 | ||||
| 
 | ||||
|     crawler_type = data.get('crawler_type', None) | ||||
| 
 | ||||
|     cookiejar_uuid = data.get('cookiejar_uuid', None) | ||||
|     if cookiejar_uuid: | ||||
|         if not exist_cookiejar(cookiejar_uuid): | ||||
|             return ({'error': 'unknow cookiejar uuid', 'cookiejar_uuid': cookiejar_uuid}, 404) | ||||
|         level = get_cookiejar_level(cookiejar_uuid) | ||||
|         if level == 0: # # TODO: check if user is admin ###################################################### | ||||
|             cookie_owner = get_cookiejar_owner(cookiejar_uuid) | ||||
|             if cookie_owner != user_id: | ||||
|                 return ({'error': 'The access to this cookiejar is restricted'}, 403) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     create_crawler_task(url, screenshot=screenshot, har=har, depth_limit=depth_limit, | ||||
|                         max_pages=max_pages, crawler_type=crawler_type, | ||||
|                         auto_crawler=auto_crawler, crawler_delta=crawler_delta, | ||||
|                         cookiejar_uuid=cookiejar_uuid, user_agent=user_agent) | ||||
| 
 | ||||
| 
 | ||||
| # # TODO: # FIXME: REPLACE ME | ||||
| def api_create_crawler_task(user_id, url, screenshot=True, har=True, depth_limit=1, max_pages=100, auto_crawler=False, crawler_delta=3600, crawler_type=None, cookiejar_uuid=None, user_agent=None): | ||||
|     # validate url | ||||
|     if url is None or url=='' or url=='\n': | ||||
|  | @ -802,10 +875,16 @@ def create_domain_metadata(domain_type, domain, current_port, date, date_month): | |||
|         all_domain_ports.append(current_port) | ||||
|         r_serv_onion.hset('{}_metadata:{}'.format(domain_type, domain), 'ports', ';'.join(all_domain_ports)) | ||||
| 
 | ||||
| def add_last_crawled_domain(domain_type, domain, port, epoch): | ||||
|     # update list, last crawled domains | ||||
|     redis_crawler.lpush(f'last_{domain_type}', f'{domain}:{port};{epoch}') | ||||
|     redis_crawler.ltrim(f'last_{domain_type}', 0, 15) | ||||
| 
 | ||||
| # add root_item to history | ||||
| # if down -> root_item = epoch_date | ||||
| def add_domain_root_item(root_item, domain_type, domain, epoch_date, port): | ||||
|     # Create/Update crawler history | ||||
|     r_serv_onion.zadd('crawler_history_{}:{}:{}'.format(domain_type, domain, port), epoch_date, root_item) | ||||
|     r_serv_onion.zadd(f'crawler_history_{domain_type}:{domain}:{port}', epoch_date, root_item) | ||||
| 
 | ||||
| def create_item_metadata(item_id, domain, url, port, item_father): | ||||
|     r_serv_metadata.hset('paste_metadata:{}'.format(item_id), 'father', item_father) | ||||
|  | @ -1498,5 +1577,5 @@ if __name__ == '__main__': | |||
|     #print(get_all_queues_stats()) | ||||
| 
 | ||||
|     #res = get_auto_crawler_all_domain() | ||||
|     res = update_auto_crawler_queue() | ||||
|     res = get_all_cookiejar() | ||||
|     print(res) | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) | |||
| import ConfigLoader | ||||
| 
 | ||||
| config_loader = ConfigLoader.ConfigLoader() | ||||
| r_serv_db = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_db = config_loader.get_db_conn("Kvrocks_DB") | ||||
| r_cache = config_loader.get_redis_conn("Redis_Cache") | ||||
| config_loader = None | ||||
| 
 | ||||
|  |  | |||
|  | @ -185,6 +185,7 @@ def get_obj_id_item_id(parent_type, parent_id): | |||
|     else: | ||||
|         return None | ||||
| 
 | ||||
| # # TODO: # FIXME: TO MIGRATE ?????? | ||||
| def add_map_obj_id_item_id(obj_id, item_id, obj_type): | ||||
|     if obj_type == 'twitter_id': | ||||
|         r_serv_metadata.hset('map:twitter_id:item_id', obj_id, item_id) | ||||
|  |  | |||
|  | @ -9,13 +9,13 @@ from flask import url_for | |||
| 
 | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
| from lib.objects import abstract_object | ||||
| from lib.objects.abstract_subtype_object import AbstractSubtypeObject, get_all_id | ||||
| 
 | ||||
| config_loader = ConfigLoader() | ||||
| 
 | ||||
| config_loader = None | ||||
| 
 | ||||
| class CryptoCurrency(abstract_object.AbstractObject): | ||||
| class CryptoCurrency(AbstractSubtypeObject): | ||||
|     """ | ||||
|     AIL CryptoCurrency Object. (strings) | ||||
|     """ | ||||
|  | @ -88,29 +88,45 @@ class CryptoCurrency(abstract_object.AbstractObject): | |||
|                 obj_attr.add_tag(tag) | ||||
|         return obj | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     def get_meta(self, options=set()): | ||||
|         return self._get_meta() | ||||
| 
 | ||||
| 
 | ||||
|     def exist_correlation(self): | ||||
|         pass | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
| def build_crypto_regex(subtype, search_id): | ||||
|     pass | ||||
| def get_all_subtypes(): | ||||
|     return ['bitcoin', 'bitcoin-cash', 'dash', 'ethereum', 'litecoin', 'monero', 'zcash'] | ||||
| 
 | ||||
| def search_by_name(subtype, search_id): | ||||
| 
 | ||||
|     # # TODO: BUILD regex | ||||
|     obj = CryptoCurrency(subtype, search_id) | ||||
|     if obj.exists(): | ||||
|         return search_id | ||||
|     else: | ||||
|         regex = build_crypto_regex(subtype, search_id) | ||||
|         return abstract_object.search_subtype_obj_by_id('cryptocurrency', subtype, regex) | ||||
| # def build_crypto_regex(subtype, search_id): | ||||
| #     pass | ||||
| # | ||||
| # def search_by_name(subtype, search_id): ################################################## | ||||
| # | ||||
| #     # # TODO: BUILD regex | ||||
| #     obj = CryptoCurrency(subtype, search_id) | ||||
| #     if obj.exists(): | ||||
| #         return search_id | ||||
| #     else: | ||||
| #         regex = build_crypto_regex(subtype, search_id) | ||||
| #         return abstract_object.search_subtype_obj_by_id('cryptocurrency', subtype, regex) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #if __name__ == '__main__': | ||||
| 
 | ||||
| 
 | ||||
| # by days -> need first/last entry USEFULL FOR DATA RETENTION UI | ||||
| 
 | ||||
| def get_all_cryptocurrencies(): | ||||
|     cryptos = {} | ||||
|     for subtype in get_all_subtypes(): | ||||
|         cryptos[subtype] = get_all_cryptocurrencies_by_subtype(subtype) | ||||
|     return cryptos | ||||
| 
 | ||||
| def get_all_cryptocurrencies_by_subtype(subtype): | ||||
|     return get_all_id('cryptocurrency', subtype) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     res = get_all_cryptocurrencies() | ||||
|     print(res) | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| 
 | ||||
| import os | ||||
| import sys | ||||
| import requests | ||||
| import zipfile | ||||
| 
 | ||||
| from flask import url_for | ||||
| from io import BytesIO | ||||
|  | @ -10,11 +12,17 @@ from io import BytesIO | |||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
| from lib.objects.abstract_object import AbstractObject | ||||
| from lib.item_basic import is_crawled, get_item_domain | ||||
| 
 | ||||
| from packages import Date | ||||
| 
 | ||||
| config_loader = ConfigLoader() | ||||
| r_metadata = config_loader.get_db_conn("Kvrocks_Objects") | ||||
| 
 | ||||
| r_metadata = config_loader.get_redis_conn("ARDB_Metadata") | ||||
| HASH_DIR = config_loader.get_config_str('Directories', 'hash') | ||||
| baseurl = config_loader.get_config_str("Notifications", "ail_domain") | ||||
| VT_TOKEN = 'f1a6281c8a533172a45d901435452f67f5e61fd06a83dcc058f3f7b4aab66f5b' | ||||
| config_loader = None | ||||
| 
 | ||||
| 
 | ||||
|  | @ -32,17 +40,14 @@ class Decoded(AbstractObject): | |||
|     def __init__(self, id): | ||||
|         super(Decoded, self).__init__('decoded', id) | ||||
| 
 | ||||
|     def exists(self): | ||||
|         return r_metadata.exists(f'metadata_hash:{self.id}') | ||||
| 
 | ||||
|     # def get_ail_2_ail_payload(self): | ||||
|     #     payload = {'raw': self.get_gzip_content(b64=True), | ||||
|     #                 'compress': 'gzip'} | ||||
|     #     return payload | ||||
| 
 | ||||
|     def get_sha1(self): | ||||
|         return self.id.split('/')[0] | ||||
| 
 | ||||
|     def get_file_type(self): | ||||
|         return r_metadata.hget(f'metadata_hash:{self.get_sha1()}', 'estimated_type') | ||||
| 
 | ||||
|     # # WARNING: UNCLEAN DELETE /!\ TEST ONLY /!\ | ||||
|     def delete(self): | ||||
|         # # TODO: | ||||
|  | @ -50,13 +55,14 @@ class Decoded(AbstractObject): | |||
| 
 | ||||
|     def get_link(self, flask_context=False): | ||||
|         if flask_context: | ||||
|             url = url_for('correlation.show_correlation', object_type="decoded", correlation_id=value) | ||||
|             url = url_for('correlation.show_correlation', object_type="decoded", correlation_id=self.id) | ||||
|         else: | ||||
|             url = f'{baseurl}/correlation/show_correlation?object_type={self.type}&correlation_id={self.id}' | ||||
|         return url | ||||
| 
 | ||||
|     def get_svg_icon(self): | ||||
|         file_type = self.get_file_type() | ||||
|         file_type = self.get_estimated_type() | ||||
|         file_type = file_type.split('/')[0] | ||||
|         if file_type == 'application': | ||||
|             icon = '\uf15b' | ||||
|         elif file_type == 'audio': | ||||
|  | @ -85,12 +91,23 @@ class Decoded(AbstractObject): | |||
|     def get_filepath(self, mimetype=None): | ||||
|         return os.path.join(os.environ['AIL_HOME'], self.get_rel_path(mimetype=mimetype)) | ||||
| 
 | ||||
|     def get_file_content(self, mimetype=None): | ||||
|     def get_content(self, mimetype=None): | ||||
|         filepath = self.get_filepath(mimetype=mimetype) | ||||
|         with open(filepath, 'rb') as f: | ||||
|             file_content = BytesIO(f.read()) | ||||
|         return file_content | ||||
| 
 | ||||
|     def get_zip_content(self): | ||||
|         mimetype = self.get_estimated_type() | ||||
|         zip_content = BytesIO() | ||||
|         with zipfile.ZipFile(zip_content, "w") as zf: | ||||
|             # TODO: Fix password | ||||
|             #zf.setpassword(b"infected") | ||||
|             zf.writestr( self.id, self.get_content().getvalue()) | ||||
|         zip_content.seek(0) | ||||
|         return zip_content | ||||
| 
 | ||||
| 
 | ||||
|     def get_misp_object(self): | ||||
|         obj_attrs = [] | ||||
|         obj = MISPObject('file') | ||||
|  | @ -99,7 +116,7 @@ class Decoded(AbstractObject): | |||
| 
 | ||||
|         obj_attrs.append( obj.add_attribute('sha1', value=self.id) ) | ||||
|         obj_attrs.append( obj.add_attribute('mimetype', value=self.get_estimated_type()) ) | ||||
|         obj_attrs.append( obj.add_attribute('malware-sample', value=self.id, data=self.get_file_content()) ) | ||||
|         obj_attrs.append( obj.add_attribute('malware-sample', value=self.id, data=self.get_content()) ) | ||||
|         for obj_attr in obj_attrs: | ||||
|             for tag in self.get_tags(): | ||||
|                 obj_attr.add_tag(tag) | ||||
|  | @ -108,24 +125,312 @@ class Decoded(AbstractObject): | |||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     def get_decoders(self): | ||||
|         return ['base64', 'binary', 'hexadecimal'] | ||||
| 
 | ||||
|     def exist_correlation(self): | ||||
|     def get_first_seen(self): | ||||
|         res = r_metadata.hget(f'metadata_hash:{self.id}', 'first_seen') | ||||
|         if res: | ||||
|             return int(res) | ||||
|         else: | ||||
|             return 99999999 | ||||
| 
 | ||||
|     def get_last_seen(self): | ||||
|         res = r_metadata.hget(f'metadata_hash:{self.id}', 'last_seen') | ||||
|         if res: | ||||
|             return int(res) | ||||
|         else: | ||||
|             return 0 | ||||
| 
 | ||||
|     def set_first_seen(self, date): | ||||
|         r_metadata.hset(f'metadata_hash:{self.id}', 'first_seen', date) | ||||
| 
 | ||||
|     def set_last_seen(self, date): | ||||
|         r_metadata.hset(f'metadata_hash:{self.id}', 'last_seen', date) | ||||
| 
 | ||||
|     def update_daterange(self, date): | ||||
|         first_seen = self.get_first_seen() | ||||
|         last_seen = self.get_last_seen() | ||||
|         if date < first_seen: | ||||
|             self.set_first_seen(date) | ||||
|         if date > last_seen: | ||||
|             self.set_last_seen(date) | ||||
| 
 | ||||
|     def get_meta(self): | ||||
|         pass | ||||
| 
 | ||||
|     def create(self, content, date): | ||||
|     def get_meta_vt(self): | ||||
|         meta = {} | ||||
|         meta['link'] = r_metadata.hget(f'metadata_hash:{self.id}', 'vt_link') | ||||
|         meta['report'] = r_metadata.hget(f'metadata_hash:{self.id}', 'vt_report') | ||||
|         return meta | ||||
| 
 | ||||
|     def guess_mimetype(self, bytes_content): | ||||
|         return magic.from_buffer(bytes_content, mime=True) | ||||
| 
 | ||||
|     def _save_meta(self, filepath, mimetype): | ||||
|         # create hash metadata | ||||
|         r_metadata.hset(f'metadata_hash:{self.id}', 'size', os.path.getsize(filepath)) | ||||
|         r_metadata.hset(f'metadata_hash:{self.id}', 'estimated_type', mimetype) | ||||
|         r_metadata.sadd('hash_all_type', mimetype) #################################################### rename ???? | ||||
| 
 | ||||
|     def save_file(self, content, mimetype): ##################################################### | ||||
|         filepath = self.get_filepath(mimetype=mimetype) | ||||
|         if os.path.isfile(filepath): | ||||
|             #print('File already exist') | ||||
|             return False | ||||
|         # create dir | ||||
|         dirname = os.path.dirname(filepath) | ||||
|         if not os.path.exists(dirname): | ||||
|             os.makedirs(dirname) | ||||
|         with open(filepath, 'wb') as f: | ||||
|             f.write(file_content) | ||||
| 
 | ||||
|         # create hash metadata | ||||
|         self._save_meta(filepath, mimetype) | ||||
|         return True | ||||
| 
 | ||||
|     # avoid counting the same hash multiple time on the same item | ||||
|     #       except if defferent encoding | ||||
| 
 | ||||
|     def is_seen_this_day(self, date): | ||||
|         for decoder in get_decoders_names(): | ||||
|              if r_metadata.zscore(f'{decoder_name}_date:{date}', self.id): | ||||
|                 return True | ||||
|         return False | ||||
| 
 | ||||
|     def add(self, decoder_name, date, obj_id, mimetype): | ||||
| 
 | ||||
|         if not self.is_seen_this_day(date): | ||||
|             # mimetype | ||||
|             r_metadata.zincrby(f'decoded:mimetype:{date}', mimetype, 1) | ||||
|             r_metadata.sadd(f'decoded:mimetypes', mimetype) | ||||
| 
 | ||||
|         # filter hash encoded in the same object | ||||
|         if not self.is_correlated('item', None, obj_id): | ||||
| 
 | ||||
|             r_metadata.hincrby(f'metadata_hash:{self.id}', f'{decoder_name}_decoder', 1) | ||||
|             r_metadata.zincrby(f'{decoder_name}_type:{mimetype}', date, 1) | ||||
| 
 | ||||
|             r_metadata.incrby(f'{decoder_name}_decoded:{date}', 1) | ||||
|             r_metadata.zincrby(f'{decoder_name}_date:{date}', self.id, 1) | ||||
| 
 | ||||
| 
 | ||||
|             self.update_daterange(date) | ||||
| 
 | ||||
|         # First Hash for this decoder this day | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         Decoded.save_decoded_file_content(sha1_string, decoded_file, item_date, mimetype=mimetype) | ||||
|         ####correlation Decoded.save_item_relationship(sha1_string, item_id) | ||||
|         Decoded.create_decoder_matadata(sha1_string, item_id, decoder_name) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|             # Correlations | ||||
|             self.add_correlation('item', '', obj_id) | ||||
|             # domain | ||||
|             if is_crawled(obj_id): | ||||
|                 domain = get_item_domain(obj_id) | ||||
|                 self.add_correlation('domain', '', domain) | ||||
| 
 | ||||
| 
 | ||||
|         # Filter duplicates ###################################################################### | ||||
|         # Filter on item + hash for this day | ||||
| 
 | ||||
|         # filter Obj Duplicate | ||||
| 
 | ||||
|         # first time we see this day | ||||
|         # iterate on all decoder | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         ###################################################################### | ||||
| 
 | ||||
|         # first time we see this hash today | ||||
| 
 | ||||
| 
 | ||||
|         # mimetype # # # # # # # # | ||||
|         r_metadata.zincrby(f'decoded:mimetype:{date}', mimetype, 1) | ||||
| 
 | ||||
|         # create hash metadata | ||||
|         r_metadata.sadd(f'decoded:mimetypes', mimetype) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     # # TODO: DUPLICATES + check fields | ||||
|     def add(self, decoder_name, date, obj_id, mimetype): | ||||
|         self.update_daterange(date) | ||||
| 
 | ||||
|         r_metadata.incrby(f'{decoder_type}_decoded:{date}', 1) | ||||
|         r_metadata.zincrby(f'{decoder_type}_date:{date}', self.id, 1) | ||||
| 
 | ||||
|         r_metadata.hincrby(f'metadata_hash:{self.id}', f'{decoder_type}_decoder', 1) | ||||
|         r_metadata.zincrby(f'{decoder_type}_type:{mimetype}', date, 1) # # TODO: # DUP1 | ||||
| 
 | ||||
|         ################################################################ # TODO:  REMOVE ????????????????????????????????? | ||||
|         r_metadata.zincrby(f'{decoder_type}_hash:{self.id}', obj_id, 1) # number of b64 on this item | ||||
| 
 | ||||
| 
 | ||||
|         # first time we see this hash encoding on this item | ||||
|         if not r_metadata.zscore(f'{decoder_type}_hash:{self.id}', obj_id): | ||||
| 
 | ||||
|             # create hash metadata | ||||
|             r_metadata.sadd(f'hash_{decoder_type}_all_type', mimetype) | ||||
| 
 | ||||
|             # first time we see this hash encoding today | ||||
|             if not r_metadata.zscore(f'{decoder_type}_date:{date}', self.id): | ||||
|                 r_metadata.zincrby(f'{decoder_type}_type:{mimetype}', date, 1) # # TODO: # DUP1 | ||||
| 
 | ||||
| 
 | ||||
|         # Correlations | ||||
|         self.add_correlation('item', '', obj_id) | ||||
|         # domain | ||||
|         if is_crawled(obj_id): | ||||
|             domain = get_item_domain(obj_id) | ||||
|             self.add_correlation('domain', '', domain) | ||||
| 
 | ||||
| 
 | ||||
|     # NB of MIMETYPE / DAY -> ALL HASH OR UNIQ HASH ?????? | ||||
| 
 | ||||
|     # # TODO: ADD items | ||||
|     def create(self, content, date, mimetype=None): | ||||
|         if not mimetype: | ||||
|             mimetype = self.guess_mimetype(content) | ||||
|         self.save_file(content, mimetype) | ||||
| 
 | ||||
| 
 | ||||
|         update_decoded_daterange(sha1_string, date_from) | ||||
|         if date_from != date_to and date_to: | ||||
|             update_decoded_daterange(sha1_string, date_to) | ||||
| 
 | ||||
|         ####################################################################################### | ||||
|         ####################################################################################### | ||||
| 
 | ||||
|         ####################################################################################### | ||||
|         ####################################################################################### | ||||
| 
 | ||||
|     def set_vt_report(self, report): | ||||
|         r_metadata.hset(f'metadata_hash:{self.id}', 'vt_report', report) | ||||
| 
 | ||||
|     def set_meta_vt(self, link, report): | ||||
|         r_metadata.hset(f'metadata_hash:{self.id}', 'vt_link', link) | ||||
|         self.set_vt_report(report) | ||||
| 
 | ||||
|     def refresh_vt_report(self): | ||||
|         params = {'apikey': VT_TOKEN, 'resource': self.id} | ||||
|         response = requests.get('https://www.virustotal.com/vtapi/v2/file/report', params=params) | ||||
|         if response.status_code == 200: | ||||
|             json_response = response.json() | ||||
|             response_code = json_response['response_code'] | ||||
|             # report exist | ||||
|             if response_code == 1: | ||||
|                 total = json_response['total'] | ||||
|                 detection = json_response['positives'] | ||||
|                 report = f'Detection {detection}/{total}' | ||||
|             # no report found | ||||
|             elif response_code == 0: | ||||
|                 report = 'No report found' | ||||
|             # file in queue | ||||
|             elif response_code == -2: | ||||
|                 report = 'In Queue - Refresh' | ||||
|             self.set_vt_report(report) | ||||
|             print(json_response) | ||||
|             print(response_code) | ||||
|             print(report) | ||||
|             return report | ||||
|         elif response.status_code == 403: | ||||
|             Flask_config.vt_enabled = False | ||||
|             return 'Virustotal key is incorrect (e.g. for public API not for virustotal intelligence), authentication failed' | ||||
|         elif response.status_code == 204: | ||||
|             return 'Rate Limited' | ||||
| 
 | ||||
|     def send_to_vt(self): | ||||
|         files = {'file': (self.id, self.get_content())} | ||||
|         response = requests.post('https://www.virustotal.com/vtapi/v2/file/scan', files=files, params= {'apikey': VT_TOKEN}) | ||||
|         json_response = response.json() | ||||
|         link = json_response['permalink'].split('analysis')[0] + 'analysis/' | ||||
|         self.set_meta_vt(link, 'Please Refresh') | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
| def get_decoders_names(): | ||||
|     return ['base64', 'binary', 'hexadecimal'] | ||||
| 
 | ||||
| def get_all_mimetypes(): | ||||
|     return r_metadata.smembers(f'decoded:mimetypes') | ||||
| 
 | ||||
| #if __name__ == '__main__': | ||||
| def sanityze_decoder_names(decoder_name): | ||||
|     if decoder_name not in Decodeds.get_decoders_names(): | ||||
|         return None | ||||
|     else: | ||||
|         return decoder_name | ||||
| 
 | ||||
| def sanityze_mimetype(mimetype): | ||||
|     if mimetype == 'All types': | ||||
|         return None | ||||
|     elif not r_metadata.sismember('hash_all_type', mimetype): | ||||
|         return None | ||||
|     else: | ||||
|         return mimetype | ||||
| 
 | ||||
| def pie_chart_mimetype_json(date_from, date_to, mimetype, decoder_name): | ||||
|     if mimetype: | ||||
|         all_mimetypes = [mimetype] | ||||
|     else: | ||||
|         all_mimetypes = get_all_mimetypes() | ||||
|     date_range = Date.substract_date(date_from, date_to) | ||||
|     for date in date_range: | ||||
|         for mimet in all_mimetypes: | ||||
|             pass | ||||
| 
 | ||||
| def pie_chart_decoder_json(date_from, date_to, mimetype): | ||||
|     all_decoder = get_decoders_names() | ||||
|     date_range = Date.substract_date(date_from, date_to) | ||||
|     if not date_range: | ||||
|         date_range.append(Date.get_today_date_str()) | ||||
|     nb_decoder = {} | ||||
|     for date in date_range: | ||||
|         for decoder_name in all_decoder: | ||||
|             if not mimetype: | ||||
|                 nb = r_metadata.get(f'{decoder_name}_decoded:{date}') | ||||
|                 if nb is None: | ||||
|                     nb = 0 | ||||
|                 else: | ||||
|                     nb = int(nb) | ||||
|             else: | ||||
|                 nb = r_metadata.zscore(f'{decoder_name}_type:{mimetype}', date) | ||||
|             nb_decoder[decoder_name] = nb_decoder.get(decoder_name, 0) + nb | ||||
|     pie_chart = [] | ||||
|     for decoder_name in all_decoder: | ||||
|         pie_chart.append({'name': decoder_name, 'value': nb_decoder[decoder_name]}) | ||||
|     return pie_chart | ||||
| 
 | ||||
| def api_pie_chart_decoder_json(date_from, date_to, mimetype): | ||||
|     mimetype = sanityze_mimetype(mimetype) | ||||
|     date = Date.sanitise_date_range(date_from, date_to) | ||||
|     return pie_chart_decoder_json(date['date_from'], date['date_to'], mimetype) | ||||
| 
 | ||||
| def _delete_old_json_descriptor(): | ||||
|     decodeds = [] | ||||
|     hash_dir = os.path.join(os.environ['AIL_HOME'], HASH_DIR) | ||||
|     for root, dirs, files in os.walk(hash_dir): | ||||
|         for file in files: | ||||
|             if file.endswith('.json'): | ||||
|                 decoded_path = f'{root}/{file}' | ||||
|                 os.remove(decoded_path) | ||||
|     return decodeds | ||||
| 
 | ||||
| def get_all_decodeds(): | ||||
|     decodeds = [] | ||||
|     hash_dir = os.path.join(os.environ['AIL_HOME'], HASH_DIR) | ||||
|     if not hash_dir.endswith("/"): | ||||
|         hash_dir = f"{hash_dir}/" | ||||
|     for root, dirs, files in os.walk(hash_dir): | ||||
|         for file in files: | ||||
|             decoded_path = f'{root}{file}' | ||||
|             decodeds.append(file) | ||||
|     return decodeds | ||||
| 
 | ||||
|  #if __name__ == '__main__': | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ class Domain(AbstractObject): | |||
|         else: | ||||
|             return 'regular' | ||||
| 
 | ||||
|     def get_first_seen(selfr_int=False, separator=True): | ||||
|     def get_first_seen(self, r_int=False, separator=True): | ||||
|         first_seen = r_onion.hget(f'{self.domain_type}_metadata:{self.id}', 'first_seen') | ||||
|         if first_seen: | ||||
|             if separator: | ||||
|  | @ -62,12 +62,59 @@ class Domain(AbstractObject): | |||
|                 last_check = int(last_check) | ||||
|         return last_check | ||||
| 
 | ||||
|     def get_ports(self): | ||||
|     def _set_first_seen(self, date): | ||||
|         r_onion.hset(f'{self.domain_type}_metadata:{self.id}', 'first_seen', date) | ||||
| 
 | ||||
|     def _set_last_check(self, date): | ||||
|         r_onion.hset(f'{self.domain_type}_metadata:{self.id}', 'last_check', date) | ||||
| 
 | ||||
|     def update_daterange(self, date): | ||||
|         first_seen = self.get_first_seen(r_int=True) | ||||
|         last_check = self.get_last_check(r_int=True) | ||||
|         if not first_seen: | ||||
|             self._set_first_seen(date) | ||||
|             self._set_last_check(date) | ||||
|         elif int(first_seen) > date: | ||||
|             self._set_first_seen(date) | ||||
|         elif int(last_check) < date: | ||||
|             self._set_last_check(date) | ||||
| 
 | ||||
|     def get_last_origin(self): | ||||
|         return r_onion.hget(f'{self.domain_type}_metadata:{self.id}', 'paste_parent') | ||||
| 
 | ||||
|     def set_last_origin(self, origin_id): | ||||
|         r_onion.hset(f'{self.domain_type}_metadata:{self.id}', 'paste_parent', origin_id) | ||||
| 
 | ||||
|     def is_up(self, ports=[]): | ||||
|         if not ports: | ||||
|             ports = self.get_ports() | ||||
|         for port in ports: | ||||
|             res = r_onion.zrevrange(f'crawler_history_{self.domain_type}:{self.id}:{port}', 0, 0, withscores=True) | ||||
|             if res: | ||||
|                 item_core, epoch = res[0] | ||||
|                 if item_core != str(epoch): | ||||
|                     return True | ||||
|         return False | ||||
| 
 | ||||
|     def get_ports(self, r_set=False): | ||||
|         l_ports = r_onion.hget(f'{self.domain_type}_metadata:{self.id}', 'ports') | ||||
|         if l_ports: | ||||
|             return l_ports.split(";") | ||||
|             l_ports = l_ports.split(";") | ||||
|             if r_set: | ||||
|                 return set(l_ports) | ||||
|             else: | ||||
|                 return l_ports | ||||
|         return [] | ||||
| 
 | ||||
|     def _set_ports(self, ports): | ||||
|         ports = ';'.join(ports) | ||||
|         r_onion.hset(f'{self.domain_type}_metadata:{self.id}', 'ports', ports) | ||||
| 
 | ||||
|     def add_ports(self, port): | ||||
|         ports = self.get_ports(r_set=True) | ||||
|         ports.add(port) | ||||
|         self._set_ports(ports) | ||||
| 
 | ||||
|     def get_history_by_port(self, port, status=False, root=False): | ||||
|         ''' | ||||
|         Return . | ||||
|  | @ -94,6 +141,23 @@ class Domain(AbstractObject): | |||
|             history.append(dict_history) | ||||
|         return history | ||||
| 
 | ||||
|     def get_languages(self): | ||||
|         return r_onion.smembers(f'domain:language:{self.id}') | ||||
| 
 | ||||
|     def get_meta(self): | ||||
|         meta = {} | ||||
|         meta['type'] = self.domain_type | ||||
|         meta['first_seen'] = self.get_first_seen() | ||||
|         meta['last_check'] = self.get_last_check() | ||||
|         meta['last_origin'] = self.last_origin() | ||||
|         meta['ports'] = self.get_ports() | ||||
|         meta['status'] = self.is_up(ports=ports) | ||||
|         meta['tags'] = self.get_last_origin() | ||||
|         #meta['is_tags_safe'] = | ||||
|         meta['languages'] = self.get_languages() | ||||
|         #meta['screenshot'] = | ||||
| 
 | ||||
| 
 | ||||
|     # # WARNING: UNCLEAN DELETE /!\ TEST ONLY /!\ | ||||
|     def delete(self): | ||||
|         # # TODO: | ||||
|  | @ -179,16 +243,74 @@ class Domain(AbstractObject): | |||
|                 obj_attr.add_tag(tag) | ||||
|         return obj | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     def add_language(self, language): | ||||
|         r_onion.sadd('all_domains_languages', language) | ||||
|         r_onion.sadd(f'all_domains_languages:{self.domain_type}', language) | ||||
|         r_onion.sadd(f'language:domains:{self.domain_type}:{language}', self.id) | ||||
|         r_onion.sadd(f'domain:language:{self.id}', language) | ||||
| 
 | ||||
|     def exist_correlation(self): | ||||
|         pass | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
| 
 | ||||
|     def create(self, first_seen, last_check, ports, status, tags, languages): | ||||
| 
 | ||||
| 
 | ||||
|         r_onion.hset(f'{self.domain_type}_metadata:{self.id}', 'first_seen', first_seen) | ||||
|         r_onion.hset(f'{self.domain_type}_metadata:{self.id}', 'last_check', last_check) | ||||
| 
 | ||||
|         for language in languages: | ||||
|             self.add_language(language) | ||||
| 
 | ||||
|     #### CRAWLER #### | ||||
| 
 | ||||
|     # add root_item to history | ||||
|     # if domain down -> root_item = epoch | ||||
|     def _add_history_root_item(self, root_item, epoch, port): | ||||
|         # Create/Update crawler history | ||||
|         r_onion.zadd(f'crawler_history_{self.domain_type}:{self.id}:{port}', epoch, int(root_item)) | ||||
| 
 | ||||
|     # if domain down -> root_item = epoch | ||||
|     def add_history(self, epoch, port, root_item=None): | ||||
|         date = time.strftime('%Y%m%d', time.gmtime(epoch)) | ||||
|         try: | ||||
|             int(root_item) | ||||
|         except ValueError: | ||||
|             root_item = None | ||||
|         # UP | ||||
|         if root_item: | ||||
|             r_onion.sadd(f'full_{self.domain_type}_up', self.id) | ||||
|             r_onion.sadd(f'{self.domain_type}_up:{date}', self.id) # # TODO:  -> store first day | ||||
|             r_onion.sadd(f'month_{self.domain_type}_up:{date[0:6]}', self.id) # # TODO:  -> store first month | ||||
|             self._add_history_root_item(root_item, epoch, port) | ||||
|         else: | ||||
|             r_onion.sadd(f'{self.domain_type}_down:{date}', self.id) # # TODO:  -> store first month | ||||
|             self._add_history_root_item(epoch, epoch, port) | ||||
| 
 | ||||
|     def add_crawled_item(self, url, port, item_id, item_father): | ||||
|         r_metadata.hset(f'paste_metadata:{item_id}', 'father', item_father) | ||||
|         r_metadata.hset(f'paste_metadata:{item_id}', 'domain', f'{self.id}:{port}') | ||||
|         r_metadata.hset(f'paste_metadata:{item_id}', 'real_link', url) | ||||
|         # add this item_id to his father | ||||
|         r_metadata.sadd(f'paste_children:{item_father}', item_id) | ||||
| 
 | ||||
|     ##-- CRAWLER --## | ||||
| 
 | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
| def get_all_domains_types(): | ||||
|     return ['onion', 'regular'] # i2p | ||||
| 
 | ||||
| def get_all_domains_languages(): | ||||
|     return r_onion.smembers('all_domains_languages') | ||||
| 
 | ||||
| def get_domains_up_by_type(domain_type): | ||||
|     return r_onion.smembers(f'full_{domain_type}_up') | ||||
| 
 | ||||
| ################################################################################ | ||||
| ################################################################################ | ||||
| 
 | ||||
| #if __name__ == '__main__': | ||||
|  |  | |||
|  | @ -22,19 +22,9 @@ from export.Export import get_ail_uuid # # TODO: REPLACE | |||
| from lib.objects.abstract_object import AbstractObject | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
| from lib import item_basic | ||||
| from lib import domain_basic | ||||
| 
 | ||||
| from packages import Tag | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/')) | ||||
| import Cryptocurrency | ||||
| import Pgp | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib/')) | ||||
| import Correlate_object | ||||
| import Decoded | ||||
| import Screenshot | ||||
| import Username | ||||
| 
 | ||||
| from flask import url_for | ||||
| 
 | ||||
|  | @ -310,6 +300,51 @@ class Item(AbstractObject): | |||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
| def _get_dir_source_name(dir, source_name=None, l_sources_name=set(), filter_dir=False): | ||||
|     if not l_sources_name: | ||||
|         l_sources_name = set() | ||||
|     if source_name: | ||||
|         l_dir = os.listdir(os.path.join(dir, source_name)) | ||||
|     else: | ||||
|         l_dir = os.listdir(dir) | ||||
|     # empty directory | ||||
|     if not l_dir: | ||||
|         return l_sources_name.add(source_name) | ||||
|     else: | ||||
|         for src_name in l_dir: | ||||
|             if len(src_name) == 4: | ||||
|                 #try: | ||||
|                 int(src_name) | ||||
|                 to_add = os.path.join(source_name) | ||||
|                 # filter sources, remove first directory | ||||
|                 if filter_dir: | ||||
|                     to_add = to_add.replace('archive/', '').replace('alerts/', '') | ||||
|                 l_sources_name.add(to_add) | ||||
|                 return l_sources_name | ||||
|                 #except: | ||||
|                 #    pass | ||||
|             if source_name: | ||||
|                 src_name = os.path.join(source_name, src_name) | ||||
|             l_sources_name = _get_dir_source_name(dir, source_name=src_name, l_sources_name=l_sources_name, filter_dir=filter_dir) | ||||
|     return l_sources_name | ||||
| 
 | ||||
| def get_items_sources(filter_dir=False, r_list=False): | ||||
|     res = _get_dir_source_name(ITEMS_FOLDER, filter_dir=filter_dir) | ||||
|     if res: | ||||
|         if r_list: | ||||
|             res = list(res) | ||||
|         return res | ||||
|     else: | ||||
|         return [] | ||||
| 
 | ||||
| def get_items_by_source(source): | ||||
|     l_items = [] | ||||
|     dir_item = os.path.join(os.environ['AIL_HOME'], ITEMS_FOLDER, source) | ||||
|     for root, dirs, files in os.walk(dir_item): | ||||
|         for file in files: | ||||
|             item_id = os.path.join(root, file).replace(ITEMS_FOLDER, '', 1) | ||||
|             l_items.append(item_id) | ||||
|     return l_items | ||||
| 
 | ||||
| ################################################################################ | ||||
| ################################################################################ | ||||
|  | @ -526,117 +561,6 @@ def api_get_items_sources(): | |||
| #         return {'status': 'error', 'reason': 'Invalid source', 'provide': source}, 400 | ||||
| #     return {'status': 'success', 'reason': 'Valid source', 'provide': source}, 200 | ||||
| 
 | ||||
| ### | ||||
| ### correlation | ||||
| ### | ||||
| def get_item_cryptocurrency(item_id, currencies_type=None, get_nb=False): | ||||
|     ''' | ||||
|     Return all cryptocurrencies of a given item. | ||||
| 
 | ||||
|     :param item_id: item id | ||||
|     :param currencies_type: list of cryptocurrencies type | ||||
|     :type currencies_type: list, optional | ||||
|     ''' | ||||
|     return Cryptocurrency.cryptocurrency.get_item_correlation_dict(item_id, correlation_type=currencies_type, get_nb=get_nb) | ||||
| 
 | ||||
| def get_item_pgp(item_id, currencies_type=None, get_nb=False): | ||||
|     ''' | ||||
|     Return all pgp of a given item. | ||||
| 
 | ||||
|     :param item_id: item id | ||||
|     :param currencies_type: list of cryptocurrencies type | ||||
|     :type currencies_type: list, optional | ||||
|     ''' | ||||
|     return Pgp.pgp.get_item_correlation_dict(item_id, correlation_type=currencies_type, get_nb=get_nb) | ||||
| 
 | ||||
| def get_item_username(item_id, sub_type=None, get_nb=False): | ||||
|     ''' | ||||
|     Return all pgp of a given item. | ||||
| 
 | ||||
|     :param item_id: item id | ||||
|     :param sub_type: list of username type | ||||
|     :type sub_type: list, optional | ||||
|     ''' | ||||
|     return Username.correlation.get_item_correlation_dict(item_id, correlation_type=sub_type, get_nb=get_nb) | ||||
| 
 | ||||
| def get_item_decoded(item_id): | ||||
|     ''' | ||||
|     Return all pgp of a given item. | ||||
| 
 | ||||
|     :param item_id: item id | ||||
|     :param currencies_type: list of cryptocurrencies type | ||||
|     :type currencies_type: list, optional | ||||
|     ''' | ||||
|     return Decoded.get_item_decoded(item_id) | ||||
| 
 | ||||
| def get_item_all_screenshot(item_id): | ||||
|     ''' | ||||
|     Return all screenshot of a given item. | ||||
| 
 | ||||
|     :param item_id: item id | ||||
|     ''' | ||||
|     return Screenshot.get_item_screenshot_list(item_id) | ||||
| 
 | ||||
| def get_item_all_correlation(item_id, correlation_names=[], get_nb=False): | ||||
|     ''' | ||||
|     Retun all correlation of a given item id. | ||||
| 
 | ||||
|     :param item_id: item id | ||||
|     :type domain: str | ||||
| 
 | ||||
|     :return: a dict of all correlation for a item id | ||||
|     :rtype: dict | ||||
|     ''' | ||||
|     if not correlation_names: | ||||
|         correlation_names = Correlate_object.get_all_correlation_names() | ||||
|     item_correl = {} | ||||
|     for correlation_name in correlation_names: | ||||
|         if correlation_name=='cryptocurrency': | ||||
|             res = get_item_cryptocurrency(item_id, get_nb=get_nb) | ||||
|         elif correlation_name=='pgp': | ||||
|             res = get_item_pgp(item_id, get_nb=get_nb) | ||||
|         elif correlation_name=='username': | ||||
|             res = get_item_username(item_id, get_nb=get_nb) | ||||
|         elif correlation_name=='decoded': | ||||
|             res = get_item_decoded(item_id) | ||||
|         elif correlation_name=='screenshot': | ||||
|             res = get_item_all_screenshot(item_id) | ||||
|         else: | ||||
|             res = None | ||||
|         # add correllation to dict | ||||
|         if res: | ||||
|             item_correl[correlation_name] = res | ||||
|     return item_correl | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## TODO: REFRACTOR | ||||
| def _get_item_correlation(correlation_name, correlation_type, item_id): | ||||
|     res = r_serv_metadata.smembers('item_{}_{}:{}'.format(correlation_name, correlation_type, item_id)) | ||||
|     if res: | ||||
|         return list(res) | ||||
|     else: | ||||
|         return [] | ||||
| 
 | ||||
| ## TODO: REFRACTOR | ||||
| def get_item_bitcoin(item_id): | ||||
|     return _get_item_correlation('cryptocurrency', 'bitcoin', item_id) | ||||
| 
 | ||||
| ## TODO: REFRACTOR | ||||
| def get_item_pgp_key(item_id): | ||||
|     return _get_item_correlation('pgpdump', 'key', item_id) | ||||
| 
 | ||||
| ## TODO: REFRACTOR | ||||
| def get_item_pgp_name(item_id): | ||||
|     return _get_item_correlation('pgpdump', 'name', item_id) | ||||
| 
 | ||||
| ## TODO: REFRACTOR | ||||
| def get_item_pgp_mail(item_id): | ||||
|     return _get_item_correlation('pgpdump', 'mail', item_id) | ||||
| 
 | ||||
| ## TODO: REFRACTOR | ||||
| def get_item_pgp_correlation(item_id): | ||||
|     pass | ||||
| 
 | ||||
| ### | ||||
| ### GET Internal Module DESC | ||||
|  | @ -804,60 +728,63 @@ def create_item(obj_id, obj_metadata, io_content): | |||
|     # Item not created | ||||
|     return False | ||||
| 
 | ||||
| # # TODO: | ||||
| def delete_item(obj_id): | ||||
|     # check if item exists | ||||
|     if not exist_item(obj_id): | ||||
|         return False | ||||
|     else: | ||||
|         delete_item_duplicate(obj_id) | ||||
|         # delete MISP event | ||||
|         r_serv_metadata.delete('misp_events:{}'.format(obj_id)) | ||||
|         r_serv_metadata.delete('hive_cases:{}'.format(obj_id)) | ||||
|     pass | ||||
| 
 | ||||
|         os.remove(get_item_filename(obj_id)) | ||||
| 
 | ||||
|         # get all correlation | ||||
|         obj_correlations = get_item_all_correlation(obj_id) | ||||
|         for correlation in obj_correlations: | ||||
|             if correlation=='cryptocurrency' or correlation=='pgp': | ||||
|                 for obj2_subtype in obj_correlations[correlation]: | ||||
|                     for obj2_id in obj_correlations[correlation][obj2_subtype]: | ||||
|                         Correlate_object.delete_obj_relationship(correlation, obj2_id, 'item', obj_id, | ||||
|                                                             obj1_subtype=obj2_subtype) | ||||
|             else: | ||||
|                 for obj2_id in obj_correlations[correlation]: | ||||
|                     Correlate_object.delete_obj_relationship(correlation, obj2_id, 'item', obj_id) | ||||
| 
 | ||||
|         # delete father/child | ||||
|         delete_node(obj_id) | ||||
| 
 | ||||
|         # delete item metadata | ||||
|         r_serv_metadata.delete('paste_metadata:{}'.format(obj_id)) | ||||
| 
 | ||||
|         return True | ||||
| 
 | ||||
|     ### TODO in inport V2 | ||||
|     # delete from tracked items | ||||
| 
 | ||||
|     # # # TODO: # FIXME: LATER | ||||
|     # delete from queue | ||||
|     ### | ||||
|     return False | ||||
|     # # check if item exists | ||||
|     # if not exist_item(obj_id): | ||||
|     #     return False | ||||
|     # else: | ||||
|     #     delete_item_duplicate(obj_id) | ||||
|     #     # delete MISP event | ||||
|     #     r_serv_metadata.delete('misp_events:{}'.format(obj_id)) | ||||
|     #     r_serv_metadata.delete('hive_cases:{}'.format(obj_id)) | ||||
|     # | ||||
|     #     os.remove(get_item_filename(obj_id)) | ||||
|     # | ||||
|     #     # get all correlation | ||||
|     #     obj_correlations = get_item_all_correlation(obj_id) | ||||
|     #     for correlation in obj_correlations: | ||||
|     #         if correlation=='cryptocurrency' or correlation=='pgp': | ||||
|     #             for obj2_subtype in obj_correlations[correlation]: | ||||
|     #                 for obj2_id in obj_correlations[correlation][obj2_subtype]: | ||||
|     #                     Correlate_object.delete_obj_relationship(correlation, obj2_id, 'item', obj_id, | ||||
|     #                                                         obj1_subtype=obj2_subtype) | ||||
|     #         else: | ||||
|     #             for obj2_id in obj_correlations[correlation]: | ||||
|     #                 Correlate_object.delete_obj_relationship(correlation, obj2_id, 'item', obj_id) | ||||
|     # | ||||
|     #     # delete father/child | ||||
|     #     delete_node(obj_id) | ||||
|     # | ||||
|     #     # delete item metadata | ||||
|     #     r_serv_metadata.delete('paste_metadata:{}'.format(obj_id)) | ||||
|     # | ||||
|     #     return True | ||||
|     # | ||||
|     # ### TODO in inport V2 | ||||
|     # # delete from tracked items | ||||
|     # | ||||
|     # # # # TODO: # FIXME: LATER | ||||
|     # # delete from queue | ||||
|     # ### | ||||
|     # return False | ||||
| 
 | ||||
| #### #### | ||||
| def delete_node(item_id): | ||||
|     if is_node(item_id): | ||||
|         if is_crawled(item_id): | ||||
|             delete_domain_node(item_id) | ||||
|         item_basic._delete_node(item_id) | ||||
| 
 | ||||
| def delete_domain_node(item_id): | ||||
|     if is_domain_root(item_id): | ||||
|         # remove from domain history | ||||
|         domain, port = get_item_domain_with_port(item_id).split(':') | ||||
|         domain_basic.delete_domain_item_core(item_id, domain, port) | ||||
|     for child_id in get_all_domain_node_by_item_id(item_id): | ||||
|         delete_item(child_id) | ||||
| # def delete_node(item_id): | ||||
| #     if is_node(item_id): | ||||
| #         if is_crawled(item_id): | ||||
| #             delete_domain_node(item_id) | ||||
| #         item_basic._delete_node(item_id) | ||||
| # | ||||
| # def delete_domain_node(item_id): | ||||
| #     if is_domain_root(item_id): | ||||
| #         # remove from domain history | ||||
| #         domain, port = get_item_domain_with_port(item_id).split(':') | ||||
| #         domain_basic.delete_domain_item_core(item_id, domain, port) | ||||
| #     for child_id in get_all_domain_node_by_item_id(item_id): | ||||
| #         delete_item(child_id) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ import redis | |||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib/')) | ||||
| import ConfigLoader | ||||
| 
 | ||||
| from abstract_object import AbstractObject | ||||
| from lib.objects.abstract_subtype_object import AbstractSubtypeObject, get_all_id | ||||
| from flask import url_for | ||||
| 
 | ||||
| config_loader = ConfigLoader.ConfigLoader() | ||||
|  | @ -22,7 +22,7 @@ config_loader = None | |||
| ################################################################################ | ||||
| ################################################################################ | ||||
| 
 | ||||
| class Pgp(AbstractObject): | ||||
| class Pgp(AbstractSubtypeObject): | ||||
|     """ | ||||
|     AIL Pgp Object. (strings) | ||||
|     """ | ||||
|  | @ -78,13 +78,18 @@ class Pgp(AbstractObject): | |||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
|     def exist_correlation(self): | ||||
|         pass | ||||
| def get_all_subtypes(): | ||||
|     return ['key', 'mail', 'name'] | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| def get_all_pgps(): | ||||
|     pgps = {} | ||||
|     for subtype in get_all_subtypes(): | ||||
|         pgps[subtype] = get_all_pgps_by_subtype(subtype) | ||||
|     return pgps | ||||
| 
 | ||||
| def get_all_pgps_by_subtype(subtype): | ||||
|     return get_all_id('pgp', subtype) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import os | |||
| import sys | ||||
| 
 | ||||
| from io import BytesIO | ||||
| from flask import url_for | ||||
| 
 | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
|  | @ -71,6 +72,15 @@ class Screenshot(AbstractObject): | |||
|                 obj_attr.add_tag(tag) | ||||
|         return obj | ||||
| 
 | ||||
|     def get_meta(self, options=set()): | ||||
|         meta = {} | ||||
|         meta['id'] = self.id | ||||
|         metadata_dict['img'] = get_screenshot_rel_path(sha256_string) ######### # TODO: Rename ME ?????? | ||||
|         meta['tags'] = self.get_tags() | ||||
|         # TODO: ADD IN ABSTRACT CLASS | ||||
|         #meta['is_tags_safe'] = Tag.is_tags_safe(metadata_dict['tags']) ################## # TODO: ADD IN ABSZTRACT CLASS | ||||
|         return meta | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|  | @ -81,6 +91,26 @@ class Screenshot(AbstractObject): | |||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
| def get_screenshot_dir(): | ||||
|     return SCREENSHOT_FOLDER | ||||
| 
 | ||||
| # get screenshot relative path | ||||
| def get_screenshot_rel_path(sha256_str, add_extension=False): | ||||
|     screenshot_path =  os.path.join(sha256_str[0:2], sha256_str[2:4], sha256_str[4:6], sha256_str[6:8], sha256_str[8:10], sha256_str[10:12], sha256_str[12:]) | ||||
|     if add_extension: | ||||
|         screenshot_path = f'{screenshot_path}.png' | ||||
|     return screenshot_path | ||||
| 
 | ||||
| 
 | ||||
| def get_all_screenshots(): | ||||
|     screenshots = [] | ||||
|     screenshot_dir = os.path.join(os.environ['AIL_HOME'], SCREENSHOT_FOLDER) | ||||
|     for root, dirs, files in os.walk(screenshot_dir): | ||||
|         for file in files: | ||||
|             screenshot_path = f'{root}{file}' | ||||
|             screenshot_id = screenshot_path.replace(SCREENSHOT_FOLDER, '').replace('/', '')[:-4] | ||||
|             screenshots.append(screenshot_id) | ||||
|     return screenshots | ||||
| 
 | ||||
| 
 | ||||
| #if __name__ == '__main__': | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ from pymisp import MISPObject | |||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib/')) | ||||
| import ConfigLoader | ||||
| 
 | ||||
| from abstract_subtype_object import AbstractSubtypeObject | ||||
| from lib.objects.abstract_subtype_object import AbstractSubtypeObject, get_all_id | ||||
| 
 | ||||
| config_loader = ConfigLoader.ConfigLoader() | ||||
| 
 | ||||
|  | @ -82,16 +82,20 @@ class Username(AbstractSubtypeObject): | |||
|                 obj_attr.add_tag(tag) | ||||
|         return obj | ||||
| 
 | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| 
 | ||||
|     def exist_correlation(self): | ||||
|         pass | ||||
| def get_all_subtypes(): | ||||
|     return ['telegram', 'twitter', 'jabber'] | ||||
| 
 | ||||
|     ############################################################################ | ||||
|     ############################################################################ | ||||
| def get_all_usernames(): | ||||
|     users = {} | ||||
|     for subtype in get_all_subtypes(): | ||||
|         users[subtype] = get_all_usernames_by_subtype(subtype) | ||||
|     return users | ||||
| 
 | ||||
| def get_all_usernames_by_subtype(subtype): | ||||
|     return get_all_id('username', subtype) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ sys.path.append(os.environ['AIL_BIN']) | |||
| ################################## | ||||
| from packages import Tag | ||||
| from lib import Duplicate | ||||
| from lib.correlations_engine import get_correlations, add_obj_correlation, delete_obj_correlation, exists_obj_correlation, is_obj_correlated | ||||
| from lib.Investigations import is_object_investigated, get_obj_investigations, delete_obj_investigations | ||||
| from lib.Tracker import is_obj_tracked, get_obj_all_trackers, delete_obj_trackers | ||||
| 
 | ||||
|  | @ -156,13 +157,35 @@ class AbstractObject(ABC): | |||
|     def get_misp_object(self): | ||||
|         pass | ||||
| 
 | ||||
|     # # TODO: | ||||
|     # @abstractmethod | ||||
|     # def get_correlations(self, message): | ||||
|     #     """ | ||||
|     #     Get object correlations | ||||
|     #     """ | ||||
|     #     pass | ||||
|     def get_correlations(self): | ||||
|         """ | ||||
|         Get object correlations | ||||
|         """ | ||||
|         return get_correlations(self.type, self.subtype, self.id) | ||||
| 
 | ||||
|     def add_correlation(self, type2, subtype2, id2): | ||||
|         """ | ||||
|         Add object correlation | ||||
|         """ | ||||
|         add_obj_correlation(self.type, self.subtype, self.id, type2, subtype2, id2) | ||||
| 
 | ||||
|     def exists_correlation(self, type2): | ||||
|         """ | ||||
|         Check if an object is correlated | ||||
|         """ | ||||
|         return exists_obj_correlation(self.type, self.subtype, self.id, type2) | ||||
| 
 | ||||
|     def is_correlated(self, type2, subtype2, id2): | ||||
|         """ | ||||
|         Check if an object is correlated by another object | ||||
|         """ | ||||
|         return is_obj_correlated(self.type, self.subtype, self.id, type2, subtype2, id2) | ||||
| 
 | ||||
|     def delete_correlation(self, type2, subtype2, id2): | ||||
|         """ | ||||
|         Get object correlations | ||||
|         """ | ||||
|         delete_obj_correlation(self.type, self.subtype, self.id, type2, subtype2, id2) | ||||
| 
 | ||||
| 
 | ||||
|     # # TODO: get favicon | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ sys.path.append(os.environ['AIL_BIN']) | |||
| ################################## | ||||
| from lib.objects.abstract_object import AbstractObject | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
| from lib.item_basic import is_crawled, get_item_domain | ||||
| 
 | ||||
| # LOAD CONFIG | ||||
| config_loader = ConfigLoader() | ||||
|  | @ -43,7 +44,6 @@ class AbstractSubtypeObject(AbstractObject): | |||
|         self.type = obj_type | ||||
|         self.subtype = subtype | ||||
| 
 | ||||
|     # # TODO: # FIXME:  REMOVE R_INT ???????????????????????????????????????????????????????????????????? | ||||
|     def get_first_seen(self, r_int=False): | ||||
|         first_seen = r_metadata.hget(f'{self.type}_metadata_{self.subtype}:{self.id}', 'first_seen') | ||||
|         if r_int: | ||||
|  | @ -54,7 +54,6 @@ class AbstractSubtypeObject(AbstractObject): | |||
|         else: | ||||
|             return first_seen | ||||
| 
 | ||||
|     # # TODO: # FIXME:  REMOVE R_INT ???????????????????????????????????????????????????????????????????? | ||||
|     def get_last_seen(self, r_int=False): | ||||
|         last_seen = r_metadata.hget(f'{self.type}_metadata_{self.subtype}:{self.id}', 'last_seen') | ||||
|         if r_int: | ||||
|  | @ -113,49 +112,38 @@ class AbstractSubtypeObject(AbstractObject): | |||
|             if date > last_seen: | ||||
|                 self.set_last_seen(date) | ||||
| 
 | ||||
| # | ||||
| # HANDLE Others objects ???? | ||||
| # | ||||
| # NEW field => first record(last record) | ||||
| #                   by subtype ?????? | ||||
| 
 | ||||
| #               => data Retention + efficicent search | ||||
| # | ||||
| # | ||||
| 
 | ||||
|     def add(self, date, item_id): | ||||
|         self.update_correlation_daterange() | ||||
|         self.update_daterange(date) | ||||
|         # daily | ||||
|         r_metadata.hincrby(f'{self.type}:{self.subtype}:{date}', self.id, 1) | ||||
|         # all type | ||||
|         # all subtypes | ||||
|         r_metadata.zincrby(f'{self.type}_all:{self.subtype}', self.id, 1) | ||||
| 
 | ||||
|         ####################################################################### | ||||
|         ####################################################################### | ||||
|         # REPLACE WITH CORRELATION ????? | ||||
| 
 | ||||
|         # global set | ||||
|         r_serv_metadata.sadd(f'set_{self.type}_{self.subtype}:{self.id}', item_id) | ||||
| 
 | ||||
|         ## object_metadata | ||||
|         # item | ||||
|         r_serv_metadata.sadd(f'item_{self.type}_{self.subtype}:{item_id}', self.id) | ||||
| 
 | ||||
|         # new correlation | ||||
|         # | ||||
|         #       How to filter by correlation type ???? | ||||
|         # | ||||
|         f'correlation:obj:{self.type}:{self.subtype}:{self.id}',                f'{obj_type}:{obj_subtype}:{obj_id}' | ||||
|         f'correlation:obj:{self.type}:{self.subtype}:{obj_type}:{self.id}',     f'{obj_subtype}:{obj_id}' | ||||
| 
 | ||||
|         # | ||||
|         # | ||||
|         # | ||||
|         # | ||||
|         # | ||||
|         # | ||||
|         # | ||||
|         # | ||||
|         # Correlations | ||||
|         self.add_correlation('item', '', item_id) | ||||
|         # domain | ||||
|         if is_crawled(item_id): | ||||
|             domain = get_item_domain(item_id) | ||||
|             self.add_correlation('domain', '', domain) | ||||
| 
 | ||||
| 
 | ||||
|         # # domain | ||||
|         # if item_basic.is_crawled(item_id): | ||||
|         #     domain = item_basic.get_item_domain(item_id) | ||||
|         #     self.save_domain_correlation(domain, subtype, obj_id) | ||||
| 
 | ||||
|     # TODO:ADD objects + Stats | ||||
|     def create(self, first_seen, last_seen): | ||||
|         pass | ||||
| 
 | ||||
|         self.set_first_seen(first_seen) | ||||
|         self.set_last_seen(last_seen) | ||||
| 
 | ||||
| 
 | ||||
|     def _delete(self): | ||||
|  | @ -168,16 +156,7 @@ class AbstractSubtypeObject(AbstractObject): | |||
|     # get_metadata | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
|     # | ||||
| 
 | ||||
| 
 | ||||
| def get_all_id(obj_type, subtype): | ||||
|     return r_metadata.zrange(f'{obj_type}_all:{subtype}', 0, -1) | ||||
|  |  | |||
|  | @ -73,7 +73,7 @@ class Credential(AbstractModule): | |||
| 
 | ||||
|         # Database | ||||
|         config_loader = ConfigLoader.ConfigLoader() | ||||
|         self.server_cred = config_loader.get_redis_conn("ARDB_TermCred") | ||||
|         #self.server_cred = config_loader.get_redis_conn("ARDB_TermCred") | ||||
|         self.server_statistics = config_loader.get_redis_conn("ARDB_Statistics") | ||||
| 
 | ||||
|         # Config values | ||||
|  | @ -172,32 +172,33 @@ class Credential(AbstractModule): | |||
|                 self.redis_logger.info(to_print) | ||||
|                 print(f'found {nb_cred} credentials') | ||||
| 
 | ||||
|             # For searching credential in termFreq | ||||
|             for cred in all_credentials: | ||||
|                 cred = cred.split('@')[0] #Split to ignore mail address | ||||
| 
 | ||||
|                 # unique number attached to unique path | ||||
|                 uniq_num_path = self.server_cred.incr(Credential.REDIS_KEY_NUM_PATH) | ||||
|                 self.server_cred.hmset(Credential.REDIS_KEY_ALL_PATH_SET, {item.get_id(): uniq_num_path}) | ||||
|                 self.server_cred.hmset(Credential.REDIS_KEY_ALL_PATH_SET_REV, {uniq_num_path: item.get_id()}) | ||||
| 
 | ||||
|                 # unique number attached to unique username | ||||
|                 uniq_num_cred = self.server_cred.hget(Credential.REDIS_KEY_ALL_CRED_SET, cred) | ||||
|                 if uniq_num_cred is None: | ||||
|                     # cred do not exist, create new entries | ||||
|                     uniq_num_cred = self.server_cred.incr(Credential.REDIS_KEY_NUM_USERNAME) | ||||
|                     self.server_cred.hmset(Credential.REDIS_KEY_ALL_CRED_SET, {cred: uniq_num_cred}) | ||||
|                     self.server_cred.hmset(Credential.REDIS_KEY_ALL_CRED_SET_REV, {uniq_num_cred: cred}) | ||||
| 
 | ||||
|                 # Add the mapping between the credential and the path | ||||
|                 self.server_cred.sadd(Credential.REDIS_KEY_MAP_CRED_TO_PATH+'_'+str(uniq_num_cred), uniq_num_path) | ||||
| 
 | ||||
|                 # Split credentials on capital letters, numbers, dots and so on | ||||
|                 # Add the split to redis, each split point towards its initial credential unique number | ||||
|                 splitedCred = re.findall(Credential.REGEX_CRED, cred) | ||||
|                 for partCred in splitedCred: | ||||
|                     if len(partCred) > self.minimumLengthThreshold: | ||||
|                         self.server_cred.sadd(partCred, uniq_num_cred) | ||||
|             # # TODO: # FIXME: TEMP DESABLE | ||||
|             # # For searching credential in termFreq | ||||
|             # for cred in all_credentials: | ||||
|             #     cred = cred.split('@')[0] #Split to ignore mail address | ||||
|             # | ||||
|             #     # unique number attached to unique path | ||||
|             #     uniq_num_path = self.server_cred.incr(Credential.REDIS_KEY_NUM_PATH) | ||||
|             #     self.server_cred.hmset(Credential.REDIS_KEY_ALL_PATH_SET, {item.get_id(): uniq_num_path}) | ||||
|             #     self.server_cred.hmset(Credential.REDIS_KEY_ALL_PATH_SET_REV, {uniq_num_path: item.get_id()}) | ||||
|             # | ||||
|             #     # unique number attached to unique username | ||||
|             #     uniq_num_cred = self.server_cred.hget(Credential.REDIS_KEY_ALL_CRED_SET, cred) | ||||
|             #     if uniq_num_cred is None: | ||||
|             #         # cred do not exist, create new entries | ||||
|             #         uniq_num_cred = self.server_cred.incr(Credential.REDIS_KEY_NUM_USERNAME) | ||||
|             #         self.server_cred.hmset(Credential.REDIS_KEY_ALL_CRED_SET, {cred: uniq_num_cred}) | ||||
|             #         self.server_cred.hmset(Credential.REDIS_KEY_ALL_CRED_SET_REV, {uniq_num_cred: cred}) | ||||
|             # | ||||
|             #     # Add the mapping between the credential and the path | ||||
|             #     self.server_cred.sadd(Credential.REDIS_KEY_MAP_CRED_TO_PATH+'_'+str(uniq_num_cred), uniq_num_path) | ||||
|             # | ||||
|             #     # Split credentials on capital letters, numbers, dots and so on | ||||
|             #     # Add the split to redis, each split point towards its initial credential unique number | ||||
|             #     splitedCred = re.findall(Credential.REGEX_CRED, cred) | ||||
|             #     for partCred in splitedCred: | ||||
|             #         if len(partCred) > self.minimumLengthThreshold: | ||||
|             #             self.server_cred.sadd(partCred, uniq_num_cred) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|  |  | |||
|  | @ -11,7 +11,6 @@ | |||
| ################################## | ||||
| import time | ||||
| import os | ||||
| import redis | ||||
| import base64 | ||||
| from hashlib import sha1 | ||||
| import magic | ||||
|  | @ -26,10 +25,19 @@ sys.path.append(os.environ['AIL_BIN']) | |||
| # Import Project packages | ||||
| ################################## | ||||
| from modules.abstract_module import AbstractModule | ||||
| from Helper import Process | ||||
| from packages import Item | ||||
| from lib import ConfigLoader | ||||
| from lib import Decoded | ||||
| from lib.ConfigLoader import ConfigLoader | ||||
| from lib.objects.Items import Item | ||||
| from lib.objects import Decodeds | ||||
| 
 | ||||
| config_loader = ConfigLoader() | ||||
| serv_metadata = config_loader.get_redis_conn("ARDB_Metadata") | ||||
| hex_max_execution_time = config_loader.get_config_int("Hex", "max_execution_time") | ||||
| binary_max_execution_time = config_loader.get_config_int("Binary", "max_execution_time") | ||||
| base64_max_execution_time = config_loader.get_config_int("Base64", "max_execution_time") | ||||
| config_loader = None | ||||
| 
 | ||||
| ##################################################### | ||||
| ##################################################### | ||||
| 
 | ||||
| # # TODO: use regex_helper | ||||
| class TimeoutException(Exception): | ||||
|  | @ -38,9 +46,15 @@ class TimeoutException(Exception): | |||
| def timeout_handler(signum, frame): | ||||
|     raise TimeoutException | ||||
| 
 | ||||
| 
 | ||||
| # # TODO: # FIXME: Remove signal -> replace with regex_helper | ||||
| signal.signal(signal.SIGALRM, timeout_handler) | ||||
| 
 | ||||
| 
 | ||||
| ##################################################### | ||||
| #################################################### | ||||
| 
 | ||||
| 
 | ||||
| class Decoder(AbstractModule): | ||||
|     """ | ||||
|     Decoder module for AIL framework | ||||
|  | @ -65,8 +79,6 @@ class Decoder(AbstractModule): | |||
|     def __init__(self): | ||||
|         super(Decoder, self).__init__() | ||||
| 
 | ||||
|         serv_metadata = ConfigLoader.ConfigLoader().get_redis_conn("ARDB_Metadata") | ||||
| 
 | ||||
|         regex_binary = '[0-1]{40,}' | ||||
|         #regex_hex = '(0[xX])?[A-Fa-f0-9]{40,}' | ||||
|         regex_hex = '[A-Fa-f0-9]{40,}' | ||||
|  | @ -79,10 +91,6 @@ class Decoder(AbstractModule): | |||
|         # map decoder function | ||||
|         self.decoder_function = {'binary':self.binary_decoder,'hexadecimal':self.hex_decoder, 'base64':self.base64_decoder} | ||||
| 
 | ||||
|         hex_max_execution_time = self.process.config.getint("Hex", "max_execution_time") | ||||
|         binary_max_execution_time = self.process.config.getint("Binary", "max_execution_time") | ||||
|         base64_max_execution_time = self.process.config.getint("Base64", "max_execution_time") | ||||
| 
 | ||||
|         # list all decoder with regex, | ||||
|         decoder_binary = {'name': 'binary', 'regex': cmp_regex_binary, 'encoded_min_size': 300, 'max_execution_time': binary_max_execution_time} | ||||
|         decoder_hexadecimal = {'name': 'hexadecimal', 'regex': cmp_regex_hex, 'encoded_min_size': 300, 'max_execution_time': hex_max_execution_time} | ||||
|  | @ -102,11 +110,9 @@ class Decoder(AbstractModule): | |||
| 
 | ||||
|     def compute(self, message): | ||||
| 
 | ||||
|         obj_id = Item.get_item_id(message) | ||||
| 
 | ||||
|         # Extract info from message | ||||
|         content = Item.get_item_content(obj_id) | ||||
|         date = Item.get_item_date(obj_id) | ||||
|         item = Item(message) | ||||
|         content = item.get_content() | ||||
|         date = item.get_date() | ||||
| 
 | ||||
|         for decoder in self.decoder_order: # add threshold and size limit | ||||
|             # max execution time on regex | ||||
|  | @ -117,16 +123,16 @@ class Decoder(AbstractModule): | |||
|             except TimeoutException: | ||||
|                 encoded_list = [] | ||||
|                 self.process.incr_module_timeout_statistic() # add encoder type | ||||
|                 self.redis_logger.debug(f"{obj_id} processing timeout") | ||||
|                 self.redis_logger.debug(f"{item.id} processing timeout") | ||||
|                 continue | ||||
|             else: | ||||
|                 signal.alarm(0) | ||||
| 
 | ||||
|                 if(len(encoded_list) > 0): | ||||
|                     content = self.decode_string(content, message, date, encoded_list, decoder['name'], decoder['encoded_min_size']) | ||||
|                     content = self.decode_string(content, item.id, date, encoded_list, decoder['name'], decoder['encoded_min_size']) | ||||
| 
 | ||||
| 
 | ||||
|     def decode_string(self, content, item_id, item_date, encoded_list, decoder_name, encoded_min_size): | ||||
|     def decode_string(self, content, item_id, date, encoded_list, decoder_name, encoded_min_size): | ||||
|         find = False | ||||
|         for encoded in encoded_list: | ||||
|             if len(encoded) >=  encoded_min_size: | ||||
|  | @ -134,16 +140,18 @@ class Decoder(AbstractModule): | |||
|                 find = True | ||||
| 
 | ||||
|                 sha1_string = sha1(decoded_file).hexdigest() | ||||
|                 mimetype = Decoded.get_file_mimetype(decoded_file) | ||||
|                 decoded = Decoded(sha1_string) | ||||
| 
 | ||||
|                 mimetype = decoded.guess_mimetype(decoded_file) | ||||
|                 if not mimetype: | ||||
|                     self.redis_logger.debug(item_id) | ||||
|                     self.redis_logger.debug(sha1_string) | ||||
|                     print(item_id) | ||||
|                     print(sha1_string) | ||||
|                     raise Exception('Invalid mimetype') | ||||
|                 Decoded.save_decoded_file_content(sha1_string, decoded_file, item_date, mimetype=mimetype) | ||||
|                 Decoded.save_item_relationship(sha1_string, item_id) | ||||
|                 Decoded.create_decoder_matadata(sha1_string, item_id, decoder_name) | ||||
|                     raise Exception(f'Invalid mimetype: {sha1_string} {item_id}') | ||||
| 
 | ||||
|                 decoded.create(content, date) | ||||
|                 decoded.add(decoder_name, date, item_id, mimetype) | ||||
| 
 | ||||
|                 save_item_relationship(sha1_string, item_id) ################################ | ||||
| 
 | ||||
|                 #remove encoded from item content | ||||
|                 content = content.replace(encoded, '', 1) | ||||
|  | @ -151,24 +159,18 @@ class Decoder(AbstractModule): | |||
|                 self.redis_logger.debug(f'{item_id} : {decoder_name} - {mimetype}') | ||||
|                 print(f'{item_id} : {decoder_name} - {mimetype}') | ||||
|         if(find): | ||||
|             self.set_out_item(decoder_name, item_id) | ||||
|             self.redis_logger.info(f'{decoder_name} decoded') | ||||
|             print(f'{decoder_name} decoded') | ||||
| 
 | ||||
|             # Send to Tags | ||||
|             msg = f'infoleak:automatic-detection="{decoder_name}";{item_id}' | ||||
|             self.send_message_to_queue(msg, 'Tags') | ||||
| 
 | ||||
|         # perf: remove encoded from item content | ||||
|         return content | ||||
| 
 | ||||
| 
 | ||||
|     def set_out_item(self, decoder_name, item_id): | ||||
| 
 | ||||
|         self.redis_logger.info(f'{decoder_name} decoded') | ||||
|         print(f'{decoder_name} decoded') | ||||
| 
 | ||||
|         # Send to duplicate | ||||
|         self.send_message_to_queue(item_id, 'Duplicate') | ||||
| 
 | ||||
|         # Send to Tags | ||||
|         msg = f'infoleak:automatic-detection="{decoder_name}";{item_id}' | ||||
|         self.send_message_to_queue(msg, 'Tags') | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| 
 | ||||
|     # # TODO: TEST ME | ||||
|     module = Decoder() | ||||
|     module.run() | ||||
|  |  | |||
|  | @ -208,7 +208,7 @@ class Global(AbstractModule): | |||
| 
 | ||||
|         return curr_file_content | ||||
| 
 | ||||
|     # # TODO: add stats incomplete_file/Not a gzipped file  | ||||
|     # # TODO: add stats incomplete_file/Not a gzipped file | ||||
|     def gunzip_bytes_obj(self, filename, bytes_obj): | ||||
|         gunzipped_bytes_obj = None | ||||
|         try: | ||||
|  |  | |||
|  | @ -50,6 +50,8 @@ class Telegram(AbstractModule): | |||
|         # extract telegram links | ||||
|         telegram_links = self.regex_findall(self.re_telegram_link, item.get_id(), item_content) | ||||
|         for telegram_link_tuple in telegram_links: | ||||
|             print(telegram_link_tuple) | ||||
|             print(telegram_link_tuple[2:-2].split("', '", 1)) | ||||
|             base_url, url_path = telegram_link_tuple[2:-2].split("', '", 1) | ||||
|             dict_url = telegram.get_data_from_telegram_url(base_url, url_path) | ||||
|             if dict_url.get('username'): | ||||
|  |  | |||
|  | @ -153,6 +153,12 @@ def sanitise_date_range(date_from, date_to, separator='', date_type='str'): | |||
|         date_to = date_from | ||||
| 
 | ||||
|     if date_type=='str': | ||||
|         # remove separators | ||||
|         if len(date_from) == 10: | ||||
|             date_from = date_from[0:4] + date_from[5:7] + date_from[8:10] | ||||
|         if len(date_to) == 10: | ||||
|             date_to = date_to[0:4] + date_to[5:7] + date_to[8:10] | ||||
| 
 | ||||
|         if not validate_str_date(date_from, separator=separator): | ||||
|             date_from = datetime.date.today().strftime("%Y%m%d") | ||||
|         if not validate_str_date(date_to, separator=separator): | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ from pymispgalaxies import Galaxies, Clusters | |||
| 
 | ||||
| config_loader = ConfigLoader.ConfigLoader() | ||||
| r_serv_tags = config_loader.get_redis_conn("ARDB_Tags") | ||||
| #r_serv_tags = config_loader.get_db_conn("Kvrocks_Tags") | ||||
| r_serv_metadata = config_loader.get_redis_conn("ARDB_Metadata") | ||||
| config_loader = None | ||||
| 
 | ||||
|  | @ -89,7 +90,7 @@ def get_all_taxonomies_tags(): # # TODO: add + REMOVE + Update | |||
| def get_all_galaxies_tags(): # # TODO: add + REMOVE + Update | ||||
|     return r_serv_tags.smembers('active_galaxies_tags') | ||||
| 
 | ||||
| def get_all_custom_tags(): | ||||
| def get_all_custom_tags(): # # TODO: add + REMOVE + Update | ||||
|     return r_serv_tags.smembers('tags:custom') | ||||
| 
 | ||||
| def get_taxonomies_enabled_tags(r_list=False): | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ import Date | |||
| import Item | ||||
| 
 | ||||
| config_loader = ConfigLoader.ConfigLoader() | ||||
| r_serv_term = config_loader.get_redis_conn("Kvrocks_DB") | ||||
| r_serv_term = config_loader.get_db_conn("Kvrocks_DB") | ||||
| config_loader = None | ||||
| 
 | ||||
| email_regex = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}' | ||||
|  |  | |||
|  | @ -52,6 +52,8 @@ from blueprints.hunters import hunters | |||
| from blueprints.old_endpoints import old_endpoints | ||||
| from blueprints.ail_2_ail_sync import ail_2_ail_sync | ||||
| from blueprints.settings_b import settings_b | ||||
| from blueprints.objects_decoded import objects_decoded | ||||
| from blueprints.objects_range import objects_range | ||||
| 
 | ||||
| 
 | ||||
| Flask_dir = os.environ['AIL_FLASK'] | ||||
|  | @ -113,6 +115,8 @@ app.register_blueprint(hunters, url_prefix=baseUrl) | |||
| app.register_blueprint(old_endpoints, url_prefix=baseUrl) | ||||
| app.register_blueprint(ail_2_ail_sync, url_prefix=baseUrl) | ||||
| app.register_blueprint(settings_b, url_prefix=baseUrl) | ||||
| app.register_blueprint(objects_decoded, url_prefix=baseUrl) | ||||
| app.register_blueprint(objects_range, url_prefix=baseUrl) | ||||
| # =========       =========# | ||||
| 
 | ||||
| # ========= Cookie name ======== | ||||
|  |  | |||
|  | @ -19,6 +19,17 @@ import Flask_config | |||
| # Import Role_Manager | ||||
| from Role_Manager import login_admin, login_analyst, login_read_only | ||||
| 
 | ||||
| 
 | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| ################################## | ||||
| # Import Project packages | ||||
| ################################## | ||||
| from lib.objects import ail_objects | ||||
| 
 | ||||
| 
 | ||||
| ################################################################################ | ||||
| 
 | ||||
| 
 | ||||
| sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib')) | ||||
| import Correlate_object | ||||
| import Domain | ||||
|  | @ -244,22 +255,22 @@ def get_description(): | |||
| @login_required | ||||
| @login_read_only | ||||
| def graph_node_json(): | ||||
|     correlation_id = request.args.get('correlation_id') | ||||
|     type_id = request.args.get('type_id') | ||||
|     object_type = request.args.get('object_type') | ||||
|     obj_id = request.args.get('correlation_id') #######################3 | ||||
|     subtype = request.args.get('type_id') ####################### | ||||
|     obj_type = request.args.get('object_type') ####################### | ||||
|     max_nodes = sanitise_nb_max_nodes(request.args.get('max_nodes')) | ||||
| 
 | ||||
|     correlation_names = sanitise_correlation_names(request.args.get('correlation_names')) | ||||
|     correlation_objects = sanitise_correlation_objects(request.args.get('correlation_objects')) | ||||
| 
 | ||||
|     # # TODO: remove me, rename screenshot to image | ||||
|     if object_type == 'image': | ||||
|         object_type == 'screenshot' | ||||
|     # # TODO: remove me, rename screenshot | ||||
|     if obj_type == 'image': | ||||
|         obj_type == 'screenshot' | ||||
| 
 | ||||
|     mode = sanitise_graph_mode(request.args.get('mode')) | ||||
| 
 | ||||
|     res = Correlate_object.get_graph_node_object_correlation(object_type, correlation_id, mode, correlation_names, correlation_objects, requested_correl_type=type_id, max_nodes=max_nodes) | ||||
|     return jsonify(res) | ||||
|     filter_types = correlation_names + correlation_objects | ||||
|     json_graph = ail_objects.get_correlations_graph_node(obj_type, subtype, obj_id, filter_types=filter_types, max_nodes=max_nodes, level=2, flask_context=True) | ||||
|     #json_graph = Correlate_object.get_graph_node_object_correlation(obj_type, obj_id, 'union', correlation_names, correlation_objects, requested_correl_type=subtype, max_nodes=max_nodes) | ||||
|     return jsonify(json_graph) | ||||
| 
 | ||||
| @correlation.route('/correlation/subtype_search', methods=['POST']) | ||||
| @login_required | ||||
|  |  | |||
|  | @ -0,0 +1,98 @@ | |||
| #!/usr/bin/env python3 | ||||
| # -*-coding:UTF-8 -* | ||||
| 
 | ||||
| ''' | ||||
|     Blueprint Flask: crawler splash endpoints: dashboard, onion crawler ... | ||||
| ''' | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| import json | ||||
| 
 | ||||
| from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file | ||||
| from flask_login import login_required, current_user | ||||
| 
 | ||||
| # Import Role_Manager | ||||
| from Role_Manager import login_admin, login_analyst, login_read_only | ||||
| 
 | ||||
| sys.path.append(os.environ['AIL_BIN']) | ||||
| ################################## | ||||
| # Import Project packages | ||||
| ################################## | ||||
| from lib.objects import Decodeds | ||||
| 
 | ||||
| 
 | ||||
| # ============ BLUEPRINT ============ | ||||
| objects_decoded = Blueprint('objects_decoded', __name__, template_folder=os.path.join(os.environ['AIL_FLASK'], 'templates/objects/decoded')) | ||||
| 
 | ||||
| # ============ VARIABLES ============ | ||||
| 
 | ||||
| 
 | ||||
| # ============ FUNCTIONS ============ | ||||
| 
 | ||||
| 
 | ||||
| # ============= ROUTES ============== | ||||
| 
 | ||||
| # # TODO: # FIXME: CHECK IF OBJ EXIST | ||||
| 
 | ||||
| @objects_decoded.route("/object/decoded/download") #completely shows the paste in a new tab | ||||
| @login_required | ||||
| @login_read_only | ||||
| def decoded_download(): | ||||
|     obj_id = request.args.get('id') | ||||
| 
 | ||||
|     # # TODO: sanitize hash | ||||
|     obj_id = obj_id.split('/')[0] | ||||
|     decoded = Decodeds.Decoded(obj_id) | ||||
|     if decoded.exists(): | ||||
|         filename = f'{decoded.id}.zip' | ||||
|         zip_content = decoded.get_zip_content() | ||||
|         return send_file(zip_content, attachment_filename=filename, as_attachment=True) | ||||
|     else: | ||||
|         abort(404) | ||||
| 
 | ||||
| @objects_decoded.route("/object/decoded/send_to_vt") #completely shows the paste in a new tab | ||||
| @login_required | ||||
| @login_read_only | ||||
| def send_to_vt(): | ||||
|     obj_id = request.args.get('id') | ||||
| 
 | ||||
|     # # TODO: sanitize hash | ||||
|     obj_id = obj_id.split('/')[0] | ||||
|     decoded = Decodeds.Decoded(obj_id) | ||||
|     if decoded.exists(): | ||||
|         decoded.send_to_vt() | ||||
|         return jsonify(decoded.get_meta_vt()) | ||||
|     else: | ||||
|         abort(404) | ||||
| 
 | ||||
| @objects_decoded.route("/object/decoded/refresh_vt_report") #completely shows the paste in a new tab | ||||
| @login_required | ||||
| @login_read_only | ||||
| def refresh_vt_report(): | ||||
|     obj_id = request.args.get('id') | ||||
| 
 | ||||
|     # # TODO: sanitize hash | ||||
|     obj_id = obj_id.split('/')[0] | ||||
|     decoded = Decodeds.Decoded(obj_id) | ||||
|     if decoded.exists(): | ||||
|         report = decoded.refresh_vt_report() | ||||
|         return jsonify(hash=decoded.id, report=report) | ||||
|     else: | ||||
|         abort(404) | ||||
| 
 | ||||
| @objects_decoded.route("/object/decoded/decoder_pie_chart_json", methods=['GET']) | ||||
| @login_required | ||||
| @login_read_only | ||||
| def decoder_pie_chart_json(): | ||||
|     date_from = request.args.get('date_from') | ||||
|     date_to = request.args.get('date_to') | ||||
|     mimetype = request.args.get('type') | ||||
|     return jsonify(Decodeds.api_pie_chart_decoder_json(date_from, date_to, mimetype)) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #####################################################3 | ||||
|  | @ -12,7 +12,6 @@ import json | |||
| from Date import Date | ||||
| 
 | ||||
| from io import BytesIO | ||||
| import zipfile | ||||
| 
 | ||||
| from hashlib import sha256 | ||||
| 
 | ||||
|  | @ -208,23 +207,6 @@ def get_all_keys_id_from_item(correlation_type, item_path): | |||
|                 all_keys_id_dump.add( (key_id, type_id) ) | ||||
|     return all_keys_id_dump | ||||
| 
 | ||||
| def one(): | ||||
|     return 1 | ||||
| 
 | ||||
| ''' | ||||
| def decode_base58(bc, length): | ||||
|     n = 0 | ||||
|     for char in bc: | ||||
|         n = n * 58 + digits58.index(char) | ||||
|     return n.to_bytes(length, 'big') | ||||
| 
 | ||||
| def check_bc(bc): | ||||
|     try: | ||||
|         bcbytes = decode_base58(bc, 25) | ||||
|         return bcbytes[-4:] == sha256(sha256(bcbytes[:-4]).digest()).digest()[:4] | ||||
|     except Exception: | ||||
|         return False | ||||
| ''' | ||||
| 
 | ||||
| def get_correlation_type_search_endpoint(correlation_type): | ||||
|     if correlation_type == 'pgpdump': | ||||
|  | @ -262,37 +244,6 @@ def get_range_type_json_endpoint(correlation_type): | |||
|         endpoint = 'hashDecoded.hashDecoded_page' | ||||
|     return endpoint | ||||
| 
 | ||||
| def get_graph_node_json_endpoint(correlation_type): | ||||
|     if correlation_type == 'pgpdump': | ||||
|         endpoint = 'hashDecoded.pgpdump_graph_node_json' | ||||
|     elif correlation_type == 'cryptocurrency': | ||||
|         endpoint = 'hashDecoded.cryptocurrency_graph_node_json' | ||||
|     elif correlation_type == 'username': | ||||
|         endpoint = 'hashDecoded.username_graph_node_json' | ||||
|     else: | ||||
|         endpoint = 'hashDecoded.hashDecoded_page' | ||||
|     return endpoint | ||||
| 
 | ||||
| def get_graph_line_json_endpoint(correlation_type): | ||||
|     if correlation_type == 'pgpdump': | ||||
|         endpoint = 'hashDecoded.pgpdump_graph_line_json' | ||||
|     elif correlation_type == 'cryptocurrency': | ||||
|         endpoint = 'hashDecoded.cryptocurrency_graph_line_json' | ||||
|     elif correlation_type == 'username': | ||||
|         endpoint = 'hashDecoded.username_graph_line_json' | ||||
|     else: | ||||
|         endpoint = 'hashDecoded.hashDecoded_page' | ||||
|     return endpoint | ||||
| 
 | ||||
| def get_font_family(correlation_type): | ||||
|     if correlation_type == 'pgpdump': | ||||
|         font = 'fa' | ||||
|     elif correlation_type == 'cryptocurrency': | ||||
|         font = 'fab' | ||||
|     else: | ||||
|         font = 'fa' | ||||
|     return font | ||||
| 
 | ||||
| ############ CORE CORRELATION ############ | ||||
| 
 | ||||
| def main_correlation_page(correlation_type, type_id, date_from, date_to, show_decoded_files): | ||||
|  | @ -392,27 +343,7 @@ def main_correlation_page(correlation_type, type_id, date_from, date_to, show_de | |||
|                                                 date_from=date_from, date_to=date_to, | ||||
|                                                 show_decoded_files=show_decoded_files) | ||||
| 
 | ||||
| # def show_correlation(correlation_type, type_id, key_id): | ||||
| #     if is_valid_type_id(correlation_type, type_id): | ||||
| #         key_id_metadata = get_key_id_metadata(correlation_type, type_id, key_id) | ||||
| #         if key_id_metadata: | ||||
| # | ||||
| #             num_day_sparkline = 6 | ||||
| #             date_range_sparkline = get_date_range(num_day_sparkline) | ||||
| # | ||||
| #             sparkline_values = list_sparkline_type_id_values(date_range_sparkline, correlation_type, type_id, key_id) | ||||
| #             return render_template('showCorrelation.html', key_id=key_id, type_id=type_id, | ||||
| #                             correlation_type=correlation_type, | ||||
| #                             graph_node_endpoint=get_graph_node_json_endpoint(correlation_type), | ||||
| #                             graph_line_endpoint=get_graph_line_json_endpoint(correlation_type), | ||||
| #                             font_family=get_font_family(correlation_type), | ||||
| #                             key_id_metadata=key_id_metadata, | ||||
| #                             type_icon=get_icon(correlation_type, type_id), | ||||
| #                             sparkline_values=sparkline_values) | ||||
| #         else: | ||||
| #             return '404' | ||||
| #     else: | ||||
| #         return 'error' | ||||
| 
 | ||||
| 
 | ||||
| def correlation_type_range_type_json(correlation_type, date_from, date_to): | ||||
|     date_range = [] | ||||
|  | @ -463,46 +394,6 @@ def correlation_type_range_type_json(correlation_type, date_from, date_to): | |||
| 
 | ||||
|     return jsonify(range_type) | ||||
| 
 | ||||
| def correlation_graph_node_json(correlation_type, type_id, key_id): | ||||
|     if key_id is not None and is_valid_type_id(correlation_type, type_id): | ||||
| 
 | ||||
|         nodes_set_dump = set() | ||||
|         nodes_set_paste = set() | ||||
|         links_set = set() | ||||
| 
 | ||||
|         key_id_metadata = get_key_id_metadata(correlation_type, type_id, key_id) | ||||
| 
 | ||||
|         nodes_set_dump.add((key_id, 1, type_id, key_id_metadata['first_seen'], key_id_metadata['last_seen'], key_id_metadata['nb_seen'])) | ||||
| 
 | ||||
|         #get related paste | ||||
|         l_pastes = r_serv_metadata.smembers('set_{}_{}:{}'.format(correlation_type, type_id, key_id)) | ||||
|         for paste in l_pastes: | ||||
|             nodes_set_paste.add((paste, 2)) | ||||
|             links_set.add((key_id, paste)) | ||||
| 
 | ||||
|             for key_id_with_type_id in get_all_keys_id_from_item(correlation_type, paste): | ||||
|                 new_key_id, typ_id = key_id_with_type_id | ||||
|                 if new_key_id != key_id: | ||||
| 
 | ||||
|                     key_id_metadata = get_key_id_metadata(correlation_type, typ_id, new_key_id) | ||||
| 
 | ||||
|                     nodes_set_dump.add((new_key_id, 3, typ_id, key_id_metadata['first_seen'], key_id_metadata['last_seen'], key_id_metadata['nb_seen'])) | ||||
|                     links_set.add((new_key_id, paste)) | ||||
| 
 | ||||
|         nodes = [] | ||||
|         for node in nodes_set_dump: | ||||
|             nodes.append({"id": node[0], "group": node[1], "first_seen": node[3], "last_seen": node[4], "nb_seen_in_paste": node[5], 'icon': get_icon_text(correlation_type, node[2]),"url": url_for(get_show_key_id_endpoint(correlation_type), type_id=node[2], key_id=node[0]), 'hash': True}) | ||||
|         for node in nodes_set_paste: | ||||
|             nodes.append({"id": node[0], "group": node[1],"url": url_for('objects_item.showItem', id=node[0]), 'hash': False}) | ||||
|         links = [] | ||||
|         for link in links_set: | ||||
|             links.append({"source": link[0], "target": link[1]}) | ||||
|         json = {"nodes": nodes, "links": links} | ||||
|         return jsonify(json) | ||||
| 
 | ||||
|     else: | ||||
|         return jsonify({}) | ||||
| 
 | ||||
| # ============= ROUTES ============== | ||||
| @hashDecoded.route("/hashDecoded/all_hash_search", methods=['POST']) | ||||
| @login_required | ||||
|  | @ -634,113 +525,8 @@ def hashDecoded_page(): | |||
|                                                 encoding=encoding, all_encoding=all_encoding, date_from=date_from, date_to=date_to, show_decoded_files=show_decoded_files) | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/hash_by_type') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def hash_by_type(): | ||||
|     type = request.args.get('type') | ||||
|     type = 'text/plain' | ||||
|     return render_template('hash_type.html',type = type) | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/hash_hash') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def hash_hash(): | ||||
|     hash = request.args.get('hash') | ||||
|     return render_template('hash_hash.html') | ||||
| 
 | ||||
| # | ||||
| # @hashDecoded.route('/hashDecoded/showHash') | ||||
| # @login_required | ||||
| # @login_analyst | ||||
| # def showHash(): | ||||
| #     hash = request.args.get('hash') | ||||
| #     #hash = 'e02055d3efaad5d656345f6a8b1b6be4fe8cb5ea' | ||||
| # | ||||
| #     # TODO FIXME show error | ||||
| #     if hash is None: | ||||
| #         return hashDecoded_page() | ||||
| # | ||||
| #     estimated_type = r_serv_metadata.hget('metadata_hash:'+hash, 'estimated_type') | ||||
| #     # hash not found | ||||
| #     # TODO FIXME show error | ||||
| #     if estimated_type is None: | ||||
| #         return hashDecoded_page() | ||||
| # | ||||
| #     else: | ||||
| #         file_icon = get_file_icon(estimated_type) | ||||
| #         size = r_serv_metadata.hget('metadata_hash:'+hash, 'size') | ||||
| #         first_seen = r_serv_metadata.hget('metadata_hash:'+hash, 'first_seen') | ||||
| #         last_seen = r_serv_metadata.hget('metadata_hash:'+hash, 'last_seen') | ||||
| #         nb_seen_in_all_pastes = r_serv_metadata.hget('metadata_hash:'+hash, 'nb_seen_in_all_pastes') | ||||
| # | ||||
| #         # get all encoding for this hash | ||||
| #         list_hash_decoder = [] | ||||
| #         list_decoder = r_serv_metadata.smembers('all_decoder') | ||||
| #         for decoder in list_decoder: | ||||
| #             encoding = r_serv_metadata.hget('metadata_hash:'+hash, decoder+'_decoder') | ||||
| #             if encoding is not None: | ||||
| #                 list_hash_decoder.append({'encoding': decoder, 'nb_seen': encoding}) | ||||
| # | ||||
| #         num_day_type = 6 | ||||
| #         date_range_sparkline = get_date_range(num_day_type) | ||||
| #         sparkline_values = list_sparkline_values(date_range_sparkline, hash) | ||||
| # | ||||
| #         if r_serv_metadata.hexists('metadata_hash:'+hash, 'vt_link'): | ||||
| #             b64_vt = True | ||||
| #             b64_vt_link = r_serv_metadata.hget('metadata_hash:'+hash, 'vt_link') | ||||
| #             b64_vt_report = r_serv_metadata.hget('metadata_hash:'+hash, 'vt_report') | ||||
| #         else: | ||||
| #             b64_vt = False | ||||
| #             b64_vt_link = '' | ||||
| #             b64_vt_report = r_serv_metadata.hget('metadata_hash:'+hash, 'vt_report') | ||||
| #             # hash never refreshed | ||||
| #             if b64_vt_report is None: | ||||
| #                 b64_vt_report = '' | ||||
| # | ||||
| #         return render_template('showHash.html', hash=hash, vt_enabled=vt_enabled, b64_vt=b64_vt, b64_vt_link=b64_vt_link, | ||||
| #                                 b64_vt_report=b64_vt_report, | ||||
| #                                 size=size, estimated_type=estimated_type, file_icon=file_icon, | ||||
| #                                 first_seen=first_seen, list_hash_decoder=list_hash_decoder, | ||||
| #                                 last_seen=last_seen, nb_seen_in_all_pastes=nb_seen_in_all_pastes, sparkline_values=sparkline_values) | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/downloadHash') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def downloadHash(): | ||||
|     hash = request.args.get('hash') | ||||
|     # sanitize hash | ||||
|     hash = hash.split('/')[0] | ||||
| 
 | ||||
|     # hash exist | ||||
|     if r_serv_metadata.hget('metadata_hash:'+hash, 'estimated_type') is not None: | ||||
| 
 | ||||
|         b64_full_path = Decoded.get_decoded_filepath(hash) | ||||
|         hash_content = '' | ||||
|         try: | ||||
|             with open(b64_full_path, 'rb') as f: | ||||
|                 hash_content = f.read() | ||||
| 
 | ||||
|             # zip buffer | ||||
|             result = BytesIO() | ||||
|             temp = BytesIO() | ||||
|             temp.write(hash_content) | ||||
| 
 | ||||
|             with zipfile.ZipFile(result, "w") as zf: | ||||
|                 #zf.setpassword(b"infected") | ||||
|                 zf.writestr( hash, temp.getvalue()) | ||||
| 
 | ||||
|             filename = hash + '.zip' | ||||
|             result.seek(0) | ||||
| 
 | ||||
|             return send_file(result, attachment_filename=filename, as_attachment=True) | ||||
|         except Exception as e: | ||||
|             print(e) | ||||
|             return 'Server Error' | ||||
|     else: | ||||
|         return 'hash: ' + hash + " don't exist" | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/hash_by_type_json') | ||||
|  | @ -778,62 +564,6 @@ def hash_by_type_json(): | |||
|         return jsonify() | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/decoder_type_json') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def decoder_type_json(): | ||||
|     date_from = request.args.get('date_from') | ||||
|     date_to = request.args.get('date_to') | ||||
| 
 | ||||
|     typ = request.args.get('type') | ||||
| 
 | ||||
|     if typ == 'All types': | ||||
|         typ = None | ||||
| 
 | ||||
|     # verify file type input | ||||
|     if typ is not None: | ||||
|         #retrieve + char | ||||
|         typ = typ.replace(' ', '+') | ||||
|         if typ not in r_serv_metadata.smembers('hash_all_type'): | ||||
|             typ = None | ||||
| 
 | ||||
|     all_decoder = r_serv_metadata.smembers('all_decoder') | ||||
|     # sort DESC decoder for color | ||||
|     all_decoder = sorted(all_decoder) | ||||
| 
 | ||||
|     date_range = [] | ||||
|     if date_from is not None and date_to is not None: | ||||
|         #change format | ||||
|         try: | ||||
|             if len(date_from) != 8: | ||||
|                 date_from = date_from[0:4] + date_from[5:7] + date_from[8:10] | ||||
|                 date_to = date_to[0:4] + date_to[5:7] + date_to[8:10] | ||||
|             date_range = substract_date(date_from, date_to) | ||||
|         except: | ||||
|             pass | ||||
| 
 | ||||
|     if not date_range: | ||||
|         date_range.append(datetime.date.today().strftime("%Y%m%d")) | ||||
| 
 | ||||
|     nb_decoded = {} | ||||
|     for decoder in all_decoder: | ||||
|         nb_decoded[decoder] = 0 | ||||
| 
 | ||||
|     for date in date_range: | ||||
|         for decoder in all_decoder: | ||||
|             if typ is None: | ||||
|                 nb_decod = r_serv_metadata.get(decoder+'_decoded:'+date) | ||||
|             else: | ||||
|                 nb_decod = r_serv_metadata.zscore(decoder+'_type:'+typ, date) | ||||
| 
 | ||||
|             if nb_decod is not None: | ||||
|                 nb_decoded[decoder] = nb_decoded[decoder] + int(nb_decod) | ||||
| 
 | ||||
|     to_json = [] | ||||
|     for decoder in all_decoder: | ||||
|         to_json.append({'name': decoder, 'value': nb_decoded[decoder]}) | ||||
|     return jsonify(to_json) | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/top5_type_json') | ||||
| @login_required | ||||
|  | @ -881,7 +611,7 @@ def top5_type_json(): | |||
|     for date in date_range: | ||||
|         for typ in all_type: | ||||
|             for decoder in all_decoder: | ||||
|                 nb_decoded = r_serv_metadata.zscore('{}_type:{}'.format(decoder, typ), date) | ||||
|                 nb_decoded = r_serv_metadata.zscore(f'{decoder}_type:{typ}', date) # daily_type key:date mimetype 3 | ||||
|                 if nb_decoded is not None: | ||||
|                     if typ in nb_types_decoded: | ||||
|                         nb_types_decoded[typ] = nb_types_decoded[typ] + int(nb_decoded) | ||||
|  | @ -1005,145 +735,6 @@ def hash_graph_line_json(): | |||
|     else: | ||||
|         return jsonify() | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/hash_graph_node_json') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def hash_graph_node_json(): | ||||
|     hash = request.args.get('hash') | ||||
| 
 | ||||
|     estimated_type = r_serv_metadata.hget('metadata_hash:'+hash, 'estimated_type') | ||||
| 
 | ||||
|     if hash is not None and estimated_type is not None: | ||||
| 
 | ||||
|         nodes_set_hash = set() | ||||
|         nodes_set_paste = set() | ||||
|         links_set = set() | ||||
| 
 | ||||
|         url = hash | ||||
|         first_seen = r_serv_metadata.hget('metadata_hash:'+hash, 'first_seen') | ||||
|         last_seen = r_serv_metadata.hget('metadata_hash:'+hash, 'last_seen') | ||||
|         nb_seen_in_paste = r_serv_metadata.hget('metadata_hash:'+hash, 'nb_seen_in_all_pastes') | ||||
|         size = r_serv_metadata.hget('metadata_hash:'+hash, 'size') | ||||
| 
 | ||||
|         nodes_set_hash.add((hash, 1, first_seen, last_seen, estimated_type, nb_seen_in_paste, size, url)) | ||||
| 
 | ||||
|         #get related paste | ||||
|         l_pastes = r_serv_metadata.zrange('nb_seen_hash:'+hash, 0, -1) | ||||
|         for paste in l_pastes: | ||||
|             # dynamic update | ||||
|             if PASTES_FOLDER in paste: | ||||
|                 score = r_serv_metadata.zscore('nb_seen_hash:{}'.format(hash), paste) | ||||
|                 r_serv_metadata.zrem('nb_seen_hash:{}'.format(hash), paste) | ||||
|                 paste = paste.replace(PASTES_FOLDER, '', 1) | ||||
|                 r_serv_metadata.zadd('nb_seen_hash:{}'.format(hash), score, paste) | ||||
|             url = paste | ||||
|             #nb_seen_in_this_paste = nb_in_file = int(r_serv_metadata.zscore('nb_seen_hash:'+hash, paste)) | ||||
|             nb_hash_in_paste = r_serv_metadata.scard('hash_paste:'+paste) | ||||
| 
 | ||||
|             nodes_set_paste.add((paste, 2,nb_hash_in_paste,url)) | ||||
|             links_set.add((hash, paste)) | ||||
| 
 | ||||
|             l_hash = r_serv_metadata.smembers('hash_paste:'+paste) | ||||
|             for child_hash in l_hash: | ||||
|                 if child_hash != hash: | ||||
|                     url = child_hash | ||||
|                     first_seen = r_serv_metadata.hget('metadata_hash:'+child_hash, 'first_seen') | ||||
|                     last_seen = r_serv_metadata.hget('metadata_hash:'+child_hash, 'last_seen') | ||||
|                     nb_seen_in_paste = r_serv_metadata.hget('metadata_hash:'+child_hash, 'nb_seen_in_all_pastes') | ||||
|                     size = r_serv_metadata.hget('metadata_hash:'+child_hash, 'size') | ||||
|                     estimated_type = r_serv_metadata.hget('metadata_hash:'+child_hash, 'estimated_type') | ||||
| 
 | ||||
|                     nodes_set_hash.add((child_hash, 3, first_seen, last_seen, estimated_type, nb_seen_in_paste, size, url)) | ||||
|                     links_set.add((child_hash, paste)) | ||||
| 
 | ||||
|                     #l_pastes_child = r_serv_metadata.zrange('nb_seen_hash:'+child_hash, 0, -1) | ||||
|                     #for child_paste in l_pastes_child: | ||||
| 
 | ||||
|         nodes = [] | ||||
|         for node in nodes_set_hash: | ||||
|             nodes.append({"id": node[0], "group": node[1], "first_seen": node[2], "last_seen": node[3], 'estimated_type': node[4], "nb_seen_in_paste": node[5], "size": node[6], 'icon': get_file_icon_text(node[4]),"url": url_for('hashDecoded.showHash', hash=node[7]), 'hash': True}) | ||||
|         for node in nodes_set_paste: | ||||
|             nodes.append({"id": node[0], "group": node[1], "nb_seen_in_paste": node[2],"url": url_for('objects_item.showItem', id=node[3]), 'hash': False}) | ||||
|         links = [] | ||||
|         for link in links_set: | ||||
|             links.append({"source": link[0], "target": link[1]}) | ||||
|         json = {"nodes": nodes, "links": links} | ||||
|         return jsonify(json) | ||||
| 
 | ||||
|     else: | ||||
|         return jsonify({}) | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/hash_types') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def hash_types(): | ||||
|     date_from = 20180701 | ||||
|     date_to = 20180706 | ||||
|     return render_template('hash_types.html', date_from=date_from, date_to=date_to) | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/send_file_to_vt_js') | ||||
| @login_required | ||||
| @login_analyst | ||||
| def send_file_to_vt_js(): | ||||
|     hash = request.args.get('hash') | ||||
| 
 | ||||
|     b64_full_path = Decoded.get_decoded_filepath(hash) | ||||
|     b64_content = '' | ||||
|     with open(b64_full_path, 'rb') as f: | ||||
|         b64_content = f.read() | ||||
| 
 | ||||
|     files = {'file': (hash, b64_content)} | ||||
|     response = requests.post('https://www.virustotal.com/vtapi/v2/file/scan', files=files, params= {'apikey': vt_auth}) | ||||
|     json_response = response.json() | ||||
|     #print(json_response) | ||||
| 
 | ||||
|     vt_link = json_response['permalink'].split('analysis')[0] + 'analysis/' | ||||
|     r_serv_metadata.hset('metadata_hash:'+hash, 'vt_link', vt_link) | ||||
|     vt_report = 'Please Refresh' | ||||
|     r_serv_metadata.hset('metadata_hash:'+hash, 'vt_report', vt_report) | ||||
| 
 | ||||
|     return jsonify({'vt_link': vt_link, 'vt_report': vt_report}) | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/hashDecoded/update_vt_result') | ||||
| @login_required | ||||
| @login_analyst | ||||
| def update_vt_result(): | ||||
|     hash = request.args.get('hash') | ||||
| 
 | ||||
|     params = {'apikey': vt_auth, 'resource': hash} | ||||
|     response = requests.get('https://www.virustotal.com/vtapi/v2/file/report', params=params) | ||||
|     if response.status_code == 200: | ||||
|         json_response = response.json() | ||||
|         response_code = json_response['response_code'] | ||||
|         # report exist | ||||
|         if response_code == 1: | ||||
|             total = json_response['total'] | ||||
|             positive = json_response['positives'] | ||||
| 
 | ||||
|             b64_vt_report = 'Detection {}/{}'.format(positive, total) | ||||
|         # no report found | ||||
|         elif response_code == 0: | ||||
|             b64_vt_report = 'No report found' | ||||
|             pass | ||||
|         # file in queue | ||||
|         elif response_code == -2: | ||||
|             b64_vt_report = 'File in queue' | ||||
|             pass | ||||
| 
 | ||||
|         r_serv_metadata.hset('metadata_hash:'+hash, 'vt_report', b64_vt_report) | ||||
|         return jsonify(hash=hash, report_vt=b64_vt_report) | ||||
|     elif response.status_code == 403: | ||||
|         Flask_config.vt_enabled = False | ||||
|         print('Virustotal key is incorrect (e.g. for public API not for virustotal intelligence), authentication failed or reaching limits.') | ||||
|         return jsonify() | ||||
|     else: | ||||
|         # TODO FIXME make json response | ||||
|         return jsonify() | ||||
| 
 | ||||
| ############################ PGPDump ############################ | ||||
| 
 | ||||
| @hashDecoded.route('/decoded/pgp_by_type_json') ## TODO: REFRACTOR | ||||
|  | @ -1191,7 +782,7 @@ def pgp_by_type_json(): | |||
|     else: | ||||
|         return jsonify() | ||||
| 
 | ||||
| ############################ Correlation ############################ | ||||
| ############################ DateRange ############################ | ||||
| @hashDecoded.route("/correlation/pgpdump", methods=['GET']) | ||||
| @login_required | ||||
| @login_read_only | ||||
|  | @ -1258,22 +849,10 @@ def all_username_search(): | |||
|     show_decoded_files = request.form.get('show_decoded_files') | ||||
|     return redirect(url_for('hashDecoded.username_page', date_from=date_from, date_to=date_to, type_id=type_id, show_decoded_files=show_decoded_files)) | ||||
| 
 | ||||
| # @hashDecoded.route('/correlation/show_pgpdump') | ||||
| # @login_required | ||||
| # @login_analyst | ||||
| # def show_pgpdump(): | ||||
| #     type_id = request.args.get('type_id') | ||||
| #     key_id = request.args.get('key_id') | ||||
| #     return show_correlation('pgpdump', type_id, key_id) | ||||
| # | ||||
| # | ||||
| # @hashDecoded.route('/correlation/show_cryptocurrency') | ||||
| # @login_required | ||||
| # @login_analyst | ||||
| # def show_cryptocurrency(): | ||||
| #     type_id = request.args.get('type_id') | ||||
| #     key_id = request.args.get('key_id') | ||||
| #     return show_correlation('cryptocurrency', type_id, key_id) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @hashDecoded.route('/correlation/cryptocurrency_range_type_json') | ||||
| @login_required | ||||
|  | @ -1299,30 +878,16 @@ def username_range_type_json(): | |||
|     date_to = request.args.get('date_to') | ||||
|     return correlation_type_range_type_json('username', date_from, date_to) | ||||
| 
 | ||||
| @hashDecoded.route('/correlation/pgpdump_graph_node_json') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def pgpdump_graph_node_json(): | ||||
|     type_id = request.args.get('type_id') | ||||
|     key_id = request.args.get('key_id') | ||||
|     return correlation_graph_node_json('pgpdump', type_id, key_id) | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| ########################################################################################## | ||||
| 
 | ||||
| # # TODO: REFRACTOR | ||||
| @hashDecoded.route('/correlation/cryptocurrency_graph_node_json') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def cryptocurrency_graph_node_json(): | ||||
|     type_id = request.args.get('type_id') | ||||
|     key_id = request.args.get('key_id') | ||||
|     return correlation_graph_node_json('cryptocurrency', type_id, key_id) | ||||
| 
 | ||||
| @hashDecoded.route('/correlation/username_graph_node_json') | ||||
| @login_required | ||||
| @login_read_only | ||||
| def username_graph_node_json(): | ||||
|     type_id = request.args.get('type_id') | ||||
|     key_id = request.args.get('key_id') | ||||
|     return correlation_graph_node_json('username', type_id, key_id) | ||||
| 
 | ||||
| # # TODO: REFRACTOR | ||||
| @hashDecoded.route('/correlation/pgpdump_graph_line_json') | ||||
|  |  | |||
|  | @ -253,7 +253,7 @@ | |||
| 					chart.stackBarChart = barchart_type_stack("{{ url_for('hashDecoded.range_type_json') }}?date_from={{date_from}}&date_to={{date_to}}", 'id'); | ||||
| 					{% endif %} | ||||
| 
 | ||||
| 					draw_pie_chart("pie_chart_encoded" ,"{{ url_for('hashDecoded.decoder_type_json') }}?date_from={{date_from}}&date_to={{date_to}}&type={{type}}", "{{ url_for('hashDecoded.hashDecoded_page') }}?date_from={{date_from}}&date_to={{date_to}}&type={{type}}&encoding="); | ||||
| 					draw_pie_chart("pie_chart_encoded" ,"{{ url_for('objects_decoded.decoder_pie_chart_json') }}?date_from={{date_from}}&date_to={{date_to}}&type={{type}}", "{{ url_for('hashDecoded.hashDecoded_page') }}?date_from={{date_from}}&date_to={{date_to}}&type={{type}}&encoding="); | ||||
| 					draw_pie_chart("pie_chart_top5_types" ,"{{ url_for('hashDecoded.top5_type_json') }}?date_from={{date_from}}&date_to={{date_to}}&type={{type}}", "{{ url_for('hashDecoded.hashDecoded_page') }}?date_from={{date_from}}&date_to={{date_to}}&type="); | ||||
| 
 | ||||
| 					chart.onResize(); | ||||
|  | @ -280,18 +280,18 @@ function toggle_sidebar(){ | |||
| <script> | ||||
| 	function updateVTReport(hash) { | ||||
| 		//updateReport | ||||
| 		$.getJSON("{{ url_for('hashDecoded.update_vt_result') }}?hash="+hash, | ||||
| 		$.getJSON("{{ url_for('objects_decoded.refresh_vt_report') }}?id="+hash, | ||||
| 			function(data) { | ||||
| 				content = '<i class="fas fa-sync-alt"></i> ' +data['report_vt'] | ||||
| 				content = '<i class="fas fa-sync-alt"></i> ' +data['report'] | ||||
| 				$( "#report_vt_"+hash ).html(content); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	function sendFileToVT(hash) { | ||||
| 		//send file to vt | ||||
| 		$.getJSON("{{ url_for('hashDecoded.send_file_to_vt_js') }}?hash="+hash, | ||||
| 		$.getJSON("{{ url_for('objects_decoded.send_to_vt') }}?id="+hash, | ||||
| 			function(data) { | ||||
| 				var content = '<a id="submit_vt_'+hash+'" class="btn btn-primary" target="_blank" href="'+ data['vt_link'] +'"><i class="fa fa-link"> '+ ' VT Report' +'</i></a>'; | ||||
| 				var content = '<a id="submit_vt_'+hash+'" class="btn btn-primary" target="_blank" href="'+ data['link'] +'"><i class="fa fa-link"> '+ ' VT Report' +'</i></a>'; | ||||
| 				$('#submit_vt_'+hash).remove(); | ||||
| 				$('darkbutton_'+hash).append(content); | ||||
| 		}); | ||||
|  |  | |||
|  | @ -521,7 +521,31 @@ def get_item_cryptocurrency_bitcoin(): | |||
| ''' | ||||
| 
 | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| # # # # # # # # # # # # # #        DOMAIN       # # # # # # # # # # # # # # # # # | ||||
| # # # # # # # # # # # # # #        CRAWLER      # # # # # # # # # # # # # # # # | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| @restApi.route("api/v1/crawl/domain", methods=['POST']) | ||||
| @token_required('analyst') | ||||
| def crawl_domain(): | ||||
|     data = request.get_json() | ||||
| 
 | ||||
|     url = data.get('url', None) | ||||
|     screenshot = data.get('screenshot', None) | ||||
|     har = data.get('har', None) | ||||
|     depth_limit = data.get('depth_limit', None) | ||||
|     max_pages = data.get('max_pages', None) | ||||
|     auto_crawler = data.get('auto_crawler', None) | ||||
|     crawler_delta = data.get('crawler_delta', None) | ||||
|     crawler_type = data.get('url', None) | ||||
|     cookiejar_uuid = data.get('url', None) | ||||
|     user_agent = data.get('url', None) | ||||
| 
 | ||||
|     res = crawlers.api_create_crawler_task(json_dict) | ||||
|     res[0]['domain'] = domain | ||||
|     return create_json_response(res[0], res[1]) | ||||
| 
 | ||||
| 
 | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| # # # # # # # # # # # # # #        DOMAIN       # # # # # # # # # # # # # # # # | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| @restApi.route("api/v1/get/domain/status/minimal", methods=['POST']) | ||||
| @token_required('analyst') | ||||
|  | @ -654,6 +678,11 @@ def import_json_item(): | |||
|     res = importer.api_import_json_item(data_json) | ||||
|     return Response(json.dumps(res[0]), mimetype='application/json'), res[1] | ||||
| 
 | ||||
| 
 | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| # # # # # # # # # # # # #        CORE       # # # # # # # # # # # # # # # # # # | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| 
 | ||||
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | ||||
| # | ||||
| # | ||||
|  |  | |||
|  | @ -84,7 +84,7 @@ | |||
| 			Virus Total submission is disabled | ||||
| 		{% endif %} | ||||
| 
 | ||||
| 		<a href="{{ url_for('hashDecoded.downloadHash') }}?hash={{ dict_object["correlation_id"] }}" target="blank" class="float-right" style="font-size: 15px"> | ||||
| 		<a href="{{ url_for('objects_decoded.decoded_download') }}?id={{ dict_object["correlation_id"] }}" target="blank" class="float-right" style="font-size: 15px"> | ||||
| 			<button class='btn btn-info'><i class="fas fa-download"></i> Download Decoded file | ||||
| 			</button> | ||||
| 		</a> | ||||
|  | @ -107,9 +107,9 @@ | |||
| <script> | ||||
| 	function sendFileToVT(hash) { | ||||
| 		//send file to vt | ||||
| 		$.getJSON("{{ url_for('hashDecoded.send_file_to_vt_js') }}?hash="+hash, | ||||
| 		$.getJSON("{{ url_for('objects_decoded.send_to_vt') }}?id="+hash, | ||||
| 			function(data) { | ||||
| 				var content = '<a id="submit_vt_b" class="btn btn-primary" target="_blank" href="'+ data['vt_link'] +'"><i class="fas fa-link"> '+ ' VT Report' +'</i></a>'; | ||||
| 				var content = '<a id="submit_vt_b" class="btn btn-primary" target="_blank" href="'+ data['link'] +'"><i class="fas fa-link"> '+ ' VT Report' +'</i></a>'; | ||||
| 				$('#submit_vt_b').remove(); | ||||
| 				$('darkbutton').append(content); | ||||
| 		}); | ||||
|  | @ -117,9 +117,9 @@ | |||
| 
 | ||||
| 	function updateVTReport(hash) { | ||||
| 		//updateReport | ||||
| 		$.getJSON("{{ url_for('hashDecoded.update_vt_result') }}?hash="+hash, | ||||
| 		$.getJSON("{{ url_for('objects_decoded.refresh_vt_report') }}?id="+hash, | ||||
| 			function(data) { | ||||
| 				var content = '<i class="fas fa-sync-alt"></i> ' +data['report_vt']; | ||||
| 				var content = '<i class="fas fa-sync-alt"></i> ' +data['report']; | ||||
| 				$( "#report_vt_b" ).html(content); | ||||
| 		}); | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Terrtia
						Terrtia