From 9041349df0eb0b29216d8f0621de5744a30804b7 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Fri, 30 Oct 2020 18:43:14 +0100 Subject: [PATCH 01/11] Added support for the platforms 'PRE' and 'Network' --- constants.py | 11 +++++++---- editor/src/constants.js | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/constants.py b/constants.py index 33b7544..39b0214 100644 --- a/constants.py +++ b/constants.py @@ -182,8 +182,8 @@ EQL_INVALID_RESULT_TECH = '[!] Invalid technique administration content. Check y HEALTH_ERROR_TXT = '[!] 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 - ' -PLATFORMS = {'windows': 'Windows', 'linux': 'Linux', 'macos': 'macOS', 'aws': 'AWS', 'gcp': 'GCP', 'azure': 'Azure', - 'azure ad': 'Azure AD', 'office 365': 'Office 365', 'saas': 'SaaS'} +PLATFORMS = {'windows': 'Windows', 'linux': 'Linux', 'pre': 'PRE', 'macos': 'macOS', 'aws': 'AWS', 'gcp': 'GCP', 'azure': 'Azure', + 'azure ad': 'Azure AD', 'office 365': 'Office 365', 'saas': 'SaaS', 'network': 'Network'} # Data sources applicable per platform DATA_SOURCES = {'Windows': ['Access tokens', 'Anti-virus', 'API monitoring', 'Application logs', 'Asset management', 'Authentication logs', 'Binary file metadata', 'BIOS', 'Browser extensions', @@ -199,6 +199,7 @@ DATA_SOURCES = {'Windows': ['Access tokens', 'Anti-virus', 'API monitoring', 'Ap 'Network intrusion detection system', 'Network protocol analysis', 'Packet capture', 'PowerShell logs', 'Process command-line parameters', 'Process monitoring', 'Process use of network', 'Sensor health and status', 'Services', 'SSL/TLS inspection', 'System calls', 'Third-party application logs', 'User interface', 'VBR', 'Web application firewall logs', 'Web logs', 'Web proxy'], + 'PRE': ['Domain registration', 'Email gateway', 'Mail server', 'Network device logs', 'Packet capture', 'Social media monitoring', 'SSL/TLS certificates', 'Web logs'], 'macOS': ['Anti-virus', 'API monitoring', 'Application logs', 'Asset management', 'Authentication logs', 'Binary file metadata', 'BIOS', 'Browser extensions', 'Component firmware', 'Data loss prevention', 'Detonation chamber', 'Digital certificate logs', 'Disk forensics', 'DNS records', 'EFI', 'Email gateway', 'Environment variable', 'File monitoring', 'Host network interface', 'Kernel drivers', 'Mail server', 'Malware reverse engineering', 'MBR', 'Named Pipes', 'Netflow/Enclave netflow', 'Network device logs', @@ -210,7 +211,7 @@ DATA_SOURCES = {'Windows': ['Access tokens', 'Anti-virus', 'API monitoring', 'Ap 'Network intrusion detection system', 'Network protocol analysis', 'Packet capture', 'Sensor health and status', 'SSL/TLS inspection', 'Third-party application logs', 'Web application firewall logs', 'Web logs', 'Web proxy'], 'GCP': ['Anti-virus', 'API monitoring', 'Application logs', 'Asset management', 'Authentication logs', 'Binary file metadata', 'Data loss prevention', 'Detonation chamber', - 'DNS records', 'Email gateway', 'File monitoring', 'Mail server', 'Malware reverse engineering', 'Netflow/Enclave netflow', 'Network device logs', + 'DNS records', 'Email gateway', 'File monitoring', 'GCP audit logs', 'Mail server', 'Malware reverse engineering', 'Netflow/Enclave netflow', 'Network device logs', 'Network intrusion detection system', 'Network protocol analysis', 'Packet capture', 'Sensor health and status', 'SSL/TLS inspection', 'Stackdriver logs', 'Third-party application logs', 'Web application firewall logs', 'Web logs', 'Web proxy'], 'Azure': ['Anti-virus', 'API monitoring', 'Application logs', 'Asset management', 'Authentication logs', 'Azure activity logs', 'Azure OS logs', 'Binary file metadata', @@ -221,5 +222,7 @@ DATA_SOURCES = {'Windows': ['Access tokens', 'Anti-virus', 'API monitoring', 'Ap 'Office 365': ['Anti-virus', 'API monitoring', 'Authentication logs', 'Azure activity logs', 'Data loss prevention', 'Detonation chamber', 'Email gateway', 'Mail server', 'Malware reverse engineering', 'Office 365 account logs', 'Office 365 audit logs', 'Office 365 trace logs', 'Sensor health and status'], 'SaaS': ['Anti-virus', 'API monitoring', 'Application logs', 'Authentication logs', 'Data loss prevention', 'Detonation chamber', 'Email gateway', 'Mail server', - 'Malware reverse engineering', 'OAuth audit logs', 'Sensor health and status', 'Third-party application logs', 'Web application firewall logs', 'Web logs'] + 'Malware reverse engineering', 'OAuth audit logs', 'Sensor health and status', 'Third-party application logs', 'Web application firewall logs', 'Web logs'], + 'Network': ['File monitoring', 'Netflow/Enclave netflow', 'Network device command history', 'Network device configuration', 'Network device logs', 'Network device run-time memory', + 'Network protocol analysis', 'Packet capture'] } diff --git a/editor/src/constants.js b/editor/src/constants.js index 67bd2a8..8c8f88d 100644 --- a/editor/src/constants.js +++ b/editor/src/constants.js @@ -85,16 +85,18 @@ export default { comment: '', auto_generated: false }, - PLATFORMS: ['all', 'Windows', 'Linux', 'macOS', 'AWS', 'GCP', 'Azure', 'Azure AD', 'Office 365', 'SaaS'], + PLATFORMS: ['all', 'Windows', 'Linux', 'PRE', 'macOS', 'AWS', 'GCP', 'Azure', 'Azure AD', 'Office 365', 'SaaS', 'Network'], PLATFORM_CONVERSION: { windows: 'Windows', linux: 'Linux', + pre: 'PRE', macos: 'macOS', aws: 'AWS', gcp: 'GCP', azure: 'Azure', 'azure ad': 'Azure AD', 'office 365': 'Office 365', - saas: 'SaaS' + saas: 'SaaS', + network: 'Network' } }; From 61510f8a879508d81ab416512ee5c3dca7362e13 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Fri, 30 Oct 2020 21:16:51 +0100 Subject: [PATCH 02/11] Bumped the version number --- Dockerfile | 2 +- README.md | 2 +- constants.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2e25780..57e55e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.8-slim-buster -LABEL version="1.4.1" +LABEL version="1.4.2" # copy DeTT&CT and install the requirements COPY . /opt/DeTTECT diff --git a/README.md b/README.md index 7e90202..e0608b2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ DeTT&CT #### Detect Tactics, Techniques & Combat Threats -Latest version: [1.4.1](https://github.com/rabobank-cdc/DeTTECT/wiki/Changelog#version-141) +Latest version: [1.4.2](https://github.com/rabobank-cdc/DeTTECT/wiki/Changelog#version-142) To get started with DeTT&CT, check out this [page](https://github.com/rabobank-cdc/DeTTECT/wiki/Getting-started), our [talk](https://www.youtube.com/watch?v=_kWpekkhomU) at hack.lu 2019 and our blog on: - [mbsecure.nl/blog/2019/5/dettact-mapping-your-blue-team-to-mitre-attack](https://www.mbsecure.nl/blog/2019/5/dettact-mapping-your-blue-team-to-mitre-attack) or diff --git a/constants.py b/constants.py index 39b0214..0a7eb8c 100644 --- a/constants.py +++ b/constants.py @@ -2,7 +2,7 @@ import re APP_NAME = 'DeTT&CT' APP_DESC = 'Detect Tactics, Techniques & Combat Threats' -VERSION = '1.4.1' +VERSION = '1.4.2' EXPIRE_TIME = 60 * 60 * 24 From 70b1a0111c61587ef8c352114c219c848fe08260 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Fri, 30 Oct 2020 21:19:11 +0100 Subject: [PATCH 03/11] Textual change for the interactive menu --- dettect.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dettect.py b/dettect.py index 4f51f07..96a56bb 100644 --- a/dettect.py +++ b/dettect.py @@ -14,7 +14,8 @@ def _init_menu(): menu_parser = argparse.ArgumentParser(description='Detect Tactics, Techniques & Combat Threats', epilog='Source: https://github.com/rabobank-cdc/DeTTECT') menu_parser.add_argument('--version', action='version', version='%(prog)s ' + VERSION) - menu_parser.add_argument('-i', '--interactive', help='launch the interactive menu, which has support for all modes', + menu_parser.add_argument('-i', '--interactive', help='launch the interactive menu, which has support for all modes but not ' + 'all of the arguments that are available in the CLI', action='store_true') # add subparsers From 52a3f77ced68a582f3555ebfaeb95fa453fea905 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Fri, 30 Oct 2020 21:19:31 +0100 Subject: [PATCH 04/11] Added support for Navigator v4.0 --- generic.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/generic.py b/generic.py index c8a2b37..6afe8ba 100644 --- a/generic.py +++ b/generic.py @@ -219,15 +219,11 @@ def _get_base_template(name, description, stage, platform, sorting): """ layer = dict() layer['name'] = name - layer['version'] = '3.0' - layer['domain'] = 'mitre-enterprise' + layer['versions'] = {'navigator': '4.0', 'layer': '4.0'} + layer['domain'] = 'enterprise-attack' layer['description'] = description - if stage == 'attack': - layer['filters'] = {'stages': ['act'], 'platforms': platform} - else: - layer['filters'] = {'stages': ['prepare'], 'platforms': platform} - + layer['filters'] = {'platforms': platform} layer['sorting'] = sorting layer['layout'] = {"layout": "flat", "showName": True, "showID": False} layer['hideDisable'] = False From 386e9c717827872c6679f40bc106c2f9172c6833 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Fri, 30 Oct 2020 21:23:15 +0100 Subject: [PATCH 05/11] Fixed a bug which did not allow the value 'all' for the argument '-p/--platform' --- dettect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dettect.py b/dettect.py index 96a56bb..de084dd 100644 --- a/dettect.py +++ b/dettect.py @@ -335,7 +335,7 @@ def _platform_lookup(): Lookup the platform value with the correct capitalisation. return: lambda function to be used by argparse type= """ - return lambda p: PLATFORMS.get(p.lower(), '') + return lambda p: PLATFORMS.get(p.lower(), '') if p.lower() != 'all' else 'all' def _prepare_folders(): From 54d0259565c3a5254488c57d5f53368469eaa7d4 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Sat, 31 Oct 2020 07:31:17 +0100 Subject: [PATCH 06/11] Added support for the platforms 'PRE' and 'Network' --- editor/script/refresh_attack_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/script/refresh_attack_data.py b/editor/script/refresh_attack_data.py index 6f3d2f7..ec00bfb 100644 --- a/editor/script/refresh_attack_data.py +++ b/editor/script/refresh_attack_data.py @@ -4,7 +4,7 @@ from attackcti import attack_client FILE_DATA_SOURCES = 'data_sources.json' FILE_TECHNIQUES = 'techniques.json' FILE_SOFTWARE = 'software.json' -PLATFORMS = ['Windows', 'Linux', 'macOS', 'AWS', 'GCP', 'Azure', 'Azure AD', 'Office 365', 'SaaS'] +PLATFORMS = ['Windows', 'Linux', 'macOS', 'PRE', 'AWS', 'GCP', 'Azure', 'Azure AD', 'Office 365', 'SaaS', 'Network'] class ATTACKData(): From cd5b71ea9f5b60aa395960d2e41fc13459b5a923 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Sat, 31 Oct 2020 11:13:30 +0100 Subject: [PATCH 07/11] Fixed a bug regarding the 'platform' kv-pair value 'all' --- generic.py | 2 +- health.py | 27 +++++++++++++-------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/generic.py b/generic.py index 6afe8ba..525ad01 100644 --- a/generic.py +++ b/generic.py @@ -1107,7 +1107,7 @@ def get_platform_from_yaml(yaml_content): platform = [platform] platform = [p.lower() for p in platform if p is not None] - if platform == ['all']: + if 'all' in platform: platform = list(PLATFORMS.values()) else: valid_platform_list = [] diff --git a/health.py b/health.py index 22a01d3..bfb171c 100644 --- a/health.py +++ b/health.py @@ -94,23 +94,22 @@ def check_health_data_sources(filename, ds_content, health_is_called, no_print=F ATT&CK Platform is not part of the EQL search result :return: False if no errors have been found, otherwise True """ - from generic import get_applicable_data_sources_platform + from generic import get_applicable_data_sources_platform, get_platform_from_yaml has_error = False - platform = ds_content.get('platform', None) + platform = get_platform_from_yaml(ds_content) if not src_eql: - if platform != 'all' and platform != ['all']: - if isinstance(platform, str): - platform = [platform] - if platform is None or len(platform) == 0 or platform == '': - platform = ['empty'] - for p in platform: - if p.lower() not in PLATFORMS.keys(): - has_error = _print_error_msg( - '[!] EMPTY or INVALID value for \'platform\' within the data source admin. ' - 'file: %s (should be value(s) of: [%s] or all)' % (p, ', '.join(list(PLATFORMS.values()))), - health_is_called) + if isinstance(platform, str): + platform = [platform] + if platform is None or len(platform) == 0 or platform == '': + platform = ['empty'] + for p in platform: + if p.lower() not in PLATFORMS.keys(): + has_error = _print_error_msg( + '[!] EMPTY or INVALID value for \'platform\' within the data source admin. ' + 'file: %s (should be value(s) of: [%s] or all)' % (p, ', '.join(list(PLATFORMS.values()))), + health_is_called) ds_list = [kv['data_source_name'].lower() for kv in ds_content['data_sources']] @@ -275,7 +274,7 @@ def _check_health_techniques(filename, technique_content, health_is_called): for p in platform: if p.lower() not in PLATFORMS.keys(): has_error = _print_error_msg( - '[!] EMPTY or INVALID value for \'platform\' within the data source admin. ' + '[!] EMPTY or INVALID value for \'platform\' within the technique admin. ' 'file: %s (should be value(s) of: [%s] or all)' % (p, ', '.join(list(PLATFORMS.values()))), health_is_called) From b3705c782edb06028aecbf14eed9c2e6cbab6bff Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Sat, 31 Oct 2020 11:14:02 +0100 Subject: [PATCH 08/11] Added new data sources --- sample-data/data-sources-empty.yaml | 86 ++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/sample-data/data-sources-empty.yaml b/sample-data/data-sources-empty.yaml index 0d2f02b..c6c3b4e 100644 --- a/sample-data/data-sources-empty.yaml +++ b/sample-data/data-sources-empty.yaml @@ -4,7 +4,7 @@ version: 1.0 file_type: data-source-administration name: empty-data-source-admin-file # Fill in the correct MITRE ATT&CK enterprise platform(s). Multiple can be included using a list -# - (Windows, Linux, macOS, AWS, GCP, Azure, Azure AD, Office 365, SaaS) +# - (Windows, Linux, macOS, PRE, AWS, GCP, Azure, Azure AD, Office 365, SaaS, Network) # Also, take into account which data sources are applicable per platform. For more info see: # - https://github.com/rabobank-cdc/DeTTECT/wiki/Data-sources-per-platform platform: @@ -35,6 +35,18 @@ data_sources: timeliness: 0 consistency: 0 retention: 0 + - data_source_name: GCP audit logs + date_registered: + date_connected: + products: [] + available_for_data_analytics: False + comment: '' + data_quality: + device_completeness: 0 + data_field_completeness: 0 + timeliness: 0 + consistency: 0 + retention: 0 - data_source_name: Process command-line parameters date_registered: date_connected: @@ -119,6 +131,42 @@ data_sources: timeliness: 0 consistency: 0 retention: 0 + - data_source_name: Network device command history + date_registered: + date_connected: + products: [] + available_for_data_analytics: False + comment: '' + data_quality: + device_completeness: 0 + data_field_completeness: 0 + timeliness: 0 + consistency: 0 + retention: 0 + - data_source_name: Network device configuration + date_registered: + date_connected: + products: [] + available_for_data_analytics: False + comment: '' + data_quality: + device_completeness: 0 + data_field_completeness: 0 + timeliness: 0 + consistency: 0 + retention: 0 + - data_source_name: Network device run-time memory + date_registered: + date_connected: + products: [] + available_for_data_analytics: False + comment: '' + data_quality: + device_completeness: 0 + data_field_completeness: 0 + timeliness: 0 + consistency: 0 + retention: 0 - data_source_name: Windows event logs date_registered: date_connected: @@ -203,6 +251,18 @@ data_sources: timeliness: 0 consistency: 0 retention: 0 + - data_source_name: SSL/TLS certificates + date_registered: + date_connected: + products: [] + available_for_data_analytics: False + comment: '' + data_quality: + device_completeness: 0 + data_field_completeness: 0 + timeliness: 0 + consistency: 0 + retention: 0 - data_source_name: SSL/TLS inspection date_registered: date_connected: @@ -371,6 +431,18 @@ data_sources: timeliness: 0 consistency: 0 retention: 0 + - data_source_name: Social media monitoring + date_registered: + date_connected: + products: [] + available_for_data_analytics: False + comment: '' + data_quality: + device_completeness: 0 + data_field_completeness: 0 + timeliness: 0 + consistency: 0 + retention: 0 - data_source_name: Web logs date_registered: date_connected: @@ -491,6 +563,18 @@ data_sources: timeliness: 0 consistency: 0 retention: 0 + - data_source_name: Domain registration + date_registered: + date_connected: + products: [] + available_for_data_analytics: False + comment: '' + data_quality: + device_completeness: 0 + data_field_completeness: 0 + timeliness: 0 + consistency: 0 + retention: 0 - data_source_name: Browser extensions date_registered: date_connected: From 94e8b5e4b50dc3f6e23c08a18a97b9236b40426d Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Sat, 31 Oct 2020 21:01:09 +0100 Subject: [PATCH 09/11] Removed support for PRE-ATT&CK from the Group mode --- data_source_mapping.py | 2 +- dettect.py | 26 ++++++++++++-------------- generic.py | 28 +++++++++++----------------- group_mapping.py | 35 +++++++++++++++-------------------- interactive_menu.py | 24 +++++++++--------------- technique_mapping.py | 8 ++++---- 6 files changed, 52 insertions(+), 71 deletions(-) diff --git a/data_source_mapping.py b/data_source_mapping.py index 7ad7608..b0b793a 100644 --- a/data_source_mapping.py +++ b/data_source_mapping.py @@ -26,7 +26,7 @@ def generate_data_sources_layer(filename, output_filename, layer_name, platform= if not layer_name: layer_name = 'Data sources ' + name - layer = get_layer_template_data_sources(layer_name, 'description', 'attack', platform) + layer = get_layer_template_data_sources(layer_name, 'description', platform) layer['techniques'] = my_techniques json_string = simplejson.dumps(layer).replace('}, ', '},\n') diff --git a/dettect.py b/dettect.py index de084dd..dab7743 100644 --- a/dettect.py +++ b/dettect.py @@ -25,7 +25,7 @@ def _init_menu(): 'group, generic} --help', metavar='', dest='subparser') parser_editor = subparsers.add_parser('editor', aliases=['e'], help='DeTT&CT Editor', - description='Start the DeTT&CT Editor for easy editing the YAML administration files.') + description='Start the DeTT&CT Editor for easy editing the YAML administration files') parser_editor.add_argument('-p', '--port', help='port where the webserver listens on (default is 8080)', required=False, default=8080) # create the data source parser @@ -69,9 +69,9 @@ def _init_menu(): parser_data_sources.add_argument('-ln', '--layer-name', help='set the name of the Navigator layer') parser_data_sources.add_argument('--health', help='check the YAML file(s) for errors', action='store_true') parser_data_sources.add_argument('--local-stix-path', help='path to a local STIX repository to use DeTT&CT offline ' - 'or to use a specific version of STIX objects.') + 'or to use a specific version of STIX objects') parser_data_sources.add_argument('--update-to-sub-techniques', help='Update the technique administration YAML file ' - 'to ATT&CK with sub-techniques.', action='store_true') + 'to ATT&CK with sub-techniques', action='store_true') # create the visibility parser parser_visibility = subparsers.add_parser('visibility', aliases=['v'], @@ -107,9 +107,9 @@ def _init_menu(): parser_visibility.add_argument('-ln', '--layer-name', help='set the name of the Navigator layer') parser_visibility.add_argument('--health', help='check the YAML file for errors', action='store_true') parser_visibility.add_argument('--local-stix-path', help='path to a local STIX repository to use DeTT&CT offline ' - 'or to use a specific version of STIX objects.') + 'or to use a specific version of STIX objects') parser_visibility.add_argument('--update-to-sub-techniques', help='Update the technique administration YAML file ' - 'to ATT&CK with sub-techniques.', action='store_true') + 'to ATT&CK with sub-techniques', action='store_true') # create the detection parser parser_detection = subparsers.add_parser('detection', aliases=['d'], @@ -147,9 +147,9 @@ def _init_menu(): parser_detection.add_argument('-ln', '--layer-name', help='set the name of the Navigator layer') parser_detection.add_argument('--health', help='check the YAML file(s) for errors', action='store_true') parser_detection.add_argument('--local-stix-path', help='path to a local STIX repository to use DeTT&CT offline ' - 'or to use a specific version of STIX objects.') + 'or to use a specific version of STIX objects') parser_detection.add_argument('--update-to-sub-techniques', help='Update the technique administration YAML file ' - 'to ATT&CK with sub-techniques.', action='store_true') + 'to ATT&CK with sub-techniques', action='store_true') # create the group parser parser_group = subparsers.add_parser('group', aliases=['g'], @@ -159,7 +159,7 @@ def _init_menu(): parser_group.add_argument('-g', '--groups', help='specify the ATT&CK Groups to include. Group can be its ID, ' 'name or alias (default is all groups). Multiple Groups can be ' 'provided with extra \'-g/--group\' arguments. Another option is ' - 'to provide a YAML file with a custom group(s).', + 'to provide a YAML file with a custom group(s)', default=None, action='append') parser_group.add_argument('-o', '--overlay', help='specify what to overlay on the group(s) (provided using the ' 'arguments \-g/--groups\): group(s), visibility or detection. ' @@ -180,8 +180,6 @@ def _init_menu(): 'can be provided with extra \'-p/--platform\' arguments', choices=['all'] + list(PLATFORMS.values()), default=None, action='append', type=_platform_lookup()) - parser_group.add_argument('-s', '--stage', help='specify the stage (default = attack)', - choices=['attack', 'pre-attack'], default='attack') parser_group.add_argument('-sd', '--search-detection', help='only include detection objects which match the ' 'provided EQL query') parser_group.add_argument('-sv', '--search-visibility', help='only include visibility objects which match the ' @@ -194,9 +192,9 @@ def _init_menu(): parser_group.add_argument('-ln', '--layer-name', help='set the name of the Navigator layer') parser_group.add_argument('--health', help='check the YAML file(s) for errors', action='store_true') parser_group.add_argument('--local-stix-path', help='path to a local STIX repository to use DeTT&CT offline ' - 'or to use a specific version of STIX objects.') + 'or to use a specific version of STIX objects') parser_group.add_argument('--update-to-sub-techniques', help='Update the technique administration YAML file ' - 'to ATT&CK with sub-techniques.', action='store_true') + 'to ATT&CK with sub-techniques', action='store_true') # create the generic parser parser_generic = subparsers.add_parser('generic', description='Generic functions which will output to stdout.', @@ -216,7 +214,7 @@ def _init_menu(): 'date (default = modified)', choices=['modified', 'created'], default='modified') parser_generic.add_argument('--local-stix-path', help='path to a local STIX repository to use DeTT&CT offline ' - 'or to use a specific version of STIX objects.') + 'or to use a specific version of STIX objects') return menu_parser @@ -289,7 +287,7 @@ def _menu(menu_parser): # TODO add search capabilities elif args.subparser in ['group', 'g']: - generate_group_heat_map(args.groups, args.overlay, args.overlay_type, args.stage, args.platform, + generate_group_heat_map(args.groups, args.overlay, args.overlay_type, args.platform, args.software_group, args.search_visibility, args.search_detection, args.health, args.output_filename, args.layer_name, include_all_score_objs=args.all_scores) diff --git a/generic.py b/generic.py index 525ad01..9f34e27 100644 --- a/generic.py +++ b/generic.py @@ -206,13 +206,12 @@ def init_yaml(): return _yaml -def _get_base_template(name, description, stage, platform, sorting): +def _get_base_template(name, description, platform, sorting): """ Prepares a base template for the json layer file that can be loaded into the MITRE ATT&CK Navigator. More information on the layer format can be found here: https://github.com/mitre/attack-navigator/blob/master/layers/ :param name: name :param description: description - :param stage: stage (act | prepare) :param platform: platform :param sorting: sorting :return: layer template dictionary @@ -236,19 +235,18 @@ def _get_base_template(name, description, stage, platform, sorting): return layer -def get_layer_template_groups(name, max_count, description, stage, platform, overlay_type): +def get_layer_template_groups(name, max_count, description, 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 layer format can be found here: https://github.com/mitre/attack-navigator/blob/master/layers/ :param name: name :param max_count: the sum of all count values :param description: description - :param stage: stage (act | prepare) :param platform: platform :param overlay_type: group, visibility or detection :return: layer template dictionary """ - layer = _get_base_template(name, description, stage, platform, 3) + layer = _get_base_template(name, description, platform, 3) layer['gradient'] = {'colors': [COLOR_GRADIENT_MIN, COLOR_GRADIENT_MAX], 'minValue': 0, 'maxValue': max_count} layer['legendItems'] = [] layer['legendItems'].append({'label': 'Tech. not often used', 'color': COLOR_GRADIENT_MIN}) @@ -285,17 +283,16 @@ def get_layer_template_groups(name, max_count, description, stage, platform, ove return layer -def get_layer_template_detections(name, description, stage, platform): +def get_layer_template_detections(name, description, platform): """ Prepares a base template for the json layer file that can be loaded into the MITRE ATT&CK Navigator. More information on the layer format can be found here: https://github.com/mitre/attack-navigator/blob/master/layers/ :param name: name :param description: description - :param stage: stage (act | prepare) :param platform: platform :return: layer template dictionary """ - layer = _get_base_template(name, description, stage, platform, 0) + layer = _get_base_template(name, description, platform, 0) layer['legendItems'] = \ [ {'label': 'Detection score 0: Forensics/Context', 'color': COLOR_D_0}, @@ -308,17 +305,16 @@ def get_layer_template_detections(name, description, stage, platform): return layer -def get_layer_template_data_sources(name, description, stage, platform): +def get_layer_template_data_sources(name, description, platform): """ Prepares a base template for the json layer file that can be loaded into the MITRE ATT&CK Navigator. More information on the layer format can be found here: https://github.com/mitre/attack-navigator/blob/master/layers/ :param name: name :param description: description - :param stage: stage (act | prepare) :param platform: platform :return: layer template dictionary """ - layer = _get_base_template(name, description, stage, platform, 0) + layer = _get_base_template(name, description, platform, 0) layer['legendItems'] = \ [ {'label': '1-25% of data sources available', 'color': COLOR_DS_25p}, @@ -330,17 +326,16 @@ def get_layer_template_data_sources(name, description, stage, platform): return layer -def get_layer_template_visibility(name, description, stage, platform): +def get_layer_template_visibility(name, description, platform): """ Prepares a base template for the json layer file that can be loaded into the MITRE ATT&CK Navigator. More information on the layer format can be found here: https://github.com/mitre/attack-navigator/blob/master/layers/ :param name: name :param description: description - :param stage: stage (act | prepare) :param platform: platform :return: layer template dictionary """ - layer = _get_base_template(name, description, stage, platform, 0) + layer = _get_base_template(name, description, platform, 0) layer['legendItems'] = \ [ {'label': 'Visibility score 1: Minimal', 'color': COLOR_V_1}, @@ -351,17 +346,16 @@ def get_layer_template_visibility(name, description, stage, platform): return layer -def get_layer_template_layered(name, description, stage, platform): +def get_layer_template_layered(name, description, platform): """ Prepares a base template for the json layer file that can be loaded into the MITRE ATT&CK Navigator. More information on the layer format can be found here: https://github.com/mitre/attack-navigator/blob/master/layers/ :param name: name :param description: description - :param stage: stage (act | prepare) :param platform: platform :return: layer template dictionary """ - layer = _get_base_template(name, description, stage, platform, 0) + layer = _get_base_template(name, description, platform, 0) layer['legendItems'] = \ [ {'label': 'Visibility and detection', 'color': COLOR_OVERLAY_BOTH}, diff --git a/group_mapping.py b/group_mapping.py index 8c1ded2..b772638 100644 --- a/group_mapping.py +++ b/group_mapping.py @@ -44,19 +44,18 @@ def _are_groups_found(groups_found, argument_groups): if not group_id: # the group that has been provided through the command line cannot be found in ATT&CK print('[!] Unknown ATT&CK group: ' + group_arg) group_found = False - elif group_id not in groups_found: # group not present in filtered data sate (i.e. platform and stage) + elif group_id not in groups_found: # group not present in filtered (platform) data set print('[!] Group not part of the data set: ' + group_arg) group_found = False return group_found -def _get_software_techniques(groups, stage, platform): +def _get_software_techniques(groups, platform): """ Get all techniques (in a dict) from the provided list of groups in relation to the software these groups use, and hence techniques they support. :param groups: ATT&CK groups - :param stage: attack or pre-attack :param platform: one or multiple values from PLATFORMS constant :return: dictionary with info on groups """ @@ -108,7 +107,7 @@ def _get_software_techniques(groups, stage, platform): # software matches the ATT&CK Matrix and platform # and the group is a group we are interested in if s['x_mitre_platforms']: # there is software that do not have a platform, skip those - if s['matrix'] == 'mitre-' + stage and len(set(s['x_mitre_platforms']).intersection(set(platform))) > 0 and \ + if s['matrix'] == 'mitre-attack' and len(set(s['x_mitre_platforms']).intersection(set(platform))) > 0 and \ (groups[0] == 'all' or s['group_id'].lower() in groups or _is_in_group(s['aliases'], groups)): if s['group_id'] not in groups_dict: groups_dict[s['group_id']] = {'group_name': s['name']} @@ -149,11 +148,10 @@ def _generate_group_id(group_name, campaign): return CG_GROUPS[group_name + campaign] -def _get_group_techniques(groups, stage, platform, file_type): +def _get_group_techniques(groups, platform, file_type): """ Get all techniques (in a dict) from the provided list of groups :param groups: group ID, group name/alias or a YAML file with group(s) data - :param stage: attack or pre-attack :param platform: one or multiple values from PLATFORMS constant :param file_type: the file type of the YAML file as present in the key 'file_type' :return: returns dictionary with all techniques from the provided list of groups or -1 when group is not found @@ -196,7 +194,7 @@ def _get_group_techniques(groups, stage, platform, file_type): platforms = ['Windows'] # group matches the: matrix/stage, platform and the group(s) we are interested in - if gr['matrix'] == 'mitre-' + stage and len(set(platforms).intersection(set(platform))) > 0 and \ + if gr['matrix'] == 'mitre-attack' and len(set(platforms).intersection(set(platform))) > 0 and \ (groups[0] == 'all' or gr['group_id'].lower() in groups or _is_in_group(gr['aliases'], groups)): if gr['group_id'] not in groups_dict: groups_found.add(gr['group_id']) @@ -477,7 +475,7 @@ def _get_group_list(groups, file_type): return groups -def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, software_groups, search_visibility, +def generate_group_heat_map(groups, overlay, overlay_type, platform, software_groups, search_visibility, search_detection, health_is_called, output_filename, layer_name, include_all_score_objs=False): """ Calls all functions that are necessary for the generation of the heat map and write a json layer to disk. @@ -485,7 +483,6 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft :param overlay: group(s), visibility or detections to overlay (group ID, group name/alias, YAML file with group(s), detections or visibility) :param overlay_type: group, visibility or detection - :param stage: attack or pre-attack :param platform: one or multiple the values from PLATFORMS constant or None (default = Windows) :param software_groups: specify if techniques from related software should be included :param search_visibility: visibility EQL search query @@ -567,11 +564,11 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft # we are not overlaying visibility or detection, overlay group will therefore contain information on another group elif len(overlay) > 0: - overlay_dict = _get_group_techniques(overlay, stage, platform, overlay_file_type) + overlay_dict = _get_group_techniques(overlay, platform, overlay_file_type) if overlay_dict == -1: return None # returns None when the provided Group(s) to be overlaid, contains Groups not part of ATT&CK - groups_dict = _get_group_techniques(groups, stage, platform, groups_file_type) + groups_dict = _get_group_techniques(groups, platform, groups_file_type) if groups_dict == -1: return None # returns None when the provided Group contains Groups not part of ATT&CK if len(groups_dict) == 0: @@ -582,9 +579,9 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft if software_groups and overlay: if overlay_type not in [OVERLAY_TYPE_VISIBILITY, OVERLAY_TYPE_DETECTION]: # if a group overlay is provided, get the software techniques for the overlay - groups_software_dict = _get_software_techniques(overlay, stage, platform) + groups_software_dict = _get_software_techniques(overlay, platform) elif software_groups: - groups_software_dict = _get_software_techniques(groups, stage, platform) + groups_software_dict = _get_software_techniques(groups, platform) 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, @@ -597,26 +594,24 @@ def generate_group_heat_map(groups, overlay, overlay_type, stage, platform, soft groups_list = _get_group_list(groups_dict, groups_file_type) overlay_list = _get_group_list(overlay_dict, overlay_file_type) - desc = 'stage: ' + stage + ' | platform(s): ' + platform_to_name(platform, separator=', ') + ' | group(s): ' \ + desc = 'stage: attack | platform(s): ' + platform_to_name(platform, separator=', ') + ' | group(s): ' \ + ', '.join(groups_list) + ' | overlay group(s): ' + ', '.join(overlay_list) if not layer_name: - layer_name = stage[0].upper() + stage[1:] + ' - ' + platform_to_name(platform, separator=', ') + layer_name = 'Attack - ' + platform_to_name(platform, separator=', ') - layer = get_layer_template_groups(layer_name, max_count, desc, stage, platform, overlay_type) + layer = get_layer_template_groups(layer_name, max_count, desc, platform, overlay_type) layer['techniques'] = technique_layer json_string = simplejson.dumps(layer).replace('}, ', '},\n') if not output_filename: - if stage == 'pre-attack': - filename = '_'.join(groups_list) - elif overlay: + if overlay: filename = platform_to_name(platform) + '_' + '_'.join(groups_list) + '-overlay_' + '_'.join(overlay_list) else: filename = platform_to_name(platform) + '_' + '_'.join(groups_list) - filename = create_output_filename(stage, filename) + filename = create_output_filename('attack', filename) write_file(filename, json_string) else: write_file(output_filename, json_string) diff --git a/interactive_menu.py b/interactive_menu.py index b30ac12..0515d1f 100644 --- a/interactive_menu.py +++ b/interactive_menu.py @@ -7,7 +7,6 @@ from eql_yaml import * groups = 'all' software_group = False default_platform = ['Windows'] -default_stage = 'attack' default_matrix = 'enterprise' groups_overlay = '' overlay_type = 'group' @@ -460,7 +459,7 @@ def _menu_groups(): Prints and handles the Threat actor group mapping functionality. :return: """ - global groups, software_group, default_platform, default_stage, groups_overlay, overlay_type, eql_all_scores, \ + global groups, software_group, default_platform, groups_overlay, overlay_type, eql_all_scores, \ eql_query_detection, eql_query_visibility _clear() print('Menu: %s' % MENU_NAME_THREAT_ACTOR_GROUP_MAPPING) @@ -468,12 +467,11 @@ def _menu_groups(): print('Options:') print('1. Software group: %s' % str(software_group)) print('2. Platform: %s' % ','.join(default_platform)) - print('3. Stage: %s' % default_stage) - print('4. Groups: %s' % groups) - print('5. Overlay: ') + print('3. Groups: %s' % groups) + print('4. Overlay: ') print(' - %s: %s' % ('File' if os.path.exists(groups_overlay) else 'Groups', groups_overlay)) print(' - Type: %s' % overlay_type) - print('6. EQL search: ') + print('5. EQL search: ') eql_d_str = '' if not eql_query_detection else eql_query_detection eql_v_str = '' if not eql_query_visibility else eql_query_visibility print(' - Only include detection objects which match the EQL query: ' + eql_d_str) @@ -481,7 +479,7 @@ def _menu_groups(): print(' - Include all \'score\' objects from the \'score_logbook\' in the EQL search: ' + str(eql_all_scores)) print('') print('Select what you want to do:') - print('7. Generate a heat map layer.') + print('6. Generate a heat map layer.') print('9. Back to main menu.') choice = _ask_input() if choice == '1': @@ -491,15 +489,11 @@ def _menu_groups(): p = _ask_input().lower() default_platform = [PLATFORMS[p]] if p in PLATFORMS.keys() else ['all'] elif choice == '3': - print('Specify stage (pre-attack, attack):') - s = _ask_input().lower() - default_stage = 'pre-attack' if s == 'pre-attack' else 'attack' - elif choice == '4': print('Specify the groups to include separated using commas. Group can be their ID, name or alias ' '(default is all groups). Other option is to provide a YAML file with a custom group(s)') g = _ask_input() groups = g if g != '' else 'all' - elif choice == '5': + elif choice == '4': print('') print('1. Overlay with groups.') print('2. Overlay with detections.') @@ -521,7 +515,7 @@ def _menu_groups(): elif choice == '4': overlay_type = '' groups_overlay = '' - elif choice == '6': + elif choice == '5': print('') print('1. Only include detection objects which match the EQL query: ' + eql_d_str) print('2. Only include visibility objects which match the EQL query: ' + eql_v_str) @@ -537,8 +531,8 @@ def _menu_groups(): elif choice == '3': eql_all_scores = not eql_all_scores - elif choice == '7': - generate_group_heat_map(groups, groups_overlay, overlay_type, default_stage, default_platform, + elif choice == '6': + generate_group_heat_map(groups, groups_overlay, overlay_type, default_platform, software_group, eql_query_visibility, eql_query_detection, False, None, None, include_all_score_objs=eql_all_scores) _wait() diff --git a/technique_mapping.py b/technique_mapping.py index 0ad220c..87140f7 100644 --- a/technique_mapping.py +++ b/technique_mapping.py @@ -23,14 +23,14 @@ def generate_detection_layer(filename_techniques, filename_data_sources, overlay mapped_techniques_detection = _map_and_colorize_techniques_for_detections(my_techniques) if not layer_name: layer_name = 'Detections ' + name - layer_detection = get_layer_template_detections(layer_name, 'description', 'attack', platform) + layer_detection = get_layer_template_detections(layer_name, 'description', platform) _write_layer(layer_detection, mapped_techniques_detection, 'detection', name, output_filename) else: my_data_sources = _load_data_sources(filename_data_sources) mapped_techniques_both = _map_and_colorize_techniques_for_overlaid(my_techniques, my_data_sources, platform) if not layer_name: layer_name = 'Visibility and Detection ' + name - layer_both = get_layer_template_layered(layer_name, 'description', 'attack', platform) + layer_both = get_layer_template_layered(layer_name, 'description', platform) _write_layer(layer_both, mapped_techniques_both, 'visibility_and_detection', name, output_filename) @@ -53,13 +53,13 @@ def generate_visibility_layer(filename_techniques, filename_data_sources, overla mapped_techniques_visibility = _map_and_colorize_techniques_for_visibility(my_techniques, my_data_sources, platform) if not layer_name: layer_name = 'Visibility ' + name - layer_visibility = get_layer_template_visibility(layer_name, 'description', 'attack', platform) + layer_visibility = get_layer_template_visibility(layer_name, 'description', platform) _write_layer(layer_visibility, mapped_techniques_visibility, 'visibility', name, output_filename) else: mapped_techniques_both = _map_and_colorize_techniques_for_overlaid(my_techniques, my_data_sources, platform) if not layer_name: layer_name = 'Visibility and Detection ' + name - layer_both = get_layer_template_layered(layer_name, 'description', 'attack', platform) + layer_both = get_layer_template_layered(layer_name, 'description', platform) _write_layer(layer_both, mapped_techniques_both, 'visibility_and_detection', name, output_filename) From e4c8681c19272b86762b08b5d062100a3e137cb0 Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Sun, 1 Nov 2020 11:01:50 +0100 Subject: [PATCH 10/11] Manual refresh to ATT&CK CTI repo 8.0 --- editor/src/data/software.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/editor/src/data/software.json b/editor/src/data/software.json index 81b2f7d..a683509 100644 --- a/editor/src/data/software.json +++ b/editor/src/data/software.json @@ -380,7 +380,9 @@ "Azure AD", "GCP", "Linux", + "Network", "Office 365", + "PRE", "SaaS", "Windows", "macOS" @@ -644,7 +646,9 @@ "Azure AD", "GCP", "Linux", + "Network", "Office 365", + "PRE", "SaaS", "Windows", "macOS" @@ -1714,7 +1718,9 @@ "Azure AD", "GCP", "Linux", + "Network", "Office 365", + "PRE", "SaaS", "Windows", "macOS" @@ -2823,7 +2829,9 @@ "Azure AD", "GCP", "Linux", + "Network", "Office 365", + "PRE", "SaaS", "Windows", "macOS" @@ -2839,7 +2847,9 @@ "Azure AD", "GCP", "Linux", + "Network", "Office 365", + "PRE", "SaaS", "Windows", "macOS" @@ -3517,7 +3527,9 @@ "Azure AD", "GCP", "Linux", + "Network", "Office 365", + "PRE", "SaaS", "Windows", "macOS" @@ -3596,5 +3608,13 @@ "Windows" ], "autosuggest": "S0518 - PolyglotDuke" + }, + { + "software_id": "S0519", + "software_name": "SYNful Knock", + "platforms": [ + "Network" + ], + "autosuggest": "S0519 - SYNful Knock" } ] \ No newline at end of file From ca88e257e446bf107a25fa06a8c2584a3a2a854a Mon Sep 17 00:00:00 2001 From: Marcus Bakker Date: Wed, 4 Nov 2020 11:09:53 +0100 Subject: [PATCH 11/11] Updated the dependencies --- editor/package-lock.json | 191 ++++++++++++++++++++++----------------- editor/package.json | 8 +- requirements.txt | 2 +- 3 files changed, 115 insertions(+), 86 deletions(-) diff --git a/editor/package-lock.json b/editor/package-lock.json index 152b453..b0ae6b5 100644 --- a/editor/package-lock.json +++ b/editor/package-lock.json @@ -1076,9 +1076,9 @@ } }, "@eslint/eslintrc": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.0.tgz", - "integrity": "sha512-+cIGPCBdLCzqxdtwppswP+zTsH9BOIGzAeKfBIbtb4gW/giMlfMwP0HUSFfhzh20f9u8uZ8hOp62+4GPquTbwQ==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz", + "integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -1940,17 +1940,6 @@ "unique-filename": "^1.1.1" } }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -2004,41 +1993,12 @@ "path-exists": "^4.0.0" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, - "optional": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -2132,16 +2092,6 @@ "ansi-regex": "^5.0.0" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "terser-webpack-plugin": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", @@ -2159,18 +2109,6 @@ "webpack-sources": "^1.4.3" } }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.0.0-beta.8", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.8.tgz", - "integrity": "sha512-oouKUQWWHbSihqSD7mhymGPX1OQ4hedzAHyvm8RdyHh6m3oIvoRF+NM45i/bhNOlo8jCnuJhaSUf/6oDjv978g==", - "dev": true, - "optional": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - } - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -5318,13 +5256,13 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.0.tgz", - "integrity": "sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.1.tgz", + "integrity": "sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.0", + "@eslint/eslintrc": "^0.2.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -12055,9 +11993,9 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", "dev": true }, "validate-npm-package-license": { @@ -12216,6 +12154,97 @@ } } }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.0.0-beta.9", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.9.tgz", + "integrity": "sha512-mu9pg6554GbXDSO8LlxkQM6qUJzUkb/A0FJc9LgRqnU9MCnhzEXwCt1Zx5NObvFpzs2mH2dH/uUCDwL8Qaz9sA==", + "dev": true, + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "optional": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "optional": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "vue-property-decorator": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.5.1.tgz", @@ -12233,9 +12262,9 @@ } }, "vue-router": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.7.tgz", - "integrity": "sha512-CbHXue5BLrDivOk5O4eZ0WT4Yj8XwdXa4kCnsEIOzYUPF/07ZukayA2jGxDCJxLc9SgVQX9QX0OuGOwGlVB4Qg==" + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.8.tgz", + "integrity": "sha512-3BsR84AqarcmweXjItxw3jwQsiYNssYg090yi4rlzTnCJxmHtkyCvhNz9Z7qRSOkmiV485KkUCReTp5AjNY4wg==" }, "vue-router-prefetch": { "version": "1.6.0", @@ -12243,9 +12272,9 @@ "integrity": "sha512-mLoh5on0GlO3ag0GWt+J8FkcalSAZJGJ/dNpA8PQ8X7pAoFht683FOJZlqdV7vXwKH7BjP+UfKcK09tHtNeDbw==" }, "vue-scrollto": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/vue-scrollto/-/vue-scrollto-2.19.1.tgz", - "integrity": "sha512-4+CCBLm6fTwDkKgqJIOnE4UB9ngYVoFAREJfPhT0YaEKMo6oAjnP5fv4//cuN/DxXCi75N/QOwmpOPn/xwPd5g==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/vue-scrollto/-/vue-scrollto-2.20.0.tgz", + "integrity": "sha512-7i+AGKJTThZnMEkhIPgrZjyAX+fXV7/rGdg+CV283uZZwCxwiMXaBLTmIc5RTA4uwGnT+E6eJle3mXQfM2OD3A==", "requires": { "bezier-easing": "2.1.0" } @@ -12264,9 +12293,9 @@ "integrity": "sha512-5yBGlVOQ5gvrkuoT6TtdVHLXy507EKN7X8vgXhPJsMbcJFuDTqzd6AFElSK7Bv4UwcKSU/o1OPzD9GBi86VuTQ==" }, "vue-slider-component": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/vue-slider-component/-/vue-slider-component-3.2.9.tgz", - "integrity": "sha512-b70aa66rb+9G1+RwptDSHvfBy4YXWP3fRk49pfs55WprJEVy5FM8IT5R7Yu5vYQDzgjXNGb8U0M8BZSxWeYRNg==", + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/vue-slider-component/-/vue-slider-component-3.2.10.tgz", + "integrity": "sha512-SDShSZrvCpAcjTUJzbMEDmDl6+C0vVlNwViMfsgkmWex+lcRf7Z89A9rNghnmux2oJwmz5XKDGLVZ59+q+P9uw==", "requires": { "core-js": "^3.6.5", "vue-property-decorator": "^8.0.0" diff --git a/editor/package.json b/editor/package.json index 8be14c9..cbc71bb 100755 --- a/editor/package.json +++ b/editor/package.json @@ -27,12 +27,12 @@ "vue-directive-tooltip": "^1.6.3", "vue-js-toggle-button": "^1.3.3", "vue-resource": "^1.5.1", - "vue-router": "^3.4.7", + "vue-router": "^3.4.8", "vue-router-prefetch": "^1.6.0", - "vue-scrollto": "^2.19.1", + "vue-scrollto": "^2.20.0", "vue-showdown": "^2.4.1", "vue-simple-suggest": "^1.10.3", - "vue-slider-component": "^3.2.9", + "vue-slider-component": "^3.2.10", "vue2-transitions": "^0.3.0", "vuejs-datepicker": "^1.6.2", "vuejs-smart-table": "0.0.5", @@ -42,7 +42,7 @@ "@vue/cli-plugin-babel": "^4.5.8", "@vue/cli-plugin-eslint": "^4.5.8", "@vue/cli-service": "^4.5.8", - "eslint": "^7.12.0", + "eslint": "^7.12.1", "eslint-loader": "^4.0.2", "eslint-plugin-vue": "^6.2.2", "vue-template-compiler": "^2.6.12" diff --git a/requirements.txt b/requirements.txt index 152671a..b7478ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ attackcti==0.3.3 simplejson==3.17.2 plotly==4.12.0 -pandas==1.1.3 +pandas==1.1.4 xlsxwriter==1.3.7 ruamel.yaml==0.16.12 eql==0.9.5