From 5fdcb2376d4f42bee5964632d5706b3f214b98f2 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Tue, 14 May 2019 12:58:06 +0200 Subject: [PATCH 01/18] added a new option '--health' to check a technique administration YAML file on errors. --- dettact.py | 6 ++ generic.py | 139 +++++++++++++++++++++++++++++++++++++++++++ group_mapping.py | 5 +- technique_mapping.py | 66 ++------------------ 4 files changed, 153 insertions(+), 63 deletions(-) diff --git a/dettact.py b/dettact.py index 04073350..d9bc7eb8 100644 --- a/dettact.py +++ b/dettact.py @@ -58,6 +58,7 @@ def init_menu(): action='store_true') parser_visibility.add_argument('-o', '--overlay', help='generate a visibility layer overlayed with detections for ' 'the ATT&CK navigator', action='store_true') + parser_visibility.add_argument('--health', help='check the technique YAML file for errors', action='store_true') # create the detection parser parser_detection = subparsers.add_parser('detection', aliases=['d'], @@ -81,6 +82,7 @@ def init_menu(): 'the ATT&CK navigator', action='store_true') parser_detection.add_argument('-g', '--graph', help='generate a graph with detections added through time', action='store_true') + parser_detection.add_argument('--health', help='check the technique YAML file for errors', action='store_true') # create the group parser parser_group = subparsers.add_parser('group', aliases=['g'], @@ -171,6 +173,8 @@ def menu(menu_parser): export_techniques_list_to_excel(args.file_tech) if args.excel and args.applicable != 'all': print("[!] Filtering on 'applicable_to' is not supported for Excel output") + if args.health: + check_yaml_file_health(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION) elif args.subparser in ['group', 'g']: generate_group_heat_map(args.groups, args.overlay, args.overlay_type, args.stage, args.platform, args.software_group, args.applicable) @@ -194,6 +198,8 @@ def menu(menu_parser): export_techniques_list_to_excel(args.file_tech) if args.excel and args.applicable != 'all': print("[!] Filtering on 'applicable_to' is not supported for Excel output") + if args.health: + check_yaml_file_health(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION) elif args.subparser in ['generic', 'ge']: if args.statistics: diff --git a/generic.py b/generic.py index 219310d2..50155c63 100644 --- a/generic.py +++ b/generic.py @@ -337,3 +337,142 @@ def calculate_score(l, zero_value=0): number += 1 s = int(round(s / number, 0) if number > 0 else zero_value) return s + + +def _add_entry_to_list_in_dictionary(dict, technique_id, key, entry): + """ + Ensures a list will be created if it doesn't exist in the given dict[technique_id][key] and adds the entry to the + list. If the dict[technique_id] doesn't exist yet, it will be created. + :param dict: the dictionary + :param technique_id: the id of the technique in the main dict + :param key: the key where the list in the dictionary resides + :param entry: the entry to add to the list + :return: + """ + if technique_id not in dict.keys(): + dict[technique_id] = {} + if not key in dict[technique_id].keys(): + dict[technique_id][key] = [] + dict[technique_id][key].append(entry) + + +def load_techniques(filename, detection_or_visibility='all', filter_applicable_to='all'): + """ + Loads the techniques (including detection and visibility properties) from the given yaml file. + :param filename: the filename of the yaml file containing the techniques administration + :param detection_or_visibility: used to indicate to filter applicable_to field for detection or visibility. When + using 'all' no filtering will be applied. + :param filter_applicable_to: filter techniques based on applicable_to field in techniques administration YAML file + :return: dictionary with techniques (incl. properties), name and platform + """ + + my_techniques = {} + with open(filename, 'r') as yaml_file: + yaml_content = yaml.load(yaml_file, Loader=yaml.FullLoader) + for d in yaml_content['techniques']: + # Add detection items: + if type(d['detection']) == dict: # There is just one detection entry + if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in d[detection_or_visibility]['applicable_to'] or 'all' in d[detection_or_visibility]['applicable_to']: + _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'detection', d['detection']) + elif type(d['detection']) == list: # There are multiple detection entries + for de in d['detection']: + if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in de['applicable_to'] or 'all' in de['applicable_to']: + _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'detection', de) + + # Add visibility items + if type(d['visibility']) == dict: # There is just one visibility entry + if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in d[detection_or_visibility]['applicable_to'] or 'all' in d[detection_or_visibility]['applicable_to']: + _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'visibility', d['visibility']) + elif type(d['visibility']) == list: # There are multiple visibility entries + for de in d['visibility']: + if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in de['applicable_to'] or 'all' in de['applicable_to']: + _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'visibility', de) + + name = yaml_content['name'] + platform = yaml_content['platform'] + return my_techniques, name, platform + + +def check_yaml_file_health(filename, file_type): + """ + Check on error in the provided YAML file. + :param filename: YAML file location + :param file_type: currenlty only 'FILE_TYPE_TECHNIQUE_ADMINISTRATION' is being supported + :return: + """ + if file_type == FILE_TYPE_TECHNIQUE_ADMINISTRATION: + # check for duplicate tech IDs + with open(filename, 'r') as yaml_file: + yaml_content = yaml.load(yaml_file, Loader=yaml.FullLoader) + + tech_ids = list(map(lambda x: x['technique_id'], yaml_content['techniques'])) + tech_dup = [] + for tech in tech_ids: + if tech not in tech_dup: + tech_dup.append(tech) + else: + print('[!] Duplicate technique ID: ' + tech) + + # checks on: + # - empty key-value pairs: 'date_implemented', 'date_registered', 'location', 'applicable_to', 'score' + # - invalid date format for: 'date_implemented', 'date_registered' + # - detection or visibility score out-of-range + # - missing key-value pairs: 'applicable_to', 'date_registered', 'date_implemented', 'score', 'location', 'comment' + + techniques = load_techniques(filename) + for tech, v in techniques[0].items(): + for key in ['detection', 'visibility']: + if key not in v: + print('[!] Technique ID: ' + tech + ' is MISSING ' + key) + + for detection in v['detection']: + for key in ['applicable_to', 'date_registered', 'date_implemented', 'score', 'location', 'comment']: + if key not in detection: + print('[!] Technique ID: ' + tech + ' is MISSING the key-value pair in detection: ' + key) + + try: + if detection['score'] is None: + print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: score') + + elif not (detection['score'] >= -1 and detection['score'] <= 5): + print('[!] Technique ID: ' + tech + ' has an INVALID detection score: ' + str(detection['score']) + + ' (should be between -1 and 5)') + + elif detection['score'] > -1: + for key in ['date_implemented', 'date_registered']: + if not detection[key]: + print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) + break + try: + detection[key].year + detection[key].month + detection[key].day + except AttributeError: + print('[!] Technique ID: ' + tech + ' has an INVALID data format for the key-value pair ' + 'in detection: ' + key + ' (should be YYYY-MM-DD)') + + for key in ['location', 'applicable_to']: + try: + if detection[key][0] is None: + print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) + except TypeError: + print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) + except KeyError: + pass + + for visibility in v['visibility']: + for key in ['applicable_to', 'score', 'comment']: + if key not in detection: + print('[!] Technique ID: ' + tech + ' is MISSING the key-value pair in visibility: ' + key) + + try: + if visibility['score'] is None: + print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in visibility: score') + elif not (visibility['score'] >= 0 and visibility['score'] <= 4): + print('[!] Technique ID: ' + tech + ' has an INVALID visibility score: ' + str(detection['score']) + + ' (should be between 0 and 4)') + except KeyError: + pass + + + diff --git a/group_mapping.py b/group_mapping.py index a3e306d5..253a8e67 100644 --- a/group_mapping.py +++ b/group_mapping.py @@ -1,6 +1,5 @@ import simplejson from generic import * -from technique_mapping import _load_techniques CG_GROUPS = {} @@ -211,7 +210,7 @@ def get_detection_techniques(filename, filter_applicable_to): # { group_id: {group_name: NAME, techniques: set{id, ...} } } groups_dict = {} - detection_techniques, name, platform = _load_techniques(filename, 'detection', filter_applicable_to) + detection_techniques, name, platform = load_techniques(filename, 'detection', filter_applicable_to) group_id = 'DETECTION' groups_dict[group_id] = {} @@ -235,7 +234,7 @@ def get_visibility_techniques(filename, filter_applicable_to): # { group_id: {group_name: NAME, techniques: set{id, ...} } } groups_dict = {} - visibility_techniques, name, platform = _load_techniques(filename, 'visibility', filter_applicable_to) + visibility_techniques, name, platform = load_techniques(filename, 'visibility', filter_applicable_to) group_id = 'VISIBILITY' groups_dict[group_id] = {} diff --git a/technique_mapping.py b/technique_mapping.py index 782bfcc2..174030bb 100644 --- a/technique_mapping.py +++ b/technique_mapping.py @@ -14,12 +14,12 @@ def generate_detection_layer(filename_techniques, filename_data_sources, overlay :return: """ if not overlay: - my_techniques, name, platform = _load_techniques(filename_techniques, 'detection', filter_applicable_to) + my_techniques, name, platform = load_techniques(filename_techniques, 'detection', filter_applicable_to) mapped_techniques_detection = _map_and_colorize_techniques_for_detections(my_techniques) layer_detection = get_layer_template_detections('Detections ' + name + ' ' + filter_applicable_to, 'description', 'attack', platform) _write_layer(layer_detection, mapped_techniques_detection, 'detection', filter_applicable_to, name) else: - my_techniques, name, platform = _load_techniques(filename_techniques, 'all', filter_applicable_to) + my_techniques, name, platform = load_techniques(filename_techniques, 'all', filter_applicable_to) my_data_sources = _load_data_sources(filename_data_sources) mapped_techniques_both = _map_and_colorize_techniques_for_overlayed(my_techniques, my_data_sources, filter_applicable_to) layer_both = get_layer_template_layered('Visibility and Detection ' + name + ' ' + filter_applicable_to, 'description', 'attack', platform) @@ -38,12 +38,12 @@ def generate_visibility_layer(filename_techniques, filename_data_sources, overla my_data_sources = _load_data_sources(filename_data_sources) if not overlay: - my_techniques, name, platform = _load_techniques(filename_techniques, 'visibility', filter_applicable_to) + my_techniques, name, platform = load_techniques(filename_techniques, 'visibility', filter_applicable_to) mapped_techniques_visibility = _map_and_colorize_techniques_for_visibility(my_techniques, my_data_sources) layer_visibility = get_layer_template_visibility('Visibility ' + name + ' ' + filter_applicable_to, 'description', 'attack', platform) _write_layer(layer_visibility, mapped_techniques_visibility, 'visibility', filter_applicable_to, name) else: - my_techniques, name, platform = _load_techniques(filename_techniques, 'all', filter_applicable_to) + my_techniques, name, platform = load_techniques(filename_techniques, 'all', filter_applicable_to) mapped_techniques_both = _map_and_colorize_techniques_for_overlayed(my_techniques, my_data_sources, filter_applicable_to) layer_both = get_layer_template_layered('Visibility and Detection ' + name + ' ' + filter_applicable_to, 'description', 'attack', platform) _write_layer(layer_both, mapped_techniques_both, 'visibility_and_detection', filter_applicable_to, name) @@ -56,7 +56,7 @@ def plot_detection_graph(filename, filter_applicable_to): :param filter_applicable_to: filter techniques based on applicable_to field in techniques administration YAML file :return: """ - my_techniques, name, platform = _load_techniques(filename, 'detection', filter_applicable_to) + my_techniques, name, platform = load_techniques(filename, 'detection', filter_applicable_to) graph_values = [] for t in my_techniques.values(): @@ -80,60 +80,6 @@ def plot_detection_graph(filename, filter_applicable_to): print("File written: " + output_filename) -def _load_techniques(filename, detection_or_visibility, filter_applicable_to='all'): - """ - Loads the techniques (including detection and visibility properties) from the given yaml file. - :param filename: the filename of the yaml file containing the techniques administration - :param detection_or_visibility: used to indicate to filter applicable_to field for detection or visibility. When - using 'all' no filtering will be applied. - :param filter_applicable_to: filter techniques based on applicable_to field in techniques administration YAML file - :return: dictionary with techniques (incl. properties), name and platform - """ - - my_techniques = {} - with open(filename, 'r') as yaml_file: - yaml_content = yaml.load(yaml_file, Loader=yaml.FullLoader) - for d in yaml_content['techniques']: - # Add detection items: - if type(d['detection']) == dict: # There is just one detection entry - if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in d[detection_or_visibility]['applicable_to'] or 'all' in d[detection_or_visibility]['applicable_to']: - _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'detection', d['detection']) - elif type(d['detection']) == list: # There are multiple detection entries - for de in d['detection']: - if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in de['applicable_to'] or 'all' in de['applicable_to']: - _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'detection', de) - - # Add visibility items - if type(d['visibility']) == dict: # There is just one visibility entry - if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in d[detection_or_visibility]['applicable_to'] or 'all' in d[detection_or_visibility]['applicable_to']: - _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'visibility', d['visibility']) - elif type(d['visibility']) == list: # There are multiple visibility entries - for de in d['visibility']: - if detection_or_visibility == 'all' or filter_applicable_to == 'all' or filter_applicable_to in de['applicable_to'] or 'all' in de['applicable_to']: - _add_entry_to_list_in_dictionary(my_techniques, d['technique_id'], 'visibility', de) - - name = yaml_content['name'] - platform = yaml_content['platform'] - return my_techniques, name, platform - - -def _add_entry_to_list_in_dictionary(dict, technique_id, key, entry): - """ - Ensures a list will be created if it doesn't exist in the given dict[technique_id][key] and adds the entry to the - list. If the dict[technique_id] doesn't exist yet, it will be created. - :param dict: the dictionary - :param technique_id: the id of the technique in the main dict - :param key: the key where the list in the dictionary resides - :param entry: the entry to add to the list - :return: - """ - if technique_id not in dict.keys(): - dict[technique_id] = {} - if not key in dict[technique_id].keys(): - dict[technique_id][key] = [] - dict[technique_id][key].append(entry) - - def _load_data_sources(filename): """ Loads the data sources (including all properties) from the given yaml file. @@ -384,7 +330,7 @@ def export_techniques_list_to_excel(filename): :param filename: the filename of the yaml file containing the techniques administration :return: """ - my_techniques, name, platform = _load_techniques(filename, 'all') + my_techniques, name, platform = load_techniques(filename, 'all') my_techniques = dict(sorted(my_techniques.items(), key=lambda kv: kv[0], reverse=False)) mitre_techniques = load_attack_data(DATATYPE_ALL_TECH) From ff492db9ff563ed2d475293ab10e6ca5fc6fb5ec Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Tue, 14 May 2019 13:56:07 +0200 Subject: [PATCH 02/18] fixed a small bug in new code --- generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic.py b/generic.py index 50155c63..d1e7543b 100644 --- a/generic.py +++ b/generic.py @@ -462,7 +462,7 @@ def check_yaml_file_health(filename, file_type): for visibility in v['visibility']: for key in ['applicable_to', 'score', 'comment']: - if key not in detection: + if key not in visibility: print('[!] Technique ID: ' + tech + ' is MISSING the key-value pair in visibility: ' + key) try: From 24be857eb2a9da5317999830a5e5929b26cd218c Mon Sep 17 00:00:00 2001 From: Ruben Bouman Date: Wed, 15 May 2019 10:05:19 +0200 Subject: [PATCH 03/18] Added both detection and visibility score to detection/visibility overlay. --- group_mapping.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/group_mapping.py b/group_mapping.py index a3e306d5..328dc57b 100644 --- a/group_mapping.py +++ b/group_mapping.py @@ -328,7 +328,7 @@ def get_technique_count(groups, groups_overlay, groups_software, overlay_type, a def get_technique_layer(techniques_count, groups, overlay, groups_software, overlay_file_type, overlay_type, - all_techniques, max_tech_count_group): + all_techniques): """ Create the technique layer that will be part of the ATT&CK navigator json file :param techniques_count: involved techniques with count (to be used within the scores) @@ -338,7 +338,6 @@ def get_technique_layer(techniques_count, groups, overlay, groups_software, over :param overlay_file_type: the file type of the YAML file as present in the key 'file_type' :param overlay_type: group, visibility or detection :param all_techniques: dictionary with all techniques loaded from techniques administration YAML file - :param max_tech_count_group: the maximum number of times a technique is used among threat actor groups :return: dictionary """ techniques_layer = [] @@ -384,7 +383,8 @@ def get_technique_layer(techniques_count, groups, overlay, groups_software, over # Add applicable_to to metadata in case of overlay for detection/visibility: if overlay_file_type == FILE_TYPE_TECHNIQUE_ADMINISTRATION: metadata_dict['Applicable to'] = set([a for v in all_techniques[tech][overlay_type] for a in v['applicable_to']]) - metadata_dict[overlay_type.capitalize() + ' score'] = [str(techniques_count[tech]['count'] - max_tech_count_group)] + metadata_dict['Detection score'] = [str(calculate_score(all_techniques[tech]['detection']))] + metadata_dict['Visibility score'] = [str(calculate_score(all_techniques[tech]['visibility']))] if 'Overlay' not in metadata_dict: metadata_dict['Overlay'] = set() @@ -508,7 +508,7 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft technique_count, max_tech_count_group = get_technique_count(groups_dict, overlay_dict, groups_software_dict, overlay_type, all_techniques) technique_layer = get_technique_layer(technique_count, groups_dict, overlay_dict, groups_software_dict, - overlay_file_type, overlay_type, all_techniques, max_tech_count_group) + overlay_file_type, overlay_type, all_techniques) # make a list group names for the involved groups. if groups == ['all']: From 7c027606d9a28e1969de73e98e20d30a60f954c9 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Wed, 15 May 2019 11:00:33 +0200 Subject: [PATCH 04/18] small improvement in the health check for tech. YAML files --- generic.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/generic.py b/generic.py index d1e7543b..65e0accf 100644 --- a/generic.py +++ b/generic.py @@ -451,12 +451,12 @@ def check_yaml_file_health(filename, file_type): print('[!] Technique ID: ' + tech + ' has an INVALID data format for the key-value pair ' 'in detection: ' + key + ' (should be YYYY-MM-DD)') - for key in ['location', 'applicable_to']: - try: - if detection[key][0] is None: - print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) - except TypeError: + for key in ['location', 'applicable_to']: + try: + if detection[key][0] is None: print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) + except TypeError: + print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) except KeyError: pass @@ -476,3 +476,4 @@ def check_yaml_file_health(filename, file_type): + From 9a9aa013556d332923eae4196c172821808a7096 Mon Sep 17 00:00:00 2001 From: Ruben Bouman Date: Wed, 15 May 2019 14:43:25 +0200 Subject: [PATCH 05/18] Provided a groups YAML file for the Red Canary threat detection 2019 report, listing all frequently used techniques including lists per sector. Adjusted functionality in DeTT&CT to support the use of 'weight' in group files. --- generic.py | 10 +-- group_mapping.py | 45 +++++++----- sample-data/redcanary.yaml | 141 +++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 21 deletions(-) create mode 100644 sample-data/redcanary.yaml diff --git a/generic.py b/generic.py index d1e7543b..e84cf223 100644 --- a/generic.py +++ b/generic.py @@ -96,13 +96,13 @@ def _get_base_template(name, description, stage, platform, sorting): return layer -def get_layer_template_groups(name, max_score, description, stage, platform, overlay_type): +def get_layer_template_groups(name, max_count, description, stage, platform, overlay_type): """ Prepares a base template for the json layer file that can be loaded into the MITRE ATT&CK Navigator. More information on the version 2.1 layer format: https://github.com/mitre/attack-navigator/blob/master/layers/LAYERFORMATv2_1.md :param name: name - :param max_score: max_score = max_tech_count_group + :param max_count: the sum of all count values :param description: description :param stage: stage (act | prepare) :param platform: platform @@ -110,10 +110,10 @@ def get_layer_template_groups(name, max_score, description, stage, platform, ove :return: layer template dictionary """ layer = _get_base_template(name, description, stage, platform, 3) - layer['gradient'] = {'colors': [COLOR_GRADIENT_MIN, COLOR_GRADIENT_MAX], 'minValue': 0, 'maxValue': max_score} + layer['gradient'] = {'colors': [COLOR_GRADIENT_MIN, COLOR_GRADIENT_MAX], 'minValue': 0, 'maxValue': max_count} layer['legendItems'] = [] - layer['legendItems'].append({'label': 'Tech. ref. for ' + str(1) + ' group', 'color': COLOR_GRADIENT_MIN}) - layer['legendItems'].append({'label': 'Tech. ref. for ' + str(max_score) + ' groups', 'color': COLOR_GRADIENT_MAX}) + layer['legendItems'].append({'label': 'Tech. not often used', 'color': COLOR_GRADIENT_MIN}) + layer['legendItems'].append({'label': 'Tech. used frequently', 'color': COLOR_GRADIENT_MAX}) if overlay_type == OVERLAY_TYPE_GROUP: layer['legendItems'].append({'label': 'Groups overlay: tech. in group + overlay', 'color': COLOR_GROUP_OVERLAY_MATCH}) diff --git a/group_mapping.py b/group_mapping.py index ec1e8adc..d2d61785 100644 --- a/group_mapping.py +++ b/group_mapping.py @@ -163,11 +163,17 @@ def get_group_techniques(groups, stage, platform, file_type): for group in config['groups']: if group['enabled']: - group_id = get_group_id(group['group_name'], group['campaign']) + campaign = group['campaign'] if group['campaign'] else '' + group_id = get_group_id(group['group_name'], campaign) groups_dict[group_id] = dict() groups_dict[group_id]['group_name'] = group['group_name'] - groups_dict[group_id]['techniques'] = set(group['technique_id']) + if type(group['technique_id']) == list: + groups_dict[group_id]['techniques'] = set(group['technique_id']) + groups_dict[group_id]['weight'] = dict((i, 1) for i in group['technique_id']) + elif type(group['technique_id']) == dict: + groups_dict[group_id]['techniques'] = set(group['technique_id'].keys()) + groups_dict[group_id]['weight'] = group['technique_id'] groups_dict[group_id]['campaign'] = group['campaign'] groups_dict[group_id]['software'] = group['software_id'] else: @@ -187,8 +193,10 @@ def get_group_techniques(groups, stage, platform, file_type): groups_found.add(e['group_id']) groups_dict[e['group_id']] = {'group_name': e['group']} groups_dict[e['group_id']]['techniques'] = set() + groups_dict[e['group_id']]['weight'] = dict() groups_dict[e['group_id']]['techniques'].add(e['technique_id']) + groups_dict[e['group_id']]['weight'][e['technique_id']] = 1 # do not call 'is_group_found' when groups is a YAML file # (this could contain groups that do not exists within ATT&CK) @@ -216,10 +224,12 @@ def get_detection_techniques(filename, filter_applicable_to): groups_dict[group_id] = {} groups_dict[group_id]['group_name'] = 'Detection' groups_dict[group_id]['techniques'] = set() + groups_dict[group_id]['weight'] = dict() for t, v in detection_techniques.items(): s = calculate_score(v['detection']) if s > 0: groups_dict[group_id]['techniques'].add(t) + groups_dict[group_id]['weight'][t] = 1 return groups_dict, detection_techniques @@ -240,10 +250,12 @@ def get_visibility_techniques(filename, filter_applicable_to): groups_dict[group_id] = {} groups_dict[group_id]['group_name'] = 'Visibility' groups_dict[group_id]['techniques'] = set() + groups_dict[group_id]['weight'] = dict() for t, v in visibility_techniques.items(): s = calculate_score(v['visibility']) if s > 0: groups_dict[group_id]['techniques'].add(t) + groups_dict[group_id]['weight'][t] = 1 return groups_dict, visibility_techniques @@ -256,7 +268,7 @@ def get_technique_count(groups, groups_overlay, groups_software, overlay_type, a :param groups_software: a dict with with data on which techniques are used within related software :param overlay_type: group, visibility or detection :param all_techniques: dict containing all technique data for visibility or detection - :return: dictionary + :return: dictionary, max_count """ # { technique_id: {count: ..., groups: set{} } techniques_dict = {} @@ -266,23 +278,23 @@ def get_technique_count(groups, groups_overlay, groups_software, overlay_type, a if tech not in techniques_dict: techniques_dict[tech] = dict() techniques_dict[tech]['groups'] = set() - techniques_dict[tech]['count'] = 1 + techniques_dict[tech]['count'] = v['weight'][tech] # We only want to increase the score when comparing groups and not for visibility or detection. # This allows to have proper sorting of the heat map, which in turn improves the ability to visually # compare this heat map with the detection/visibility ATT&CK Navigator layers. else: - techniques_dict[tech]['count'] += 1 + techniques_dict[tech]['count'] += v['weight'][tech] techniques_dict[tech]['groups'].add(group) - max_tech_count_group = max(techniques_dict.values(), key=lambda v: v['count'])['count'] + max_count = max(techniques_dict.values(), key=lambda v: v['count'])['count'] # create dict {tech_id: score+max_tech_count} to be used for when doing an overlay of the type visibility or detection if overlay_type != OVERLAY_TYPE_GROUP: dict_tech_score = {} list_tech = groups_overlay[overlay_type.upper()]['techniques'] for tech in list_tech: - dict_tech_score[tech] = calculate_score(all_techniques[tech][overlay_type]) + max_tech_count_group + dict_tech_score[tech] = calculate_score(all_techniques[tech][overlay_type]) + max_count for group, v in groups_overlay.items(): for tech in v['techniques']: @@ -290,23 +302,23 @@ def get_technique_count(groups, groups_overlay, groups_software, overlay_type, a techniques_dict[tech] = dict() techniques_dict[tech]['groups'] = set() if overlay_type == OVERLAY_TYPE_GROUP: - techniques_dict[tech]['count'] = 1 + techniques_dict[tech]['count'] = v['weight'][tech] else: techniques_dict[tech]['count'] = dict_tech_score[tech] elif group in groups: if tech not in groups[group]['techniques']: if overlay_type == OVERLAY_TYPE_GROUP: - techniques_dict[tech]['count'] += 1 + techniques_dict[tech]['count'] += v['weight'][tech] else: techniques_dict[tech]['count'] = dict_tech_score[tech] - # Only to this when it was not already counted by being part of 'groups'. + # Only do this when it was not already counted by being part of 'groups'. # Meaning the group in 'groups_overlay' was also part of 'groups' (match on Group ID) and the # technique was already counted for that group / it is not a new technique for that group coming # from a YAML file else: if overlay_type == OVERLAY_TYPE_GROUP: # increase count when the group in the YAML file is a custom group - techniques_dict[tech]['count'] += 1 + techniques_dict[tech]['count'] += v['weight'][tech] else: techniques_dict[tech]['count'] = dict_tech_score[tech] @@ -323,7 +335,7 @@ def get_technique_count(groups, groups_overlay, groups_software, overlay_type, a techniques_dict[tech]['groups'] = set() techniques_dict[tech]['groups'].add(group) - return techniques_dict, max_tech_count_group + return techniques_dict, max_count def get_technique_layer(techniques_count, groups, overlay, groups_software, overlay_file_type, overlay_type, @@ -505,7 +517,7 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft elif software_groups: groups_software_dict = get_software_techniques(groups, stage, platform) - technique_count, max_tech_count_group = get_technique_count(groups_dict, overlay_dict, groups_software_dict, overlay_type, all_techniques) + technique_count, max_count = get_technique_count(groups_dict, overlay_dict, groups_software_dict, overlay_type, all_techniques) technique_layer = get_technique_layer(technique_count, groups_dict, overlay_dict, groups_software_dict, overlay_file_type, overlay_type, all_techniques) @@ -519,15 +531,16 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft desc = 'stage: ' + stage + ' | platform: ' + platform + ' | group(s): ' + ', '.join(groups_list) + \ ' | overlay group(s): ' + ', '.join(overlay_list) - layer = get_layer_template_groups(stage[0].upper() + stage[1:] + ' ' + platform, max_tech_count_group, desc, stage, platform, overlay_type) + layer = get_layer_template_groups(stage[0].upper() + stage[1:] + ' ' + platform, max_count, desc, stage, platform, overlay_type) layer['techniques'] = technique_layer json_string = simplejson.dumps(layer).replace('}, ', '},\n') if overlay: - filename = "output/" + stage + '_' + platform.lower() + '_' + '_'.join(groups_list) + '-overlay_' + '_'.join(overlay_list) + '_' + filter_applicable_to.replace(' ', '_') + '.json' + filename = "output/" + stage + '_' + platform.lower() + '_' + '_'.join(groups_list) + '-overlay_' + '_'.join(overlay_list) + '_' + filter_applicable_to.replace(' ', '_') else: - filename = "output/" + stage + '_' + platform.lower() + '_' + '_'.join(groups_list) + '.json' + filename = "output/" + stage + '_' + platform.lower() + '_' + '_'.join(groups_list) + filename = filename[:255] + '.json' with open(filename, 'w') as f: # write layer file to disk f.write(json_string) print('Written layer: ' + filename) diff --git a/sample-data/redcanary.yaml b/sample-data/redcanary.yaml new file mode 100644 index 00000000..888519cf --- /dev/null +++ b/sample-data/redcanary.yaml @@ -0,0 +1,141 @@ +%YAML 1.2 +--- +version: 1.0 +file_type: group-administration +groups: + - + group_name: Red Canary Threat Detection Report 2019 - financials + campaign: + technique_id: [T1015, T1036, T1060, T1064, T1085, T1086, T1089, T1090, T1117, T1193] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - communication + campaign: + technique_id: [T1086, T1035, T1117, T1064, T1003, T1090, T1036, T1060, T1193, T1053] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - education + campaign: + technique_id: [T1086, T1077, T1053, T1064, T1003, T1060, T1055, T1036, T1089, T1090] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - energy + campaign: + technique_id: [T1086, T1193, T1059, T1047, T1085, T1035, T1064, T1036, T1097, T1003] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - government + campaign: + technique_id: [T1117, T1060, T1086, T1003, T1036, T1193, T1027, T1089, T1015, T1105] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - health + campaign: + technique_id: [T1086, T1003, T1117, T1059, T1105, T1053, T1193, T1036, T1064, T1090] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - hospitality + campaign: + technique_id: [T1086, T1064, T1036, T1140, T1100, T1047, T1193, T1090, T1015, T1003] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - industrial + campaign: + technique_id: [T1086, T1064, T1117, T1090, T1036, T1060, T1085, T1193, T1015, T1059] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - meida + campaign: + technique_id: [T1086, T1193, T1090, T1064, T1036, T1060, T1059, T1003, T1015, T1089] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - nonprofit + campaign: + technique_id: [T1086, T1059, T1064, T1089, T1117, T1036, T1003, T1193, T1060, T1105] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - pharmaceuticals + campaign: + technique_id: [T1003, T1086, T1064, T1036, T1193, T1035, T1047, T1059, T1055, T1085] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - retail + campaign: + technique_id: [T1193, T1086, T1064, T1059, T1060, T1090, T1036, T1015, T1089, T1055] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - services + campaign: + technique_id: [T1086, T1117, T1047, T1003, T1064, T1087, T1193, T1060, T1036, T1090] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - technology + campaign: + technique_id: [T1087, T1035, T1086, T1090, T1089, T1064, T1193, T1003, T1036, T1117] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - transportation + campaign: + technique_id: [T1086, T1035, T1085, T1064, T1117, T1059, T1060, T1090, T1089, T1036] + software_id: [] + enabled: False + - + group_name: Red Canary Threat Detection Report 2019 - overall + campaign: + technique_id: + T1086: 1774 + T1064: 794 + T1117: 710 + T1090: 607 + T1193: 424 + T1036: 419 + T1003: 405 + T1060: 378 + T1085: 372 + T1035: 336 + T1089: 313 + T1059: 294 + T1087: 289 + T1015: 252 + T1053: 232 + T1047: 200 + T1055: 156 + T1027: 121 + T1077: 116 + T1097: 86 + T1105: 71 + T1197: 62 + T1204: 57 + T1140: 52 + T1088: 45 + T1070: 45 + T1074: 39 + T1170: 32 + T1100: 30 + T1127: 29 + T1069: 27 + T1420: 27 + T1146: 27 + T1028: 25 + T1002: 20 + T1218: 18 + T1048: 18 + T1118: 15 + T1068: 13 + T1121: 13 + software_id: [] + enabled: True From 4b94efa6514f652068713166b7eeca98bea84c72 Mon Sep 17 00:00:00 2001 From: Ruben Bouman Date: Thu, 16 May 2019 08:24:14 +0200 Subject: [PATCH 06/18] Moved threat actor info from redcanary to new folder "threat-actor-data". --- {sample-data => threat-actor-data}/redcanary.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {sample-data => threat-actor-data}/redcanary.yaml (100%) diff --git a/sample-data/redcanary.yaml b/threat-actor-data/redcanary.yaml similarity index 100% rename from sample-data/redcanary.yaml rename to threat-actor-data/redcanary.yaml From 7c88bb46d86b903e9a239cf4e0219ac407563f7b Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Thu, 16 May 2019 13:30:42 +0200 Subject: [PATCH 07/18] Renamed the .yaml file and created Navigator layers. --- ...redcanary.yaml => 20190319-RedCanary.yaml} | 32 ++++++------- ...rt 2019 (1st edition) - communication.json | 17 +++++++ ...Report 2019 (1st edition) - education.json | 17 +++++++ ...on Report 2019 (1st edition) - energy.json | 17 +++++++ ...eport 2019 (1st edition) - financials.json | 17 +++++++ ...eport 2019 (1st edition) - government.json | 17 +++++++ ...on Report 2019 (1st edition) - health.json | 17 +++++++ ...port 2019 (1st edition) - hospitality.json | 17 +++++++ ...eport 2019 (1st edition) - industrial.json | 17 +++++++ ...ion Report 2019 (1st edition) - media.json | 17 +++++++ ...Report 2019 (1st edition) - nonprofit.json | 17 +++++++ ...n Report 2019 (1st edition) - overall.json | 47 +++++++++++++++++++ ... 2019 (1st edition) - pharmaceuticals.json | 17 +++++++ ...on Report 2019 (1st edition) - retail.json | 17 +++++++ ... Report 2019 (1st edition) - services.json | 17 +++++++ ...eport 2019 (1st edition) - technology.json | 17 +++++++ ...t 2019 (1st edition) - transportation.json | 17 +++++++ 17 files changed, 318 insertions(+), 16 deletions(-) rename threat-actor-data/{redcanary.yaml => 20190319-RedCanary.yaml} (69%) create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - communication.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - education.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - energy.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - financials.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - government.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - health.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - hospitality.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - industrial.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - media.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - nonprofit.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - overall.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - retail.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - services.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - technology.json create mode 100644 threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - transportation.json diff --git a/threat-actor-data/redcanary.yaml b/threat-actor-data/20190319-RedCanary.yaml similarity index 69% rename from threat-actor-data/redcanary.yaml rename to threat-actor-data/20190319-RedCanary.yaml index 888519cf..b49a7d6e 100644 --- a/threat-actor-data/redcanary.yaml +++ b/threat-actor-data/20190319-RedCanary.yaml @@ -4,97 +4,97 @@ version: 1.0 file_type: group-administration groups: - - group_name: Red Canary Threat Detection Report 2019 - financials + group_name: Red Canary Threat Detection Report 2019 (1st edition) - financials campaign: technique_id: [T1015, T1036, T1060, T1064, T1085, T1086, T1089, T1090, T1117, T1193] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - communication + group_name: Red Canary Threat Detection Report 2019 (1st edition) - communication campaign: technique_id: [T1086, T1035, T1117, T1064, T1003, T1090, T1036, T1060, T1193, T1053] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - education + group_name: Red Canary Threat Detection Report 2019 (1st edition) - education campaign: technique_id: [T1086, T1077, T1053, T1064, T1003, T1060, T1055, T1036, T1089, T1090] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - energy + group_name: Red Canary Threat Detection Report 2019 (1st edition) - energy campaign: technique_id: [T1086, T1193, T1059, T1047, T1085, T1035, T1064, T1036, T1097, T1003] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - government + group_name: Red Canary Threat Detection Report 2019 (1st edition) - government campaign: technique_id: [T1117, T1060, T1086, T1003, T1036, T1193, T1027, T1089, T1015, T1105] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - health + group_name: Red Canary Threat Detection Report 2019 (1st edition) - health campaign: technique_id: [T1086, T1003, T1117, T1059, T1105, T1053, T1193, T1036, T1064, T1090] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - hospitality + group_name: Red Canary Threat Detection Report 2019 (1st edition) - hospitality campaign: technique_id: [T1086, T1064, T1036, T1140, T1100, T1047, T1193, T1090, T1015, T1003] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - industrial + group_name: Red Canary Threat Detection Report 2019 (1st edition) - industrial campaign: technique_id: [T1086, T1064, T1117, T1090, T1036, T1060, T1085, T1193, T1015, T1059] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - meida + group_name: Red Canary Threat Detection Report 2019 (1st edition) - media campaign: technique_id: [T1086, T1193, T1090, T1064, T1036, T1060, T1059, T1003, T1015, T1089] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - nonprofit + group_name: Red Canary Threat Detection Report 2019 (1st edition) - nonprofit campaign: technique_id: [T1086, T1059, T1064, T1089, T1117, T1036, T1003, T1193, T1060, T1105] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - pharmaceuticals + group_name: Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals campaign: technique_id: [T1003, T1086, T1064, T1036, T1193, T1035, T1047, T1059, T1055, T1085] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - retail + group_name: Red Canary Threat Detection Report 2019 (1st edition) - retail campaign: technique_id: [T1193, T1086, T1064, T1059, T1060, T1090, T1036, T1015, T1089, T1055] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - services + group_name: Red Canary Threat Detection Report 2019 (1st edition) - services campaign: technique_id: [T1086, T1117, T1047, T1003, T1064, T1087, T1193, T1060, T1036, T1090] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - technology + group_name: Red Canary Threat Detection Report 2019 (1st edition) - technology campaign: technique_id: [T1087, T1035, T1086, T1090, T1089, T1064, T1193, T1003, T1036, T1117] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - transportation + group_name: Red Canary Threat Detection Report 2019 (1st edition) - transportation campaign: technique_id: [T1086, T1035, T1085, T1064, T1117, T1059, T1060, T1090, T1089, T1036] software_id: [] enabled: False - - group_name: Red Canary Threat Detection Report 2019 - overall + group_name: Red Canary Threat Detection Report 2019 (1st edition) - overall campaign: technique_id: T1086: 1774 diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - communication.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - communication.json new file mode 100644 index 00000000..37087c09 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - communication.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - communication | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1053", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1035", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - communication"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - education.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - education.json new file mode 100644 index 00000000..92528fcd --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - education.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - education | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1055", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1077", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1053", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - education"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - energy.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - energy.json new file mode 100644 index 00000000..02472347 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - energy.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - energy | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1085", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1047", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1035", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1097", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - energy"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - financials.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - financials.json new file mode 100644 index 00000000..34ebf6c6 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - financials.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - financials | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1085", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1015", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - financials"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - government.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - government.json new file mode 100644 index 00000000..9106bcb1 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - government.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - government | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1015", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1027", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1105", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - government"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - health.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - health.json new file mode 100644 index 00000000..bc394fd8 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - health.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - health | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1053", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1105", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - health"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - hospitality.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - hospitality.json new file mode 100644 index 00000000..f87c1da7 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - hospitality.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - hospitality | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1015", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1047", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1140", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1100", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - hospitality"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - industrial.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - industrial.json new file mode 100644 index 00000000..40defa28 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - industrial.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - industrial | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1015", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1085", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - industrial"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - media.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - media.json new file mode 100644 index 00000000..017448ad --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - media.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - media | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1015", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - media"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - nonprofit.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - nonprofit.json new file mode 100644 index 00000000..a1fe5bad --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - nonprofit.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - nonprofit | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1105", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - nonprofit"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - overall.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - overall.json new file mode 100644 index 00000000..3961f7e0 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - overall.json @@ -0,0 +1,47 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - overall | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1197", "score": 62, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1069", "score": 27, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1087", "score": 289, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1118", "score": 15, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1140", "score": 52, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1053", "score": 232, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1048", "score": 18, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1002", "score": 20, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1420", "score": 27, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1088", "score": 45, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1028", "score": 25, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1070", "score": 45, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1090", "score": 607, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1015", "score": 252, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1047", "score": 200, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1068", "score": 13, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1170", "score": 32, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1074", "score": 39, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1117", "score": 710, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1060", "score": 378, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1121", "score": 13, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1100", "score": 30, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1127", "score": 29, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1003", "score": 405, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1193", "score": 424, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1146", "score": 27, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1105", "score": 71, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1089", "score": 313, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1204", "score": 57, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1218", "score": 18, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1077", "score": 116, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1059", "score": 294, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1085", "score": 372, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1086", "score": 1774, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1055", "score": 156, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1097", "score": 86, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1035", "score": 336, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1064", "score": 794, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1036", "score": 419, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}, +{"techniqueID": "T1027", "score": 121, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - overall"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1774}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals.json new file mode 100644 index 00000000..2c130f6d --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1085", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1035", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1047", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1055", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - pharmaceuticals"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - retail.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - retail.json new file mode 100644 index 00000000..6af01837 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - retail.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - retail | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1015", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}, +{"techniqueID": "T1055", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - retail"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - services.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - services.json new file mode 100644 index 00000000..d5904d5b --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - services.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - services | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1087", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}, +{"techniqueID": "T1047", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - services"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - technology.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - technology.json new file mode 100644 index 00000000..5e6191a9 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - technology.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - technology | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1087", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1193", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1035", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1003", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - technology"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file diff --git a/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - transportation.json b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - transportation.json new file mode 100644 index 00000000..453fbe37 --- /dev/null +++ b/threat-actor-data/ATT&CK-Navigator-layers/20190319-RedCanary/attack_windows_Red Canary Threat Detection Report 2019 (1st edition) - transportation.json @@ -0,0 +1,17 @@ +{"name": "Attack Windows", "version": "2.1", "domain": "mitre-enterprise", "description": "stage: attack | platform: Windows | group(s): Red Canary Threat Detection Report 2019 (1st edition) - transportation | overlay group(s): ", "filters": {"stages": ["act"], "platforms": ["windows"]}, +"sorting": 3, "viewMode": 0, "hideDisable": false, "techniques": [{"techniqueID": "T1036", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1060", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1090", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1085", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1117", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1064", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1035", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1086", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1059", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}, +{"techniqueID": "T1089", "score": 1, "metadata": [{"name": "-Groups", "value": "Red Canary Threat Detection Report 2019 (1st edition) - transportation"}]}], "showTacticRowBackground": false, "tacticRowBackground": "#dddddd", "selectTechniquesAcrossTactics": true, "gradient": {"colors": ["#ffcece", "#ff0000"], "minValue": 0, "maxValue": 1}, +"legendItems": [{"label": "Tech. not often used", "color": "#ffcece"}, +{"label": "Tech. used frequently", "color": "#ff0000"}, +{"label": "Groups overlay: tech. in group + overlay", "color": "#f9a825"}, +{"label": "Groups overlay: tech. in overlay", "color": "#ffee58"}, +{"label": "Src. of tech. is only software", "color": "#0d47a1 "}, +{"label": "Src. of tech. is group(s)/overlay + software", "color": "#64b5f6 "}]} \ No newline at end of file From bdb57f02700f89b9f7f898792f22fbf61abe88e3 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Fri, 17 May 2019 14:05:48 +0200 Subject: [PATCH 08/18] Fixed some errors --- sample-data/techniques-administration-endpoints.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sample-data/techniques-administration-endpoints.yaml b/sample-data/techniques-administration-endpoints.yaml index e90d7d32..61044163 100644 --- a/sample-data/techniques-administration-endpoints.yaml +++ b/sample-data/techniques-administration-endpoints.yaml @@ -1527,7 +1527,8 @@ techniques: date_registered: date_implemented: score: -1 - location: '' + location: + - '' comment: '' visibility: applicable_to: ['all'] @@ -1818,7 +1819,8 @@ techniques: date_registered: date_implemented: score: -1 - location: '' + location: + - '' comment: '' visibility: applicable_to: ['all'] @@ -2148,8 +2150,8 @@ techniques: technique_name: Data Encrypted for Impact detection: applicable_to: ['all'] - date_registered: - date_implemented: + date_registered: 2019-05-01 + date_implemented: 2015-01-01 score: 4 location: - 'Model J' From 3de186c96e029ce4630ec10ba38fae8491f44cb7 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Fri, 17 May 2019 14:08:17 +0200 Subject: [PATCH 09/18] added the health check to the menu --- interactive_menu.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/interactive_menu.py b/interactive_menu.py index 00968872..c8415823 100644 --- a/interactive_menu.py +++ b/interactive_menu.py @@ -267,6 +267,7 @@ def menu_detection(filename_t): print('3. Generate a layer for detection coverage overlayed with visibility for the ATT&CK Navigator.') print('4. Generate a graph with detections added through time.') print('5. Generate an Excel sheet with all administrated techniques.') + print('6. Check the technique YAML file for errors.') print('9. Back to main menu.') choice = ask_input() if choice == '1': @@ -291,6 +292,10 @@ def menu_detection(filename_t): print('Generating Excel file...') export_techniques_list_to_excel(filename_t) wait() + elif choice == '6': + print('Checking the technique YAML file for errors...') + check_yaml_file_health(filename_t, FILE_TYPE_TECHNIQUE_ADMINISTRATION) + wait() elif choice == '9': interactive_menu() elif choice == 'q': @@ -320,6 +325,7 @@ def menu_visibility(filename_t, filename_ds): print('2. Generate a layer for visibility for the ATT&CK Navigator.') print('3. Generate a layer for visibility overlayed with detection coverage for the ATT&CK Navigator.') print('4. Generate an Excel sheet with all administrated techniques.') + print('5. Check the technique YAML file for errors.') print('9. Back to main menu.') choice = ask_input() if choice == '1': @@ -337,6 +343,10 @@ def menu_visibility(filename_t, filename_ds): print('Generating Excel file...') export_techniques_list_to_excel(filename_t) wait() + elif choice == '5': + print('Checking the technique YAML file for errors...') + check_yaml_file_health(filename_t, FILE_TYPE_TECHNIQUE_ADMINISTRATION) + wait() elif choice == '9': interactive_menu() elif choice == 'q': From f10e4ea9ab8a5a29203cb7be9b4341f3213650e0 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Sun, 19 May 2019 14:10:25 +0200 Subject: [PATCH 10/18] - The health function now checks for very similar values within the key-value pair 'applicable_to'. E.g. 'server' and 'servers'. - The health function is now always called for technique admin files. Showing a generic error message if possible errors are found. - Created new function 'check_file' to separate the functionality from 'check_file_type'. --- dettact.py | 26 +++---- generic.py | 178 +++++++++++++++++++++++++++++--------------- group_mapping.py | 4 +- interactive_menu.py | 6 +- 4 files changed, 135 insertions(+), 79 deletions(-) diff --git a/dettact.py b/dettact.py index d9bc7eb8..d591c2f8 100644 --- a/dettact.py +++ b/dettact.py @@ -145,7 +145,7 @@ def menu(menu_parser): interactive_menu() elif args.subparser in ['datasource', 'ds']: - if check_file_type(args.file, FILE_TYPE_DATA_SOURCE_ADMINISTRATION): + if check_file(args.file, FILE_TYPE_DATA_SOURCE_ADMINISTRATION, args.health): if args.layer: generate_data_sources_layer(args.file) if args.excel: @@ -162,19 +162,18 @@ def menu(menu_parser): 'administration YAML file (\'--file-ds\')') quit() - if check_file_type(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION) and \ - check_file_type(args.file_ds, FILE_TYPE_DATA_SOURCE_ADMINISTRATION): + if check_file(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION, args.health) and \ + check_file(args.file_ds, FILE_TYPE_DATA_SOURCE_ADMINISTRATION, args.health): if args.layer: generate_visibility_layer(args.file_tech, args.file_ds, False, args.applicable) if args.overlay: generate_visibility_layer(args.file_tech, args.file_ds, True, args.applicable) - if args.excel and check_file_type(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION) and args.applicable == 'all': - export_techniques_list_to_excel(args.file_tech) - if args.excel and args.applicable != 'all': - print("[!] Filtering on 'applicable_to' is not supported for Excel output") - if args.health: - check_yaml_file_health(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION) + if check_file(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION, args.health): + if args.excel and args.applicable == 'all': + export_techniques_list_to_excel(args.file_tech) + if args.excel and args.applicable != 'all': + print('[!] Filtering on \'applicable_to\' is not supported for Excel output') elif args.subparser in ['group', 'g']: generate_group_heat_map(args.groups, args.overlay, args.overlay_type, args.stage, args.platform, args.software_group, args.applicable) @@ -184,13 +183,13 @@ def menu(menu_parser): if not args.file_ds: print('[!] Doing an overlay requires adding the data source administration YAML file (\'--file-ds\')') quit() - if not check_file_type(args.file_ds, FILE_TYPE_DATA_SOURCE_ADMINISTRATION): + if not check_file(args.file_ds, FILE_TYPE_DATA_SOURCE_ADMINISTRATION, args.health): quit() - if check_file_type(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION): + if check_file(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION, args.health): if args.layer: generate_detection_layer(args.file_tech, args.file_ds, False, args.applicable) - if args.overlay and check_file_type(args.file_ds, FILE_TYPE_DATA_SOURCE_ADMINISTRATION): + if args.overlay and check_file(args.file_ds, FILE_TYPE_DATA_SOURCE_ADMINISTRATION, args.health): generate_detection_layer(args.file_tech, args.file_ds, True, args.applicable) if args.graph: plot_detection_graph(args.file_tech, args.applicable) @@ -198,8 +197,6 @@ def menu(menu_parser): export_techniques_list_to_excel(args.file_tech) if args.excel and args.applicable != 'all': print("[!] Filtering on 'applicable_to' is not supported for Excel output") - if args.health: - check_yaml_file_health(args.file_tech, FILE_TYPE_TECHNIQUE_ADMINISTRATION) elif args.subparser in ['generic', 'ge']: if args.statistics: @@ -210,6 +207,7 @@ def menu(menu_parser): else: menu_parser.print_help() + def prepare_folders(): """ Create the folders 'cache' and 'output' if they do not exist. diff --git a/generic.py b/generic.py index ee81910a..189748ca 100644 --- a/generic.py +++ b/generic.py @@ -4,6 +4,7 @@ import yaml from upgrade import upgrade_yaml_file from constants import * +from difflib import SequenceMatcher # Due to performance reasons the import of attackcti is within the function that makes use of this library. @@ -283,45 +284,6 @@ def get_all_mitre_data_sources(): return sorted(data_sources) -def check_file_type(filename, file_type=None): - """ - Check if the provided YAML file has the key 'file_type' and possible if that key matches a specific value. - :param filename: path to a YAML file - :param file_type: value to check against the 'file_type' key in the YAML file - :return: the file_type if present, else None is returned. - """ - if not os.path.exists(filename): - print('[!] File: \'' + filename + '\' does not exist') - return None - with open(filename, 'r') as yaml_file: - try: - yaml_content = yaml.load(yaml_file, Loader=yaml.FullLoader) - except Exception as e: - print('[!] File: \'' + filename + '\' is not a valid YAML file.') - print(' ' + str(e)) # print more detailed error information to help the user in fixing the error. - return None - - # This check is performed because a text file will also be considered to be valid YAML. But, we are using - # key-value pairs within the YAML files. - if not hasattr(yaml_content, 'keys'): - print('[!] File: \'' + filename + '\' is not a valid YAML file.') - return None - - if 'file_type' not in yaml_content.keys(): - print('[!] File: \'' + filename + '\' does not contain a file_type key.') - return None - elif file_type: - if file_type != yaml_content['file_type']: - print('[!] File: \'' + filename + '\' is not a file type of: \'' + file_type + '\'') - return None - else: - upgrade_yaml_file(filename, file_type, yaml_content['version'], load_attack_data(DATATYPE_ALL_TECH)) - return yaml_content['file_type'] - else: - upgrade_yaml_file(filename, file_type, yaml_content['version'], load_attack_data(DATATYPE_ALL_TECH)) - return yaml_content['file_type'] - - def calculate_score(l, zero_value=0): """ Calculates the average score in the given list which contains dictionaries with 'score' field. @@ -393,13 +355,22 @@ def load_techniques(filename, detection_or_visibility='all', filter_applicable_t return my_techniques, name, platform -def check_yaml_file_health(filename, file_type): +def _print_error_msg(msg, print_error): + if print_error: + print(msg) + return True + + +def check_yaml_file_health(filename, file_type, health_is_called): """ Check on error in the provided YAML file. :param filename: YAML file location - :param file_type: currenlty only 'FILE_TYPE_TECHNIQUE_ADMINISTRATION' is being supported + :param file_type: currently only 'FILE_TYPE_TECHNIQUE_ADMINISTRATION' is being supported + :param health_is_called: boolean that specifies if detailed errors in the file will be printed and then quit() :return: """ + + has_error = False if file_type == FILE_TYPE_TECHNIQUE_ADMINISTRATION: # check for duplicate tech IDs with open(filename, 'r') as yaml_file: @@ -411,69 +382,156 @@ def check_yaml_file_health(filename, file_type): if tech not in tech_dup: tech_dup.append(tech) else: - print('[!] Duplicate technique ID: ' + tech) + has_error = _print_error_msg('[!] Duplicate technique ID: ' + tech, health_is_called) # checks on: # - empty key-value pairs: 'date_implemented', 'date_registered', 'location', 'applicable_to', 'score' # - invalid date format for: 'date_implemented', 'date_registered' # - detection or visibility score out-of-range # - missing key-value pairs: 'applicable_to', 'date_registered', 'date_implemented', 'score', 'location', 'comment' + # - check on 'applicable_to' values which are very similar + all_applicable_to = set() techniques = load_techniques(filename) for tech, v in techniques[0].items(): + for key in ['detection', 'visibility']: if key not in v: - print('[!] Technique ID: ' + tech + ' is MISSING ' + key) + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is MISSING ' + key, health_is_called) + else: + # create at set containing all values for 'applicable_to' + all_applicable_to.update([a for v in v[key] for a in v['applicable_to']]) for detection in v['detection']: for key in ['applicable_to', 'date_registered', 'date_implemented', 'score', 'location', 'comment']: if key not in detection: - print('[!] Technique ID: ' + tech + ' is MISSING the key-value pair in detection: ' + key) + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is MISSING the key-value pair in detection: ' + key, health_is_called) try: if detection['score'] is None: - print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: score') + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: score', health_is_called) elif not (detection['score'] >= -1 and detection['score'] <= 5): - print('[!] Technique ID: ' + tech + ' has an INVALID detection score: ' + str(detection['score']) + - ' (should be between -1 and 5)') + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' has an INVALID detection score: ' + + str(detection['score']) + ' (should be between -1 and 5)', health_is_called) elif detection['score'] > -1: for key in ['date_implemented', 'date_registered']: if not detection[key]: - print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key, health_is_called) break try: detection[key].year detection[key].month detection[key].day except AttributeError: - print('[!] Technique ID: ' + tech + ' has an INVALID data format for the key-value pair ' - 'in detection: ' + key + ' (should be YYYY-MM-DD)') - + has_error = _print_error_msg('[!] Technique ID: ' + tech + + ' has an INVALID data format for the key-value pair in detection: ' + + key + ' (should be YYYY-MM-DD)', health_is_called) for key in ['location', 'applicable_to']: - try: - if detection[key][0] is None: - print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) - except TypeError: - print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key) + if not isinstance(detection[key], list): + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' has for the key-value pair \'' + + key + '\' a string value assigned (should be a list)', health_is_called) + else: + try: + if detection[key][0] is None: + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key, health_is_called) + except TypeError: + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in detection: ' + key, health_is_called) except KeyError: pass for visibility in v['visibility']: for key in ['applicable_to', 'score', 'comment']: if key not in visibility: - print('[!] Technique ID: ' + tech + ' is MISSING the key-value pair in visibility: ' + key) + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is MISSING the key-value pair in visibility: ' + key, health_is_called) try: if visibility['score'] is None: - print('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in visibility: score') + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' is has an EMPTY key-value pair in visibility: score', health_is_called) elif not (visibility['score'] >= 0 and visibility['score'] <= 4): - print('[!] Technique ID: ' + tech + ' has an INVALID visibility score: ' + str(detection['score']) + - ' (should be between 0 and 4)') + has_error = _print_error_msg('[!] Technique ID: ' + tech + ' has an INVALID visibility score: ' + + str(detection['score']) + ' (should be between 0 and 4)', health_is_called) except KeyError: pass + # get values within the key-value pair 'applicable_to' which are a very close match + similar = set() + for i1 in all_applicable_to: + for i2 in all_applicable_to: + match_value = SequenceMatcher(None, i1, i2).ratio() + if match_value > 0.8 and match_value != 1: + print(match_value) + similar.add(i1) + similar.add(i2) + + if len(similar) > 0: + has_error = _print_error_msg('[!] There are values in the key-value pair \'applicable_to\' which are very similar. Correct where necessary:', health_is_called) + for s in similar: + _print_error_msg(' - ' + s, health_is_called) + + if has_error and not health_is_called: + print('[!] The below YAML file contains possible errors. It\'s recommended to check via the \'--health\' ' + 'argument or using the option in the interactive menu: \n - ' + filename) + + if has_error: + print('') # print a newline + + +def check_file_type(filename, file_type=None): + """ + Check if the provided YAML file has the key 'file_type' and possible if that key matches a specific value. + :param filename: path to a YAML file + :param file_type: value to check against the 'file_type' key in the YAML file + :return: the file_type if present, else None is returned + """ + if not os.path.exists(filename): + print('[!] File: \'' + filename + '\' does not exist') + return None + with open(filename, 'r') as yaml_file: + try: + yaml_content = yaml.load(yaml_file, Loader=yaml.FullLoader) + except Exception as e: + print('[!] File: \'' + filename + '\' is not a valid YAML file.') + print(' ' + str(e)) # print more detailed error information to help the user in fixing the error. + return None + + # This check is performed because a text file will also be considered to be valid YAML. But, we are using + # key-value pairs within the YAML files. + if not hasattr(yaml_content, 'keys'): + print('[!] File: \'' + filename + '\' is not a valid YAML file.') + return None + + if 'file_type' not in yaml_content.keys(): + print('[!] File: \'' + filename + '\' does not contain a file_type key.') + return None + elif file_type: + if file_type != yaml_content['file_type']: + print('[!] File: \'' + filename + '\' is not a file type of: \'' + file_type + '\'') + return None + else: + return yaml_content + else: + return yaml_content + + +def check_file(filename, file_type=None, health_is_called=False): + """ + Calls three functions to perform the following checks: is the file a valid YAML file, needs the file to be upgrade, + does the file contain errors. + :param filename: path to a YAML file + :param file_type: value to check against the 'file_type' key in the YAML file + :param health_is_called: boolean that specifies if detailed errors in the file will be printed by the function 'check_yaml_file_health' and then quit() + :return: the file_type if present, else None is returned + """ + + yaml_content = check_file_type(filename, file_type) + # if the file is a valid YAML, continue. Else, return None + if yaml_content: + upgrade_yaml_file(filename, file_type, yaml_content['version'], load_attack_data(DATATYPE_ALL_TECH)) + check_yaml_file_health(filename, file_type, health_is_called) + return yaml_content['file_type'] + return yaml_content # value is None diff --git a/group_mapping.py b/group_mapping.py index d2d61785..c933cdbb 100644 --- a/group_mapping.py +++ b/group_mapping.py @@ -468,7 +468,7 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft groups_file_type = None if os.path.isfile(groups): - groups_file_type = check_file_type(groups, file_type=FILE_TYPE_GROUP_ADMINISTRATION) + groups_file_type = check_file(groups, file_type=FILE_TYPE_GROUP_ADMINISTRATION) if not groups_file_type: return else: @@ -482,7 +482,7 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft expected_file_type = FILE_TYPE_GROUP_ADMINISTRATION if overlay_type == OVERLAY_TYPE_GROUP \ else FILE_TYPE_TECHNIQUE_ADMINISTRATION \ if overlay_type in [OVERLAY_TYPE_VISIBILITY, OVERLAY_TYPE_DETECTION] else None - overlay_file_type = check_file_type(overlay, expected_file_type) + overlay_file_type = check_file(overlay, expected_file_type) if not overlay_file_type: return else: diff --git a/interactive_menu.py b/interactive_menu.py index c8415823..d712d73a 100644 --- a/interactive_menu.py +++ b/interactive_menu.py @@ -136,7 +136,7 @@ def select_file(title, what, expected_file_type, b_clear=True): else: if choice.isdigit() and int(choice) < n: filename = files[int(choice) - 1] - file_type = check_file_type(filename, file_type=expected_file_type) + file_type = check_file(filename, file_type=expected_file_type) if file_type: print('Selected file: ' + filename) wait() @@ -294,7 +294,7 @@ def menu_detection(filename_t): wait() elif choice == '6': print('Checking the technique YAML file for errors...') - check_yaml_file_health(filename_t, FILE_TYPE_TECHNIQUE_ADMINISTRATION) + check_yaml_file_health(filename_t, FILE_TYPE_TECHNIQUE_ADMINISTRATION, health_is_called=True) wait() elif choice == '9': interactive_menu() @@ -345,7 +345,7 @@ def menu_visibility(filename_t, filename_ds): wait() elif choice == '5': print('Checking the technique YAML file for errors...') - check_yaml_file_health(filename_t, FILE_TYPE_TECHNIQUE_ADMINISTRATION) + check_yaml_file_health(filename_t, FILE_TYPE_TECHNIQUE_ADMINISTRATION, health_is_called=True) wait() elif choice == '9': interactive_menu() From 621ac3a367b0eb98a05813b26062ca21b7c5d2f8 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Mon, 20 May 2019 14:49:35 +0200 Subject: [PATCH 11/18] updated help texts --- dettact.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dettact.py b/dettact.py index d591c2f8..e4ad9bc3 100644 --- a/dettact.py +++ b/dettact.py @@ -43,8 +43,9 @@ def init_menu(): # create the visibility parser parser_visibility = subparsers.add_parser('visibility', aliases=['v'], help='visibility coverage mapping based on techniques and data sources', - description='Create a heat map based on visibility scores or overlay ' - 'visibility with detections.') + description='Create a heat map based on visibility scores, overlay ' + 'visibility with detections, output to Excel or check the ' + 'health of the technique administration YAML file.') parser_visibility.add_argument('-ft', '--file-tech', help='path to the technique administration YAML file (used to ' 'score the level of visibility)', required=True) parser_visibility.add_argument('-fd', '--file-ds', help='path to the data source administration YAML file (used to ' @@ -64,8 +65,9 @@ def init_menu(): parser_detection = subparsers.add_parser('detection', aliases=['d'], help='detection coverage mapping based on techniques', description='Create a heat map based on detection scores, overlay ' - 'detections with visibility or generate a detection ' - 'improvement graph.') + 'detections with visibility, generate a detection ' + 'improvement graph, output to Excel or check the health of ' + 'the technique administration YAML file.') parser_detection.add_argument('-ft', '--file-tech', help='path to the technique administration YAML file (used to ' 'score the level of visibility)', required=True) parser_detection.add_argument('-fd', '--file-ds', help='path to the data source administration YAML file (used in ' From 2f480b0c4e415968d7e9b652f5999f26f2235a08 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Mon, 20 May 2019 14:54:16 +0200 Subject: [PATCH 12/18] fixed a typo --- dettact.py | 4 ++-- interactive_menu.py | 6 +++--- technique_mapping.py | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dettact.py b/dettact.py index e4ad9bc3..0e278e34 100644 --- a/dettact.py +++ b/dettact.py @@ -57,7 +57,7 @@ def init_menu(): action='store_true') parser_visibility.add_argument('-e', '--excel', help='generate an Excel sheet with all administrated techniques', action='store_true') - parser_visibility.add_argument('-o', '--overlay', help='generate a visibility layer overlayed with detections for ' + parser_visibility.add_argument('-o', '--overlay', help='generate a visibility layer overlaid with detections for ' 'the ATT&CK navigator', action='store_true') parser_visibility.add_argument('--health', help='check the technique YAML file for errors', action='store_true') @@ -80,7 +80,7 @@ def init_menu(): action='store_true') parser_detection.add_argument('-e', '--excel', help='generate an Excel sheet with all administrated techniques', action='store_true') - parser_detection.add_argument('-o', '--overlay', help='generate a detection layer overlayed with visibility for ' + parser_detection.add_argument('-o', '--overlay', help='generate a detection layer overlaid with visibility for ' 'the ATT&CK navigator', action='store_true') parser_detection.add_argument('-g', '--graph', help='generate a graph with detections added through time', action='store_true') diff --git a/interactive_menu.py b/interactive_menu.py index d712d73a..5bcaef63 100644 --- a/interactive_menu.py +++ b/interactive_menu.py @@ -264,7 +264,7 @@ def menu_detection(filename_t): print('') print('Select what you want to do:') print('2. Generate a layer for detection coverage for the ATT&CK Navigator.') - print('3. Generate a layer for detection coverage overlayed with visibility for the ATT&CK Navigator.') + print('3. Generate a layer for detection coverage overlaid with visibility for the ATT&CK Navigator.') print('4. Generate a graph with detections added through time.') print('5. Generate an Excel sheet with all administrated techniques.') print('6. Check the technique YAML file for errors.') @@ -323,7 +323,7 @@ def menu_visibility(filename_t, filename_ds): print('') print('Select what you want to do:') print('2. Generate a layer for visibility for the ATT&CK Navigator.') - print('3. Generate a layer for visibility overlayed with detection coverage for the ATT&CK Navigator.') + print('3. Generate a layer for visibility overlaid with detection coverage for the ATT&CK Navigator.') print('4. Generate an Excel sheet with all administrated techniques.') print('5. Check the technique YAML file for errors.') print('9. Back to main menu.') @@ -336,7 +336,7 @@ def menu_visibility(filename_t, filename_ds): generate_visibility_layer(filename_t, filename_ds, False, filter_applicable_to) wait() elif choice == '3': - print('Writing visibility coverage layer overlayed with detections...') + print('Writing visibility coverage layer overlaid with detections...') generate_visibility_layer(filename_t, filename_ds, True, filter_applicable_to) wait() elif choice == '4': diff --git a/technique_mapping.py b/technique_mapping.py index 174030bb..cc7f2305 100644 --- a/technique_mapping.py +++ b/technique_mapping.py @@ -6,7 +6,7 @@ def generate_detection_layer(filename_techniques, filename_data_sources, overlay, filter_applicable_to): """ - Generates layer for detection coverage and optionally an overlayed version with visibility coverage. + Generates layer for detection coverage and optionally an overlaid version with visibility coverage. :param filename_techniques: the filename of the yaml file containing the techniques administration :param filename_data_sources: the filename of the yaml file containing the data sources administration :param overlay: boolean value to specify if an overlay between detection and visibility should be generated @@ -21,14 +21,14 @@ def generate_detection_layer(filename_techniques, filename_data_sources, overlay else: my_techniques, name, platform = load_techniques(filename_techniques, 'all', filter_applicable_to) my_data_sources = _load_data_sources(filename_data_sources) - mapped_techniques_both = _map_and_colorize_techniques_for_overlayed(my_techniques, my_data_sources, filter_applicable_to) + mapped_techniques_both = _map_and_colorize_techniques_for_overlaid(my_techniques, my_data_sources, filter_applicable_to) layer_both = get_layer_template_layered('Visibility and Detection ' + name + ' ' + filter_applicable_to, 'description', 'attack', platform) _write_layer(layer_both, mapped_techniques_both, 'visibility_and_detection', filter_applicable_to, name) def generate_visibility_layer(filename_techniques, filename_data_sources, overlay, filter_applicable_to): """ - Generates layer for visibility coverage and optionally an overlayed version with detection coverage. + Generates layer for visibility coverage and optionally an overlaid version with detection coverage. :param filename_techniques: the filename of the yaml file containing the techniques administration :param filename_data_sources: the filename of the yaml file containing the data sources administration :param overlay: boolean value to specify if an overlay between detection and visibility should be generated @@ -44,7 +44,7 @@ def generate_visibility_layer(filename_techniques, filename_data_sources, overla _write_layer(layer_visibility, mapped_techniques_visibility, 'visibility', filter_applicable_to, name) else: my_techniques, name, platform = load_techniques(filename_techniques, 'all', filter_applicable_to) - mapped_techniques_both = _map_and_colorize_techniques_for_overlayed(my_techniques, my_data_sources, filter_applicable_to) + mapped_techniques_both = _map_and_colorize_techniques_for_overlaid(my_techniques, my_data_sources, filter_applicable_to) layer_both = get_layer_template_layered('Visibility and Detection ' + name + ' ' + filter_applicable_to, 'description', 'attack', platform) _write_layer(layer_both, mapped_techniques_both, 'visibility_and_detection', filter_applicable_to, name) @@ -233,7 +233,7 @@ def _map_and_colorize_techniques_for_visibility(my_techniques, my_data_sources): return mapped_techniques -def _map_and_colorize_techniques_for_overlayed(my_techniques, my_data_sources, filter_applicable_to): +def _map_and_colorize_techniques_for_overlaid(my_techniques, my_data_sources, filter_applicable_to): """ Determine the color of the techniques based on both detection and visibility. :param my_techniques: the configured techniques From 223b7801d2ea45c5caa412a13365c1c1756a2799 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Wed, 22 May 2019 10:00:27 +0200 Subject: [PATCH 13/18] fixed a typo in T1171 --- sample-data/techniques-administration-endpoints.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sample-data/techniques-administration-endpoints.yaml b/sample-data/techniques-administration-endpoints.yaml index 61044163..4f828d1a 100644 --- a/sample-data/techniques-administration-endpoints.yaml +++ b/sample-data/techniques-administration-endpoints.yaml @@ -442,7 +442,7 @@ techniques: - technique_id: T1171 technique_name: LLMNR/NBT-NS Poisoning detection: - - applicable_to: ['client endpoint'] + - applicable_to: ['client endpoints'] date_registered: 2019-01-10 date_implemented: 2017-01-01 score: 2 @@ -460,7 +460,7 @@ techniques: - 'Model I' comment: '' visibility: - - applicable_to: ['client endpoint'] + - applicable_to: ['client endpoints'] score: 2 comment: '' - applicable_to: ['servers'] From 34aba1e278a2a833764e2d60e83ac6d1cca49c10 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Thu, 23 May 2019 09:36:03 +0200 Subject: [PATCH 14/18] Fixt a small bug causing an exception in the data source menu --- dettact.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dettact.py b/dettact.py index 0e278e34..f1069a68 100644 --- a/dettact.py +++ b/dettact.py @@ -147,7 +147,7 @@ def menu(menu_parser): interactive_menu() elif args.subparser in ['datasource', 'ds']: - if check_file(args.file, FILE_TYPE_DATA_SOURCE_ADMINISTRATION, args.health): + if check_file(args.file, FILE_TYPE_DATA_SOURCE_ADMINISTRATION): if args.layer: generate_data_sources_layer(args.file) if args.excel: From 2dd93279551bd389ca43085d1ee1be39cacee507 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Thu, 23 May 2019 09:37:08 +0200 Subject: [PATCH 15/18] removed an unnecessary print statement --- generic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/generic.py b/generic.py index 189748ca..43284846 100644 --- a/generic.py +++ b/generic.py @@ -461,7 +461,6 @@ def check_yaml_file_health(filename, file_type, health_is_called): for i2 in all_applicable_to: match_value = SequenceMatcher(None, i1, i2).ratio() if match_value > 0.8 and match_value != 1: - print(match_value) similar.add(i1) similar.add(i2) From 70a33fc018a2eb7b5632d81c583f45e41b15290b Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Thu, 23 May 2019 09:43:07 +0200 Subject: [PATCH 16/18] update on text --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e285d177..2b4bc82a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ DeTT&CT #### Detect Tactics, Techniques & Combat Threats -Latest version: [1.1](https://github.com/rabobank-cdc/DeTTACT/wiki/Changelog#version-11) +Latest version: [1.1.1](Changelog#version-111) To get started with DeTT&CT, check out the [Wiki](https://github.com/rabobank-cdc/DeTTACT/wiki/Getting-started). @@ -37,7 +37,7 @@ of which can be visualised by loading JSON layer files into the [ATT&CK Navigato See below an example of mapping your data sources to ATT&CK which gives you a rough overview of your visibility coverage: - DeTT&CT - Data quality + DeTT&CT - Data quality ## Installation and requirements From 7db280b94c01f95f074aa05380d9e9146978eb29 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Thu, 23 May 2019 09:44:20 +0200 Subject: [PATCH 17/18] updated the version from 1.1 to 1.1.1 --- constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.py b/constants.py index f9db3c9e..ab569631 100644 --- a/constants.py +++ b/constants.py @@ -1,6 +1,6 @@ APP_NAME = 'DeTT&CT' APP_DESC = 'Detect Tactics, Techniques & Combat Threats' -VERSION = '1.1' +VERSION = '1.1.1' EXPIRE_TIME = 60*60*24 From 5fef4b6981df7421df3ca36034d115664091172c Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Thu, 23 May 2019 09:51:39 +0200 Subject: [PATCH 18/18] moved the overall to the top --- threat-actor-data/20190319-RedCanary.yaml | 92 +++++++++++------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/threat-actor-data/20190319-RedCanary.yaml b/threat-actor-data/20190319-RedCanary.yaml index b49a7d6e..a3bc5b40 100644 --- a/threat-actor-data/20190319-RedCanary.yaml +++ b/threat-actor-data/20190319-RedCanary.yaml @@ -3,6 +3,52 @@ version: 1.0 file_type: group-administration groups: + - + group_name: Red Canary Threat Detection Report 2019 (1st edition) - overall + campaign: + technique_id: + T1086: 1774 + T1064: 794 + T1117: 710 + T1090: 607 + T1193: 424 + T1036: 419 + T1003: 405 + T1060: 378 + T1085: 372 + T1035: 336 + T1089: 313 + T1059: 294 + T1087: 289 + T1015: 252 + T1053: 232 + T1047: 200 + T1055: 156 + T1027: 121 + T1077: 116 + T1097: 86 + T1105: 71 + T1197: 62 + T1204: 57 + T1140: 52 + T1088: 45 + T1070: 45 + T1074: 39 + T1170: 32 + T1100: 30 + T1127: 29 + T1069: 27 + T1420: 27 + T1146: 27 + T1028: 25 + T1002: 20 + T1218: 18 + T1048: 18 + T1118: 15 + T1068: 13 + T1121: 13 + software_id: [] + enabled: True - group_name: Red Canary Threat Detection Report 2019 (1st edition) - financials campaign: @@ -93,49 +139,3 @@ groups: technique_id: [T1086, T1035, T1085, T1064, T1117, T1059, T1060, T1090, T1089, T1036] software_id: [] enabled: False - - - group_name: Red Canary Threat Detection Report 2019 (1st edition) - overall - campaign: - technique_id: - T1086: 1774 - T1064: 794 - T1117: 710 - T1090: 607 - T1193: 424 - T1036: 419 - T1003: 405 - T1060: 378 - T1085: 372 - T1035: 336 - T1089: 313 - T1059: 294 - T1087: 289 - T1015: 252 - T1053: 232 - T1047: 200 - T1055: 156 - T1027: 121 - T1077: 116 - T1097: 86 - T1105: 71 - T1197: 62 - T1204: 57 - T1140: 52 - T1088: 45 - T1070: 45 - T1074: 39 - T1170: 32 - T1100: 30 - T1127: 29 - T1069: 27 - T1420: 27 - T1146: 27 - T1028: 25 - T1002: 20 - T1218: 18 - T1048: 18 - T1118: 15 - T1068: 13 - T1121: 13 - software_id: [] - enabled: True