From 8efc3e654c499e06a23434cc1a5451d32c23e7a0 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 23 Feb 2021 08:21:49 +0200 Subject: [PATCH 01/17] Extracted exploiters from reports in front end and back end --- .../reporting/issue_processing/__init__.py | 0 .../exploit_processing/__init__.py | 0 .../exploiter_descriptor_enum.py | 32 + .../exploit_processing/processors/__init__.py | 0 .../processors/cred_exploit.py | 33 + .../exploit_processing/processors/exploit.py | 21 + .../processors/shellshock_exploit.py | 16 + .../reporting/issue_processing/issue.py | 0 .../issue_processing/issue_processor.py | 0 .../cc/services/reporting/report.py | 330 +----- .../cc/services/reporting/test_report.py | 51 + .../report-components/SecurityReport.js | 955 ++++-------------- .../security/IssueDescriptor.js | 7 + .../security/issues/AzurePasswordIssue.js | 22 + .../security/issues/CrossSegmentIssue.js | 84 ++ .../security/issues/DrupalIssue.js | 23 + .../security/issues/ElasticIssue.js | 22 + .../security/issues/HadoopIssue.js | 22 + .../security/issues/MS08_067Issue.js | 23 + .../security/issues/MssqlIssue.js | 23 + .../issues/PthCriticalServiceIssue.js | 6 + .../security/issues/SambacryIssue.js | 27 + .../security/issues/SharedPasswordsIssue.js | 49 + .../security/issues/ShellShockIssue.js | 29 + .../security/issues/SmbIssue.js | 36 + .../security/issues/SshIssue.js | 38 + .../security/issues/StolenCredsIssue.js | 5 + .../security/issues/StrongUsersOnCritIssue.js | 15 + .../security/issues/Struts2Issue.js | 25 + .../security/issues/TunnelIssue.js | 18 + .../security/issues/VsftpdIssue.js | 35 + .../security/issues/WeakPasswordIssue.js | 6 + .../security/issues/WebLogicIssue.js | 22 + .../security/issues/WmiIssue.js | 36 + .../security/issues/utils.js | 6 + 35 files changed, 962 insertions(+), 1055 deletions(-) create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/__init__.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/__init__.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/__init__.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/issue.py create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/issue_processor.py create mode 100644 monkey/monkey_island/cc/services/reporting/test_report.py create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/IssueDescriptor.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/utils.js diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/__init__.py b/monkey/monkey_island/cc/services/reporting/issue_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/__init__.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py new file mode 100644 index 000000000..e6820b178 --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py @@ -0,0 +1,32 @@ +from dataclasses import dataclass +from enum import Enum +from typing import Type + +from monkey_island.cc.services.reporting.issue_processing.exploit_processing import CredExploitProcessor +from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploitProcessor +from monkey_island.cc.services.reporting.issue_processing.exploit_processing import \ + ShellShockExploitProcessor + + +@dataclass +class ExploiterDescriptor: + # Must match with class names of exploiters in Infection Monkey code + class_name: str + display_name: str + processor: Type[ExploitProcessor] + + +class ExploiterDescriptorEnum(Enum): + SMB = ExploiterDescriptor('SmbExploiter', 'SMB Exploiter', CredExploitProcessor) + WMI = ExploiterDescriptor('WmiExploiter', 'WMI Exploiter', CredExploitProcessor) + SSH = ExploiterDescriptor('SSHExploiter', 'SSH Exploiter', CredExploitProcessor) + SAMBACRY = ExploiterDescriptor('SambaCryExploiter', 'SambaCry Exploiter', CredExploitProcessor) + ELASTIC = ExploiterDescriptor('ElasticGroovyExploiter', 'Elastic Groovy Exploiter', ExploitProcessor) + MS08_067 = ExploiterDescriptor('Ms08_067_Exploiter', 'Conficker Exploiter', ExploitProcessor) + SHELLSHOCK = ExploiterDescriptor('ShellShockExploiter', 'ShellShock Exploiter', ShellShockExploitProcessor) + STRUTS2 = ExploiterDescriptor('Struts2Exploiter', 'Struts2 Exploiter', ExploitProcessor) + WEBLOGIC = ExploiterDescriptor('WebLogicExploiter', 'Oracle WebLogic Exploiter', ExploitProcessor) + HADOOP = ExploiterDescriptor('HadoopExploiter', 'Hadoop/Yarn Exploiter', ExploitProcessor) + MSSQL = ExploiterDescriptor('MSSQLExploiter', 'MSSQL Exploiter', ExploitProcessor) + VSFTPD = ExploiterDescriptor('VSFTPDExploiter', 'VSFTPD Backdoor Exploiter', CredExploitProcessor) + DRUPAL = ExploiterDescriptor('DrupalExploiter', 'Drupal Server Exploiter', ExploitProcessor) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/__init__.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py new file mode 100644 index 000000000..fc61676b8 --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from enum import Enum + +from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploitProcessor, \ + ExploiterReportInfo + + +class CredentialType(Enum): + PASSWORD = 'password' + HASH = 'hash' + KEY = 'key' + + +class CredExploitProcessor(ExploitProcessor): + + @staticmethod + def get_exploit_info_by_dict(class_name: str, exploit_dict: dict) -> ExploiterReportInfo: + exploit_info = ExploitProcessor.get_exploit_info_by_dict(class_name, exploit_dict) + + for attempt in exploit_dict['data']['attempts']: + if attempt['result']: + exploit_info.username = attempt['user'] + if attempt['password']: + exploit_info.credential_type = CredentialType.PASSWORD.value + exploit_info.password = attempt['password'] + elif attempt['ssh_key']: + exploit_info.credential_type = CredentialType.KEY.value + exploit_info.ssh_key = attempt['ssh_key'] + else: + exploit_info.credential_type = CredentialType.HASH.value + return exploit_info + return exploit_info diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py new file mode 100644 index 000000000..79ebb2dfb --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py @@ -0,0 +1,21 @@ +from __future__ import annotations + +from dataclasses import dataclass + +from monkey_island.cc.services.node import NodeService + + +@dataclass +class ExploiterReportInfo: + machine: str + ip_address: str + type: str + + +class ExploitProcessor: + + @staticmethod + def get_exploit_info_by_dict(class_name: str, exploit_dict: dict) -> ExploiterReportInfo: + ip_addr = exploit_dict['data']['machine']['ip_addr'] + machine = NodeService.get_node_hostname(NodeService.get_node_or_monkey_by_ip(ip_addr)) + return ExploiterReportInfo(ip_address=ip_addr, machine=machine, type=class_name) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py new file mode 100644 index 000000000..181a19f41 --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py @@ -0,0 +1,16 @@ +from __future__ import annotations + +from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploitProcessor, \ + ExploiterReportInfo + + +class ShellShockExploitProcessor(ExploitProcessor): + + @staticmethod + def get_exploit_info_by_dict(class_name: str, exploit_dict: dict) -> ExploiterReportInfo: + exploit_info = ExploitProcessor.get_exploit_info_by_dict(class_name, exploit_dict) + + urls = exploit_dict['data']['info']['vulnerable_urls'] + exploit_info.port = urls[0].split(':')[2].split('/')[0] + exploit_info.paths = ['/' + url.split(':')[2].split('/')[1] for url in urls] + return exploit_info diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/issue.py b/monkey/monkey_island/cc/services/reporting/issue_processing/issue.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/issue_processor.py b/monkey/monkey_island/cc/services/reporting/issue_processing/issue_processor.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index a23aa6d85..30f096fb7 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -2,7 +2,7 @@ import functools import ipaddress import itertools import logging -from enum import Enum +from typing import Dict, List from bson import json_util @@ -17,6 +17,10 @@ from common.config_value_paths import (EXPLOITER_CLASSES_PATH, LOCAL_NETWORK_SCA USER_LIST_PATH) from monkey_island.cc.services.configuration.utils import get_config_network_segments_as_subnet_groups from monkey_island.cc.services.node import NodeService +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_descriptor_enum import ExploiterDescriptorEnum, \ + ExploiterDescriptor +from monkey_island.cc.services.reporting.issue_processing.exploit_processing import CredentialType +from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploiterReportInfo from monkey_island.cc.services.reporting.pth_report import PTHReportService from monkey_island.cc.services.reporting.report_exporter_manager import ReportExporterManager from monkey_island.cc.services.reporting.report_generation_synchronisation import safe_generate_regular_report @@ -26,52 +30,19 @@ __author__ = "itay.mizeretz" logger = logging.getLogger(__name__) +def build_exploiter_descriptor_dict() -> Dict[str, ExploiterDescriptor]: + descriptor_dict = {} + for descriptor in ExploiterDescriptorEnum: + descriptor_dict[descriptor.value.class_name] = descriptor + return descriptor_dict + + class ReportService: - def __init__(self): - pass + exploiter_descriptors = build_exploiter_descriptor_dict() - EXPLOIT_DISPLAY_DICT = \ - { - 'SmbExploiter': 'SMB Exploiter', - 'WmiExploiter': 'WMI Exploiter', - 'SSHExploiter': 'SSH Exploiter', - 'SambaCryExploiter': 'SambaCry Exploiter', - 'ElasticGroovyExploiter': 'Elastic Groovy Exploiter', - 'Ms08_067_Exploiter': 'Conficker Exploiter', - 'ShellShockExploiter': 'ShellShock Exploiter', - 'Struts2Exploiter': 'Struts2 Exploiter', - 'WebLogicExploiter': 'Oracle WebLogic Exploiter', - 'HadoopExploiter': 'Hadoop/Yarn Exploiter', - 'MSSQLExploiter': 'MSSQL Exploiter', - 'VSFTPDExploiter': 'VSFTPD Backdoor Exploiter', - 'DrupalExploiter': 'Drupal Server Exploiter', - 'ZerologonExploiter': 'Windows Server Zerologon Exploiter' - } - - class ISSUES_DICT(Enum): - WEAK_PASSWORD = 0 - STOLEN_CREDS = 1 - ELASTIC = 2 - SAMBACRY = 3 - SHELLSHOCK = 4 - CONFICKER = 5 - AZURE = 6 - STOLEN_SSH_KEYS = 7 - STRUTS2 = 8 - WEBLOGIC = 9 - HADOOP = 10 - PTH_CRIT_SERVICES_ACCESS = 11 - MSSQL = 12 - VSFTPD = 13 - DRUPAL = 14 - ZEROLOGON = 15 - ZEROLOGON_PASSWORD_RESTORE_FAILED = 16 - - class WARNINGS_DICT(Enum): - CROSS_SEGMENT = 0 - TUNNEL = 1 - SHARED_LOCAL_ADMIN = 2 - SHARED_PASSWORDS = 3 + class DerivedIssueEnum: + WEAK_PASSWORD = "weak_password" + STOLEN_CREDS = "stolen_creds" @staticmethod def get_first_monkey_time(): @@ -169,9 +140,7 @@ class ReportService: 'label': exploited_node['label'], 'ip_addresses': exploited_node['ip_addresses'], 'domain_name': exploited_node['domain_name'], - 'exploits': list(set( - [ReportService.EXPLOIT_DISPLAY_DICT[exploit['exploiter']] for exploit in exploited_node['exploits'] - if exploit['result']])) + 'exploits': ReportService.get_exploits_used_on_node(exploited_node) } for exploited_node in exploited] @@ -179,6 +148,10 @@ class ReportService: return exploited + @staticmethod + def get_exploits_used_on_node(node: dict) -> List[str]: + return list(set([exploit['exploiter'] for exploit in node['exploits'] if exploit['result']])) + @staticmethod def get_stolen_creds(): creds = [] @@ -281,148 +254,12 @@ class ReportService: return creds @staticmethod - def process_general_exploit(exploit): - ip_addr = exploit['data']['machine']['ip_addr'] - return {'machine': NodeService.get_node_hostname(NodeService.get_node_or_monkey_by_ip(ip_addr)), - 'ip_address': ip_addr} - - @staticmethod - def process_general_creds_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - - for attempt in exploit['data']['attempts']: - if attempt['result']: - processed_exploit['username'] = attempt['user'] - if attempt['password']: - processed_exploit['type'] = 'password' - processed_exploit['password'] = attempt['password'] - elif attempt['ssh_key']: - processed_exploit['type'] = 'ssh_key' - processed_exploit['ssh_key'] = attempt['ssh_key'] - else: - processed_exploit['type'] = 'hash' - return processed_exploit - return processed_exploit - - @staticmethod - def process_smb_exploit(exploit): - processed_exploit = ReportService.process_general_creds_exploit(exploit) - if processed_exploit['type'] == 'password': - processed_exploit['type'] = 'smb_password' - else: - processed_exploit['type'] = 'smb_pth' - return processed_exploit - - @staticmethod - def process_wmi_exploit(exploit): - processed_exploit = ReportService.process_general_creds_exploit(exploit) - if processed_exploit['type'] == 'password': - processed_exploit['type'] = 'wmi_password' - else: - processed_exploit['type'] = 'wmi_pth' - return processed_exploit - - @staticmethod - def process_ssh_exploit(exploit): - processed_exploit = ReportService.process_general_creds_exploit(exploit) - # Check if it's ssh key or ssh login credentials exploit - if processed_exploit['type'] == 'ssh_key': - return processed_exploit - else: - processed_exploit['type'] = 'ssh' - return processed_exploit - - @staticmethod - def process_vsftpd_exploit(exploit): - processed_exploit = ReportService.process_general_creds_exploit(exploit) - processed_exploit['type'] = 'vsftp' - return processed_exploit - - @staticmethod - def process_sambacry_exploit(exploit): - processed_exploit = ReportService.process_general_creds_exploit(exploit) - processed_exploit['type'] = 'sambacry' - return processed_exploit - - @staticmethod - def process_elastic_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'elastic' - return processed_exploit - - @staticmethod - def process_conficker_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'conficker' - return processed_exploit - - @staticmethod - def process_shellshock_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'shellshock' - urls = exploit['data']['info']['vulnerable_urls'] - processed_exploit['port'] = urls[0].split(':')[2].split('/')[0] - processed_exploit['paths'] = ['/' + url.split(':')[2].split('/')[1] for url in urls] - return processed_exploit - - @staticmethod - def process_struts2_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'struts2' - return processed_exploit - - @staticmethod - def process_weblogic_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'weblogic' - return processed_exploit - - @staticmethod - def process_hadoop_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'hadoop' - return processed_exploit - - @staticmethod - def process_mssql_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'mssql' - return processed_exploit - - @staticmethod - def process_drupal_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'drupal' - return processed_exploit - - @staticmethod - def process_zerologon_exploit(exploit): - processed_exploit = ReportService.process_general_exploit(exploit) - processed_exploit['type'] = 'zerologon' - processed_exploit['password_restored'] = exploit['data']['info']['password_restored'] - return processed_exploit - - @staticmethod - def process_exploit(exploit): + def process_exploit(exploit) -> ExploiterReportInfo: exploiter_type = exploit['data']['exploiter'] - EXPLOIT_PROCESS_FUNCTION_DICT = { - 'SmbExploiter': ReportService.process_smb_exploit, - 'WmiExploiter': ReportService.process_wmi_exploit, - 'SSHExploiter': ReportService.process_ssh_exploit, - 'SambaCryExploiter': ReportService.process_sambacry_exploit, - 'ElasticGroovyExploiter': ReportService.process_elastic_exploit, - 'Ms08_067_Exploiter': ReportService.process_conficker_exploit, - 'ShellShockExploiter': ReportService.process_shellshock_exploit, - 'Struts2Exploiter': ReportService.process_struts2_exploit, - 'WebLogicExploiter': ReportService.process_weblogic_exploit, - 'HadoopExploiter': ReportService.process_hadoop_exploit, - 'MSSQLExploiter': ReportService.process_mssql_exploit, - 'VSFTPDExploiter': ReportService.process_vsftpd_exploit, - 'DrupalExploiter': ReportService.process_drupal_exploit, - 'ZerologonExploiter': ReportService.process_zerologon_exploit - } - - return EXPLOIT_PROCESS_FUNCTION_DICT[exploiter_type](exploit) + exploiter_descriptor = ReportService.exploiter_descriptors[exploiter_type].value + processor = exploiter_descriptor.processor() + exploiter_info = processor.get_exploit_info_by_dict(exploiter_descriptor.class_name, exploit) + return exploiter_info @staticmethod def get_exploits(): @@ -585,7 +422,8 @@ class ReportService: @staticmethod def get_cross_segment_issues(): scans = mongo.db.telemetry.find({'telem_category': 'scan'}, - {'monkey_guid': 1, 'data.machine.ip_addr': 1, 'data.machine.services': 1, 'data.machine.icmp': 1}) + {'monkey_guid': 1, 'data.machine.ip_addr': 1, 'data.machine.services': 1, + 'data.machine.icmp': 1}) cross_segment_issues = [] @@ -627,32 +465,6 @@ class ReportService: else: return None - @staticmethod - def get_issues(): - ISSUE_GENERATORS = [ - ReportService.get_exploits, - ReportService.get_tunnels, - ReportService.get_island_cross_segment_issues, - ReportService.get_azure_issues, - PTHReportService.get_duplicated_passwords_issues, - PTHReportService.get_strong_users_on_crit_issues - ] - - issues = functools.reduce(lambda acc, issue_gen: acc + issue_gen(), ISSUE_GENERATORS, []) - - issues_dict = {} - for issue in issues: - if issue.get('is_local', True): - machine = issue.get('machine').upper() - aws_instance_id = ReportService.get_machine_aws_instance_id(issue.get('machine')) - if machine not in issues_dict: - issues_dict[machine] = [] - if aws_instance_id: - issue['aws_instance_id'] = aws_instance_id - issues_dict[machine].append(issue) - logger.info('Issues generated for reporting') - return issues_dict - @staticmethod def get_manual_monkeys(): return [monkey['hostname'] for monkey in mongo.db.monkey.find({}, {'hostname': 1, 'parent': 1, 'guid': 1}) if @@ -677,8 +489,8 @@ class ReportService: if exploits == default_exploits: return ['default'] - return [ReportService.EXPLOIT_DISPLAY_DICT[exploit] for exploit in - exploits] + # TODO investigate strange code + return [exploit for exploit in exploits] @staticmethod def get_config_ips(): @@ -689,68 +501,37 @@ class ReportService: return ConfigService.get_config_value(LOCAL_NETWORK_SCAN_PATH, True, True) @staticmethod - def get_issues_overview(issues, config_users, config_passwords): - issues_byte_array = [False] * len(ReportService.ISSUES_DICT) + def get_issue_set(issues, config_users, config_passwords): + issue_set = set() for machine in issues: for issue in issues[machine]: - if issue['type'] == 'elastic': - issues_byte_array[ReportService.ISSUES_DICT.ELASTIC.value] = True - elif issue['type'] == 'sambacry': - issues_byte_array[ReportService.ISSUES_DICT.SAMBACRY.value] = True - elif issue['type'] == 'vsftp': - issues_byte_array[ReportService.ISSUES_DICT.VSFTPD.value] = True - elif issue['type'] == 'shellshock': - issues_byte_array[ReportService.ISSUES_DICT.SHELLSHOCK.value] = True - elif issue['type'] == 'conficker': - issues_byte_array[ReportService.ISSUES_DICT.CONFICKER.value] = True - elif issue['type'] == 'azure_password': - issues_byte_array[ReportService.ISSUES_DICT.AZURE.value] = True - elif issue['type'] == 'ssh_key': - issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True - elif issue['type'] == 'struts2': - issues_byte_array[ReportService.ISSUES_DICT.STRUTS2.value] = True - elif issue['type'] == 'weblogic': - issues_byte_array[ReportService.ISSUES_DICT.WEBLOGIC.value] = True - elif issue['type'] == 'mssql': - issues_byte_array[ReportService.ISSUES_DICT.MSSQL.value] = True - elif issue['type'] == 'hadoop': - issues_byte_array[ReportService.ISSUES_DICT.HADOOP.value] = True - elif issue['type'] == 'drupal': - issues_byte_array[ReportService.ISSUES_DICT.DRUPAL.value] = True - elif issue['type'] == 'zerologon': - if not issue['password_restored']: - issues_byte_array[ReportService.ISSUES_DICT.ZEROLOGON_PASSWORD_RESTORE_FAILED.value] = True - issues_byte_array[ReportService.ISSUES_DICT.ZEROLOGON.value] = True - elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ - issue['username'] in config_users or issue['type'] == 'ssh': - issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True - elif issue['type'] == 'strong_users_on_crit': - issues_byte_array[ReportService.ISSUES_DICT.PTH_CRIT_SERVICES_ACCESS.value] = True - elif issue['type'].endswith('_pth') or issue['type'].endswith('_password'): - issues_byte_array[ReportService.ISSUES_DICT.STOLEN_CREDS.value] = True + # TODO check if this actually works, because stolen passwords get added to config + # so any password will be in config. We need to separate stolen passwords from initial + # passwords in config. + if ReportService._is_weak_credential_issue(issue, config_users, config_passwords): + issue_set.add(ReportService.DerivedIssueEnum.WEAK_PASSWORD) + elif ReportService._is_stolen_credential_issue(issue): + issue_set.add(ReportService.DerivedIssueEnum.STOLEN_CREDS) - return issues_byte_array + issue_set.add(issue['type']) + + return issue_set @staticmethod - def get_warnings_overview(issues, cross_segment_issues): - warnings_byte_array = [False] * len(ReportService.WARNINGS_DICT) + def _is_weak_credential_issue(issue: dict, config_usernames: List[str], config_passwords: List[str]) -> bool: + # Only credential exploiter issues have 'credential_type' + return 'credential_type' in issue and \ + issue['credential_type'] == CredentialType.PASSWORD.value and \ + issue['password'] in config_passwords and \ + issue['username'] in config_usernames - for machine in issues: - for issue in issues[machine]: - if issue['type'] == 'island_cross_segment': - warnings_byte_array[ReportService.WARNINGS_DICT.CROSS_SEGMENT.value] = True - elif issue['type'] == 'tunnel': - warnings_byte_array[ReportService.WARNINGS_DICT.TUNNEL.value] = True - elif issue['type'] == 'shared_admins': - warnings_byte_array[ReportService.WARNINGS_DICT.SHARED_LOCAL_ADMIN.value] = True - elif issue['type'] == 'shared_passwords': - warnings_byte_array[ReportService.WARNINGS_DICT.SHARED_PASSWORDS.value] = True - - if len(cross_segment_issues) != 0: - warnings_byte_array[ReportService.WARNINGS_DICT.CROSS_SEGMENT.value] = True - - return warnings_byte_array + @staticmethod + def _is_stolen_credential_issue(issue: dict) -> bool: + # Only credential exploiter issues have 'credential_type' + return 'credential_type' in issue and \ + (issue['credential_type'] == CredentialType.PASSWORD.value or + issue['credential_type'] == CredentialType.HASH.value) @staticmethod def is_report_generated(): @@ -780,8 +561,7 @@ class ReportService: 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), - 'issues': ReportService.get_issues_overview(issues, config_users, config_passwords), - 'warnings': ReportService.get_warnings_overview(issues, cross_segment_issues), + 'issues': ReportService.get_issue_set(issues, config_users, config_passwords), 'cross_segment_issues': cross_segment_issues }, 'glance': diff --git a/monkey/monkey_island/cc/services/reporting/test_report.py b/monkey/monkey_island/cc/services/reporting/test_report.py new file mode 100644 index 000000000..9983371a4 --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/test_report.py @@ -0,0 +1,51 @@ +import datetime +from copy import deepcopy + +from monkey_island.cc.services.reporting.report import ReportService + +NODE_DICT = { + 'id': '602f62118e30cf35830ff8e4', + 'label': 'WinDev2010Eval.mshome.net', + 'group': 'monkey_windows', + 'os': 'windows', + 'dead': True, + 'exploits': [{'result': True, + 'exploiter': 'DrupalExploiter', + 'info': {'display_name': 'Drupal Server', + 'started': datetime.datetime(2021, 2, 19, 9, 0, 14, 950000), + 'finished': datetime.datetime(2021, 2, 19, 9, 0, 14, 950000), + 'vulnerable_urls': [], + 'vulnerable_ports': [], + 'executed_cmds': []}, + 'attempts': [], + 'timestamp': datetime.datetime(2021, 2, 19, 9, 0, 14, 984000), + 'origin': 'MonkeyIsland : 192.168.56.1'}, + + {'result': True, + 'exploiter': 'ElasticGroovyExploiter', + 'info': {'display_name': 'Elastic search', + 'started': datetime.datetime(2021, 2, 19, 9, 0, 15, 16000), + 'finished': datetime.datetime(2021, 2, 19, 9, 0, 15, 17000), + 'vulnerable_urls': [], 'vulnerable_ports': [], 'executed_cmds': []}, + 'attempts': [], + 'timestamp': datetime.datetime(2021, 2, 19, 9, 0, 15, 60000), + 'origin': 'MonkeyIsland : 192.168.56.1'}] +} + +NODE_DICT_DUPLICATE_EXPLOITS = deepcopy(NODE_DICT) +NODE_DICT_DUPLICATE_EXPLOITS['exploits'][1] = NODE_DICT_DUPLICATE_EXPLOITS['exploits'][0] + +NODE_DICT_FAILED_EXPLOITS = deepcopy(NODE_DICT) +NODE_DICT_FAILED_EXPLOITS['exploits'][0]['result'] = False +NODE_DICT_FAILED_EXPLOITS['exploits'][1]['result'] = False + + +def test_get_exploits_used_on_node(): + exploits = ReportService.get_exploits_used_on_node(NODE_DICT) + assert sorted(exploits) == sorted(['ElasticGroovyExploiter', 'DrupalExploiter']) + + exploits = ReportService.get_exploits_used_on_node(NODE_DICT_DUPLICATE_EXPLOITS) + assert exploits == ['DrupalExploiter'] + + exploits = ReportService.get_exploits_used_on_node(NODE_DICT_FAILED_EXPLOITS) + assert exploits == [] diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index e3a1621eb..bd5ae3a30 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -5,7 +5,6 @@ import PostBreach from 'components/report-components/security/PostBreach'; import {ReactiveGraph} from 'components/reactive-graph/ReactiveGraph'; import {edgeGroupToColor, getOptions} from 'components/map/MapOptions'; import StolenPasswords from 'components/report-components/security/StolenPasswords'; -import CollapsibleWellComponent from 'components/report-components/security/CollapsibleWell'; import {Line} from 'rc-progress'; import AuthComponent from '../AuthComponent'; import StrongUsers from 'components/report-components/security/StrongUsers'; @@ -21,41 +20,141 @@ import {faMinus} from '@fortawesome/free-solid-svg-icons/faMinus'; import guardicoreLogoImage from '../../images/guardicore-logo.png' import {faExclamationTriangle} from '@fortawesome/free-solid-svg-icons'; import '../../styles/App.css'; +import {generateSmbPasswordReport, generateSmbPthReport} from './security/issues/SmbIssue'; +import {Struts2IssueOverview, Struts2IssueReport} from './security/issues/Struts2Issue'; +import {WebLogicIssueOverview, WebLogicIssueReport} from './security/issues/WebLogicIssue'; +import {HadoopIssueOverview, HadoopIssueReport} from './security/issues/HadoopIssue'; +import {MssqlIssueOverview, MssqlIssueReport} from './security/issues/MssqlIssue'; +import {DrupalIssueOverview, DrupalIssueReport} from './security/issues/DrupalIssue'; +import {VsftpdIssueOverview, VsftpdIssueReport} from './security/issues/VsftpdIssue'; +import {generateWmiPasswordIssue, generateWmiPthIssue} from './security/issues/WmiIssue'; +import {ShhIssueReport, SshIssueOverview} from './security/issues/SshIssue'; +import {SambacryIssueOverview, SambacryIssueReport} from './security/issues/SambacryIssue'; +import {ElasticIssueOverview, ElasticIssueReport} from './security/issues/ElasticIssue'; +import {ShellShockIssueOverview, ShellShockIssueReport} from './security/issues/ShellShockIssue'; +import {MS08_067IssueOverview, MS08_067IssueReport} from './security/issues/MS08_067Issue'; +import { + crossSegmentIssueOverview, + generateCrossSegmentIssue +} from './security/issues/CrossSegmentIssue'; +import {sharedAdminsDomainIssueOverview, sharedPasswordsIssueOverview} from './security/issues/SharedPasswordsIssue'; +import {generateTunnelIssue, generateTunnelIssueOverview} from './security/issues/TunnelIssue'; class ReportPageComponent extends AuthComponent { - Issue = - { - WEAK_PASSWORD: 0, - STOLEN_CREDS: 1, - ELASTIC: 2, - SAMBACRY: 3, - SHELLSHOCK: 4, - CONFICKER: 5, - AZURE: 6, - STOLEN_SSH_KEYS: 7, - STRUTS2: 8, - WEBLOGIC: 9, - HADOOP: 10, - PTH_CRIT_SERVICES_ACCESS: 11, - MSSQL: 12, - VSFTPD: 13, - DRUPAL: 14, - ZEROLOGON: 15, - ZEROLOGON_PASSWORD_RESTORE_FAILED: 16 - }; + credentialTypes = { + PASSWORD: 'password', + HASH: 'hash', + KEY: 'key', + } - NotThreats = [this.Issue.ZEROLOGON_PASSWORD_RESTORE_FAILED]; + issueContentTypes = { + OVERVIEW: 'overview', + REPORT: 'report', + TYPE: 'type' + } - Warning = + issueTypes = { + WARNING: 'warning', + DANGER: 'danger' + } + + IssueDescriptorEnum = { - CROSS_SEGMENT: 0, - TUNNEL: 1, - SHARED_LOCAL_ADMIN: 2, - SHARED_PASSWORDS: 3, - SHARED_PASSWORDS_DOMAIN: 4 - }; + 'SmbExploiter': { + [this.issueContentTypes.REPORT]: { + [this.credentialTypes.PASSWORD]: generateSmbPasswordReport, + [this.credentialTypes.HASH]: generateSmbPthReport + }, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'Struts2Exploiter': { + [this.issueContentTypes.OVERVIEW]: Struts2IssueOverview, + [this.issueContentTypes.REPORT]: Struts2IssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'WebLogicExploiter': { + [this.issueContentTypes.OVERVIEW]: WebLogicIssueOverview, + [this.issueContentTypes.REPORT]: WebLogicIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'HadoopExploiter': { + [this.issueContentTypes.OVERVIEW]: HadoopIssueOverview, + [this.issueContentTypes.REPORT]: HadoopIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'MSSQLExploiter': { + [this.issueContentTypes.OVERVIEW]: MssqlIssueOverview, + [this.issueContentTypes.REPORT]: MssqlIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'DrupalExploiter': { + [this.issueContentTypes.OVERVIEW]: DrupalIssueOverview, + [this.issueContentTypes.REPORT]: DrupalIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'VSFTPDExploiter': { + [this.issueContentTypes.OVERVIEW]: VsftpdIssueOverview, + [this.issueContentTypes.REPORT]: VsftpdIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'WmiExploiter': { + [this.issueContentTypes.REPORT]: { + [this.credentialTypes.PASSWORD]: generateWmiPasswordIssue, + [this.credentialTypes.HASH]: generateWmiPthIssue + }, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'SSHExploiter': { + [this.issueContentTypes.OVERVIEW]: SshIssueOverview, + [this.issueContentTypes.REPORT]: ShhIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'SambaCryExploiter': { + [this.issueContentTypes.OVERVIEW]: SambacryIssueOverview, + [this.issueContentTypes.REPORT]: SambacryIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'ElasticGroovyExploiter': { + [this.issueContentTypes.OVERVIEW]: ElasticIssueOverview, + [this.issueContentTypes.REPORT]: ElasticIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'ShellShockExploiter': { + [this.issueContentTypes.OVERVIEW]: ShellShockIssueOverview, + [this.issueContentTypes.REPORT]: ShellShockIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'Ms08_067_Exploiter': { + [this.issueContentTypes.OVERVIEW]: MS08_067IssueOverview, + [this.issueContentTypes.REPORT]: MS08_067IssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'island_cross_segment': { + [this.issueContentTypes.OVERVIEW]: crossSegmentIssueOverview, + [this.issueContentTypes.REPORT]: generateCrossSegmentIssue, + [this.issueContentTypes.TYPE]: this.issueTypes.WARNING + }, + 'tunnel': { + [this.issueContentTypes.OVERVIEW]: generateTunnelIssueOverview, + [this.issueContentTypes.REPORT]: generateTunnelIssue, + [this.issueContentTypes.TYPE]: this.issueTypes.WARNING + }, + 'shared_passwords': { + [this.issueContentTypes.OVERVIEW]: sharedPasswordsIssueOverview, + [this.issueContentTypes.TYPE]: this.issueTypes.WARNING + }, + 'shared_admins_domain': { + [this.issueContentTypes.OVERVIEW]: sharedAdminsDomainIssueOverview, + [this.issueContentTypes.TYPE]: this.issueTypes.WARNING + }, + 'shared_passwords_domain': {}, + 'strong_users_on_crit': {}, + 'azure_password': {}, + 'weak_password': {}, + 'stolen_creds': {} + } constructor(props) { super(props); @@ -92,6 +191,8 @@ class ReportPageComponent extends AuthComponent { render() { let content; + console.log(this.state.report); + if (this.stillLoadingDataFromServer()) { content = ; } else { @@ -239,156 +340,24 @@ class ReportPageComponent extends AuthComponent { } generateReportFindingsSection() { + let overviews = this.getPotentialSecurityIssuesOverviews() + return (

Security Findings

-
-

- Immediate Threats -

- { - this.state.report.overview.issues.filter(function (x) { - return x === true; - }).length > 0 ? -
- During this simulated attack the Monkey uncovered - {this.getThreatCount()} - : -
    - {this.state.report.overview.issues[this.Issue.STOLEN_SSH_KEYS] && -
  • Stolen SSH keys are used to exploit other machines.
  • } - {this.state.report.overview.issues[this.Issue.STOLEN_CREDS] && -
  • Stolen credentials are used to exploit other machines.
  • } - {this.state.report.overview.issues[this.Issue.ELASTIC] && -
  • Elasticsearch servers are vulnerable to - . -
  • } - {this.state.report.overview.issues[this.Issue.VSFTPD] && -
  • VSFTPD is vulnerable to - . -
  • } - {this.state.report.overview.issues[this.Issue.SAMBACRY] && -
  • Samba servers are vulnerable to ‘SambaCry’ ( - ). -
  • } - {this.state.report.overview.issues[this.Issue.SHELLSHOCK] && -
  • Machines are vulnerable to ‘Shellshock’ ( - ). -
  • } - {this.state.report.overview.issues[this.Issue.CONFICKER] && -
  • Machines are vulnerable to ‘Conficker’ ( - ). -
  • } - {this.state.report.overview.issues[this.Issue.WEAK_PASSWORD] && -
  • Machines are accessible using passwords supplied by the user during the Monkey’s - configuration.
  • } - {this.state.report.overview.issues[this.Issue.AZURE] && -
  • Azure machines expose plaintext passwords ( - ). -
  • } - {this.state.report.overview.issues[this.Issue.STRUTS2] && -
  • Struts2 servers are vulnerable to remote code execution ( - ). -
  • } - {this.state.report.overview.issues[this.Issue.WEBLOGIC] && -
  • Oracle WebLogic servers are susceptible to a remote code execution vulnerability.
  • } - {this.state.report.overview.issues[this.Issue.HADOOP] && -
  • Hadoop/Yarn servers are vulnerable to remote code execution.
  • } - {this.state.report.overview.issues[this.Issue.PTH_CRIT_SERVICES_ACCESS] && -
  • Mimikatz found login credentials of a user who has admin access to a server defined as - critical.
  • } - {this.state.report.overview.issues[this.Issue.MSSQL] && -
  • MS-SQL servers are vulnerable to remote code execution via xp_cmdshell command.
  • } - {this.state.report.overview.issues[this.Issue.DRUPAL] && -
  • Drupal servers are susceptible to a remote code execution vulnerability - (). -
  • - } - {this.generateZerologonOverview()} -
-
- : -
- During this simulated attack the Monkey uncovered 0 threats. -
- } -
+ {this.getImmediateThreats()}

Potential Security Issues

{ - this.state.report.overview.warnings.filter(function (x) { - return x === true; - }).length > 0 ? + overviews.length > 0 ?
The Monkey uncovered the following possible set of issues:
    - {this.state.report.overview.warnings[this.Warning.CROSS_SEGMENT] ? -
  • Weak segmentation - Machines from different segments are able - to - communicate.
  • : null} - {this.state.report.overview.warnings[this.Warning.TUNNEL] ? -
  • Weak segmentation - Machines were able to communicate over unused - ports.
  • : null} - {this.state.report.overview.warnings[this.Warning.SHARED_LOCAL_ADMIN] ? -
  • Shared local administrator account - Different machines - have the same account as a local - administrator.
  • : null} - {this.state.report.overview.warnings[this.Warning.SHARED_PASSWORDS] ? -
  • Multiple users have the same password
  • : null} + {overviews}
: @@ -405,7 +374,7 @@ class ReportPageComponent extends AuthComponent {
The Monkey uncovered the following set of segmentation issues:
    - {this.state.report.overview.cross_segment_issues.map(x => this.generateCrossSegmentIssue(x))} + {this.state.report.overview.cross_segment_issues.map(x => generateCrossSegmentIssue(x))}
@@ -416,53 +385,40 @@ class ReportPageComponent extends AuthComponent { ); } - getThreatCount() { - let threatCount = this.state.report.overview.issues.filter(function (x) { - return x === true; - }).length + getPotentialSecurityIssuesOverviews(){ + let overviews = []; - this.NotThreats.forEach(x => { - if (this.state.report.overview.issues[x] === true) { - threatCount -= 1; + for( let key of this.IssueDescriptorEnum) { + if(this.WARNING_ISSUE_LIST[i] in this.state.report.issues) { + overviews.push(this.IssueDescriptorEnum[this.WARNING_ISSUE_LIST[i]][this.issueContentTypes.OVERVIEW]) } - }); - - if (threatCount === 1) - return '1 threat' - else - return threatCount + ' threats' + } + return overviews; } - generateZerologonOverview() { - let zerologonOverview = []; - if (this.state.report.overview.issues[this.Issue.ZEROLOGON]) { - zerologonOverview.push(<> - Some Windows domain controllers are vulnerable to 'Zerologon' ( - ). - ) - } - if (this.state.report.overview.issues[this.Issue.ZEROLOGON_PASSWORD_RESTORE_FAILED]) { - zerologonOverview.push( -
- - Automatic password restoration on a domain controller failed! - -
) - } - else { - return null; - } - return (
  • {zerologonOverview}
  • ) + getImmediateThreats() { + return ( +
    +

    + Immediate Threats +

    +
    During this simulated attack the Monkey uncovered + { + this.state.report.overview.issues.length > 0 ? + <> + + {this.state.report.overview.issues.length} threats: + + + : + <> + 0 threats. + + } +
    +
    ) } generateReportRecommendationsSection() { @@ -558,578 +514,17 @@ class ReportPageComponent extends AuthComponent { ); } - generateInfoBadges(data_array) { - return data_array.map(badge_data => {badge_data}); - } - - generateCrossSegmentIssue(crossSegmentIssue) { - let crossSegmentIssueOverview = 'Communication possible from ' - + `${crossSegmentIssue['source_subnet']} to ${crossSegmentIssue['target_subnet']}`; - - return ( -
  • - {crossSegmentIssueOverview} - -
      - {crossSegmentIssue['issues'].map( - issue => this.generateCrossSegmentIssueListItem(issue) - )} -
    -
    -
  • - ); - } - - generateCrossSegmentIssueListItem(issue) { - if (issue['is_self']) { - return this.generateCrossSegmentSingleHostMessage(issue); - } - - return this.generateCrossSegmentMultiHostMessage(issue); - } - - generateCrossSegmentSingleHostMessage(issue) { - return ( -
  • - {`Machine ${issue['hostname']} has both ips: ${issue['source']} and ${issue['target']}`} -
  • - ); - } - - generateCrossSegmentMultiHostMessage(issue) { - return ( -
  • - IP {issue['source']} ({issue['hostname']}) was able to communicate with - IP {issue['target']} using: -
      - {issue['icmp'] &&
    • ICMP
    • } - {this.generateCrossSegmentServiceListItems(issue)} -
    -
  • - ); - } - - generateCrossSegmentServiceListItems(issue) { - let service_list_items = []; - - for (const [service, info] of Object.entries(issue['services'])) { - service_list_items.push( -
  • - {service} ({info['display_name']}) -
  • - ); - } - - return service_list_items; - } - - generateShellshockPathListBadges(paths) { - return paths.map(path => {path}); - } - - generateSmbPasswordIssue(issue) { - return ( - <> - Change {issue.username}'s password to a complex one-use password - that is not shared with other computers on the network. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SMB attack. -
    - The Monkey authenticated over the SMB protocol with user {issue.username} and its password. -
    - - ); - } - - generateSmbPthIssue(issue) { - return ( - <> - Change {issue.username}'s password to a complex one-use password - that is not shared with other computers on the network. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SMB attack. -
    - The Monkey used a pass-the-hash attack over SMB protocol with user {issue.username}. -
    - - ); - } - - generateWmiPasswordIssue(issue) { - return ( - <> - Change {issue.username}'s password to a complex one-use password - that is not shared with other computers on the network. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a WMI attack. -
    - The Monkey authenticated over the WMI protocol with user {issue.username} and its password. -
    - - ); - } - - generateWmiPthIssue(issue) { - return ( - <> - Change {issue.username}'s password to a complex one-use password - that is not shared with other computers on the network. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a WMI attack. -
    - The Monkey used a pass-the-hash attack over WMI protocol with user {issue.username}. -
    - - ); - } - - generateSshIssue(issue) { - return ( - <> - Change {issue.username}'s password to a complex one-use password - that is not shared with other computers on the network. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SSH attack. -
    - The Monkey authenticated over the SSH protocol with user {issue.username} and its password. -
    - - ); - } - - generateSshKeysIssue(issue) { - return ( - <> - Protect {issue.ssh_key} private key with a pass phrase. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SSH attack. -
    - The Monkey authenticated over the SSH protocol with private key {issue.ssh_key}. -
    - - ); - } - - - generateSambaCryIssue(issue) { - return ( - <> - Change {issue.username}'s password to a complex one-use password - that is not shared with other computers on the network. -
    - Update your Samba server to 4.4.14 and up, 4.5.10 and up, or 4.6.4 and up. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SambaCry attack. -
    - The Monkey authenticated over the SMB protocol with user {issue.username} and its password, and used the SambaCry - vulnerability. -
    - - ); - } - - generateVsftpdBackdoorIssue(issue) { - return ( - <> - Update your VSFTPD server to the latest version vsftpd-3.0.3. - - The machine {issue.machine} ({issue.ip_address}) has a backdoor running at - port 6200. -
    - The attack was made possible because the VSFTPD server was not patched against CVE-2011-2523. -

    In July 2011, it was discovered that vsftpd version 2.3.4 downloadable from the master site had been - compromised. - Users logging into a compromised vsftpd-2.3.4 server may issue a ":)" smileyface as the username and gain a - command - shell on port 6200. -

    - The Monkey executed commands by first logging in with ":)" in the username and then sending commands to the - backdoor - at port 6200. -

    Read more about the security issue and remediation here. -
    - - ); - } - - generateElasticIssue(issue) { - return ( - <> - Update your Elastic Search server to version 1.4.3 and up. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to an Elastic Groovy attack. -
    - The attack was made possible because the Elastic Search server was not patched against CVE-2015-1427. -
    - - ); - } - - generateShellshockIssue(issue) { - return ( - <> - Update your Bash to a ShellShock-patched version. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a ShellShock attack. -
    - The attack was made possible because the HTTP server running on TCP port {issue.port} was vulnerable to a shell injection attack on the - paths: {this.generateShellshockPathListBadges(issue.paths)}. -
    - - ); - } - - generateAzureIssue(issue) { - return ( - <> - Delete VM Access plugin configuration files. - - Credentials could be stolen from {issue.machine} for the following users {issue.users}. Read more about the security issue and remediation here. - - - ); - } - - generateConfickerIssue(issue) { - return ( - <> - Install the latest Windows updates or upgrade to a newer operating system. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a Conficker attack. -
    - The attack was made possible because the target machine used an outdated and unpatched operating system - vulnerable to Conficker. -
    - - ); - } - - generateIslandCrossSegmentIssue(issue) { - return ( - <> - Segment your network and make sure there is no communication between machines from different segments. - - The network can probably be segmented. A monkey instance on {issue.machine} in the - networks {this.generateInfoBadges(issue.networks)} - could directly access the Monkey Island server in the - networks {this.generateInfoBadges(issue.server_networks)}. - - - ); - } - - generateSharedCredsDomainIssue(issue) { - return ( - <> - Some domain users are sharing passwords, this should be fixed by changing passwords. - - These users are sharing access password: - {this.generateInfoBadges(issue.shared_with)}. - - - ); - } - - generateSharedCredsIssue(issue) { - return ( - <> - Some users are sharing passwords, this should be fixed by changing passwords. - - These users are sharing access password: - {this.generateInfoBadges(issue.shared_with)}. - - - ); - } - - generateSharedLocalAdminsIssue(issue) { - return ( - <> - Make sure the right administrator accounts are managing the right machines, and that there isn’t an - unintentional local - admin sharing. - - Here is a list of machines which the account {issue.username} is defined as an administrator: - {this.generateInfoBadges(issue.shared_machines)} - - - ); - } - - generateStrongUsersOnCritIssue(issue) { - return ( - <> - This critical machine is open to attacks via strong users with access to it. - - The services: {this.generateInfoBadges(issue.services)} have been found on the machine - thus classifying it as a critical machine. - These users has access to it: - {this.generateInfoBadges(issue.threatening_users)}. - - - ); - } - - generateTunnelIssue(issue) { - return ( - <> - Use micro-segmentation policies to disable communication other than the required. - - Machines are not locked down at port level. Network tunnel was set up from {issue.machine} to {issue.dest}. - - - ); - } - - generateStruts2Issue(issue) { - return ( - <> - Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions. - - Struts2 server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. -
    - The attack was made possible because the server is using an old version of Jakarta based file upload - Multipart parser. For possible work-arounds and more info read here. -
    - - ); - } - - generateDrupalIssue(issue) { - return ( - <> - Upgrade Drupal server to versions 8.5.11, 8.6.10, or later. - - Drupal server at {issue.machine} ({issue.ip_address}) is vulnerable to remote command execution attack. -
    - The attack was made possible because the server is using an old version of Drupal, for which REST API is - enabled. For possible workarounds, fixes and more info read - here. -
    - - ); - } - - generateWebLogicIssue(issue) { - return ( - <> - Update Oracle WebLogic server to the latest supported version. - - Oracle WebLogic server at {issue.machine} ({issue.ip_address}) is vulnerable to one of remote code execution attacks. -
    - The attack was made possible due to one of the following vulnerabilities: - CVE-2017-10271 or - CVE-2019-2725 -
    - - ); - } - - generateHadoopIssue(issue) { - return ( - <> - Run Hadoop in secure mode ( - add Kerberos authentication). - - The Hadoop server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. -
    - The attack was made possible due to default Hadoop/Yarn configuration being insecure. -
    - - ); - } - - generateMSSQLIssue(issue) { - return ( - <> - Disable the xp_cmdshell option. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a MSSQL exploit attack. -
    - The attack was made possible because the target machine used an outdated MSSQL server configuration allowing - the usage of the xp_cmdshell command. To learn more about how to disable this feature, read - . -
    - - ); - } - - generateZerologonIssue(issue) { - return ( - <> - Install Windows security updates. - - The machine {issue.machine} ({issue.ip_address}) is vulnerable to a Zerologon exploit. -
    - The attack was possible because the latest security updates from Microsoft - have not been applied to this machine. For more information about this - vulnerability, read - . - {!issue.password_restored && -
    -
    - - The domain controller's password was changed during the exploit and could not be restored successfully. - Instructions on how to manually reset the domain controller's password can be found - . - -
    } -
    - - ); - } - generateIssue = (issue) => { - let issueData; - switch (issue.type) { - case 'vsftp': - issueData = this.generateVsftpdBackdoorIssue(issue); - break; - case 'smb_password': - issueData = this.generateSmbPasswordIssue(issue); - break; - case 'smb_pth': - issueData = this.generateSmbPthIssue(issue); - break; - case 'wmi_password': - issueData = this.generateWmiPasswordIssue(issue); - break; - case 'wmi_pth': - issueData = this.generateWmiPthIssue(issue); - break; - case 'ssh': - issueData = this.generateSshIssue(issue); - break; - case 'ssh_key': - issueData = this.generateSshKeysIssue(issue); - break; - case 'sambacry': - issueData = this.generateSambaCryIssue(issue); - break; - case 'elastic': - issueData = this.generateElasticIssue(issue); - break; - case 'shellshock': - issueData = this.generateShellshockIssue(issue); - break; - case 'conficker': - issueData = this.generateConfickerIssue(issue); - break; - case 'island_cross_segment': - issueData = this.generateIslandCrossSegmentIssue(issue); - break; - case 'shared_passwords': - issueData = this.generateSharedCredsIssue(issue); - break; - case 'shared_passwords_domain': - issueData = this.generateSharedCredsDomainIssue(issue); - break; - case 'shared_admins_domain': - issueData = this.generateSharedLocalAdminsIssue(issue); - break; - case 'strong_users_on_crit': - issueData = this.generateStrongUsersOnCritIssue(issue); - break; - case 'tunnel': - issueData = this.generateTunnelIssue(issue); - break; - case 'azure_password': - issueData = this.generateAzureIssue(issue); - break; - case 'struts2': - issueData = this.generateStruts2Issue(issue); - break; - case 'weblogic': - issueData = this.generateWebLogicIssue(issue); - break; - case 'hadoop': - issueData = this.generateHadoopIssue(issue); - break; - case 'mssql': - issueData = this.generateMSSQLIssue(issue); - break; - case 'drupal': - issueData = this.generateDrupalIssue(issue); - break; - case 'zerologon': - issueData = this.generateZerologonIssue(issue); - break; + let issueDescriptor = this.IssueDescriptorEnum[issue.type]; + + let reportFnc = (issue) => {}; + if(issue.hasOwnProperty('credential_type')) { + reportFnc = issueDescriptor[this.issueContentTypes.REPORT][issue.credential_type]; + } else { + reportFnc = issueDescriptor[this.issueContentTypes.REPORT]; } - return
  • {issueData}
  • ; + let reportContents = reportFnc(issue); + return
  • {reportContents}
  • ; }; generateIssues = (issues) => { diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/IssueDescriptor.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/IssueDescriptor.js new file mode 100644 index 000000000..330bf3828 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/IssueDescriptor.js @@ -0,0 +1,7 @@ +class IssueDescriptor { + constructor(name, overviewComponent, reportComponent) { + this.name = name; + this.overviewComponent = overviewComponent; + this.reportComponent = reportComponent; + } +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js new file mode 100644 index 000000000..5c849b1c6 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js @@ -0,0 +1,22 @@ +import React from 'react'; + +export function AzurePasswordIssueOverview() { + return (
  • Azure machines expose plaintext passwords. (More info)
  • ) +} + +export function AzurePasswordIssueReport(issue) { + return ( + <> + Delete VM Access plugin configuration files. + + Credentials could be stolen from {issue.machine} for the following users {issue.users}. Read more about the security issue and remediation here. + + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js new file mode 100644 index 000000000..48ffffb59 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js @@ -0,0 +1,84 @@ +import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; +import {generateInfoBadges} from './utils'; + +export function crossSegmentIssueOverview() { + return (
  • Weak segmentation - Machines from + different segments are able to communicate.
  • ) +} + +export function generateCrossSegmentIssue(crossSegmentIssue) { + let crossSegmentIssueOverview = 'Communication possible from ' + + `${crossSegmentIssue['source_subnet']} to ${crossSegmentIssue['target_subnet']}`; + + return ( +
  • + {crossSegmentIssueOverview} + +
      + {crossSegmentIssue['issues'].map( + issue => generateCrossSegmentIssueListItem(issue) + )} +
    +
    +
  • + ); + } + +export function generateCrossSegmentIssueListItem(issue) { + if (issue['is_self']) { + return this.generateCrossSegmentSingleHostMessage(issue); + } + + return this.generateCrossSegmentMultiHostMessage(issue); + } + +export function generateCrossSegmentSingleHostMessage(issue) { + return ( +
  • + {`Machine ${issue['hostname']} has both ips: ${issue['source']} and ${issue['target']}`} +
  • + ); + } + +export function generateCrossSegmentMultiHostMessage(issue) { + return ( +
  • + IP {issue['source']} ({issue['hostname']}) was able to communicate with + IP {issue['target']} using: +
      + {issue['icmp'] &&
    • ICMP
    • } + {this.generateCrossSegmentServiceListItems(issue)} +
    +
  • + ); + } + +export function generateCrossSegmentServiceListItems(issue) { + let service_list_items = []; + + for (const [service, info] of Object.entries(issue['services'])) { + service_list_items.push( +
  • + {service} ({info['display_name']}) +
  • + ); + } + + return service_list_items; + } + +export function generateIslandCrossSegmentIssue(issue) { + return ( + <> + Segment your network and make sure there is no communication between machines from different segments. + + The network can probably be segmented. A monkey instance on {issue.machine} in the + networks {generateInfoBadges(issue.networks)} + could directly access the Monkey Island server in the + networks {generateInfoBadges(issue.server_networks)}. + + + ); + } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js new file mode 100644 index 000000000..eefe69ea3 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js @@ -0,0 +1,23 @@ +import React from 'react'; + +export function DrupalIssueOverview() { + return (
  • Drupal server/s are vulnerable to CVE-2019-6340.
  • ) +} + +export function DrupalIssueReport(issue) { + return ( + <> + Upgrade Drupal server to versions 8.5.11, 8.6.10, or later. + + Drupal server at {issue.machine} ({issue.ip_address}) is vulnerable to remote command execution attack. +
    + The attack was made possible because the server is using an old version of Drupal, for which REST API is + enabled. For possible workarounds, fixes and more info read + here. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js new file mode 100644 index 000000000..60f42fe64 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js @@ -0,0 +1,22 @@ +import React from 'react'; + +export function ElasticIssueOverview() { + return (
  • Elasticsearch servers are vulnerable to CVE-2015-1427. +
  • ) +} + +export function ElasticIssueReport(issue) { + return ( + <> + Update your Elastic Search server to version 1.4.3 and up. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to an Elastic Groovy attack. +
    + The attack was made possible because the Elastic Search server was not patched against CVE-2015-1427. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js new file mode 100644 index 000000000..dfcf55226 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js @@ -0,0 +1,22 @@ +import React from 'react'; + +export function HadoopIssueOverview() { + return (
  • Hadoop/Yarn servers are vulnerable to remote code execution.
  • ) +} + +export function HadoopIssueReport(issue) { + return ( + <> + Run Hadoop in secure mode ( + add Kerberos authentication). + + The Hadoop server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. +
    + The attack was made possible due to default Hadoop/Yarn configuration being insecure. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js new file mode 100644 index 000000000..fb679b420 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js @@ -0,0 +1,23 @@ +import React from 'react'; + +export function MS08_067IssueOverview() { + return (
  • Machines are vulnerable to ‘Conficker’ (MS08-067).
  • ) +} + +export function MS08_067IssueReport(issue) { + return ( + <> + Install the latest Windows updates or upgrade to a newer operating system. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a Conficker attack. +
    + The attack was made possible because the target machine used an outdated and unpatched operating system + vulnerable to Conficker. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js new file mode 100644 index 000000000..2bc4ef14a --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js @@ -0,0 +1,23 @@ +import React from 'react'; + +export function MssqlIssueOverview() { + return (
  • MS-SQL servers are vulnerable to remote code execution via xp_cmdshell command.
  • ) +} + +export function MssqlIssueReport(issue) { + return ( + <> + Disable the xp_cmdshell option. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a MSSQL exploit attack. +
    + The attack was made possible because the target machine used an outdated MSSQL server configuration allowing + the usage of the xp_cmdshell command. To learn more about how to disable this feature, read + Microsoft's documentation. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js new file mode 100644 index 000000000..3a78c3008 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js @@ -0,0 +1,6 @@ +import React from 'react'; + +export function PthCriticalServiceIssueOverview() { + return (
  • Mimikatz found login credentials of a user who has admin access to a server defined as + critical.
  • ) +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js new file mode 100644 index 000000000..cce80d2ed --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js @@ -0,0 +1,27 @@ +import React from 'react'; + +export function SambacryIssueOverview() { + return (
  • Samba servers are vulnerable to ‘SambaCry’ (CVE-2017-7494).
  • ) +} + +export function SambacryIssueReport(issue) { + return ( + <> + Change {issue.username}'s password to a complex one-use password + that is not shared with other computers on the network. +
    + Update your Samba server to 4.4.14 and up, 4.5.10 and up, or 4.6.4 and up. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SambaCry attack. +
    + The Monkey authenticated over the SMB protocol with user {issue.username} and its password, and used the SambaCry + vulnerability. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js new file mode 100644 index 000000000..cd9dd2fbd --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js @@ -0,0 +1,49 @@ +import React from 'react'; + +export function sharedPasswordsIssueOverview() { + return (
  • Multiple users have the same password
  • ) +} + +export function sharedAdminsDomainIssueOverview() { + return (
  • Shared local administrator account - Different machines have the same account as a local + administrator.
  • ) +} + +export function generateSharedCredsDomainIssue(issue) { + return ( + <> + Some domain users are sharing passwords, this should be fixed by changing passwords. + + These users are sharing access password: + {this.generateInfoBadges(issue.shared_with)}. + + + ); + } + +export function generateSharedCredsIssue(issue) { + return ( + <> + Some users are sharing passwords, this should be fixed by changing passwords. + + These users are sharing access password: + {this.generateInfoBadges(issue.shared_with)}. + + + ); + } + +export function generateSharedLocalAdminsIssue(issue) { + return ( + <> + Make sure the right administrator accounts are managing the right machines, and that there isn’t an + unintentional local + admin sharing. + + Here is a list of machines which the account {issue.username} is defined as an administrator: + {this.generateInfoBadges(issue.shared_machines)} + + + ); + } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js new file mode 100644 index 000000000..1d143d221 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js @@ -0,0 +1,29 @@ +import React from 'react'; + +export function ShellShockIssueOverview() { + return (
  • Machines are vulnerable to ‘Shellshock’ (CVE-2014-6271). +
  • ) +} + + +function generateShellshockPathListBadges(paths) { + return paths.map(path => {path}); +} + +export function ShellShockIssueReport(issue) { + return ( + <> + Update your Bash to a ShellShock-patched version. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a ShellShock attack. +
    + The attack was made possible because the HTTP server running on TCP port {issue.port} was vulnerable to a shell injection attack on the + paths: {generateShellshockPathListBadges(issue.paths)}. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js new file mode 100644 index 000000000..eec516a3e --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js @@ -0,0 +1,36 @@ +import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; + +export function generateSmbPasswordReport(issue) { + return ( + <> + Change {issue.username}'s password to a complex one-use password + that is not shared with other computers on the network. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SMB attack. +
    + The Monkey authenticated over the SMB protocol with user {issue.username} and its password. +
    + + ); +} + +export function generateSmbPthReport(issue) { + return ( + <> + Change {issue.username}'s password to a complex one-use password + that is not shared with other computers on the network. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SMB attack. +
    + The Monkey used a pass-the-hash attack over SMB protocol with user {issue.username}. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js new file mode 100644 index 000000000..baf92bfb7 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js @@ -0,0 +1,38 @@ +import React from 'react'; + +export function SshIssueOverview() { + return (
  • Stolen SSH keys are used to exploit other machines.
  • ) +} + +export function ShhIssueReport(issue) { + return ( + <> + Change {issue.username}'s password to a complex one-use password + that is not shared with other computers on the network. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SSH attack. +
    + The Monkey authenticated over the SSH protocol with user {issue.username} and its password. +
    + + ); +} + +export function generateSshKeysReport(issue) { + return ( + <> + Protect {issue.ssh_key} private key with a pass phrase. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SSH attack. +
    + The Monkey authenticated over the SSH protocol with private key {issue.ssh_key}. +
    + + ); + } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js new file mode 100644 index 000000000..62d92ccc3 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js @@ -0,0 +1,5 @@ +import React from 'react'; + +export function StolenCredsIssueOverview() { + return (
  • Stolen credentials are used to exploit other machines.
  • ) +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js new file mode 100644 index 000000000..218a8704d --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js @@ -0,0 +1,15 @@ +import React from 'react'; + +export function generateStrongUsersOnCritIssue(issue) { + return ( + <> + This critical machine is open to attacks via strong users with access to it. + + The services: {this.generateInfoBadges(issue.services)} have been found on the machine + thus classifying it as a critical machine. + These users has access to it: + {this.generateInfoBadges(issue.threatening_users)}. + + + ); + } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js new file mode 100644 index 000000000..7847f447e --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js @@ -0,0 +1,25 @@ +import React from 'react'; + +export function Struts2IssueOverview() { + return (
  • Struts2 servers are vulnerable to remote code execution. ( + CVE-2017-5638)
  • ) +} + +export function Struts2IssueReport(issue) { + return ( + <> + Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions. + + Struts2 server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. +
    + The attack was made possible because the server is using an old version of Jakarta based file upload + Multipart parser. For possible work-arounds and more info read here. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js new file mode 100644 index 000000000..6d0accd56 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js @@ -0,0 +1,18 @@ +import React from 'react'; + +export function generateTunnelIssueOverview(){ + return (
  • Weak segmentation - Machines were able to communicate over unused ports.
  • ) +} + +export function generateTunnelIssue(issue) { + return ( + <> + Use micro-segmentation policies to disable communication other than the required. + + Machines are not locked down at port level. Network tunnel was set up from {issue.machine} to {issue.dest}. + + + ); + } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js new file mode 100644 index 000000000..0dae286e1 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js @@ -0,0 +1,35 @@ +import React from 'react'; + +export function VsftpdIssueOverview() { + return (
  • VSFTPD is vulnerable to CVE-2011-2523. +
  • ) +} + +export function VsftpdIssueReport(issue) { + return ( + <> + Update your VSFTPD server to the latest version vsftpd-3.0.3. + + The machine {issue.machine} ({issue.ip_address}) has a backdoor running at + port 6200. +
    + The attack was made possible because the VSFTPD server was not patched against CVE-2011-2523. +

    In July 2011, it was discovered that vsftpd version 2.3.4 downloadable from the master site had been + compromised. + Users logging into a compromised vsftpd-2.3.4 server may issue a ":)" smileyface as the username and gain a + command + shell on port 6200. +

    + The Monkey executed commands by first logging in with ":)" in the username and then sending commands to the + backdoor + at port 6200. +

    Read more about the security issue and remediation here. +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js new file mode 100644 index 000000000..0a7ba30b1 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js @@ -0,0 +1,6 @@ +import React from 'react'; + +export function WeakPasswordIssueOverview() { + return (
  • Machines are accessible using passwords supplied by the user during the Monkey’s + configuration.
  • ) +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js new file mode 100644 index 000000000..88d0112fa --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js @@ -0,0 +1,22 @@ +import React from 'react'; + +export function WebLogicIssueOverview() { + return (
  • Oracle WebLogic servers are susceptible to a remote code execution vulnerability.
  • ) +} + +export function WebLogicIssueReport(issue) { + return ( + <> + Update Oracle WebLogic server to the latest supported version. + + Oracle WebLogic server at {issue.machine} ({issue.ip_address}) is vulnerable to one of remote code execution attacks. +
    + The attack was made possible due to one of the following vulnerabilities: + CVE-2017-10271 or + CVE-2019-2725 +
    + + ); +} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js new file mode 100644 index 000000000..401f8a9d9 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js @@ -0,0 +1,36 @@ +import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; + +export function generateWmiPasswordIssue(issue) { + return ( + <> + Change {issue.username}'s password to a complex one-use password + that is not shared with other computers on the network. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a WMI attack. +
    + The Monkey authenticated over the WMI protocol with user {issue.username} and its password. +
    + + ); + } + +export function generateWmiPthIssue(issue) { + return ( + <> + Change {issue.username}'s password to a complex one-use password + that is not shared with other computers on the network. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a WMI attack. +
    + The Monkey used a pass-the-hash attack over WMI protocol with user {issue.username}. +
    + + ); + } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/utils.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/utils.js new file mode 100644 index 000000000..6bc891201 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/utils.js @@ -0,0 +1,6 @@ +import React from 'react'; + +export function generateInfoBadges(data_array) { + return data_array.map(badge_data => {badge_data}); + } From abb7ab09a96ec70220ead3f3d6be8e48eadae59f Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 25 Mar 2021 14:11:56 +0200 Subject: [PATCH 02/17] Rebased changes to include what was done in release/1.10.0 --- .../exploiter_descriptor_enum.py | 9 ++--- .../processors/cred_exploit.py | 6 ++-- .../processors/shellshock_exploit.py | 6 ++-- .../reporting/issue_processing/issue.py | 0 .../issue_processing/issue_processor.py | 0 .../cc/services/reporting/report.py | 35 +++++++++++++++++-- 6 files changed, 43 insertions(+), 13 deletions(-) delete mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/issue.py delete mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/issue_processor.py diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py index e6820b178..8628136d8 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py @@ -2,9 +2,10 @@ from dataclasses import dataclass from enum import Enum from typing import Type -from monkey_island.cc.services.reporting.issue_processing.exploit_processing import CredExploitProcessor -from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploitProcessor -from monkey_island.cc.services.reporting.issue_processing.exploit_processing import \ +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.cred_exploit import \ + CredExploitProcessor +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ExploitProcessor +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.shellshock_exploit import \ ShellShockExploitProcessor @@ -13,7 +14,7 @@ class ExploiterDescriptor: # Must match with class names of exploiters in Infection Monkey code class_name: str display_name: str - processor: Type[ExploitProcessor] + processor: Type[object] = ExploitProcessor class ExploiterDescriptorEnum(Enum): diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py index fc61676b8..720655b52 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py @@ -2,8 +2,8 @@ from __future__ import annotations from enum import Enum -from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploitProcessor, \ - ExploiterReportInfo +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import \ + ExploiterReportInfo, ExploitProcessor class CredentialType(Enum): @@ -12,7 +12,7 @@ class CredentialType(Enum): KEY = 'key' -class CredExploitProcessor(ExploitProcessor): +class CredExploitProcessor: @staticmethod def get_exploit_info_by_dict(class_name: str, exploit_dict: dict) -> ExploiterReportInfo: diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py index 181a19f41..f8d36d4d8 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py @@ -1,10 +1,10 @@ from __future__ import annotations -from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploitProcessor, \ - ExploiterReportInfo +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import \ + ExploiterReportInfo, ExploitProcessor -class ShellShockExploitProcessor(ExploitProcessor): +class ShellShockExploitProcessor: @staticmethod def get_exploit_info_by_dict(class_name: str, exploit_dict: dict) -> ExploiterReportInfo: diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/issue.py b/monkey/monkey_island/cc/services/reporting/issue_processing/issue.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/issue_processor.py b/monkey/monkey_island/cc/services/reporting/issue_processing/issue_processor.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 30f096fb7..181b8616b 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -19,8 +19,10 @@ from monkey_island.cc.services.configuration.utils import get_config_network_seg from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_descriptor_enum import ExploiterDescriptorEnum, \ ExploiterDescriptor -from monkey_island.cc.services.reporting.issue_processing.exploit_processing import CredentialType -from monkey_island.cc.services.reporting.issue_processing.exploit_processing import ExploiterReportInfo +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.cred_exploit import \ + CredentialType +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import \ + ExploiterReportInfo from monkey_island.cc.services.reporting.pth_report import PTHReportService from monkey_island.cc.services.reporting.report_exporter_manager import ReportExporterManager from monkey_island.cc.services.reporting.report_generation_synchronisation import safe_generate_regular_report @@ -544,6 +546,7 @@ class ReportService: issues = ReportService.get_issues() config_users = ReportService.get_config_users() config_passwords = ReportService.get_config_passwords() + issue_set = ReportService.get_issue_set(issues, config_users, config_passwords) cross_segment_issues = ReportService.get_cross_segment_issues() monkey_latest_modify_time = Monkey.get_latest_modifytime() @@ -561,7 +564,7 @@ class ReportService: 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), - 'issues': ReportService.get_issue_set(issues, config_users, config_passwords), + 'issues': issue_set, 'cross_segment_issues': cross_segment_issues }, 'glance': @@ -589,6 +592,32 @@ class ReportService: return report + @staticmethod + def get_issues(): + ISSUE_GENERATORS = [ + ReportService.get_exploits, + ReportService.get_tunnels, + ReportService.get_island_cross_segment_issues, + ReportService.get_azure_issues, + PTHReportService.get_duplicated_passwords_issues, + PTHReportService.get_strong_users_on_crit_issues + ] + + issues = functools.reduce(lambda acc, issue_gen: acc + issue_gen(), ISSUE_GENERATORS, []) + + issues_dict = {} + for issue in issues: + if issue.get('is_local', True): + machine = issue.get('machine').upper() + aws_instance_id = ReportService.get_machine_aws_instance_id(issue.get('machine')) + if machine not in issues_dict: + issues_dict[machine] = [] + if aws_instance_id: + issue['aws_instance_id'] = aws_instance_id + issues_dict[machine].append(issue) + logger.info('Issues generated for reporting') + return issues_dict + @staticmethod def encode_dot_char_before_mongo_insert(report_dict): """ From 280df4e67643f68848b4d88cd281f538022048b7 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Mon, 29 Mar 2021 17:41:23 +0300 Subject: [PATCH 03/17] Fixed a bug in report backend --- monkey/monkey_island/cc/services/reporting/report.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 181b8616b..42adfd5a2 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -264,7 +264,7 @@ class ReportService: return exploiter_info @staticmethod - def get_exploits(): + def get_exploits() -> dict: query = [{'$match': {'telem_category': 'exploit', 'data.result': True}}, {'$group': {'_id': {'ip_address': '$data.machine.ip_addr'}, 'data': {'$first': '$$ROOT'}, @@ -274,7 +274,7 @@ class ReportService: for exploit in mongo.db.telemetry.aggregate(query): new_exploit = ReportService.process_exploit(exploit) if new_exploit not in exploits: - exploits.append(new_exploit) + exploits.append(new_exploit.__dict__) return exploits @staticmethod @@ -594,6 +594,7 @@ class ReportService: @staticmethod def get_issues(): + # Todo refactor these into separate files with a method signature -> dict ISSUE_GENERATORS = [ ReportService.get_exploits, ReportService.get_tunnels, From d2fdabe26b5215f51f5e89709222355bea0ddf3e Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 30 Mar 2021 13:00:18 +0300 Subject: [PATCH 04/17] Added missing issue descriptors --- .../report-components/SecurityReport.js | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index bd5ae3a30..7ac1beab8 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -12,8 +12,6 @@ import ReportHeader, {ReportTypes} from './common/ReportHeader'; import ReportLoader from './common/ReportLoader'; import SecurityIssuesGlance from './common/SecurityIssuesGlance'; import PrintReportButton from './common/PrintReportButton'; -import WarningIcon from '../ui-components/WarningIcon'; -import {Button} from 'react-bootstrap'; import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import {faMinus} from '@fortawesome/free-solid-svg-icons/faMinus'; @@ -35,10 +33,19 @@ import {ShellShockIssueOverview, ShellShockIssueReport} from './security/issues/ import {MS08_067IssueOverview, MS08_067IssueReport} from './security/issues/MS08_067Issue'; import { crossSegmentIssueOverview, - generateCrossSegmentIssue + generateCrossSegmentIssue, + generateIslandCrossSegmentIssue } from './security/issues/CrossSegmentIssue'; -import {sharedAdminsDomainIssueOverview, sharedPasswordsIssueOverview} from './security/issues/SharedPasswordsIssue'; +import { + generateSharedCredsDomainIssue, generateSharedCredsIssue, generateSharedLocalAdminsIssue, + sharedAdminsDomainIssueOverview, + sharedPasswordsIssueOverview +} from './security/issues/SharedPasswordsIssue'; import {generateTunnelIssue, generateTunnelIssueOverview} from './security/issues/TunnelIssue'; +import {StolenCredsIssueOverview} from './security/issues/StolenCredsIssue'; +import {WeakPasswordIssueOverview} from './security/issues/WeakPasswordIssue'; +import {AzurePasswordIssueOverview, AzurePasswordIssueReport} from './security/issues/AzurePasswordIssue'; +import {generateStrongUsersOnCritIssue} from './security/issues/StrongUsersOnCritIssue'; class ReportPageComponent extends AuthComponent { @@ -131,9 +138,12 @@ class ReportPageComponent extends AuthComponent { [this.issueContentTypes.REPORT]: MS08_067IssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, + 'ZerologonExploiter': { + //TODO add + }, 'island_cross_segment': { [this.issueContentTypes.OVERVIEW]: crossSegmentIssueOverview, - [this.issueContentTypes.REPORT]: generateCrossSegmentIssue, + [this.issueContentTypes.REPORT]: generateIslandCrossSegmentIssue, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'tunnel': { @@ -143,17 +153,37 @@ class ReportPageComponent extends AuthComponent { }, 'shared_passwords': { [this.issueContentTypes.OVERVIEW]: sharedPasswordsIssueOverview, + [this.issueContentTypes.REPORT]: generateSharedCredsIssue, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'shared_admins_domain': { [this.issueContentTypes.OVERVIEW]: sharedAdminsDomainIssueOverview, + [this.issueContentTypes.REPORT]: generateSharedLocalAdminsIssue, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, - 'shared_passwords_domain': {}, - 'strong_users_on_crit': {}, - 'azure_password': {}, - 'weak_password': {}, - 'stolen_creds': {} + 'shared_passwords_domain': { + [this.issueContentTypes.REPORT]: generateSharedCredsDomainIssue(), + [this.issueContentTypes.TYPE]: this.issueTypes.WARNING + }, + + // This issue was missing overview section + 'strong_users_on_crit': { + [this.issueContentTypes.REPORT]: generateStrongUsersOnCritIssue, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'azure_password': { + [this.issueContentTypes.OVERVIEW]: AzurePasswordIssueOverview, + [this.issueContentTypes.REPORT]: AzurePasswordIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'weak_password': { + [this.issueContentTypes.OVERVIEW]: WeakPasswordIssueOverview, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'stolen_creds': { + [this.issueContentTypes.OVERVIEW]: StolenCredsIssueOverview, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + } } constructor(props) { @@ -191,8 +221,6 @@ class ReportPageComponent extends AuthComponent { render() { let content; - console.log(this.state.report); - if (this.stillLoadingDataFromServer()) { content = ; } else { @@ -341,7 +369,6 @@ class ReportPageComponent extends AuthComponent { generateReportFindingsSection() { let overviews = this.getPotentialSecurityIssuesOverviews() - return (

    @@ -385,18 +412,17 @@ class ReportPageComponent extends AuthComponent { ); } - getPotentialSecurityIssuesOverviews(){ + getPotentialSecurityIssuesOverviews() { let overviews = []; - for( let key of this.IssueDescriptorEnum) { - if(this.WARNING_ISSUE_LIST[i] in this.state.report.issues) { - overviews.push(this.IssueDescriptorEnum[this.WARNING_ISSUE_LIST[i]][this.issueContentTypes.OVERVIEW]) - } + for (let issueKey of this.state.report.overview.issues) { + overviews.push(this.IssueDescriptorEnum[issueKey][this.issueContentTypes.OVERVIEW]); } return overviews; } getImmediateThreats() { + let threatCount = this.countImmediateThreats() return (

    From 2b3351baec52786d9850dbf89ea1525145737774 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 30 Mar 2021 13:00:47 +0300 Subject: [PATCH 05/17] Created immediate threat counter --- .../report-components/SecurityReport.js | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index 7ac1beab8..4296e773c 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -224,6 +224,8 @@ class ReportPageComponent extends AuthComponent { if (this.stillLoadingDataFromServer()) { content = ; } else { + + console.log(this.state.report); content =
    {this.generateReportOverviewSection()} @@ -430,23 +432,29 @@ class ReportPageComponent extends AuthComponent {

    During this simulated attack the Monkey uncovered { - this.state.report.overview.issues.length > 0 ? - <> - - {this.state.report.overview.issues.length} threats: - - - : - <> - 0 threats. - + <> + + {threatCount} threats + : + }
    ) } + countImmediateThreats() { + let threatCount = 0; + let issues = this.state.report.overview.issues; + + for(let i=0; i < issues.length; i++) { + if (this.IssueDescriptorEnum[issues[i]][this.issueContentTypes.TYPE] === this.issueTypes.DANGER) { + threatCount++; + } + } + return threatCount; + } + + generateReportRecommendationsSection() { return (
    @@ -543,8 +551,9 @@ class ReportPageComponent extends AuthComponent { generateIssue = (issue) => { let issueDescriptor = this.IssueDescriptorEnum[issue.type]; - let reportFnc = (issue) => {}; - if(issue.hasOwnProperty('credential_type')) { + let reportFnc = (issue) => { + }; + if (issue.hasOwnProperty('credential_type')) { reportFnc = issueDescriptor[this.issueContentTypes.REPORT][issue.credential_type]; } else { reportFnc = issueDescriptor[this.issueContentTypes.REPORT]; From c504b21d3399cccd4705a74f4fa2c13a8bb6ab9b Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 31 Mar 2021 11:50:53 +0300 Subject: [PATCH 06/17] Fixed trivial bugs like missing imports in issue UI files --- .../security/issues/AzurePasswordIssue.js | 1 + .../security/issues/CrossSegmentIssue.js | 4 +- .../security/issues/DrupalIssue.js | 1 + .../security/issues/ElasticIssue.js | 1 + .../security/issues/HadoopIssue.js | 1 + .../security/issues/MS08_067Issue.js | 1 + .../security/issues/MssqlIssue.js | 1 + .../security/issues/SambacryIssue.js | 1 + .../security/issues/SharedPasswordsIssue.js | 8 ++- .../security/issues/ShellShockIssue.js | 1 + .../security/issues/SshIssue.js | 1 + .../security/issues/StrongUsersOnCritIssue.js | 1 + .../security/issues/Struts2Issue.js | 1 + .../security/issues/TunnelIssue.js | 1 + .../security/issues/VsftpdIssue.js | 1 + .../security/issues/WebLogicIssue.js | 1 + .../security/issues/ZerologonIssue.js | 64 +++++++++++++++++++ 17 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js index 5c849b1c6..f572347dc 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js @@ -1,4 +1,5 @@ import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; export function AzurePasswordIssueOverview() { return (
  • Azure machines expose plaintext passwords. (Drupal server/s are vulnerable to Elasticsearch servers are vulnerable to Hadoop/Yarn servers are vulnerable to remote code execution.
  • ) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js index fb679b420..b16ab7e66 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MS08_067Issue.js @@ -1,4 +1,5 @@ import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; export function MS08_067IssueOverview() { return (
  • Machines are vulnerable to ‘Conficker’ (MS-SQL servers are vulnerable to remote code execution via xp_cmdshell command.
  • ) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js index cce80d2ed..c07fcce7f 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js @@ -1,4 +1,5 @@ import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; export function SambacryIssueOverview() { return (
  • Samba servers are vulnerable to ‘SambaCry’ (Multiple users have the same password
  • ) @@ -15,7 +17,7 @@ export function generateSharedCredsDomainIssue(issue) { Some domain users are sharing passwords, this should be fixed by changing passwords. These users are sharing access password: - {this.generateInfoBadges(issue.shared_with)}. + {generateInfoBadges(issue.shared_with)}. ); @@ -27,7 +29,7 @@ export function generateSharedCredsIssue(issue) { Some users are sharing passwords, this should be fixed by changing passwords. These users are sharing access password: - {this.generateInfoBadges(issue.shared_with)}. + {generateInfoBadges(issue.shared_with)}. ); @@ -42,7 +44,7 @@ export function generateSharedLocalAdminsIssue(issue) { Here is a list of machines which the account {issue.username} is defined as an administrator: - {this.generateInfoBadges(issue.shared_machines)} + {generateInfoBadges(issue.shared_machines)} ); diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js index 1d143d221..02daa292c 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js @@ -1,4 +1,5 @@ import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; export function ShellShockIssueOverview() { return (
  • Machines are vulnerable to ‘Shellshock’ (Stolen SSH keys are used to exploit other machines.
  • ) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js index 218a8704d..7f87e72c1 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js @@ -1,4 +1,5 @@ import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; export function generateStrongUsersOnCritIssue(issue) { return ( diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js index 7847f447e..7a590ba3c 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js @@ -1,4 +1,5 @@ import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; export function Struts2IssueOverview() { return (
  • Struts2 servers are vulnerable to remote code execution. (Weak segmentation - Machines were able to communicate over unused ports.
  • ) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js index 0dae286e1..214c1896b 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js @@ -1,4 +1,5 @@ import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; export function VsftpdIssueOverview() { return (
  • VSFTPD is vulnerable to Oracle WebLogic servers are susceptible to a remote code execution vulnerability.
  • ) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js new file mode 100644 index 000000000..f125d67ec --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js @@ -0,0 +1,64 @@ +import React from 'react'; +import CollapsibleWellComponent from '../CollapsibleWell'; +import WarningIcon from '../../../ui-components/WarningIcon'; +import {Button} from 'react-bootstrap'; + +export function ZerologonIssueOverview() { + return ( +
  • + Some Windows domain controllers are vulnerable to 'Zerologon' ( + ). +
  • + ) +} + +export function ZerologonOverviewWithFailedPassResetWarning() { + let overview = [ZerologonIssueOverview()]; + overview.push( +
  • + + + Automatic password restoration on a domain controller failed! + + +
  • + ) + return overview; +} + +export function ZerologonIssueReport(issue) { + return ( + <> + Install Windows security updates. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a Zerologon exploit. +
    + The attack was possible because the latest security updates from Microsoft + have not been applied to this machine. For more information about this + vulnerability, read
    + Microsoft's documentation. + {!issue.password_restored ? +
    +
    + + The domain controller's password was changed during the exploit and could not be restored successfully. + Instructions on how to manually reset the domain controller's password can be found here. + +
    : null} + + + ); +} From e96b8eec383c8cc8564f3c2cd6beb646628712a8 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 31 Mar 2021 11:53:50 +0300 Subject: [PATCH 07/17] Refactored zerologon exploiters report part to conform to new report structure --- .../exploiter_descriptor_enum.py | 3 ++ .../processors/zerologon.py | 11 ++++++ .../cc/services/reporting/report.py | 18 +++++---- .../report-components/SecurityReport.js | 37 ++++++++++++------- 4 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/zerologon.py diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py index 8628136d8..eff1f7758 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py @@ -7,6 +7,8 @@ from monkey_island.cc.services.reporting.issue_processing.exploit_processing.pro from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ExploitProcessor from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.shellshock_exploit import \ ShellShockExploitProcessor +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.zerologon import \ + ZerologonExploitProcessor @dataclass @@ -31,3 +33,4 @@ class ExploiterDescriptorEnum(Enum): MSSQL = ExploiterDescriptor('MSSQLExploiter', 'MSSQL Exploiter', ExploitProcessor) VSFTPD = ExploiterDescriptor('VSFTPDExploiter', 'VSFTPD Backdoor Exploiter', CredExploitProcessor) DRUPAL = ExploiterDescriptor('DrupalExploiter', 'Drupal Server Exploiter', ExploitProcessor) + ZEROLOGON = ExploiterDescriptor('ZerologonExploiter', 'ZeroLogon Exploiter', ZerologonExploitProcessor) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/zerologon.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/zerologon.py new file mode 100644 index 000000000..e0be6cd42 --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/zerologon.py @@ -0,0 +1,11 @@ +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ExploitProcessor, \ + ExploiterReportInfo + + +class ZerologonExploitProcessor: + + @staticmethod + def get_exploit_info_by_dict(class_name: str, exploit_dict: dict) -> ExploiterReportInfo: + exploit_info = ExploitProcessor.get_exploit_info_by_dict(class_name, exploit_dict) + exploit_info.password_restored = exploit_dict['data']['info']['password_restored'] + return exploit_info diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 42adfd5a2..a4642c694 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -45,6 +45,7 @@ class ReportService: class DerivedIssueEnum: WEAK_PASSWORD = "weak_password" STOLEN_CREDS = "stolen_creds" + ZEROLOGON_PASS_RESTORE_FAILED = "zerologon_pass_restore_failed" @staticmethod def get_first_monkey_time(): @@ -264,7 +265,7 @@ class ReportService: return exploiter_info @staticmethod - def get_exploits() -> dict: + def get_exploits() -> List[dict]: query = [{'$match': {'telem_category': 'exploit', 'data.result': True}}, {'$group': {'_id': {'ip_address': '$data.machine.ip_addr'}, 'data': {'$first': '$$ROOT'}, @@ -439,7 +440,6 @@ class ReportService: @staticmethod def get_domain_issues(): - ISSUE_GENERATORS = [ PTHReportService.get_duplicated_passwords_issues, PTHReportService.get_shared_admins_issues, @@ -491,8 +491,7 @@ class ReportService: if exploits == default_exploits: return ['default'] - # TODO investigate strange code - return [exploit for exploit in exploits] + return exploits @staticmethod def get_config_ips(): @@ -508,13 +507,12 @@ class ReportService: for machine in issues: for issue in issues[machine]: - # TODO check if this actually works, because stolen passwords get added to config - # so any password will be in config. We need to separate stolen passwords from initial - # passwords in config. if ReportService._is_weak_credential_issue(issue, config_users, config_passwords): issue_set.add(ReportService.DerivedIssueEnum.WEAK_PASSWORD) elif ReportService._is_stolen_credential_issue(issue): issue_set.add(ReportService.DerivedIssueEnum.STOLEN_CREDS) + elif ReportService._is_zerologon_pass_restore_failed(issue): + issue_set.add(ReportService.DerivedIssueEnum.ZEROLOGON_PASS_RESTORE_FAILED) issue_set.add(issue['type']) @@ -535,6 +533,11 @@ class ReportService: (issue['credential_type'] == CredentialType.PASSWORD.value or issue['credential_type'] == CredentialType.HASH.value) + @staticmethod + def _is_zerologon_pass_restore_failed(issue: dict): + return issue['type'] == ExploiterDescriptorEnum.ZEROLOGON.value.class_name \ + and not issue['password_restored'] + @staticmethod def is_report_generated(): generated_report = mongo.db.report.find_one({}) @@ -594,7 +597,6 @@ class ReportService: @staticmethod def get_issues(): - # Todo refactor these into separate files with a method signature -> dict ISSUE_GENERATORS = [ ReportService.get_exploits, ReportService.get_tunnels, diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index 4296e773c..cdd23aa8a 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -46,6 +46,11 @@ import {StolenCredsIssueOverview} from './security/issues/StolenCredsIssue'; import {WeakPasswordIssueOverview} from './security/issues/WeakPasswordIssue'; import {AzurePasswordIssueOverview, AzurePasswordIssueReport} from './security/issues/AzurePasswordIssue'; import {generateStrongUsersOnCritIssue} from './security/issues/StrongUsersOnCritIssue'; +import { + ZerologonIssueOverview, + ZerologonIssueReport, + ZerologonOverviewWithFailedPassResetWarning +} from './security/issues/ZerologonIssue'; class ReportPageComponent extends AuthComponent { @@ -139,7 +144,12 @@ class ReportPageComponent extends AuthComponent { [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'ZerologonExploiter': { - //TODO add + [this.issueContentTypes.OVERVIEW]: ZerologonIssueOverview, + [this.issueContentTypes.REPORT]: ZerologonIssueReport, + [this.issueContentTypes.TYPE]: this.issueTypes.DANGER + }, + 'zerologon_pass_restore_failed': { + [this.issueContentTypes.OVERVIEW]: ZerologonOverviewWithFailedPassResetWarning, }, 'island_cross_segment': { [this.issueContentTypes.OVERVIEW]: crossSegmentIssueOverview, @@ -162,11 +172,9 @@ class ReportPageComponent extends AuthComponent { [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'shared_passwords_domain': { - [this.issueContentTypes.REPORT]: generateSharedCredsDomainIssue(), + [this.issueContentTypes.REPORT]: generateSharedCredsDomainIssue, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, - - // This issue was missing overview section 'strong_users_on_crit': { [this.issueContentTypes.REPORT]: generateStrongUsersOnCritIssue, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER @@ -224,8 +232,6 @@ class ReportPageComponent extends AuthComponent { if (this.stillLoadingDataFromServer()) { content = ; } else { - - console.log(this.state.report); content =
    {this.generateReportOverviewSection()} @@ -386,7 +392,7 @@ class ReportPageComponent extends AuthComponent {
    The Monkey uncovered the following possible set of issues:
      - {overviews} + {this.getPotentialSecurityIssuesOverviews()}
    : @@ -416,15 +422,18 @@ class ReportPageComponent extends AuthComponent { getPotentialSecurityIssuesOverviews() { let overviews = []; + let issues = this.state.report.overview.issues; - for (let issueKey of this.state.report.overview.issues) { - overviews.push(this.IssueDescriptorEnum[issueKey][this.issueContentTypes.OVERVIEW]); + for(let i=0; i < issues.length; i++) { + if (this.isIssuePotentialSecurityIssue(issues[i])) { + overviews.push(this.getIssueOverview(this.IssueDescriptorEnum[issues[i]])); + } } return overviews; } getImmediateThreats() { - let threatCount = this.countImmediateThreats() + let threatCount = this.getImmediateThreatCount() return (

    @@ -436,18 +445,19 @@ class ReportPageComponent extends AuthComponent { {threatCount} threats : + {this.getImmediateThreatsOverviews()} }

    ) } - countImmediateThreats() { + getImmediateThreatCount() { let threatCount = 0; let issues = this.state.report.overview.issues; for(let i=0; i < issues.length; i++) { - if (this.IssueDescriptorEnum[issues[i]][this.issueContentTypes.TYPE] === this.issueTypes.DANGER) { + if(this.isIssueImmediateThreat(issues[i])) { threatCount++; } } @@ -551,8 +561,7 @@ class ReportPageComponent extends AuthComponent { generateIssue = (issue) => { let issueDescriptor = this.IssueDescriptorEnum[issue.type]; - let reportFnc = (issue) => { - }; + let reportFnc = (issue) => {}; if (issue.hasOwnProperty('credential_type')) { reportFnc = issueDescriptor[this.issueContentTypes.REPORT][issue.credential_type]; } else { From 05fda70cd6290a82075d6aba28ddc6b19e7a7f1d Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 31 Mar 2021 11:54:20 +0300 Subject: [PATCH 08/17] Fixed SSH exploiter's report section in UI --- .../ui/src/components/report-components/SecurityReport.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index cdd23aa8a..815be49a6 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -26,7 +26,7 @@ import {MssqlIssueOverview, MssqlIssueReport} from './security/issues/MssqlIssue import {DrupalIssueOverview, DrupalIssueReport} from './security/issues/DrupalIssue'; import {VsftpdIssueOverview, VsftpdIssueReport} from './security/issues/VsftpdIssue'; import {generateWmiPasswordIssue, generateWmiPthIssue} from './security/issues/WmiIssue'; -import {ShhIssueReport, SshIssueOverview} from './security/issues/SshIssue'; +import {generateSshKeysReport, ShhIssueReport, SshIssueOverview} from './security/issues/SshIssue'; import {SambacryIssueOverview, SambacryIssueReport} from './security/issues/SambacryIssue'; import {ElasticIssueOverview, ElasticIssueReport} from './security/issues/ElasticIssue'; import {ShellShockIssueOverview, ShellShockIssueReport} from './security/issues/ShellShockIssue'; @@ -120,7 +120,10 @@ class ReportPageComponent extends AuthComponent { }, 'SSHExploiter': { [this.issueContentTypes.OVERVIEW]: SshIssueOverview, - [this.issueContentTypes.REPORT]: ShhIssueReport, + [this.issueContentTypes.REPORT]: { + [this.credentialTypes.PASSWORD]: ShhIssueReport, + [this.credentialTypes.KEY]: generateSshKeysReport + }, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'SambaCryExploiter': { From a284467a1a98e3353fac7757e6c97b2588ab28ea Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 31 Mar 2021 11:55:22 +0300 Subject: [PATCH 09/17] Improved UI by creating distinct functions related to immediate threats report component --- .../report-components/SecurityReport.js | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index 815be49a6..9ac409e8e 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -435,6 +435,13 @@ class ReportPageComponent extends AuthComponent { return overviews; } + isIssuePotentialSecurityIssue(issueName) { + let issueDescriptor = this.IssueDescriptorEnum[issueName]; + return issueDescriptor.hasOwnProperty(this.issueContentTypes.TYPE) && + issueDescriptor[this.issueContentTypes.TYPE] === this.issueTypes.WARNING && + issueDescriptor.hasOwnProperty(this.issueContentTypes.OVERVIEW); + } + getImmediateThreats() { let threatCount = this.getImmediateThreatCount() return ( @@ -467,6 +474,32 @@ class ReportPageComponent extends AuthComponent { return threatCount; } + isIssueImmediateThreat(issueName) { + let issueDescriptor = this.IssueDescriptorEnum[issueName]; + return issueDescriptor.hasOwnProperty(this.issueContentTypes.TYPE) && + issueDescriptor[this.issueContentTypes.TYPE] === this.issueTypes.DANGER && + issueDescriptor.hasOwnProperty(this.issueContentTypes.OVERVIEW); + } + + getImmediateThreatsOverviews() { + let overviews = []; + let issues = this.state.report.overview.issues; + + for(let i=0; i < issues.length; i++) { + if (this.isIssueImmediateThreat(issues[i])) { + if (issues[i] === 'ZerologonExploiter' && issues.includes('zerologon_pass_restore_failed')){ + overviews.push(this.getIssueOverview(this.IssueDescriptorEnum['zerologon_pass_restore_failed'])); + } else { + overviews.push(this.getIssueOverview(this.IssueDescriptorEnum[issues[i]])); + } + } + } + return overviews; + } + + getIssueOverview(issueDescriptor) { + return issueDescriptor[this.issueContentTypes.OVERVIEW](); + } generateReportRecommendationsSection() { return ( From 54f1d0e49c5c8e97b8652b5b3ce1de8e1c6ff16c Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 31 Mar 2021 13:07:19 +0300 Subject: [PATCH 10/17] Made naming of issue methods in UI more consistent --- .../report-components/SecurityReport.js | 132 +++++++++--------- .../security/issues/AzurePasswordIssue.js | 4 +- .../security/issues/CrossSegmentIssue.js | 20 +-- .../security/issues/DrupalIssue.js | 4 +- .../security/issues/ElasticIssue.js | 4 +- .../security/issues/HadoopIssue.js | 4 +- .../security/issues/MS08_067Issue.js | 4 +- .../security/issues/MssqlIssue.js | 4 +- .../issues/PthCriticalServiceIssue.js | 2 +- .../security/issues/SambacryIssue.js | 4 +- .../security/issues/SharedPasswordsIssue.js | 6 +- .../security/issues/ShellShockIssue.js | 8 +- .../security/issues/SmbIssue.js | 4 +- .../security/issues/SshIssue.js | 6 +- .../security/issues/StolenCredsIssue.js | 2 +- .../security/issues/StrongUsersOnCritIssue.js | 2 +- .../security/issues/Struts2Issue.js | 4 +- .../security/issues/TunnelIssue.js | 4 +- .../security/issues/VsftpdIssue.js | 4 +- .../security/issues/WeakPasswordIssue.js | 2 +- .../security/issues/WebLogicIssue.js | 4 +- .../security/issues/WmiIssue.js | 4 +- .../security/issues/ZerologonIssue.js | 8 +- 23 files changed, 120 insertions(+), 120 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index 9ac409e8e..364e77b77 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -18,38 +18,38 @@ import {faMinus} from '@fortawesome/free-solid-svg-icons/faMinus'; import guardicoreLogoImage from '../../images/guardicore-logo.png' import {faExclamationTriangle} from '@fortawesome/free-solid-svg-icons'; import '../../styles/App.css'; -import {generateSmbPasswordReport, generateSmbPthReport} from './security/issues/SmbIssue'; -import {Struts2IssueOverview, Struts2IssueReport} from './security/issues/Struts2Issue'; -import {WebLogicIssueOverview, WebLogicIssueReport} from './security/issues/WebLogicIssue'; -import {HadoopIssueOverview, HadoopIssueReport} from './security/issues/HadoopIssue'; -import {MssqlIssueOverview, MssqlIssueReport} from './security/issues/MssqlIssue'; -import {DrupalIssueOverview, DrupalIssueReport} from './security/issues/DrupalIssue'; -import {VsftpdIssueOverview, VsftpdIssueReport} from './security/issues/VsftpdIssue'; -import {generateWmiPasswordIssue, generateWmiPthIssue} from './security/issues/WmiIssue'; -import {generateSshKeysReport, ShhIssueReport, SshIssueOverview} from './security/issues/SshIssue'; -import {SambacryIssueOverview, SambacryIssueReport} from './security/issues/SambacryIssue'; -import {ElasticIssueOverview, ElasticIssueReport} from './security/issues/ElasticIssue'; -import {ShellShockIssueOverview, ShellShockIssueReport} from './security/issues/ShellShockIssue'; -import {MS08_067IssueOverview, MS08_067IssueReport} from './security/issues/MS08_067Issue'; +import {smbPasswordReport, smbPthReport} from './security/issues/SmbIssue'; +import {struts2IssueOverview, struts2IssueReport} from './security/issues/Struts2Issue'; +import {webLogicIssueOverview, webLogicIssueReport} from './security/issues/WebLogicIssue'; +import {hadoopIssueOverview, hadoopIssueReport} from './security/issues/HadoopIssue'; +import {mssqlIssueOverview, mssqlIssueReport} from './security/issues/MssqlIssue'; +import {drupalIssueOverview, drupalIssueReport} from './security/issues/DrupalIssue'; +import {vsftpdIssueOverview, vsftpdIssueReport} from './security/issues/VsftpdIssue'; +import {wmiPasswordIssueReport, wmiPthIssueReport} from './security/issues/WmiIssue'; +import {sshKeysReport, shhIssueReport, sshIssueOverview} from './security/issues/SshIssue'; +import {sambacryIssueOverview, sambacryIssueReport} from './security/issues/SambacryIssue'; +import {elasticIssueOverview, elasticIssueReport} from './security/issues/ElasticIssue'; +import {shellShockIssueOverview, shellShockIssueReport} from './security/issues/ShellShockIssue'; +import {ms08_067IssueOverview, ms08_067IssueReport} from './security/issues/MS08_067Issue'; import { crossSegmentIssueOverview, - generateCrossSegmentIssue, - generateIslandCrossSegmentIssue + crossSegmentIssueReport, + islandCrossSegmentIssueReport } from './security/issues/CrossSegmentIssue'; import { - generateSharedCredsDomainIssue, generateSharedCredsIssue, generateSharedLocalAdminsIssue, + sharedCredsDomainIssueReport, sharedCredsIssueReport, sharedLocalAdminsIssueReport, sharedAdminsDomainIssueOverview, sharedPasswordsIssueOverview } from './security/issues/SharedPasswordsIssue'; -import {generateTunnelIssue, generateTunnelIssueOverview} from './security/issues/TunnelIssue'; -import {StolenCredsIssueOverview} from './security/issues/StolenCredsIssue'; -import {WeakPasswordIssueOverview} from './security/issues/WeakPasswordIssue'; -import {AzurePasswordIssueOverview, AzurePasswordIssueReport} from './security/issues/AzurePasswordIssue'; -import {generateStrongUsersOnCritIssue} from './security/issues/StrongUsersOnCritIssue'; +import {tunnelIssueReport, tunnelIssueOverview} from './security/issues/TunnelIssue'; +import {stolenCredsIssueOverview} from './security/issues/StolenCredsIssue'; +import {weakPasswordIssueOverview} from './security/issues/WeakPasswordIssue'; +import {azurePasswordIssueOverview, azurePasswordIssueReport} from './security/issues/AzurePasswordIssue'; +import {strongUsersOnCritIssueReport} from './security/issues/StrongUsersOnCritIssue'; import { - ZerologonIssueOverview, - ZerologonIssueReport, - ZerologonOverviewWithFailedPassResetWarning + zerologonIssueOverview, + zerologonIssueReport, + zerologonOverviewWithFailedPassResetWarning } from './security/issues/ZerologonIssue'; @@ -76,123 +76,123 @@ class ReportPageComponent extends AuthComponent { { 'SmbExploiter': { [this.issueContentTypes.REPORT]: { - [this.credentialTypes.PASSWORD]: generateSmbPasswordReport, - [this.credentialTypes.HASH]: generateSmbPthReport + [this.credentialTypes.PASSWORD]: smbPasswordReport, + [this.credentialTypes.HASH]: smbPthReport }, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'Struts2Exploiter': { - [this.issueContentTypes.OVERVIEW]: Struts2IssueOverview, - [this.issueContentTypes.REPORT]: Struts2IssueReport, + [this.issueContentTypes.OVERVIEW]: struts2IssueOverview, + [this.issueContentTypes.REPORT]: struts2IssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'WebLogicExploiter': { - [this.issueContentTypes.OVERVIEW]: WebLogicIssueOverview, - [this.issueContentTypes.REPORT]: WebLogicIssueReport, + [this.issueContentTypes.OVERVIEW]: webLogicIssueOverview, + [this.issueContentTypes.REPORT]: webLogicIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'HadoopExploiter': { - [this.issueContentTypes.OVERVIEW]: HadoopIssueOverview, - [this.issueContentTypes.REPORT]: HadoopIssueReport, + [this.issueContentTypes.OVERVIEW]: hadoopIssueOverview, + [this.issueContentTypes.REPORT]: hadoopIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'MSSQLExploiter': { - [this.issueContentTypes.OVERVIEW]: MssqlIssueOverview, - [this.issueContentTypes.REPORT]: MssqlIssueReport, + [this.issueContentTypes.OVERVIEW]: mssqlIssueOverview, + [this.issueContentTypes.REPORT]: mssqlIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'DrupalExploiter': { - [this.issueContentTypes.OVERVIEW]: DrupalIssueOverview, - [this.issueContentTypes.REPORT]: DrupalIssueReport, + [this.issueContentTypes.OVERVIEW]: drupalIssueOverview, + [this.issueContentTypes.REPORT]: drupalIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'VSFTPDExploiter': { - [this.issueContentTypes.OVERVIEW]: VsftpdIssueOverview, - [this.issueContentTypes.REPORT]: VsftpdIssueReport, + [this.issueContentTypes.OVERVIEW]: vsftpdIssueOverview, + [this.issueContentTypes.REPORT]: vsftpdIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'WmiExploiter': { [this.issueContentTypes.REPORT]: { - [this.credentialTypes.PASSWORD]: generateWmiPasswordIssue, - [this.credentialTypes.HASH]: generateWmiPthIssue + [this.credentialTypes.PASSWORD]: wmiPasswordIssueReport, + [this.credentialTypes.HASH]: wmiPthIssueReport }, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'SSHExploiter': { - [this.issueContentTypes.OVERVIEW]: SshIssueOverview, + [this.issueContentTypes.OVERVIEW]: sshIssueOverview, [this.issueContentTypes.REPORT]: { - [this.credentialTypes.PASSWORD]: ShhIssueReport, - [this.credentialTypes.KEY]: generateSshKeysReport + [this.credentialTypes.PASSWORD]: shhIssueReport, + [this.credentialTypes.KEY]: sshKeysReport }, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'SambaCryExploiter': { - [this.issueContentTypes.OVERVIEW]: SambacryIssueOverview, - [this.issueContentTypes.REPORT]: SambacryIssueReport, + [this.issueContentTypes.OVERVIEW]: sambacryIssueOverview, + [this.issueContentTypes.REPORT]: sambacryIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'ElasticGroovyExploiter': { - [this.issueContentTypes.OVERVIEW]: ElasticIssueOverview, - [this.issueContentTypes.REPORT]: ElasticIssueReport, + [this.issueContentTypes.OVERVIEW]: elasticIssueOverview, + [this.issueContentTypes.REPORT]: elasticIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'ShellShockExploiter': { - [this.issueContentTypes.OVERVIEW]: ShellShockIssueOverview, - [this.issueContentTypes.REPORT]: ShellShockIssueReport, + [this.issueContentTypes.OVERVIEW]: shellShockIssueOverview, + [this.issueContentTypes.REPORT]: shellShockIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'Ms08_067_Exploiter': { - [this.issueContentTypes.OVERVIEW]: MS08_067IssueOverview, - [this.issueContentTypes.REPORT]: MS08_067IssueReport, + [this.issueContentTypes.OVERVIEW]: ms08_067IssueOverview, + [this.issueContentTypes.REPORT]: ms08_067IssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'ZerologonExploiter': { - [this.issueContentTypes.OVERVIEW]: ZerologonIssueOverview, - [this.issueContentTypes.REPORT]: ZerologonIssueReport, + [this.issueContentTypes.OVERVIEW]: zerologonIssueOverview, + [this.issueContentTypes.REPORT]: zerologonIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'zerologon_pass_restore_failed': { - [this.issueContentTypes.OVERVIEW]: ZerologonOverviewWithFailedPassResetWarning, + [this.issueContentTypes.OVERVIEW]: zerologonOverviewWithFailedPassResetWarning, }, 'island_cross_segment': { [this.issueContentTypes.OVERVIEW]: crossSegmentIssueOverview, - [this.issueContentTypes.REPORT]: generateIslandCrossSegmentIssue, + [this.issueContentTypes.REPORT]: islandCrossSegmentIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'tunnel': { - [this.issueContentTypes.OVERVIEW]: generateTunnelIssueOverview, - [this.issueContentTypes.REPORT]: generateTunnelIssue, + [this.issueContentTypes.OVERVIEW]: tunnelIssueOverview, + [this.issueContentTypes.REPORT]: tunnelIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'shared_passwords': { [this.issueContentTypes.OVERVIEW]: sharedPasswordsIssueOverview, - [this.issueContentTypes.REPORT]: generateSharedCredsIssue, + [this.issueContentTypes.REPORT]: sharedCredsIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'shared_admins_domain': { [this.issueContentTypes.OVERVIEW]: sharedAdminsDomainIssueOverview, - [this.issueContentTypes.REPORT]: generateSharedLocalAdminsIssue, + [this.issueContentTypes.REPORT]: sharedLocalAdminsIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'shared_passwords_domain': { - [this.issueContentTypes.REPORT]: generateSharedCredsDomainIssue, + [this.issueContentTypes.REPORT]: sharedCredsDomainIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.WARNING }, 'strong_users_on_crit': { - [this.issueContentTypes.REPORT]: generateStrongUsersOnCritIssue, + [this.issueContentTypes.REPORT]: strongUsersOnCritIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'azure_password': { - [this.issueContentTypes.OVERVIEW]: AzurePasswordIssueOverview, - [this.issueContentTypes.REPORT]: AzurePasswordIssueReport, + [this.issueContentTypes.OVERVIEW]: azurePasswordIssueOverview, + [this.issueContentTypes.REPORT]: azurePasswordIssueReport, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'weak_password': { - [this.issueContentTypes.OVERVIEW]: WeakPasswordIssueOverview, + [this.issueContentTypes.OVERVIEW]: weakPasswordIssueOverview, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER }, 'stolen_creds': { - [this.issueContentTypes.OVERVIEW]: StolenCredsIssueOverview, + [this.issueContentTypes.OVERVIEW]: stolenCredsIssueOverview, [this.issueContentTypes.TYPE]: this.issueTypes.DANGER } } @@ -412,7 +412,7 @@ class ReportPageComponent extends AuthComponent {
    The Monkey uncovered the following set of segmentation issues:
      - {this.state.report.overview.cross_segment_issues.map(x => generateCrossSegmentIssue(x))} + {this.state.report.overview.cross_segment_issues.map(x => crossSegmentIssueReport(x))}
    diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js index f572347dc..78afa599b 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/AzurePasswordIssue.js @@ -1,13 +1,13 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function AzurePasswordIssueOverview() { +export function azurePasswordIssueOverview() { return (
  • Azure machines expose plaintext passwords. (More info)
  • ) } -export function AzurePasswordIssueReport(issue) { +export function azurePasswordIssueReport(issue) { return ( <> Delete VM Access plugin configuration files. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js index f1d84950d..6c1ece1ea 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/CrossSegmentIssue.js @@ -7,7 +7,7 @@ export function crossSegmentIssueOverview() { different segments are able to communicate.) } -export function generateCrossSegmentIssue(crossSegmentIssue) { +export function crossSegmentIssueReport(crossSegmentIssue) { let crossSegmentIssueOverview = 'Communication possible from ' + `${crossSegmentIssue['source_subnet']} to ${crossSegmentIssue['target_subnet']}`; @@ -17,7 +17,7 @@ export function generateCrossSegmentIssue(crossSegmentIssue) {
      {crossSegmentIssue['issues'].map( - issue => generateCrossSegmentIssueListItem(issue) + issue => getCrossSegmentIssueListItem(issue) )}
    @@ -25,15 +25,15 @@ export function generateCrossSegmentIssue(crossSegmentIssue) { ); } -export function generateCrossSegmentIssueListItem(issue) { +export function getCrossSegmentIssueListItem(issue) { if (issue['is_self']) { - return generateCrossSegmentSingleHostMessage(issue); + return getCrossSegmentSingleHostMessage(issue); } - return generateCrossSegmentMultiHostMessage(issue); + return getCrossSegmentMultiHostMessage(issue); } -export function generateCrossSegmentSingleHostMessage(issue) { +export function getCrossSegmentSingleHostMessage(issue) { return (
  • {`Machine ${issue['hostname']} has both ips: ${issue['source']} and ${issue['target']}`} @@ -41,20 +41,20 @@ export function generateCrossSegmentSingleHostMessage(issue) { ); } -export function generateCrossSegmentMultiHostMessage(issue) { +export function getCrossSegmentMultiHostMessage(issue) { return (
  • IP {issue['source']} ({issue['hostname']}) was able to communicate with IP {issue['target']} using:
      {issue['icmp'] &&
    • ICMP
    • } - {this.generateCrossSegmentServiceListItems(issue)} + {getCrossSegmentServiceListItems(issue)}
  • ); } -export function generateCrossSegmentServiceListItems(issue) { +export function getCrossSegmentServiceListItems(issue) { let service_list_items = []; for (const [service, info] of Object.entries(issue['services'])) { @@ -68,7 +68,7 @@ export function generateCrossSegmentServiceListItems(issue) { return service_list_items; } -export function generateIslandCrossSegmentIssue(issue) { +export function islandCrossSegmentIssueReport(issue) { return ( <> Segment your network and make sure there is no communication between machines from different segments. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js index 15d00feb2..d5cc068bb 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/DrupalIssue.js @@ -1,12 +1,12 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function DrupalIssueOverview() { +export function drupalIssueOverview() { return (
  • Drupal server/s are vulnerable to CVE-2019-6340.
  • ) } -export function DrupalIssueReport(issue) { +export function drupalIssueReport(issue) { return ( <> Upgrade Drupal server to versions 8.5.11, 8.6.10, or later. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js index 04198a309..4d389bf2b 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ElasticIssue.js @@ -1,13 +1,13 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function ElasticIssueOverview() { +export function elasticIssueOverview() { return (
  • Elasticsearch servers are vulnerable to CVE-2015-1427.
  • ) } -export function ElasticIssueReport(issue) { +export function elasticIssueReport(issue) { return ( <> Update your Elastic Search server to version 1.4.3 and up. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js index e63e541ef..ff126ef8a 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/HadoopIssue.js @@ -1,11 +1,11 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function HadoopIssueOverview() { +export function hadoopIssueOverview() { return (
  • Hadoop/Yarn servers are vulnerable to remote code execution.
  • ) } -export function HadoopIssueReport(issue) { +export function hadoopIssueReport(issue) { return ( <> Run Hadoop in secure mode (Machines are vulnerable to ‘Conficker’ (MS08-067). ) } -export function MS08_067IssueReport(issue) { +export function ms08_067IssueReport(issue) { return ( <> Install the latest Windows updates or upgrade to a newer operating system. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js index c1ff6e9ec..e8e1bb162 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/MssqlIssue.js @@ -1,11 +1,11 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function MssqlIssueOverview() { +export function mssqlIssueOverview() { return (
  • MS-SQL servers are vulnerable to remote code execution via xp_cmdshell command.
  • ) } -export function MssqlIssueReport(issue) { +export function mssqlIssueReport(issue) { return ( <> Disable the xp_cmdshell option. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js index 3a78c3008..73589715b 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/PthCriticalServiceIssue.js @@ -1,6 +1,6 @@ import React from 'react'; -export function PthCriticalServiceIssueOverview() { +export function pthCriticalServiceIssueOverview() { return (
  • Mimikatz found login credentials of a user who has admin access to a server defined as critical.
  • ) } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js index c07fcce7f..05bcb6850 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SambacryIssue.js @@ -1,13 +1,13 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function SambacryIssueOverview() { +export function sambacryIssueOverview() { return (
  • Samba servers are vulnerable to ‘SambaCry’ (CVE-2017-7494).
  • ) } -export function SambacryIssueReport(issue) { +export function sambacryIssueReport(issue) { return ( <> Change {issue.username}'s password to a complex one-use password diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js index 8308a6357..2a09dbb83 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SharedPasswordsIssue.js @@ -11,7 +11,7 @@ export function sharedAdminsDomainIssueOverview() { administrator.) } -export function generateSharedCredsDomainIssue(issue) { +export function sharedCredsDomainIssueReport(issue) { return ( <> Some domain users are sharing passwords, this should be fixed by changing passwords. @@ -23,7 +23,7 @@ export function generateSharedCredsDomainIssue(issue) { ); } -export function generateSharedCredsIssue(issue) { +export function sharedCredsIssueReport(issue) { return ( <> Some users are sharing passwords, this should be fixed by changing passwords. @@ -35,7 +35,7 @@ export function generateSharedCredsIssue(issue) { ); } -export function generateSharedLocalAdminsIssue(issue) { +export function sharedLocalAdminsIssueReport(issue) { return ( <> Make sure the right administrator accounts are managing the right machines, and that there isn’t an diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js index 02daa292c..b2496fb21 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ShellShockIssue.js @@ -1,18 +1,18 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function ShellShockIssueOverview() { +export function shellShockIssueOverview() { return (
  • Machines are vulnerable to ‘Shellshock’ (CVE-2014-6271).
  • ) } -function generateShellshockPathListBadges(paths) { +function getShellshockPathListBadges(paths) { return paths.map(path => {path}); } -export function ShellShockIssueReport(issue) { +export function shellShockIssueReport(issue) { return ( <> Update your Bash to a ShellShock-patched version. @@ -23,7 +23,7 @@ export function ShellShockIssueReport(issue) {
    The attack was made possible because the HTTP server running on TCP port {issue.port} was vulnerable to a shell injection attack on the - paths: {generateShellshockPathListBadges(issue.paths)}. + paths: {getShellshockPathListBadges(issue.paths)}. ); diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js index eec516a3e..66e2117ff 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SmbIssue.js @@ -1,7 +1,7 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function generateSmbPasswordReport(issue) { +export function smbPasswordReport(issue) { return ( <> Change {issue.username}'s password to a complex one-use password @@ -18,7 +18,7 @@ export function generateSmbPasswordReport(issue) { ); } -export function generateSmbPthReport(issue) { +export function smbPthReport(issue) { return ( <> Change {issue.username}'s password to a complex one-use password diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js index d13862372..cb74018d8 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/SshIssue.js @@ -1,11 +1,11 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function SshIssueOverview() { +export function sshIssueOverview() { return (
  • Stolen SSH keys are used to exploit other machines.
  • ) } -export function ShhIssueReport(issue) { +export function shhIssueReport(issue) { return ( <> Change {issue.username}'s password to a complex one-use password @@ -22,7 +22,7 @@ export function ShhIssueReport(issue) { ); } -export function generateSshKeysReport(issue) { +export function sshKeysReport(issue) { return ( <> Protect {issue.ssh_key} private key with a pass phrase. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js index 62d92ccc3..a0b0c037b 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StolenCredsIssue.js @@ -1,5 +1,5 @@ import React from 'react'; -export function StolenCredsIssueOverview() { +export function stolenCredsIssueOverview() { return (
  • Stolen credentials are used to exploit other machines.
  • ) } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js index 7f87e72c1..328207710 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/StrongUsersOnCritIssue.js @@ -1,7 +1,7 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function generateStrongUsersOnCritIssue(issue) { +export function strongUsersOnCritIssueReport(issue) { return ( <> This critical machine is open to attacks via strong users with access to it. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js index 7a590ba3c..ca4c2b2b9 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/Struts2Issue.js @@ -1,13 +1,13 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function Struts2IssueOverview() { +export function struts2IssueOverview() { return (
  • Struts2 servers are vulnerable to remote code execution. ( CVE-2017-5638)
  • ) } -export function Struts2IssueReport(issue) { +export function struts2IssueReport(issue) { return ( <> Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js index 09ed635c5..c4d52751a 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/TunnelIssue.js @@ -1,11 +1,11 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function generateTunnelIssueOverview(){ +export function tunnelIssueOverview(){ return (
  • Weak segmentation - Machines were able to communicate over unused ports.
  • ) } -export function generateTunnelIssue(issue) { +export function tunnelIssueReport(issue) { return ( <> Use micro-segmentation policies to disable communication other than the required. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js index 214c1896b..e5419a9c2 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/VsftpdIssue.js @@ -1,13 +1,13 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function VsftpdIssueOverview() { +export function vsftpdIssueOverview() { return (
  • VSFTPD is vulnerable to CVE-2011-2523.
  • ) } -export function VsftpdIssueReport(issue) { +export function vsftpdIssueReport(issue) { return ( <> Update your VSFTPD server to the latest version vsftpd-3.0.3. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js index 0a7ba30b1..ee3c6c04f 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WeakPasswordIssue.js @@ -1,6 +1,6 @@ import React from 'react'; -export function WeakPasswordIssueOverview() { +export function weakPasswordIssueOverview() { return (
  • Machines are accessible using passwords supplied by the user during the Monkey’s configuration.
  • ) } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js index 0bd5e200f..e7678c448 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WebLogicIssue.js @@ -1,11 +1,11 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function WebLogicIssueOverview() { +export function webLogicIssueOverview() { return (
  • Oracle WebLogic servers are susceptible to a remote code execution vulnerability.
  • ) } -export function WebLogicIssueReport(issue) { +export function webLogicIssueReport(issue) { return ( <> Update Oracle WebLogic server to the latest supported version. diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js index 401f8a9d9..cce631274 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/WmiIssue.js @@ -1,7 +1,7 @@ import React from 'react'; import CollapsibleWellComponent from '../CollapsibleWell'; -export function generateWmiPasswordIssue(issue) { +export function wmiPasswordIssueReport(issue) { return ( <> Change {issue.username}'s password to a complex one-use password @@ -18,7 +18,7 @@ export function generateWmiPasswordIssue(issue) { ); } -export function generateWmiPthIssue(issue) { +export function wmiPthIssueReport(issue) { return ( <> Change {issue.username}'s password to a complex one-use password diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js index f125d67ec..771aecf6c 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/issues/ZerologonIssue.js @@ -3,7 +3,7 @@ import CollapsibleWellComponent from '../CollapsibleWell'; import WarningIcon from '../../../ui-components/WarningIcon'; import {Button} from 'react-bootstrap'; -export function ZerologonIssueOverview() { +export function zerologonIssueOverview() { return (
  • Some Windows domain controllers are vulnerable to 'Zerologon' ( @@ -17,8 +17,8 @@ export function ZerologonIssueOverview() { ) } -export function ZerologonOverviewWithFailedPassResetWarning() { - let overview = [ZerologonIssueOverview()]; +export function zerologonOverviewWithFailedPassResetWarning() { + let overview = [zerologonIssueOverview()]; overview.push(
  • @@ -36,7 +36,7 @@ export function ZerologonOverviewWithFailedPassResetWarning() { return overview; } -export function ZerologonIssueReport(issue) { +export function zerologonIssueReport(issue) { return ( <> Install Windows security updates. From 72a97e64654ce716b38f51ebb5aa0c3e1fa8c0e7 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 2 Apr 2021 11:59:28 +0300 Subject: [PATCH 11/17] Small style fixes and improvements --- .../exploiter_descriptor_enum.py | 9 ++++++++- .../monkey_island/cc/services/reporting/report.py | 14 +++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py index eff1f7758..6378c77db 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from enum import Enum -from typing import Type +from typing import Type, Dict from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.cred_exploit import \ CredExploitProcessor @@ -34,3 +34,10 @@ class ExploiterDescriptorEnum(Enum): VSFTPD = ExploiterDescriptor('VSFTPDExploiter', 'VSFTPD Backdoor Exploiter', CredExploitProcessor) DRUPAL = ExploiterDescriptor('DrupalExploiter', 'Drupal Server Exploiter', ExploitProcessor) ZEROLOGON = ExploiterDescriptor('ZerologonExploiter', 'ZeroLogon Exploiter', ZerologonExploitProcessor) + + @staticmethod + def __dict__() -> Dict[str, ExploiterDescriptor]: + descriptor_dict = {} + for descriptor in ExploiterDescriptorEnum: + descriptor_dict[descriptor.value.class_name] = descriptor + return descriptor_dict diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index a4642c694..a70634f07 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -2,7 +2,7 @@ import functools import ipaddress import itertools import logging -from typing import Dict, List +from typing import List from bson import json_util @@ -17,8 +17,7 @@ from common.config_value_paths import (EXPLOITER_CLASSES_PATH, LOCAL_NETWORK_SCA USER_LIST_PATH) from monkey_island.cc.services.configuration.utils import get_config_network_segments_as_subnet_groups from monkey_island.cc.services.node import NodeService -from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_descriptor_enum import ExploiterDescriptorEnum, \ - ExploiterDescriptor +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_descriptor_enum import ExploiterDescriptorEnum from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.cred_exploit import \ CredentialType from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import \ @@ -32,15 +31,8 @@ __author__ = "itay.mizeretz" logger = logging.getLogger(__name__) -def build_exploiter_descriptor_dict() -> Dict[str, ExploiterDescriptor]: - descriptor_dict = {} - for descriptor in ExploiterDescriptorEnum: - descriptor_dict[descriptor.value.class_name] = descriptor - return descriptor_dict - - class ReportService: - exploiter_descriptors = build_exploiter_descriptor_dict() + exploiter_descriptors = ExploiterDescriptorEnum.__dict__ class DerivedIssueEnum: WEAK_PASSWORD = "weak_password" From de2581d3231f22550c2a318cd751a30488cde9a3 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 2 Apr 2021 12:00:04 +0300 Subject: [PATCH 12/17] Extended exploiter report info class to have all possible values that exploit processors could add --- .../exploiter_report_info.py | 23 +++++++++++++++++++ .../processors/cred_exploit.py | 13 +++-------- .../exploit_processing/processors/exploit.py | 11 ++------- 3 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_report_info.py diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_report_info.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_report_info.py new file mode 100644 index 000000000..3e1cb0601 --- /dev/null +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_report_info.py @@ -0,0 +1,23 @@ +from dataclasses import dataclass +from enum import Enum +from typing import Union, List + + +class CredentialType(Enum): + PASSWORD = 'password' + HASH = 'hash' + KEY = 'key' + + +@dataclass +class ExploiterReportInfo: + machine: str + ip_address: str + type: str + username: Union[str, None] = None + credential_type: Union[CredentialType, None] = None + ssh_key: Union[str, None] = None + password: Union[str, None] = None + port: Union[str, None] = None + paths: Union[List[str], None] = None + password_restored: Union[bool, None] = None diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py index 720655b52..dc7a38e66 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py @@ -1,15 +1,8 @@ from __future__ import annotations -from enum import Enum - -from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import \ - ExploiterReportInfo, ExploitProcessor - - -class CredentialType(Enum): - PASSWORD = 'password' - HASH = 'hash' - KEY = 'key' +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_report_info import \ + ExploiterReportInfo, CredentialType +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ExploitProcessor class CredExploitProcessor: diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py index 79ebb2dfb..d48a661d1 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py @@ -1,15 +1,8 @@ from __future__ import annotations -from dataclasses import dataclass - from monkey_island.cc.services.node import NodeService - - -@dataclass -class ExploiterReportInfo: - machine: str - ip_address: str - type: str +from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_report_info import \ + ExploiterReportInfo class ExploitProcessor: From 87cec0036de69c1ee757529f30ebec5eeb6b4aca Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 6 Apr 2021 10:11:34 +0300 Subject: [PATCH 13/17] Fixed report to show display names instead of class names of exploiters where needed --- .../exploit_processing/exploiter_descriptor_enum.py | 8 +++++++- monkey/monkey_island/cc/services/reporting/report.py | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py index 6378c77db..08c471174 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py @@ -33,7 +33,7 @@ class ExploiterDescriptorEnum(Enum): MSSQL = ExploiterDescriptor('MSSQLExploiter', 'MSSQL Exploiter', ExploitProcessor) VSFTPD = ExploiterDescriptor('VSFTPDExploiter', 'VSFTPD Backdoor Exploiter', CredExploitProcessor) DRUPAL = ExploiterDescriptor('DrupalExploiter', 'Drupal Server Exploiter', ExploitProcessor) - ZEROLOGON = ExploiterDescriptor('ZerologonExploiter', 'ZeroLogon Exploiter', ZerologonExploitProcessor) + ZEROLOGON = ExploiterDescriptor('ZerologonExploiter', 'Zerologon Exploiter', ZerologonExploitProcessor) @staticmethod def __dict__() -> Dict[str, ExploiterDescriptor]: @@ -41,3 +41,9 @@ class ExploiterDescriptorEnum(Enum): for descriptor in ExploiterDescriptorEnum: descriptor_dict[descriptor.value.class_name] = descriptor return descriptor_dict + + @staticmethod + def get_display_name_by_class_name(class_name: str) -> str: + return [descriptor.display_name.value + for descriptor in ExploiterDescriptorEnum + if descriptor.class_name.value == class_name][0] diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index a70634f07..d84c5ad94 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -145,7 +145,9 @@ class ReportService: @staticmethod def get_exploits_used_on_node(node: dict) -> List[str]: - return list(set([exploit['exploiter'] for exploit in node['exploits'] if exploit['result']])) + return list(set([ExploiterDescriptorEnum.get_display_name_by_class_name(exploit['exploiter']) + for exploit in node['exploits'] + if exploit['result']])) @staticmethod def get_stolen_creds(): @@ -483,7 +485,8 @@ class ReportService: if exploits == default_exploits: return ['default'] - return exploits + return [ExploiterDescriptorEnum.get_display_name_by_class_name(exploit) + for exploit in exploits] @staticmethod def get_config_ips(): From 6685b24da4f77a1ba16fc48fca907f153e9edf2e Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 6 Apr 2021 10:16:05 +0300 Subject: [PATCH 14/17] Removed unused annotations import --- .../exploit_processing/processors/cred_exploit.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py index dc7a38e66..43156561c 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/cred_exploit.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_report_info import \ ExploiterReportInfo, CredentialType from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ExploitProcessor From 0b34d30fd6e7908df27de705b9272eb109e7f7ea Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 6 Apr 2021 11:35:41 +0300 Subject: [PATCH 15/17] Improved exploiter descriptors and usage of them in report.py --- .../exploit_processing/exploiter_descriptor_enum.py | 13 +++---------- .../monkey_island/cc/services/reporting/report.py | 9 ++++----- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py index 08c471174..65964b5de 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/exploiter_descriptor_enum.py @@ -36,14 +36,7 @@ class ExploiterDescriptorEnum(Enum): ZEROLOGON = ExploiterDescriptor('ZerologonExploiter', 'Zerologon Exploiter', ZerologonExploitProcessor) @staticmethod - def __dict__() -> Dict[str, ExploiterDescriptor]: - descriptor_dict = {} - for descriptor in ExploiterDescriptorEnum: - descriptor_dict[descriptor.value.class_name] = descriptor - return descriptor_dict - - @staticmethod - def get_display_name_by_class_name(class_name: str) -> str: - return [descriptor.display_name.value + def get_by_class_name(class_name: str) -> ExploiterDescriptor: + return [descriptor.value for descriptor in ExploiterDescriptorEnum - if descriptor.class_name.value == class_name][0] + if descriptor.value.class_name == class_name][0] diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index d84c5ad94..6430a2559 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -32,7 +32,6 @@ logger = logging.getLogger(__name__) class ReportService: - exploiter_descriptors = ExploiterDescriptorEnum.__dict__ class DerivedIssueEnum: WEAK_PASSWORD = "weak_password" @@ -145,7 +144,7 @@ class ReportService: @staticmethod def get_exploits_used_on_node(node: dict) -> List[str]: - return list(set([ExploiterDescriptorEnum.get_display_name_by_class_name(exploit['exploiter']) + return list(set([ExploiterDescriptorEnum.get_by_class_name(exploit['exploiter']).display_name for exploit in node['exploits'] if exploit['result']])) @@ -253,9 +252,9 @@ class ReportService: @staticmethod def process_exploit(exploit) -> ExploiterReportInfo: exploiter_type = exploit['data']['exploiter'] - exploiter_descriptor = ReportService.exploiter_descriptors[exploiter_type].value + exploiter_descriptor = ExploiterDescriptorEnum.get_by_class_name(exploiter_type) processor = exploiter_descriptor.processor() - exploiter_info = processor.get_exploit_info_by_dict(exploiter_descriptor.class_name, exploit) + exploiter_info = processor.get_exploit_info_by_dict(exploiter_type, exploit) return exploiter_info @staticmethod @@ -485,7 +484,7 @@ class ReportService: if exploits == default_exploits: return ['default'] - return [ExploiterDescriptorEnum.get_display_name_by_class_name(exploit) + return [ExploiterDescriptorEnum.get_by_class_name(exploit).display_name for exploit in exploits] @staticmethod From fa0729881e6633914c62ea488278c11391987953 Mon Sep 17 00:00:00 2001 From: Shreya Date: Tue, 6 Apr 2021 18:12:03 +0530 Subject: [PATCH 16/17] Remove unused imports --- .../issue_processing/exploit_processing/processors/exploit.py | 2 -- .../exploit_processing/processors/shellshock_exploit.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py index d48a661d1..c541ba252 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/exploit.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.reporting.issue_processing.exploit_processing.exploiter_report_info import \ ExploiterReportInfo diff --git a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py index f8d36d4d8..d33bd8615 100644 --- a/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py +++ b/monkey/monkey_island/cc/services/reporting/issue_processing/exploit_processing/processors/shellshock_exploit.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import \ ExploiterReportInfo, ExploitProcessor From 7973a3533891e684771c79f3a200c3148115568e Mon Sep 17 00:00:00 2001 From: Shreya Date: Tue, 6 Apr 2021 18:31:02 +0530 Subject: [PATCH 17/17] Fix unit tests --- monkey/monkey_island/cc/services/reporting/test_report.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/test_report.py b/monkey/monkey_island/cc/services/reporting/test_report.py index 9983371a4..5f95eae47 100644 --- a/monkey/monkey_island/cc/services/reporting/test_report.py +++ b/monkey/monkey_island/cc/services/reporting/test_report.py @@ -42,10 +42,10 @@ NODE_DICT_FAILED_EXPLOITS['exploits'][1]['result'] = False def test_get_exploits_used_on_node(): exploits = ReportService.get_exploits_used_on_node(NODE_DICT) - assert sorted(exploits) == sorted(['ElasticGroovyExploiter', 'DrupalExploiter']) + assert sorted(exploits) == sorted(['Elastic Groovy Exploiter', 'Drupal Server Exploiter']) exploits = ReportService.get_exploits_used_on_node(NODE_DICT_DUPLICATE_EXPLOITS) - assert exploits == ['DrupalExploiter'] + assert exploits == ['Drupal Server Exploiter'] exploits = ReportService.get_exploits_used_on_node(NODE_DICT_FAILED_EXPLOITS) assert exploits == []