From f941c9c5fc7b8a9e6bec0d3e5633aed9376f504d Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 21 May 2020 10:57:18 +0300 Subject: [PATCH 01/10] Added port not null check on island resource --- .../cc/resources/monkey_control/remote_port_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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"} From 598872afee9d2b3b9b1bfe701271df021d0f90e3 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 21 May 2020 15:34:57 +0300 Subject: [PATCH 02/10] UI crash due to multiple redundant telemetry requests fix --- .../cc/ui/src/components/pages/MapPage.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js index 997a2ae4c..2962b839a 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -23,7 +23,8 @@ class MapPageComponent extends AuthComponent { telemetryLastTimestamp: null, isScrolledUp: false, telemetryLines: 0, - telemetryCurrentLine: 0 + telemetryCurrentLine: 0, + telemetryUpdateInProgress: false }; this.telemConsole = React.createRef(); this.handleScroll = this.handleScroll.bind(this); @@ -72,16 +73,20 @@ class MapPageComponent extends AuthComponent { }; updateTelemetryFromServer = () => { + if( this.state.telemetryUpdateInProgress ) { + return + } + this.setState({telemetryUpdateInProgress: true}); this.authFetch('/api/telemetry-feed?timestamp=' + this.state.telemetryLastTimestamp) .then(res => res.json()) .then(res => { if ('telemetries' in res) { let newTelem = this.state.telemetry.concat(res['telemetries']); - this.setState( { telemetry: newTelem, - telemetryLastTimestamp: res['timestamp'] + telemetryLastTimestamp: res['timestamp'], + telemetryUpdateInProgress: false }); this.props.onStatusChange(); From 30be2715980c9e288e953ef21efdf9a3f23c5b71 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 21 May 2020 17:30:59 +0300 Subject: [PATCH 03/10] Map jitter fix --- .../monkey_island/cc/ui/src/components/map/MapOptions.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js b/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js index 742d061f4..e09e93124 100644 --- a/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js @@ -41,9 +41,12 @@ export const basic_options = { physics: { barnesHut: { gravitationalConstant: -120000, - avoidOverlap: 0.5 + avoidOverlap: 0.5, + springLength: 100, + springConstant: 0.025 }, - minVelocity: 0.75 + minVelocity: 0.3, + maxVelocity: 25 } }; From 436472b57823f8443b03fddeab331bc48f1f50f3 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 21 May 2020 19:23:23 +0300 Subject: [PATCH 04/10] Added parameter logging on monkey start, fixed bug where dropper launched monkey inproperly --- monkey/infection_monkey/dropper.py | 11 ++++++----- monkey/infection_monkey/monkey.py | 5 +++++ 2 files changed, 11 insertions(+), 5 deletions(-) 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/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}") From bda9b04393403875173db939d2206d9fee81cbff Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 21 May 2020 19:58:02 +0300 Subject: [PATCH 05/10] Added "build_command_explicitly()" UT and improved it a bit --- .../infection_monkey/exploit/tools/helpers.py | 10 +++---- .../exploit/tools/test_helpers.py | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 monkey/infection_monkey/exploit/tools/test_helpers.py 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() From 04b00b5d8822cb35a2e49602ed3e1cfed60adab0 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 22 May 2020 09:42:21 +0300 Subject: [PATCH 06/10] Revert "UI crash due to multiple redundant telemetry requests fix" This reverts commit 598872af --- .../cc/ui/src/components/pages/MapPage.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js index 2962b839a..997a2ae4c 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -23,8 +23,7 @@ class MapPageComponent extends AuthComponent { telemetryLastTimestamp: null, isScrolledUp: false, telemetryLines: 0, - telemetryCurrentLine: 0, - telemetryUpdateInProgress: false + telemetryCurrentLine: 0 }; this.telemConsole = React.createRef(); this.handleScroll = this.handleScroll.bind(this); @@ -73,20 +72,16 @@ class MapPageComponent extends AuthComponent { }; updateTelemetryFromServer = () => { - if( this.state.telemetryUpdateInProgress ) { - return - } - this.setState({telemetryUpdateInProgress: true}); this.authFetch('/api/telemetry-feed?timestamp=' + this.state.telemetryLastTimestamp) .then(res => res.json()) .then(res => { if ('telemetries' in res) { let newTelem = this.state.telemetry.concat(res['telemetries']); + this.setState( { telemetry: newTelem, - telemetryLastTimestamp: res['timestamp'], - telemetryUpdateInProgress: false + telemetryLastTimestamp: res['timestamp'] }); this.props.onStatusChange(); From bd0b1c1d34a96929c837e73c2696b50e72198e5c Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 22 May 2020 10:53:15 +0300 Subject: [PATCH 07/10] Refactored monkey local config keys into a constant --- monkey/infection_monkey/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 46f59b570..ae466237f 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 From 2cf9c9c0fe306f2ff7c201fde6bee1bde1d54079 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 24 May 2020 13:55:11 +0300 Subject: [PATCH 08/10] Fix minor linter issues --- envs/monkey_zoo/blackbox/conftest.py | 1 - .../blackbox/island_client/monkey_island_requests.py | 7 ++++--- .../telem_sample_parsing/sample_multiplier/fake_monkey.py | 4 ++-- envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py | 8 ++++---- monkey/monkey_island/cc/bootloader_server.py | 6 ++++-- 5 files changed, 14 insertions(+), 12 deletions(-) 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/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: From 1e812b987aa021bd3d58263e8709a1f08f8dc65b Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Mon, 25 May 2020 10:05:19 +0300 Subject: [PATCH 09/10] Revert "Map jitter fix" This reverts commit 30be2715 --- .../monkey_island/cc/ui/src/components/map/MapOptions.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js b/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js index e09e93124..742d061f4 100644 --- a/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/map/MapOptions.js @@ -41,12 +41,9 @@ export const basic_options = { physics: { barnesHut: { gravitationalConstant: -120000, - avoidOverlap: 0.5, - springLength: 100, - springConstant: 0.025 + avoidOverlap: 0.5 }, - minVelocity: 0.3, - maxVelocity: 25 + minVelocity: 0.75 } }; From 3405f29f15d40a4b0b681521b525ad0bd327f272 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Mon, 25 May 2020 18:25:15 +0300 Subject: [PATCH 10/10] Added small readability changes --- monkey/infection_monkey/config.py | 2 +- monkey/infection_monkey/control.py | 2 +- monkey/monkey_island/cc/resources/monkey.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index ae466237f..910b0abd7 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -291,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/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)