diff --git a/envs/monkey_zoo/blackbox/conftest.py b/envs/monkey_zoo/blackbox/conftest.py index 0444a4101..4909bcbc7 100644 --- a/envs/monkey_zoo/blackbox/conftest.py +++ b/envs/monkey_zoo/blackbox/conftest.py @@ -24,4 +24,3 @@ def no_gcp(request): @pytest.fixture(scope='session') def quick_performance_tests(request): return request.config.getoption("--quick-performance-tests") - diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py index babc9c7a0..98acb5f7f 100644 --- a/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py @@ -90,9 +90,10 @@ class MonkeyIslandRequests(object): @_Decorators.refresh_jwt_token def patch(self, url, data: Dict): return requests.patch(self.addr + url, # noqa: DUO123 - data=data, - headers=self.get_jwt_header(), - verify=False) + data=data, + headers=self.get_jwt_header(), + verify=False + ) @_Decorators.refresh_jwt_token def delete(self, url): diff --git a/envs/monkey_zoo/blackbox/tests/performance/telem_sample_parsing/sample_multiplier/fake_monkey.py b/envs/monkey_zoo/blackbox/tests/performance/telem_sample_parsing/sample_multiplier/fake_monkey.py index 89cdf5cad..1d140e396 100644 --- a/envs/monkey_zoo/blackbox/tests/performance/telem_sample_parsing/sample_multiplier/fake_monkey.py +++ b/envs/monkey_zoo/blackbox/tests/performance/telem_sample_parsing/sample_multiplier/fake_monkey.py @@ -10,9 +10,9 @@ class FakeMonkey: self.original_guid = guid self.fake_ip_generator = fake_ip_generator self.on_island = on_island - self.fake_guid = str(random.randint(1000000000000, 9999999999999)) + self.fake_guid = str(random.randint(1000000000000, 9999999999999)) # noqa: DUO102 self.fake_ips = fake_ip_generator.generate_fake_ips_for_real_ips(ips) def change_fake_data(self): self.fake_ips = self.fake_ip_generator.generate_fake_ips_for_real_ips(self.original_ips) - self.fake_guid = str(random.randint(1000000000000, 9999999999999)) + self.fake_guid = str(random.randint(1000000000000, 9999999999999)) # noqa: DUO102 diff --git a/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py b/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py index 633f406a5..927b5b6f3 100644 --- a/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py +++ b/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py @@ -15,10 +15,10 @@ class GCPHandler(object): self.zone = zone try: # pass the key file to gcp - subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) + subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) # noqa: DUO116 LOGGER.info("GCP Handler passed key") # set project - subprocess.call(GCPHandler.get_set_project_command(project_id), shell=True) + subprocess.call(GCPHandler.get_set_project_command(project_id), shell=True) # noqa: DUO116 LOGGER.info("GCP Handler set project") LOGGER.info("GCP Handler initialized successfully") except Exception as e: @@ -32,14 +32,14 @@ class GCPHandler(object): """ LOGGER.info("Setting up all GCP machines...") try: - subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True) + subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True) # noqa: DUO116 LOGGER.info("GCP machines successfully started.") except Exception as e: LOGGER.error("GCP Handler failed to start GCP machines: %s" % e) def stop_machines(self, machine_list): try: - subprocess.call((GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True) + subprocess.call((GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True) # noqa: DUO116 LOGGER.info("GCP machines stopped successfully.") except Exception as e: LOGGER.error("GCP Handler failed to stop network machines: %s" % e) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 46f59b570..910b0abd7 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -13,6 +13,7 @@ GUID = str(uuid.getnode()) EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin') SENSITIVE_FIELDS = ["exploit_password_list", "exploit_user_list", "exploit_ssh_keys"] +LOCAL_CONFIG_VARS = ["name", "id", "current_server", "max_depth"] HIDDEN_FIELD_REPLACEMENT_CONTENT = "hidden" @@ -22,7 +23,7 @@ class Configuration(object): for key, value in list(formatted_data.items()): if key.startswith('_'): continue - if key in ["name", "id", "current_server", "max_depth"]: + if key in LOCAL_CONFIG_VARS: continue if self._depth_from_commandline and key == "depth": self.max_depth = value @@ -290,7 +291,7 @@ class Configuration(object): ########################### export_monkey_telems = False - def get_hop_count(self): + def get_hop_distance_to_island(self): return self.max_depth - self.depth diff --git a/monkey/infection_monkey/control.py b/monkey/infection_monkey/control.py index a9aa246cb..4eacc728b 100644 --- a/monkey/infection_monkey/control.py +++ b/monkey/infection_monkey/control.py @@ -327,7 +327,7 @@ class ControlClient(object): @staticmethod def should_monkey_run(vulnerable_port: str) -> bool: if vulnerable_port and \ - WormConfiguration.get_hop_count() > 1 and \ + WormConfiguration.get_hop_distance_to_island() > 1 and \ ControlClient.can_island_see_port(vulnerable_port) and \ WormConfiguration.started_on_island: raise PlannedShutdownException("Monkey shouldn't run on current machine " diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index dc7e5dc27..fe6709003 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -116,11 +116,12 @@ class MonkeyDrops(object): LOG.warning("Cannot set reference date to destination file") monkey_options = \ - build_monkey_commandline_explicitly(self.opts.parent, - self.opts.tunnel, - self.opts.server, - self.opts.depth, - self.opts.vulnerable_port) + build_monkey_commandline_explicitly(parent=self.opts.parent, + tunnel=self.opts.tunnel, + server=self.opts.server, + depth=self.opts.depth, + location=None, + vulnerable_port=self.opts.vulnerable_port) if OperatingSystem.Windows == SystemInfoCollector.get_os(): monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {'monkey_path': self._config['destination_path']} + monkey_options diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index b5fce82f7..e26f6ff01 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -46,19 +46,19 @@ def build_monkey_commandline_explicitly(parent=None, tunnel=None, server=None, d cmdline = "" if parent is not None: - cmdline += " -p " + parent + cmdline += f" -p {parent}" if tunnel is not None: - cmdline += " -t " + tunnel + cmdline += f" -t {tunnel}" if server is not None: - cmdline += " -s " + server + cmdline += f" -s {server}" if depth is not None: - if depth < 0: + if int(depth) < 0: depth = 0 cmdline += f" -d {depth}" if location is not None: cmdline += f" -l {location}" if vulnerable_port is not None: - cmdline += f" -vp {str(vulnerable_port)}" + cmdline += f" -vp {vulnerable_port}" return cmdline diff --git a/monkey/infection_monkey/exploit/tools/test_helpers.py b/monkey/infection_monkey/exploit/tools/test_helpers.py new file mode 100644 index 000000000..5d7dd422d --- /dev/null +++ b/monkey/infection_monkey/exploit/tools/test_helpers.py @@ -0,0 +1,28 @@ +import unittest + +from infection_monkey.exploit.tools.helpers import build_monkey_commandline_explicitly + + +class TestHelpers(unittest.TestCase): + + def test_build_monkey_commandline_explicitly(self): + test1 = " -p 101010 -t 10.10.101.10 -s 127.127.127.127:5000 -d 0 -l C:\\windows\\abc -vp 80" + result1 = build_monkey_commandline_explicitly(101010, + "10.10.101.10", + "127.127.127.127:5000", + 0, + "C:\\windows\\abc", + 80) + + test2 = " -p parent -s 127.127.127.127:5000 -d 0 -vp 80" + result2 = build_monkey_commandline_explicitly(parent="parent", + server="127.127.127.127:5000", + depth="0", + vulnerable_port="80") + + self.assertEqual(test1, result1) + self.assertEqual(test2, result2) + + +if __name__ == '__main__': + unittest.main() diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 6dd69e0eb..a31ea4d47 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -74,6 +74,7 @@ class InfectionMonkey(object): arg_parser.add_argument('-d', '--depth', type=int) arg_parser.add_argument('-vp', '--vulnerable-port') self._opts, self._args = arg_parser.parse_known_args(self._args) + self.log_arguments() self._parent = self._opts.parent self._default_tunnel = self._opts.tunnel @@ -387,3 +388,7 @@ class InfectionMonkey(object): def is_started_on_island(self): island_ip = remove_port_from_ip_string(self._default_server) return is_running_on_server(island_ip) and WormConfiguration.depth == WormConfiguration.max_depth + + def log_arguments(self): + arg_string = " ".join([f"{key}: {value}" for key, value in vars(self._opts).items()]) + LOG.info(f"Monkey started with arguments: {arg_string}") diff --git a/monkey/monkey_island/cc/bootloader_server.py b/monkey/monkey_island/cc/bootloader_server.py index 3024b6a42..b1f7ec484 100644 --- a/monkey/monkey_island/cc/bootloader_server.py +++ b/monkey/monkey_island/cc/bootloader_server.py @@ -10,7 +10,7 @@ import pymongo from monkey_island.cc.environment import Environment # Disable "unverified certificate" warnings when sending requests to island -urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # noqa: DUO131 logger = logging.getLogger(__name__) @@ -29,7 +29,9 @@ class BootloaderHTTPRequestHandler(BaseHTTPRequestHandler): post_data = self.rfile.read(content_length).decode() island_server_path = BootloaderHTTPRequestHandler.get_bootloader_resource_url(self.request.getsockname()[0]) island_server_path = parse.urljoin(island_server_path, self.path[1:]) - r = requests.post(url=island_server_path, data=post_data, verify=False) + # The island server doesn't always have a correct SSL cert installed (By default it comes with a self signed one), + # that's why we're not verifying the cert in this request. + r = requests.post(url=island_server_path, data=post_data, verify=False) # noqa: DUO123 try: if r.status_code != 200: diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index e61765376..181ce94b2 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -58,6 +58,7 @@ class Monkey(flask_restful.Resource): return mongo.db.monkey.update({"_id": monkey["_id"]}, update, upsert=False) # Used by monkey. can't secure. + # Called on monkey wakeup to initialize local configuration @TestTelemStore.store_test_telem def post(self, **kw): monkey_json = json.loads(request.data) diff --git a/monkey/monkey_island/cc/resources/monkey_control/remote_port_check.py b/monkey/monkey_island/cc/resources/monkey_control/remote_port_check.py index d10ad067c..06e49b145 100644 --- a/monkey/monkey_island/cc/resources/monkey_control/remote_port_check.py +++ b/monkey/monkey_island/cc/resources/monkey_control/remote_port_check.py @@ -8,7 +8,7 @@ class RemotePortCheck(flask_restful.Resource): # Used by monkey. can't secure. def get(self, port): - if check_tcp_port(request.remote_addr, port): + if port and check_tcp_port(request.remote_addr, port): return {"status": "port_visible"} else: return {"status": "port_invisible"}