From 54ac059d5ef705ea85fa553cba0014e8637fc921 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 15 May 2020 10:42:03 +0300 Subject: [PATCH] Prototype changes that fix redundant exploitations, but break multiple iterations --- monkey/infection_monkey/config.py | 10 ++++++++++ monkey/infection_monkey/monkey.py | 7 +++---- .../exceptions/planned_shutdown_exception.py | 2 ++ monkey/monkey_island/cc/resources/monkey.py | 15 +++++---------- monkey/monkey_island/cc/services/config.py | 10 ++++++++++ .../telemetry/processing/system_info.py | 18 ++++++++++++++++++ 6 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 monkey/infection_monkey/utils/exceptions/planned_shutdown_exception.py diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 5c5b5a392..e41b8a8a6 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -8,6 +8,9 @@ from itertools import product __author__ = 'itamar' +from infection_monkey.utils.exceptions.planned_shutdown_exception import PlannedShutdownException +from infection_monkey.network import info + GUID = str(uuid.getnode()) EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin') @@ -277,5 +280,12 @@ class Configuration(object): password_hashed = hashlib.sha512(sensitive_data.encode()).hexdigest() return password_hashed + @staticmethod + def should_monkey_run(): + local_ips = info.local_ips() + if set(local_ips).intersection(set(WormConfiguration.blocked_ips)): + raise PlannedShutdownException("Monkey shouldn't run on current machine " + "(blocked ip or redundant exploitation).") + WormConfiguration = Configuration() diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index c96599844..8e0763dc5 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -10,6 +10,7 @@ from infection_monkey.network.HostFinger import HostFinger from infection_monkey.utils.monkey_dir import create_monkey_dir, get_monkey_dir_path, remove_monkey_dir from infection_monkey.utils.monkey_log_path import get_monkey_log_path from infection_monkey.utils.environment import is_windows_os +from infection_monkey.utils.exceptions.planned_shutdown_exception import PlannedShutdownException from infection_monkey.config import WormConfiguration from infection_monkey.control import ControlClient from infection_monkey.model import DELAY_DELETE_CMD @@ -40,10 +41,6 @@ __author__ = 'itamar' LOG = logging.getLogger(__name__) -class PlannedShutdownException(Exception): - pass - - class InfectionMonkey(object): def __init__(self, args): self._keep_running = False @@ -129,6 +126,8 @@ class InfectionMonkey(object): StateTelem(is_done=False, version=get_version()).send() TunnelTelem().send() + WormConfiguration.should_monkey_run() + LOG.debug("Starting the post-breach phase.") self.collect_system_info_if_configured() PostBreach().execute_all_configured() diff --git a/monkey/infection_monkey/utils/exceptions/planned_shutdown_exception.py b/monkey/infection_monkey/utils/exceptions/planned_shutdown_exception.py new file mode 100644 index 000000000..f0147e1e5 --- /dev/null +++ b/monkey/infection_monkey/utils/exceptions/planned_shutdown_exception.py @@ -0,0 +1,2 @@ +class PlannedShutdownException(Exception): + pass diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index dcdc5bc12..e61765376 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -74,16 +74,11 @@ class Monkey(flask_restful.Resource): # if new monkey telem, change config according to "new monkeys" config. db_monkey = mongo.db.monkey.find_one({"guid": monkey_json["guid"]}) - if not db_monkey: - # we pull it encrypted because we then decrypt it for the monkey in get - new_config = ConfigService.get_flat_config(False, False) - monkey_json['config'] = monkey_json.get('config', {}) - monkey_json['config'].update(new_config) - else: - db_config = db_monkey.get('config', {}) - if 'current_server' in db_config: - del db_config['current_server'] - monkey_json.get('config', {}).update(db_config) + + # Update monkey configuration + new_config = ConfigService.get_flat_config(False, False) + monkey_json['config'] = monkey_json.get('config', {}) + monkey_json['config'].update(new_config) # try to find new monkey parent parent = monkey_json.get('parent') diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index e9ed3b0f6..f8d9df0de 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -74,6 +74,12 @@ class ConfigService: mongo.db.config.update({'name': 'newconfig'}, {"$set": {mongo_key: value}}) + @staticmethod + def append_to_config_array(config_key_as_arr, value): + mongo_key = ".".join(config_key_as_arr) + mongo.db.config.update({'name': 'newconfig'}, + {"$push": {mongo_key: value}}) + @staticmethod def get_flat_config(is_initial_config=False, should_decrypt=True): config_json = ConfigService.get_config(is_initial_config, should_decrypt) @@ -311,3 +317,7 @@ class ConfigService: @staticmethod def is_test_telem_export_enabled(): return ConfigService.get_config_value(['internal', 'testing', 'export_monkey_telems']) + + @staticmethod + def add_blocked_ip(ip_): + ConfigService.append_to_config_array(['basic_network', 'general', 'blocked_ips'], ip_) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/system_info.py b/monkey/monkey_island/cc/services/telemetry/processing/system_info.py index 5b842df0b..7f11c1fd3 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/system_info.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/system_info.py @@ -1,4 +1,5 @@ import logging +from ipaddress import ip_address from monkey_island.cc.encryptor import encryptor from monkey_island.cc.services import mimikatz_utils @@ -17,6 +18,7 @@ def process_system_info_telemetry(telemetry_json): process_ssh_info, process_credential_info, process_mimikatz_and_wmi_info, + try_process_network_info, dispatcher.dispatch_collector_results_to_relevant_processors ] @@ -101,3 +103,19 @@ def process_mimikatz_and_wmi_info(telemetry_json): monkey_id = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']).get('_id') wmi_handler = WMIHandler(monkey_id, telemetry_json['data']['wmi'], users_secrets) wmi_handler.process_and_handle_wmi_info() + + +def try_process_network_info(telemetry_json): + try: + process_network_info(telemetry_json) + except KeyError: + pass + + +def process_network_info(telemetry_json): + interfaces = telemetry_json['data']['network_info']['networks'] + for interface in interfaces: + ip_ = ip_address(interface['addr']) + if not ip_.is_loopback: + ConfigService.add_blocked_ip(ip_.exploded) +