def get_label_for_endpoint(endpoint_id): node_service = monkey_island.cc.services.node.NodeService if endpoint_id == ObjectId("000000000000000000000000"): return 'MonkeyIsland' if Monkey.is_monkey(endpoint_id): return Monkey.get_label_by_id(endpoint_id) else: return node_service.get_node_label( node_service.get_node_by_id(endpoint_id))
def post(self): telemetry_json = json.loads(request.data) telemetry_json['data'] = json.loads(telemetry_json['data']) telemetry_json['timestamp'] = datetime.now() telemetry_json['command_control_channel'] = {'src': request.remote_addr, 'dst': request.host} # Monkey communicated, so it's alive. Update the TTL. Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid']).renew_ttl() monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) NodeService.update_monkey_modify_time(monkey["_id"]) process_telemetry(telemetry_json) telem_id = mongo.db.telemetry.insert(telemetry_json) return mongo.db.telemetry.find_one_or_404({"_id": telem_id})
def test_get_label_by_id(self): self.fail_if_not_testing_env() self.clean_monkey_db() hostname_example = "a_hostname" ip_example = "1.1.1.1" linux_monkey = Monkey(guid=str(uuid.uuid4()), description="Linux shay-Virtual-Machine", hostname=hostname_example, ip_addresses=[ip_example]) linux_monkey.save() logger.debug(id(Monkey.get_label_by_id)) cache_info_before_query = Monkey.get_label_by_id.storage.backend.cache_info( ) self.assertEqual(cache_info_before_query.hits, 0) self.assertEqual(cache_info_before_query.misses, 0) # not cached label = Monkey.get_label_by_id(linux_monkey.id) cache_info_after_query_1 = Monkey.get_label_by_id.storage.backend.cache_info( ) self.assertEqual(cache_info_after_query_1.hits, 0) self.assertEqual(cache_info_after_query_1.misses, 1) logger.debug("1) ID: {} label: {}".format(linux_monkey.id, label)) self.assertIsNotNone(label) self.assertIn(hostname_example, label) self.assertIn(ip_example, label) # should be cached label = Monkey.get_label_by_id(linux_monkey.id) logger.debug("2) ID: {} label: {}".format(linux_monkey.id, label)) cache_info_after_query_2 = Monkey.get_label_by_id.storage.backend.cache_info( ) self.assertEqual(cache_info_after_query_2.hits, 1) self.assertEqual(cache_info_after_query_2.misses, 1) # set hostname deletes the id from the cache. linux_monkey.set_hostname("Another hostname") # should be a miss label = Monkey.get_label_by_id(linux_monkey.id) logger.debug("3) ID: {} label: {}".format(linux_monkey.id, label)) cache_info_after_query_3 = Monkey.get_label_by_id.storage.backend.cache_info( ) logger.debug("Cache info: {}".format(str(cache_info_after_query_3))) # still 1 hit only self.assertEqual(cache_info_after_query_3.hits, 1) self.assertEqual(cache_info_after_query_3.misses, 2)
def test_get_label_by_id(self): hostname_example = "a_hostname" ip_example = "1.1.1.1" linux_monkey = Monkey( guid=str(uuid.uuid4()), description="Linux shay-Virtual-Machine", hostname=hostname_example, ip_addresses=[ip_example], ) linux_monkey.save() logger.debug(id(Monkey.get_label_by_id)) cache_info_before_query = Monkey.get_label_by_id.storage.backend.cache_info( ) assert cache_info_before_query.hits == 0 assert cache_info_before_query.misses == 0 # not cached label = Monkey.get_label_by_id(linux_monkey.id) cache_info_after_query_1 = Monkey.get_label_by_id.storage.backend.cache_info( ) assert cache_info_after_query_1.hits == 0 assert cache_info_after_query_1.misses == 1 logger.debug("1) ID: {} label: {}".format(linux_monkey.id, label)) assert label is not None assert hostname_example in label assert ip_example in label # should be cached label = Monkey.get_label_by_id(linux_monkey.id) logger.debug("2) ID: {} label: {}".format(linux_monkey.id, label)) cache_info_after_query_2 = Monkey.get_label_by_id.storage.backend.cache_info( ) assert cache_info_after_query_2.hits == 1 assert cache_info_after_query_2.misses == 1 # set hostname deletes the id from the cache. linux_monkey.set_hostname("Another hostname") # should be a miss label = Monkey.get_label_by_id(linux_monkey.id) logger.debug("3) ID: {} label: {}".format(linux_monkey.id, label)) cache_info_after_query_3 = Monkey.get_label_by_id.storage.backend.cache_info( ) logger.debug("Cache info: {}".format(str(cache_info_after_query_3))) # still 1 hit only assert cache_info_after_query_3.hits == 1 assert cache_info_after_query_3.misses == 2
def process_aws_telemetry(collector_results, monkey_guid): relevant_monkey = Monkey.get_single_monkey_by_guid(monkey_guid) if "instance_id" in collector_results: instance_id = collector_results["instance_id"] relevant_monkey.aws_instance_id = instance_id relevant_monkey.save() logger.debug("Updated Monkey {} with aws instance id {}".format( str(relevant_monkey), instance_id))
def get_edge_label(edge): node_service = monkey_island.cc.services.node.NodeService from_id = edge["from"] to_id = edge["to"] try: from_label = Monkey.get_label_by_id(from_id) except MonkeyNotFoundError: from_label = node_service.get_node_by_id(from_id)['domain_name'] if to_id == ObjectId("000000000000000000000000"): to_label = 'MonkeyIsland' else: if Monkey.is_monkey(to_id): to_label = Monkey.get_label_by_id(to_id) else: to_label = node_service.get_node_label( node_service.get_node_by_id(to_id)) return "%s %s %s" % (from_label, RIGHT_ARROW, to_label)
def get_technique_status_and_data(): monkeys = list(Monkey.objects()) info = [{ "src": monkey["command_control_channel"]["src"], "dst": monkey["command_control_channel"]["dst"], } for monkey in monkeys if monkey["command_control_channel"]] if info: status = ScanStatus.USED.value else: status = ScanStatus.UNSCANNED.value return (status, info)
def get_technique_status_and_data(): monkeys = list(Monkey.objects()) info = [{ 'src': monkey['command_control_channel']['src'], 'dst': monkey['command_control_channel']['dst'] } for monkey in monkeys if monkey['command_control_channel']] if info: status = ScanStatus.USED.value else: status = ScanStatus.UNSCANNED.value return (status, info)
def get_report_data(): monkeys = list(Monkey.objects()) info = [{'src': monkey['command_control_channel']['src'], 'dst': monkey['command_control_channel']['dst']} for monkey in monkeys if monkey['command_control_channel']] if info: status = ScanStatus.USED.value else: status = ScanStatus.UNSCANNED.value data = T1041.get_base_data_by_status(status) data.update({'command_control_channel': info}) return data
def post(self): telemetry_json = json.loads(request.data) telemetry_json["data"] = json.loads(telemetry_json["data"]) telemetry_json["timestamp"] = datetime.now() telemetry_json["command_control_channel"] = { "src": request.remote_addr, "dst": request.host, } # Monkey communicated, so it's alive. Update the TTL. Monkey.get_single_monkey_by_guid( telemetry_json["monkey_guid"]).renew_ttl() monkey = NodeService.get_monkey_by_guid(telemetry_json["monkey_guid"]) NodeService.update_monkey_modify_time(monkey["_id"]) process_telemetry(telemetry_json) save_telemetry(telemetry_json) return {}, 201
def test_ttl_renewal(self): # Arrange monkey = Monkey(guid=str(uuid.uuid4())) monkey.save() assert monkey.ttl_ref is None # act + assert monkey.renew_ttl() assert monkey.ttl_ref
def test_is_monkey(self): a_monkey = Monkey(guid=str(uuid.uuid4())) a_monkey.save() cache_info_before_query = Monkey.is_monkey.storage.backend.cache_info() assert cache_info_before_query.hits == 0 # not cached assert Monkey.is_monkey(a_monkey.id) fake_id = "123456789012" assert not Monkey.is_monkey(fake_id) # should be cached assert Monkey.is_monkey(a_monkey.id) assert not Monkey.is_monkey(fake_id) cache_info_after_query = Monkey.is_monkey.storage.backend.cache_info() assert cache_info_after_query.hits == 2
def get_technique_status_and_data(): monkeys = Monkey.get_tunneled_monkeys() hops = [] for monkey in monkeys: proxy_count = 0 proxy = initial = monkey while proxy.tunnel: proxy_count += 1 proxy = proxy.tunnel if proxy_count > 1: hops.append({ "from": initial.get_network_info(), "to": proxy.get_network_info(), "count": proxy_count, }) status = ScanStatus.USED.value if hops else ScanStatus.UNSCANNED.value return (status, hops)
def get_report_data(): monkeys = Monkey.get_tunneled_monkeys() hops = [] for monkey in monkeys: proxy_count = 0 proxy = initial = monkey while proxy.tunnel: proxy_count += 1 proxy = proxy.tunnel if proxy_count > 1: hops.append({'from': initial.get_network_info(), 'to': proxy.get_network_info(), 'count': proxy_count}) status = ScanStatus.USED.value if hops else ScanStatus.UNSCANNED.value data = T1188.get_base_data_by_status(status) data.update({'hops': hops}) return data
def test_ttl_renewal(self): self.fail_if_not_testing_env() self.clean_monkey_db() # Arrange monkey = Monkey(guid=str(uuid.uuid4())) monkey.save() self.assertIsNone(monkey.ttl_ref) # act + assert monkey.renew_ttl() self.assertIsNotNone(monkey.ttl_ref)
def test_get_single_monkey_by_id(self): # Arrange a_monkey = Monkey(guid=str(uuid.uuid4())) a_monkey.save() # Act + assert # Find the existing one assert Monkey.get_single_monkey_by_id(a_monkey.id) is not None # Raise on non-existent monkey with pytest.raises(MonkeyNotFoundError) as _: _ = Monkey.get_single_monkey_by_id("abcdefabcdefabcdefabcdef")
def test_is_monkey(self): self.fail_if_not_testing_env() self.clean_monkey_db() a_monkey = Monkey(guid=str(uuid.uuid4())) a_monkey.save() cache_info_before_query = Monkey.is_monkey.storage.backend.cache_info() self.assertEqual(cache_info_before_query.hits, 0) # not cached self.assertTrue(Monkey.is_monkey(a_monkey.id)) fake_id = "123456789012" self.assertFalse(Monkey.is_monkey(fake_id)) # should be cached self.assertTrue(Monkey.is_monkey(a_monkey.id)) self.assertFalse(Monkey.is_monkey(fake_id)) cache_info_after_query = Monkey.is_monkey.storage.backend.cache_info() self.assertEqual(cache_info_after_query.hits, 2)
def test_get_single_monkey_by_id(self): self.fail_if_not_testing_env() self.clean_monkey_db() # Arrange a_monkey = Monkey(guid=str(uuid.uuid4())) a_monkey.save() # Act + assert # Find the existing one self.assertIsNotNone(Monkey.get_single_monkey_by_id(a_monkey.id)) # Raise on non-existent monkey with pytest.raises(MonkeyNotFoundError) as e_info: _ = Monkey.get_single_monkey_by_id("abcdefabcdefabcdefabcdef")
def process_hostname_telemetry(collector_results, monkey_guid): Monkey.get_single_monkey_by_guid(monkey_guid).set_hostname(collector_results["hostname"])
def test_is_dead(self): self.fail_if_not_testing_env() self.clean_monkey_db() # Arrange alive_monkey_ttl = MonkeyTtl.create_ttl_expire_in(30) alive_monkey_ttl.save() alive_monkey = Monkey(guid=str(uuid.uuid4()), dead=False, ttl_ref=alive_monkey_ttl.id) alive_monkey.save() # MIA stands for Missing In Action mia_monkey_ttl = MonkeyTtl.create_ttl_expire_in(30) mia_monkey_ttl.save() mia_monkey = Monkey(guid=str(uuid.uuid4()), dead=False, ttl_ref=mia_monkey_ttl.id) mia_monkey.save() # Emulate timeout - ttl is manually deleted here, since we're using mongomock and not a real mongo instance. sleep(1) mia_monkey_ttl.delete() dead_monkey = Monkey(guid=str(uuid.uuid4()), dead=True) dead_monkey.save() # act + assert self.assertTrue(dead_monkey.is_dead()) self.assertTrue(mia_monkey.is_dead()) self.assertFalse(alive_monkey.is_dead())
def test_get_tunneled_monkeys(self): linux_monkey = Monkey(guid=str(uuid.uuid4()), description="Linux shay-Virtual-Machine") windows_monkey = Monkey(guid=str(uuid.uuid4()), description="Windows bla bla bla", tunnel=linux_monkey) unknown_monkey = Monkey(guid=str(uuid.uuid4()), description="bla bla bla", tunnel=windows_monkey) linux_monkey.save() windows_monkey.save() unknown_monkey.save() tunneled_monkeys = Monkey.get_tunneled_monkeys() test = bool(windows_monkey in tunneled_monkeys and unknown_monkey in tunneled_monkeys and linux_monkey not in tunneled_monkeys and len(tunneled_monkeys) == 2) assert test
def test_get_os(self): linux_monkey = Monkey( guid=str(uuid.uuid4()), description= "Linux shay-Virtual-Machine 4.15.0-50-generic #54-Ubuntu", ) windows_monkey = Monkey(guid=str(uuid.uuid4()), description="Windows bla bla bla") unknown_monkey = Monkey(guid=str(uuid.uuid4()), description="bla bla bla") linux_monkey.save() windows_monkey.save() unknown_monkey.save() assert 1 == len( [m for m in Monkey.objects() if m.get_os() == "windows"]) assert 1 == len([m for m in Monkey.objects() if m.get_os() == "linux"]) assert 1 == len( [m for m in Monkey.objects() if m.get_os() == "unknown"])
def test_get_tunneled_monkeys(self): self.fail_if_not_testing_env() self.clean_monkey_db() linux_monkey = Monkey(guid=str(uuid.uuid4()), description="Linux shay-Virtual-Machine") windows_monkey = Monkey(guid=str(uuid.uuid4()), description="Windows bla bla bla", tunnel=linux_monkey) unknown_monkey = Monkey(guid=str(uuid.uuid4()), description="bla bla bla", tunnel=windows_monkey) linux_monkey.save() windows_monkey.save() unknown_monkey.save() tunneled_monkeys = Monkey.get_tunneled_monkeys() test = bool(windows_monkey in tunneled_monkeys and unknown_monkey in tunneled_monkeys and linux_monkey not in tunneled_monkeys and len(tunneled_monkeys) == 2) self.assertTrue(test, "Tunneling test")
def test_get_os(self): self.fail_if_not_testing_env() self.clean_monkey_db() linux_monkey = Monkey( guid=str(uuid.uuid4()), description= "Linux shay-Virtual-Machine 4.15.0-50-generic #54-Ubuntu") windows_monkey = Monkey(guid=str(uuid.uuid4()), description="Windows bla bla bla") unknown_monkey = Monkey(guid=str(uuid.uuid4()), description="bla bla bla") linux_monkey.save() windows_monkey.save() unknown_monkey.save() self.assertEqual( 1, len([m for m in Monkey.objects() if m.get_os() == "windows"])) self.assertEqual( 1, len([m for m in Monkey.objects() if m.get_os() == "linux"])) self.assertEqual( 1, len([m for m in Monkey.objects() if m.get_os() == "unknown"]))
def test_is_dead(self): # Arrange alive_monkey_ttl = MonkeyTtl.create_ttl_expire_in(30) alive_monkey_ttl.save() alive_monkey = Monkey(guid=str(uuid.uuid4()), dead=False, ttl_ref=alive_monkey_ttl.id) alive_monkey.save() # MIA stands for Missing In Action mia_monkey_ttl = MonkeyTtl.create_ttl_expire_in(30) mia_monkey_ttl.save() mia_monkey = Monkey(guid=str(uuid.uuid4()), dead=False, ttl_ref=mia_monkey_ttl.id) mia_monkey.save() # Emulate timeout - ttl is manually deleted here, since we're using mongomock and not a # real mongo instance. mia_monkey_ttl.delete() dead_monkey = Monkey(guid=str(uuid.uuid4()), dead=True) dead_monkey.save() # act + assert assert dead_monkey.is_dead() assert mia_monkey.is_dead() assert not alive_monkey.is_dead()
def process_environment_telemetry(collector_results, monkey_guid): relevant_monkey = Monkey.get_single_monkey_by_guid(monkey_guid) relevant_monkey.environment = collector_results["environment"] relevant_monkey.save() logger.debug("Updated Monkey {} with env {}".format( str(relevant_monkey), collector_results))