diff --git a/monkey/infection_monkey/exploit/hadoop.py b/monkey/infection_monkey/exploit/hadoop.py index c704f9814..318e37d67 100644 --- a/monkey/infection_monkey/exploit/hadoop.py +++ b/monkey/infection_monkey/exploit/hadoop.py @@ -43,7 +43,7 @@ class HadoopExploiter(WebRCE): return self.exploit_result try: - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) except KeyError: return self.exploit_result diff --git a/monkey/infection_monkey/exploit/log4shell.py b/monkey/infection_monkey/exploit/log4shell.py index dc8fe0c66..b59c72dd4 100644 --- a/monkey/infection_monkey/exploit/log4shell.py +++ b/monkey/infection_monkey/exploit/log4shell.py @@ -61,7 +61,7 @@ class Log4ShellExploiter(WebRCE): self._agent_http_server_thread = None def _start_servers(self): - target_path = get_agent_dest_path(self.host, self.options) + target_path = get_agent_dest_path(self.host) # Start http server, to serve agent to victims agent_http_path = self._start_agent_http_server(target_path) diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index c765c2de5..147403580 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -59,7 +59,7 @@ class MSSQLExploiter(HostExploiter): Also, don't forget to start_monkey_server() before self.upload_monkey() and self.stop_monkey_server() after """ - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) # Brute force to get connection creds = generate_identity_secret_pairs( diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index d711bec19..16073a014 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -134,7 +134,7 @@ class PowerShellExploiter(HostExploiter): raise ValueError(f"Unknown secret type {credentials.secret_type}") def _execute_monkey_agent_on_victim(self): - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) self._copy_monkey_binary_to_victim(monkey_path_on_victim) logger.info("Successfully copied the monkey binary to the victim.") diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 10b7009b0..825cb37ce 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -31,7 +31,7 @@ class SMBExploiter(HostExploiter): 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) + dest_path = get_agent_dest_path(self.host) creds = generate_brute_force_combinations(self.options["credentials"]) for user, password, lm_hash, ntlm_hash in interruptible_iter(creds, self.interrupt): diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index 3c4c46641..7f9619e95 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -209,7 +209,7 @@ class SSHExploiter(HostExploiter): self._set_interrupted() return self.exploit_result - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) try: with ssh.open_sftp() as ftp: diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index 05a15aed7..2739da215 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -2,9 +2,8 @@ import logging import random import string from pathlib import PurePath, PurePosixPath, PureWindowsPath -from typing import Any, Mapping -from infection_monkey.model import VictimHost +from infection_monkey.model import DROPPER_TARGET_PATH_LINUX, DROPPER_TARGET_PATH_WIN64, VictimHost logger = logging.getLogger(__name__) @@ -18,11 +17,11 @@ def get_random_file_suffix() -> str: return random_string -def get_agent_dest_path(host: VictimHost, options: Mapping[str, Any]) -> PurePath: +def get_agent_dest_path(host: VictimHost) -> PurePath: if host.os["type"] == "windows": - path = PureWindowsPath(options["dropper_target_path_win_64"]) + path = PureWindowsPath(DROPPER_TARGET_PATH_WIN64) else: - path = PurePosixPath(options["dropper_target_path_linux"]) + path = PurePosixPath(DROPPER_TARGET_PATH_LINUX) return _add_random_suffix(path) diff --git a/monkey/infection_monkey/exploit/web_rce.py b/monkey/infection_monkey/exploit/web_rce.py index 4f32a2f3f..9363f5b32 100644 --- a/monkey/infection_monkey/exploit/web_rce.py +++ b/monkey/infection_monkey/exploit/web_rce.py @@ -12,6 +12,8 @@ from infection_monkey.model import ( CHMOD_MONKEY, DOWNLOAD_TIMEOUT, DROPPER_ARG, + DROPPER_TARGET_PATH_LINUX, + DROPPER_TARGET_PATH_WIN64, ID_STRING, MONKEY_ARG, POWERSHELL_HTTP_UPLOAD, @@ -109,8 +111,8 @@ class WebRCE(HostExploiter): def pre_exploit(self): if not self.monkey_target_paths: self.monkey_target_paths = { - "linux": self.options["dropper_target_path_linux"], - "windows": self.options["dropper_target_path_win_64"], + "linux": DROPPER_TARGET_PATH_LINUX, + "windows": DROPPER_TARGET_PATH_WIN64, } self.HTTP = [str(port) for port in self.options["http_ports"]] super().pre_exploit() @@ -405,7 +407,6 @@ class WebRCE(HostExploiter): """ Gets default dropper path for the host. :return: Default monkey's destination path for corresponding host or False if failed. - E.g. config.dropper_target_path_linux(/tmp/monkey.sh) for linux host """ if not self.host.os.get("type") or ( self.host.os["type"] != "linux" and self.host.os["type"] != "windows" @@ -413,9 +414,9 @@ class WebRCE(HostExploiter): logger.error("Target's OS was either unidentified or not supported. Aborting") return False if self.host.os["type"] == "linux": - return self.options["dropper_target_path_linux"] + return DROPPER_TARGET_PATH_LINUX if self.host.os["type"] == "windows": - return self.options["dropper_target_path_win_64"] + return DROPPER_TARGET_PATH_WIN64 def get_target_url(self): """ diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index 753dc511b..a008beee2 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -10,7 +10,11 @@ from infection_monkey.exploit.tools.helpers import get_agent_dest_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.exploit.tools.wmi_tools import AccessDeniedException, WmiTools from infection_monkey.i_puppet import ExploiterResultData -from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS +from infection_monkey.model import ( + DROPPER_CMDLINE_WINDOWS, + DROPPER_TARGET_PATH_WIN64, + MONKEY_CMDLINE_WINDOWS, +) from infection_monkey.utils.brute_force import ( generate_brute_force_combinations, get_credential_string, @@ -74,7 +78,7 @@ class WmiExploiter(HostExploiter): self._set_interrupted() return self.exploit_result - target_path = get_agent_dest_path(self.host, self.options) + target_path = get_agent_dest_path(self.host) remote_full_path = SmbTools.copy_file( self.host, @@ -91,13 +95,13 @@ class WmiExploiter(HostExploiter): wmi_connection.close() return self.exploit_result # execute the remote dropper in case the path isn't final - elif remote_full_path.lower() != self.options["dropper_target_path_win_64"]: + elif remote_full_path.lower() != DROPPER_TARGET_PATH_WIN64: cmdline = DROPPER_CMDLINE_WINDOWS % { "dropper_path": remote_full_path } + build_monkey_commandline( self.host, self.current_depth - 1, - self.options["dropper_target_path_win_64"], + DROPPER_TARGET_PATH_WIN64, ) else: cmdline = MONKEY_CMDLINE_WINDOWS % { diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index 138dbf92a..e81861ee7 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -5,6 +5,10 @@ MONKEY_ARG = "m0nk3y" DROPPER_ARG = "dr0pp3r" ID_STRING = "M0NK3Y3XPL0ITABLE" +# Dropper target paths +DROPPER_TARGET_PATH_LINUX = "/tmp/monkey" +DROPPER_TARGET_PATH_WIN64 = r"C:\Windows\temp\monkey64.exe" + # Username prefix for users created by Infection Monkey USERNAME_PREFIX = "somenewuser" 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 7faa69069..c1b924439 100644 --- a/monkey/tests/data_for_tests/monkey_configs/flat_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/flat_config.json @@ -21,8 +21,6 @@ "custom_PBA_linux_cmd": "bash test.sh", "custom_PBA_windows_cmd": "powershell test.ps1", "depth": 2, - "dropper_target_path_linux": "/tmp/monkey", - "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", "exploit_lm_hash_list": ["lm_hash_1", "lm_hash_2"], "exploit_ntlm_hash_list": ["nt_hash_1", "nt_hash_2", "nt_hash_3"], "exploit_password_list": [ diff --git a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json index 31a2beace..f62cb5dcb 100644 --- a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json +++ b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json @@ -96,10 +96,6 @@ "ElasticFinger" ] }, - "dropper": { - "dropper_target_path_linux": "/tmp/monkey", - "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe" - }, "exploits": { "exploit_lm_hash_list": [], "exploit_ntlm_hash_list": [], diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py index 78ba133af..ea211444c 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py @@ -5,6 +5,8 @@ from unittest.mock import MagicMock import pytest from infection_monkey.exploit import powershell +from infection_monkey.exploit.tools.helpers import RAND_SUFFIX_LEN +from infection_monkey.model import DROPPER_TARGET_PATH_WIN64 from infection_monkey.model.host import VictimHost # Use the path_win32api_get_user_name fixture for all tests in this module @@ -14,7 +16,6 @@ USER_LIST = ["user1", "user2"] PASSWORD_LIST = ["pass1", "pass2"] LM_HASH_LIST = ["bogo_lm_1"] NT_HASH_LIST = ["bogo_nt_1", "bogo_nt_2"] -DROPPER_TARGET_PATH_64 = "C:\\agent64" mock_agent_repository = MagicMock() @@ -24,7 +25,6 @@ mock_agent_repository.get_agent_binary.return_value = BytesIO(b"BINARY_EXECUTABL @pytest.fixture def powershell_arguments(http_and_https_both_enabled_host): options = { - "dropper_target_path_win_64": DROPPER_TARGET_PATH_64, "credentials": { "exploit_user_list": USER_LIST, "exploit_password_list": PASSWORD_LIST, @@ -114,7 +114,10 @@ def test_successful_copy(monkeypatch, powershell_exploiter, powershell_arguments exploit_result = powershell_exploiter.exploit_host(**powershell_arguments) - assert DROPPER_TARGET_PATH_64 in str(mock_client.return_value.copy_file.call_args[0][1]) + # Check if the copied agent name has randomness of 8 plus dash + assert len(str(DROPPER_TARGET_PATH_WIN64)) + RAND_SUFFIX_LEN + 1 == len( + str(mock_client.return_value.copy_file.call_args[0][1]) + ) assert exploit_result.exploitation_success diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py index 2c1441961..21629f683 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py @@ -3,38 +3,39 @@ from unittest.mock import Mock import pytest from infection_monkey.exploit.tools.helpers import RAND_SUFFIX_LEN, get_agent_dest_path +from infection_monkey.model import DROPPER_TARGET_PATH_LINUX, DROPPER_TARGET_PATH_WIN64 -def _get_host_and_options(os, path): +def _get_host(os): host = Mock() host.os = {"type": os} - options = {"dropper_target_path_win_64": path, "dropper_target_path_linux": path} - return host, options + return host -@pytest.mark.parametrize("os", ["windows", "linux"]) -@pytest.mark.parametrize("path", ["C:\\monkey.exe", "/tmp/monkey-linux-64", "mon.key.exe"]) +@pytest.mark.parametrize( + "os, path", [("linux", DROPPER_TARGET_PATH_LINUX), ("windows", DROPPER_TARGET_PATH_WIN64)] +) def test_get_agent_dest_path(os, path): - host, options = _get_host_and_options(os, path) - rand_path = get_agent_dest_path(host, options) + host = _get_host(os) + rand_path = get_agent_dest_path(host) # Assert that filename got longer by RAND_SUFFIX_LEN and one dash assert len(str(rand_path)) == (len(str(path)) + RAND_SUFFIX_LEN + 1) def test_get_agent_dest_path_randomness(): - host, options = _get_host_and_options("windows", "monkey.exe") + host = _get_host("windows") - path1 = get_agent_dest_path(host, options) - path2 = get_agent_dest_path(host, options) + path1 = get_agent_dest_path(host) + path2 = get_agent_dest_path(host) assert path1 != path2 def test_get_agent_dest_path_str_place(): - host, options = _get_host_and_options("windows", "C:\\abc\\monkey.exe") + host = _get_host("windows") - rand_path = get_agent_dest_path(host, options) + rand_path = get_agent_dest_path(host) - assert str(rand_path).startswith("C:\\abc\\monkey-") + assert str(rand_path).startswith(r"C:\Windows\temp\monkey") assert str(rand_path).endswith(".exe")