Merge branch '1374/bug-fix' into develop

Pull request #1387
This commit is contained in:
Mike Salvatore 2021-07-31 19:38:40 -04:00
commit 294ec0d546
4 changed files with 146 additions and 141 deletions

View File

@ -17,7 +17,7 @@
"type": "snippet", "type": "snippet",
"path": "monkey/infection_monkey/config.py", "path": "monkey/infection_monkey/config.py",
"comments": [], "comments": [],
"firstLineNumber": 126, "firstLineNumber": 124,
"lines": [ "lines": [
" exploiter_classes = []", " exploiter_classes = []",
" system_info_collector_classes = []", " system_info_collector_classes = []",
@ -33,12 +33,11 @@
"type": "snippet", "type": "snippet",
"path": "monkey/infection_monkey/monkey.py", "path": "monkey/infection_monkey/monkey.py",
"comments": [], "comments": [],
"firstLineNumber": 159, "firstLineNumber": 220,
"lines": [ "lines": [
" ",
" if not self._keep_running or not WormConfiguration.alive:", " if not self._keep_running or not WormConfiguration.alive:",
" break", " break",
"*", " ",
"* machines = self._network.get_victim_machines(", "* machines = self._network.get_victim_machines(",
"* max_find=WormConfiguration.victims_max_find,", "* max_find=WormConfiguration.victims_max_find,",
"* stop_callback=ControlClient.check_for_stop,", "* stop_callback=ControlClient.check_for_stop,",
@ -77,11 +76,11 @@
"symbols": {}, "symbols": {},
"file_version": "2.0.1", "file_version": "2.0.1",
"meta": { "meta": {
"app_version": "0.4.1-1", "app_version": "0.4.9-1",
"file_blobs": { "file_blobs": {
"monkey/infection_monkey/config.py": "ffdea551eb1ae2b65d4700db896c746771e7954c", "monkey/infection_monkey/config.py": "0bede1c57949987f5c8025bd9b8f7aa29d02a6af",
"monkey/infection_monkey/monkey.py": "c81a6251746e3af4e93eaa7d50af44d33debe05c", "monkey/infection_monkey/monkey.py": "89d2fa8452dee70f6d2985a9bb452f0159ea8219",
"monkey/monkey_island/cc/services/config_schema/internal.py": "d03527b89c21dfb832a15e4f7d55f4027d83b453" "monkey/monkey_island/cc/services/config_schema/internal.py": "1ce1c864b1df332b65e16b4ce9ed533affd73f9c"
} }
} }
} }

View File

@ -52,6 +52,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Attempted to delete a directory when monkey config reset was called. #1054 - Attempted to delete a directory when monkey config reset was called. #1054
- An errant space in the windows commands to run monkey manually. #1153 - An errant space in the windows commands to run monkey manually. #1153
- gevent tracebacks in console output. #859 - gevent tracebacks in console output. #859
- Crash and failure to run PBAs if max depth reached. #1374
### Security ### Security
- Address minor issues discovered by Dlint. #1075 - Address minor issues discovered by Dlint. #1075

View File

@ -22,7 +22,6 @@ from infection_monkey.config import GUID, WormConfiguration
from infection_monkey.network.info import check_internet_access, local_ips from infection_monkey.network.info import check_internet_access, local_ips
from infection_monkey.transport.http import HTTPConnectProxy from infection_monkey.transport.http import HTTPConnectProxy
from infection_monkey.transport.tcp import TcpProxy from infection_monkey.transport.tcp import TcpProxy
from infection_monkey.utils.exceptions.planned_shutdown_exception import PlannedShutdownException
requests.packages.urllib3.disable_warnings() requests.packages.urllib3.disable_warnings()
@ -401,10 +400,8 @@ class ControlClient(object):
and ControlClient.can_island_see_port(vulnerable_port) and ControlClient.can_island_see_port(vulnerable_port)
and WormConfiguration.started_on_island and WormConfiguration.started_on_island
): ):
raise PlannedShutdownException( return False
"Monkey shouldn't run on current machine "
"(it will be exploited later with more depth)."
)
return True return True
@staticmethod @staticmethod

View File

@ -40,7 +40,7 @@ from infection_monkey.utils.monkey_dir import (
from infection_monkey.utils.monkey_log_path import get_monkey_log_path from infection_monkey.utils.monkey_log_path import get_monkey_log_path
from infection_monkey.windows_upgrader import WindowsUpgrader from infection_monkey.windows_upgrader import WindowsUpgrader
MAX_DEPTH_REACHED_MESSAGE = "Reached max depth, shutting down" MAX_DEPTH_REACHED_MESSAGE = "Reached max depth, skipping propagation phase."
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -62,6 +62,8 @@ class InfectionMonkey(object):
self._default_server_port = None self._default_server_port = None
self._opts = None self._opts = None
self._upgrading_to_64 = False self._upgrading_to_64 = False
self._monkey_tunnel = None
self._post_breach_phase = None
def initialize(self): def initialize(self):
LOG.info("Monkey is initializing...") LOG.info("Monkey is initializing...")
@ -125,25 +127,84 @@ class InfectionMonkey(object):
if is_running_on_island(): if is_running_on_island():
WormConfiguration.started_on_island = True WormConfiguration.started_on_island = True
ControlClient.report_start_on_island() ControlClient.report_start_on_island()
ControlClient.should_monkey_run(self._opts.vulnerable_port)
if not ControlClient.should_monkey_run(self._opts.vulnerable_port):
raise PlannedShutdownException(
"Monkey shouldn't run on current machine "
"(it will be exploited later with more depth)."
)
if firewall.is_enabled(): if firewall.is_enabled():
firewall.add_firewall_rule() firewall.add_firewall_rule()
monkey_tunnel = ControlClient.create_control_tunnel() self._monkey_tunnel = ControlClient.create_control_tunnel()
if monkey_tunnel: if self._monkey_tunnel:
monkey_tunnel.start() self._monkey_tunnel.start()
StateTelem(is_done=False, version=get_version()).send() StateTelem(is_done=False, version=get_version()).send()
TunnelTelem().send() TunnelTelem().send()
LOG.debug("Starting the post-breach phase asynchronously.") LOG.debug("Starting the post-breach phase asynchronously.")
post_breach_phase = Thread(target=self.start_post_breach_phase) self._post_breach_phase = Thread(target=self.start_post_breach_phase)
post_breach_phase.start() self._post_breach_phase.start()
LOG.debug("Starting the propagation phase.") if not InfectionMonkey.max_propagation_depth_reached():
self.shutdown_by_max_depth_reached() LOG.info("Starting the propagation phase.")
LOG.debug("Running with depth: %d" % WormConfiguration.depth)
self.propagate()
else:
LOG.info("Maximum propagation depth has been reached; monkey will not propagate.")
TraceTelem(MAX_DEPTH_REACHED_MESSAGE).send()
InfectionMonkey.run_ransomware()
# if host was exploited, before continue to closing the tunnel ensure the exploited
# host had its chance to
# connect to the tunnel
if len(self._exploited_machines) > 0:
time_to_sleep = WormConfiguration.keep_tunnel_open_time
LOG.info(
"Sleeping %d seconds for exploited machines to connect to tunnel", time_to_sleep
)
time.sleep(time_to_sleep)
except PlannedShutdownException:
LOG.info(
"A planned shutdown of the Monkey occurred. Logging the reason and finishing "
"execution."
)
LOG.exception("Planned shutdown, reason:")
finally:
if self._monkey_tunnel:
self._monkey_tunnel.stop()
self._monkey_tunnel.join()
if self._post_breach_phase:
self._post_breach_phase.join()
def start_post_breach_phase(self):
self.collect_system_info_if_configured()
PostBreach().execute_all_configured()
@staticmethod
def max_propagation_depth_reached():
return 0 == WormConfiguration.depth
def collect_system_info_if_configured(self):
LOG.debug("Calling for system info collection")
try:
system_info_collector = SystemInfoCollector()
system_info = system_info_collector.get_info()
SystemInfoTelem(system_info).send()
except Exception as e:
LOG.exception(f"Exception encountered during system info collection: {str(e)}")
def shutdown_by_not_alive_config(self):
if not WormConfiguration.alive:
raise PlannedShutdownException("Marked 'not alive' from configuration.")
def propagate(self):
for iteration_index in range(WormConfiguration.max_iterations): for iteration_index in range(WormConfiguration.max_iterations):
ControlClient.keepalive() ControlClient.keepalive()
ControlClient.load_control_config() ControlClient.load_control_config()
@ -195,17 +256,13 @@ class InfectionMonkey(object):
LOG.debug("Skipping %r - exploitation failed before", machine) LOG.debug("Skipping %r - exploitation failed before", machine)
continue continue
if monkey_tunnel: if self._monkey_tunnel:
monkey_tunnel.set_tunnel_for_host(machine) self._monkey_tunnel.set_tunnel_for_host(machine)
if self._default_server: if self._default_server:
if self._network.on_island(self._default_server): if self._network.on_island(self._default_server):
machine.set_default_server( machine.set_default_server(
get_interface_to_target(machine.ip_addr) get_interface_to_target(machine.ip_addr)
+ ( + (":" + self._default_server_port if self._default_server_port else "")
":" + self._default_server_port
if self._default_server_port
else ""
)
) )
else: else:
machine.set_default_server(self._default_server) machine.set_default_server(self._default_server)
@ -232,8 +289,6 @@ class InfectionMonkey(object):
if not self._keep_running: if not self._keep_running:
break break
InfectionMonkey.run_ransomware()
if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1): if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1):
time_to_sleep = WormConfiguration.timeout_between_iterations time_to_sleep = WormConfiguration.timeout_between_iterations
LOG.info("Sleeping %d seconds before next life cycle iteration", time_to_sleep) LOG.info("Sleeping %d seconds before next life cycle iteration", time_to_sleep)
@ -244,53 +299,6 @@ class InfectionMonkey(object):
elif not WormConfiguration.alive: elif not WormConfiguration.alive:
LOG.info("Marked not alive from configuration") LOG.info("Marked not alive from configuration")
# if host was exploited, before continue to closing the tunnel ensure the exploited
# host had its chance to
# connect to the tunnel
if len(self._exploited_machines) > 0:
time_to_sleep = WormConfiguration.keep_tunnel_open_time
LOG.info(
"Sleeping %d seconds for exploited machines to connect to tunnel", time_to_sleep
)
time.sleep(time_to_sleep)
if monkey_tunnel:
monkey_tunnel.stop()
monkey_tunnel.join()
post_breach_phase.join()
except PlannedShutdownException:
LOG.info(
"A planned shutdown of the Monkey occurred. Logging the reason and finishing "
"execution."
)
LOG.exception("Planned shutdown, reason:")
def start_post_breach_phase(self):
self.collect_system_info_if_configured()
PostBreach().execute_all_configured()
def shutdown_by_max_depth_reached(self):
if 0 == WormConfiguration.depth:
TraceTelem(MAX_DEPTH_REACHED_MESSAGE).send()
raise PlannedShutdownException(MAX_DEPTH_REACHED_MESSAGE)
else:
LOG.debug("Running with depth: %d" % WormConfiguration.depth)
def collect_system_info_if_configured(self):
LOG.debug("Calling for system info collection")
try:
system_info_collector = SystemInfoCollector()
system_info = system_info_collector.get_info()
SystemInfoTelem(system_info).send()
except Exception as e:
LOG.exception(f"Exception encountered during system info collection: {str(e)}")
def shutdown_by_not_alive_config(self):
if not WormConfiguration.alive:
raise PlannedShutdownException("Marked 'not alive' from configuration.")
def upgrade_to_64_if_needed(self): def upgrade_to_64_if_needed(self):
if WindowsUpgrader.should_upgrade(): if WindowsUpgrader.should_upgrade():
self._upgrading_to_64 = True self._upgrading_to_64 = True