def process_tunnel_telemetry(telemetry_json): monkey_id = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid'])["_id"] if telemetry_json['data']['proxy'] is not None: tunnel_host_ip = telemetry_json['data']['proxy'].split(":")[-2].replace("//", "") NodeService.set_monkey_tunnel(monkey_id, tunnel_host_ip) else: NodeService.unset_all_monkey_tunnels(monkey_id)
def get_edge_by_scan_or_exploit_telemetry(telemetry_json): dst_ip = telemetry_json['data']['machine']['ip_addr'] src_monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) dst_node = NodeService.get_monkey_by_ip(dst_ip) if dst_node is None: dst_node = NodeService.get_or_create_node(dst_ip) return EdgeService.get_or_create_edge(src_monkey["_id"], dst_node["_id"])
def get_tunnels(): return [ { 'type': 'tunnel', 'machine': NodeService.get_node_hostname(NodeService.get_node_or_monkey_by_id(tunnel['_id'])), 'dest': NodeService.get_node_hostname(NodeService.get_node_or_monkey_by_id(tunnel['tunnel'])) } for tunnel in mongo.db.monkey.find({'tunnel': {'$exists': True}}, {'tunnel': 1})]
def get(self): NodeService.update_dead_monkeys() island_monkey = NodeService.get_monkey_island_monkey() if island_monkey is not None: is_monkey_running = not island_monkey["dead"] else: is_monkey_running = False return jsonify(is_running=is_monkey_running)
def get_completed_steps(): is_any_exists = NodeService.is_any_monkey_exists() infection_done = NodeService.is_monkey_finished_running() if not infection_done: report_done = False else: report_done = ReportService.is_report_generated() return dict(run_server=True, run_monkey=is_any_exists, infection_done=infection_done, report_done=report_done)
def get(self, guid=None, **kw): NodeService.update_dead_monkeys() # refresh monkeys status if not guid: guid = request.args.get('guid') if guid: monkey_json = mongo.db.monkey.find_one_or_404({"guid": guid}) monkey_json['config'] = ConfigService.decrypt_flat_config(monkey_json['config']) return monkey_json return {}
def get_tunnels(): return [{ 'type': 'tunnel', 'machine': NodeService.get_node_hostname( NodeService.get_node_or_monkey_by_id(tunnel['_id'])), 'dest': NodeService.get_node_hostname( NodeService.get_node_or_monkey_by_id(tunnel['tunnel'])) } for tunnel in mongo.db.monkey.find({'tunnel': { '$exists': True }}, {'tunnel': 1})]
def get(self): client_ip = request.remote_addr if client_ip == "127.0.0.1": monkey = NodeService.get_monkey_island_monkey() else: monkey = NodeService.get_monkey_by_ip(client_ip) NodeService.update_dead_monkeys() if monkey is not None: is_monkey_running = not monkey["dead"] else: is_monkey_running = False return jsonify(is_running=is_monkey_running)
def process_system_info_telemetry(telemetry_json): users_secrets = {} monkey_id = NodeService.get_monkey_by_guid( telemetry_json['monkey_guid']).get('_id') if 'ssh_info' in telemetry_json['data']: ssh_info = telemetry_json['data']['ssh_info'] Telemetry.encrypt_system_info_ssh_keys(ssh_info) if telemetry_json['data']['network_info']['networks']: # We use user_name@machine_ip as the name of the ssh key stolen, thats why we need ip from telemetry Telemetry.add_ip_to_ssh_keys( telemetry_json['data']['network_info']['networks'][0], ssh_info) Telemetry.add_system_info_ssh_keys_to_config(ssh_info) if 'credentials' in telemetry_json['data']: creds = telemetry_json['data']['credentials'] Telemetry.encrypt_system_info_creds(creds) Telemetry.add_system_info_creds_to_config(creds) Telemetry.replace_user_dot_with_comma(creds) if 'mimikatz' in telemetry_json['data']: users_secrets = mimikatz_utils.MimikatzSecrets.\ extract_secrets_from_mimikatz(telemetry_json['data'].get('mimikatz', '')) if 'wmi' in telemetry_json['data']: wmi_handler = WMIHandler(monkey_id, telemetry_json['data']['wmi'], users_secrets) wmi_handler.process_and_handle_wmi_info()
def get_stolen_creds(): PASS_TYPE_DICT = { 'password': '******', 'lm_hash': 'LM hash', 'ntlm_hash': 'NTLM hash' } creds = [] for telem in mongo.db.telemetry.find( { 'telem_type': 'system_info_collection', 'data.credentials': { '$exists': True } }, { 'data.credentials': 1, 'monkey_guid': 1 }): monkey_creds = telem['data']['credentials'] if len(monkey_creds) == 0: continue origin = NodeService.get_monkey_by_guid( telem['monkey_guid'])['hostname'] for user in monkey_creds: for pass_type in monkey_creds[user]: creds.append({ 'username': user.replace(',', '.'), 'type': PASS_TYPE_DICT[pass_type], 'origin': origin }) return creds
def get_ssh_keys(): """ Return private ssh keys found as credentials :return: List of credentials """ creds = [] for telem in mongo.db.telemetry.find( { 'telem_type': 'system_info_collection', 'data.ssh_info': { '$exists': True } }, { 'data.ssh_info': 1, 'monkey_guid': 1 }): origin = NodeService.get_monkey_by_guid( telem['monkey_guid'])['hostname'] if telem['data']['ssh_info']: # Pick out all ssh keys not yet included in creds ssh_keys = [{ 'username': key_pair['name'], 'type': 'Clear SSH private key', 'origin': origin } for key_pair in telem['data']['ssh_info'] if key_pair['private_key'] and { 'username': key_pair['name'], 'type': 'Clear SSH private key', 'origin': origin } not in creds] creds.extend(ssh_keys) return creds
def get_azure_creds(): """ Recover all credentials marked as being from an Azure machine :return: List of credentials. """ creds = [] for telem in mongo.db.telemetry.find( { 'telem_type': 'system_info_collection', 'data.Azure': { '$exists': True } }, { 'data.Azure': 1, 'monkey_guid': 1 }): azure_users = telem['data']['Azure']['usernames'] if len(azure_users) == 0: continue origin = NodeService.get_monkey_by_guid( telem['monkey_guid'])['hostname'] azure_leaked_users = [{ 'username': user.replace(',', '.'), 'type': 'Clear Password', 'origin': origin } for user in azure_users] creds.extend(azure_leaked_users) logger.info('Azure machines creds generated for reporting') return creds
def get_displayed_telemetry(telem): return \ { 'id': telem['_id'], 'timestamp': telem['timestamp'].strftime('%d/%m/%Y %H:%M:%S'), 'hostname': NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname'], 'brief': TELEM_PROCESS_DICT[telem['telem_type']](telem) }
def get_tunnel_telem_brief(telem): tunnel = telem['data']['proxy'] if tunnel is None: return 'No tunnel is used.' else: tunnel_host_ip = tunnel.split(":")[-2].replace("//", "") tunnel_host = NodeService.get_monkey_by_ip(tunnel_host_ip)['hostname'] return 'Tunnel set up to machine: %s.' % tunnel_host
def get(self, **kw): monkeys = [NodeService.monkey_to_net_node(x) for x in mongo.db.monkey.find({})] nodes = [NodeService.node_to_net_node(x) for x in mongo.db.node.find({})] edges = [EdgeService.edge_to_net_edge(x) for x in mongo.db.edge.find({})] if NodeService.get_monkey_island_monkey() is None: monkey_island = [NodeService.get_monkey_island_pseudo_net_node()] edges += EdgeService.get_monkey_island_pseudo_edges() else: monkey_island = [] edges += EdgeService.get_infected_monkey_island_pseudo_edges() return \ { "nodes": monkeys + nodes + monkey_island, "edges": edges }
def get_displayed_telemetry(telem): return \ { 'id': telem['_id'], 'timestamp': telem['timestamp'].strftime('%d/%m/%Y %H:%M:%S'), 'hostname': NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname'], 'brief': TELEM_PROCESS_DICT[telem['telem_type']](telem) }
def get_manual_monkeys(): return [ monkey['hostname'] for monkey in mongo.db.monkey.find({}, { 'hostname': 1, 'parent': 1, 'guid': 1 }) if NodeService.get_monkey_manual_run(monkey) ]
def patch(self, guid): monkey_json = json.loads(request.data) update = {"$set": {'modifytime': datetime.now()}} monkey = NodeService.get_monkey_by_guid(guid) if 'keepalive' in monkey_json: update['$set']['keepalive'] = dateutil.parser.parse(monkey_json['keepalive']) else: update['$set']['keepalive'] = datetime.now() if 'config' in monkey_json: update['$set']['config'] = monkey_json['config'] if 'config_error' in monkey_json: update['$set']['config_error'] = monkey_json['config_error'] if 'tunnel' in monkey_json: tunnel_host_ip = monkey_json['tunnel'].split(":")[-2].replace("//", "") NodeService.set_monkey_tunnel(monkey["_id"], tunnel_host_ip) return mongo.db.monkey.update({"_id": monkey["_id"]}, update, upsert=False)
def get_tunnel_telem_brief(telem): tunnel = telem['data']['proxy'] if tunnel is None: return 'No tunnel is used.' else: tunnel_host_ip = tunnel.split(":")[-2].replace("//", "") tunnel_host = NodeService.get_monkey_by_ip( tunnel_host_ip)['hostname'] return 'Tunnel set up to machine: %s.' % tunnel_host
def get(self, guid=None, **kw): NodeService.update_dead_monkeys() # refresh monkeys status if not guid: guid = request.args.get('guid') timestamp = request.args.get('timestamp') if guid: monkey_json = mongo.db.monkey.find_one_or_404({"guid": guid}) return monkey_json else: result = {'timestamp': datetime.now().isoformat()} find_filter = {} if timestamp is not None: find_filter['modifytime'] = { '$gt': dateutil.parser.parse(timestamp) } result['objects'] = [x for x in mongo.db.monkey.find(find_filter)] return result
def get_scanned(): nodes = \ [NodeService.get_displayed_node_by_id(node['_id'], True) for node in mongo.db.node.find({}, {'_id': 1})] \ + [NodeService.get_displayed_node_by_id(monkey['_id'], True) for monkey in mongo.db.monkey.find({}, {'_id': 1})] nodes = [ { 'label': node['label'], 'ip_addresses': node['ip_addresses'], 'accessible_from_nodes': (x['hostname'] for x in (NodeService.get_displayed_node_by_id(edge['from'], True) for edge in EdgeService.get_displayed_edges_by_to(node['id'], True))), 'services': node['services'] } for node in nodes] return nodes
def post(self): telemetry_json = json.loads(request.data) monkey_id = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid'])['_id'] # This shouldn't contain any unicode characters. this'll take 2 time less space. log_data = str(telemetry_json['log']) log_id = LogService.add_log(monkey_id, log_data) return mongo.db.log.find_one_or_404({"_id": log_id})
def patch(self, guid): monkey_json = json.loads(request.data) update = {"$set": {'modifytime': datetime.now()}} monkey = NodeService.get_monkey_by_guid(guid) if 'keepalive' in monkey_json: update['$set']['keepalive'] = dateutil.parser.parse(monkey_json['keepalive']) else: update['$set']['keepalive'] = datetime.now() if 'config' in monkey_json: update['$set']['config'] = monkey_json['config'] if 'config_error' in monkey_json: update['$set']['config_error'] = monkey_json['config_error'] if 'tunnel' in monkey_json: tunnel_host_ip = monkey_json['tunnel'].split(":")[-2].replace("//", "") NodeService.set_monkey_tunnel(monkey["_id"], tunnel_host_ip) return mongo.db.monkey.update({"_id": monkey["_id"]}, update, upsert=False)
def post(self): telemetry_json = json.loads(request.data) telemetry_json['timestamp'] = datetime.now() monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) try: NodeService.update_monkey_modify_time(monkey["_id"]) telem_type = telemetry_json.get('telem_type') if telem_type in TELEM_PROCESS_DICT: TELEM_PROCESS_DICT[telem_type](telemetry_json) else: logger.info('Got unknown type of telemetry: %s' % telem_type) except Exception as ex: logger.error("Exception caught while processing telemetry", exc_info=True) telem_id = mongo.db.telemetry.insert(telemetry_json) return mongo.db.telemetry.find_one_or_404({"_id": telem_id})
def post(self): telemetry_json = json.loads(request.data) monkey_id = NodeService.get_monkey_by_guid( telemetry_json['monkey_guid'])['_id'] # This shouldn't contain any unicode characters. this'll take 2 time less space. log_data = str(telemetry_json['log']) log_id = LogService.add_log(monkey_id, log_data) return mongo.db.log.find_one_or_404({"_id": log_id})
def get_exploited(): exploited = \ [NodeService.get_displayed_node_by_id(monkey['_id'], True) for monkey in mongo.db.monkey.find({}, {'_id': 1}) if not NodeService.get_monkey_manual_run(NodeService.get_monkey_by_id(monkey['_id']))] \ + [NodeService.get_displayed_node_by_id(node['_id'], True) for node in mongo.db.node.find({'exploited': True}, {'_id': 1})] exploited = [ { 'label': monkey['label'], 'ip_addresses': monkey['ip_addresses'], 'exploits': list(set( [ReportService.EXPLOIT_DISPLAY_DICT[exploit['exploiter']] for exploit in monkey['exploits'] if exploit['result']])) } for monkey in exploited] return exploited
def get_displayed_telemetry(telem): monkey = NodeService.get_monkey_by_guid(telem['monkey_guid']) default_hostname = "GUID-" + telem['monkey_guid'] return \ { 'id': telem['_id'], 'timestamp': telem['timestamp'].strftime('%d/%m/%Y %H:%M:%S'), 'hostname': monkey.get('hostname', default_hostname) if monkey else default_hostname, 'brief': TELEM_PROCESS_DICT[telem['telem_type']](telem) }
def post(self): telemetry_json = json.loads(request.data) telemetry_json['timestamp'] = datetime.now() monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) try: NodeService.update_monkey_modify_time(monkey["_id"]) telem_type = telemetry_json.get('telem_type') if telem_type in TELEM_PROCESS_DICT: TELEM_PROCESS_DICT[telem_type](telemetry_json) else: print('Got unknown type of telemetry: %s' % telem_type) except StandardError as ex: print("Exception caught while processing telemetry: %s" % str(ex)) traceback.print_exc() telem_id = mongo.db.telemetry.insert(telemetry_json) return mongo.db.telemetry.find_one_or_404({"_id": telem_id})
def post(self): telemetry_json = json.loads(request.data) telemetry_json['timestamp'] = datetime.now() monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) try: NodeService.update_monkey_modify_time(monkey["_id"]) telem_type = telemetry_json.get('telem_type') if telem_type in TELEM_PROCESS_DICT: TELEM_PROCESS_DICT[telem_type](telemetry_json) else: print('Got unknown type of telemetry: %s' % telem_type) except StandardError as ex: print("Exception caught while processing telemetry: %s" % str(ex)) traceback.print_exc() telem_id = mongo.db.telemetry.insert(telemetry_json) return mongo.db.telemetry.find_one_or_404({"_id": telem_id})
def get_scanned(): nodes = \ [NodeService.get_displayed_node_by_id(node['_id'], True) for node in mongo.db.node.find({}, {'_id': 1})] \ + [NodeService.get_displayed_node_by_id(monkey['_id'], True) for monkey in mongo.db.monkey.find({}, {'_id': 1})] nodes = [{ 'label': node['label'], 'ip_addresses': node['ip_addresses'], 'accessible_from_nodes': (x['hostname'] for x in ( NodeService.get_displayed_node_by_id(edge['from'], True) for edge in EdgeService.get_displayed_edges_by_to( node['id'], True))), 'services': node['services'] } for node in nodes] return nodes
def process_exploit_telemetry(telemetry_json): edge = Telemetry.get_edge_by_scan_or_exploit_telemetry(telemetry_json) new_exploit = copy.deepcopy(telemetry_json['data']) new_exploit.pop('machine') new_exploit['timestamp'] = telemetry_json['timestamp'] mongo.db.edge.update( {'_id': edge['_id']}, {'$push': {'exploits': new_exploit}} ) if new_exploit['result']: EdgeService.set_edge_exploited(edge) for attempt in telemetry_json['data']['attempts']: if attempt['result']: found_creds = {'user': attempt['user']} for field in ['password', 'lm_hash', 'ntlm_hash']: if len(attempt[field]) != 0: found_creds[field] = attempt[field] NodeService.add_credentials_to_node(edge['to'], found_creds)
def get_exploited(): exploited = \ [NodeService.get_displayed_node_by_id(monkey['_id'], True) for monkey in mongo.db.monkey.find({}, {'_id': 1}) if not NodeService.get_monkey_manual_run(NodeService.get_monkey_by_id(monkey['_id']))] \ + [NodeService.get_displayed_node_by_id(node['_id'], True) for node in mongo.db.node.find({'exploited': True}, {'_id': 1})] exploited = [{ 'label': monkey['label'], 'ip_addresses': monkey['ip_addresses'], 'exploits': list( set([ ReportService.EXPLOIT_DISPLAY_DICT[exploit['exploiter']] for exploit in monkey['exploits'] if exploit['result'] ])) } for monkey in exploited] return exploited
def generate_report(): domain_issues = ReportService.get_domain_issues() issues = ReportService.get_issues() config_users = ReportService.get_config_users() config_passwords = ReportService.get_config_passwords() cross_segment_issues = ReportService.get_cross_segment_issues() monkey_latest_modify_time = list( NodeService.get_latest_modified_monkey())[0]['modifytime'] report = \ { 'overview': { 'manual_monkeys': ReportService.get_manual_monkeys(), 'config_users': config_users, 'config_passwords': config_passwords, 'config_exploits': ReportService.get_config_exploits(), 'config_ips': ReportService.get_config_ips(), 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), 'issues': ReportService.get_issues_overview(issues, config_users, config_passwords), 'warnings': ReportService.get_warnings_overview(issues, cross_segment_issues), 'cross_segment_issues': cross_segment_issues }, 'glance': { 'scanned': ReportService.get_scanned(), 'exploited': ReportService.get_exploited(), 'stolen_creds': ReportService.get_stolen_creds(), 'azure_passwords': ReportService.get_azure_creds(), 'ssh_keys': ReportService.get_ssh_keys(), 'strong_users': PTHReportService.get_strong_users_on_crit_details(), 'pth_map': PTHReportService.get_pth_map() }, 'recommendations': { 'issues': issues, 'domain_issues': domain_issues }, 'meta': { 'latest_monkey_modifytime': monkey_latest_modify_time } } ReportExporterManager().export(report) mongo.db.report.drop() mongo.db.report.insert_one( ReportService.encode_dot_char_before_mongo_insert(report)) return report
def get(self, **kw): monkeys = [ NodeService.monkey_to_net_node(x) for x in mongo.db.monkey.find({}) ] nodes = [ NodeService.node_to_net_node(x) for x in mongo.db.node.find({}) ] edges = [ EdgeService.edge_to_net_edge(x) for x in mongo.db.edge.find({}) ] if NodeService.get_monkey_island_monkey() is None: monkey_island = [NodeService.get_monkey_island_pseudo_net_node()] edges += EdgeService.get_monkey_island_pseudo_edges() else: monkey_island = [] edges += EdgeService.get_infected_monkey_island_pseudo_edges() return \ { "nodes": monkeys + nodes + monkey_island, "edges": edges }
def telemetry_to_displayed_telemetry(telemetry): monkey_guid_dict = {} monkeys = mongo.db.monkey.find({}) for monkey in monkeys: monkey_guid_dict[monkey["guid"]] = NodeService.get_monkey_label(monkey) objects = [] for x in telemetry: telem_monkey_guid = x.pop("monkey_guid") monkey_label = monkey_guid_dict.get(telem_monkey_guid) if monkey_label is None: monkey_label = telem_monkey_guid x["monkey"] = monkey_label objects.append(x) return objects
def get_duplicated_passwords_nodes(): users_cred_groups = [] docs = PTHReportService.__dup_passwords_mongoquery() for doc in docs: users_list = [{ 'username': user['name'], 'domain_name': user['domain_name'], 'hostname': NodeService.get_hostname_by_id(ObjectId(user['machine_id'])) if user['machine_id'] else None } for user in doc['Docs']] users_cred_groups.append({'cred_groups': users_list}) return users_cred_groups
def is_latest_report_exists(): """ This function checks if a monkey report was already generated and if it's the latest one. :return: True if report is the latest one, False if there isn't a report or its not the latest. """ latest_report_doc = mongo.db.report.find_one( {}, {'meta.latest_monkey_modifytime': 1}) if latest_report_doc: report_latest_modifytime = latest_report_doc['meta'][ 'latest_monkey_modifytime'] latest_monkey_modifytime = NodeService.get_latest_modified_monkey( )[0]['modifytime'] return report_latest_modifytime == latest_monkey_modifytime return False
def get_report(): domain_issues = ReportService.get_domain_issues() issues = ReportService.get_issues() config_users = ReportService.get_config_users() config_passwords = ReportService.get_config_passwords() cross_segment_issues = ReportService.get_cross_segment_issues() report = \ { 'overview': { 'manual_monkeys': ReportService.get_manual_monkeys(), 'config_users': config_users, 'config_passwords': config_passwords, 'config_exploits': ReportService.get_config_exploits(), 'config_ips': ReportService.get_config_ips(), 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), 'issues': ReportService.get_issues_overview(issues, config_users, config_passwords), 'warnings': ReportService.get_warnings_overview(issues, cross_segment_issues), 'cross_segment_issues': cross_segment_issues }, 'glance': { 'scanned': ReportService.get_scanned(), 'exploited': ReportService.get_exploited(), 'stolen_creds': ReportService.get_stolen_creds(), 'azure_passwords': ReportService.get_azure_creds(), 'ssh_keys': ReportService.get_ssh_keys(), 'strong_users': PTHReportService.get_strong_users_on_crit_details(), 'pth_map': PTHReportService.get_pth_map() }, 'recommendations': { 'issues': issues, 'domain_issues': domain_issues } } finished_run = NodeService.is_monkey_finished_running() if finished_run: ReportService.set_report_generated() return report
def get_cross_segment_issues_per_subnet_pair(scans, source_subnet, target_subnet): """ Gets list of cross segment issues from source_subnet to target_subnet. :param scans: List of all scan telemetry entries. Must have monkey_guid, ip_addr and services. This should be a PyMongo cursor object. :param source_subnet: The subnet which shouldn't be able to access target_subnet. :param target_subnet: The subnet which shouldn't be accessible from source_subnet. :return: """ if source_subnet == target_subnet: return [] source_subnet_range = NetworkRange.get_range_obj(source_subnet) target_subnet_range = NetworkRange.get_range_obj(target_subnet) cross_segment_issues = [] scans.rewind() # If we iterated over scans already we need to rewind. for scan in scans: target_ip = scan['data']['machine']['ip_addr'] if target_subnet_range.is_in_range(unicode(target_ip)): monkey = NodeService.get_monkey_by_guid(scan['monkey_guid']) cross_segment_ip = ReportService.get_ip_in_src_and_not_in_dst( monkey['ip_addresses'], source_subnet_range, target_subnet_range) if cross_segment_ip is not None: cross_segment_issues.append({ 'source': cross_segment_ip, 'hostname': monkey['hostname'], 'target': target_ip, 'services': scan['data']['machine']['services'], 'is_self': False }) return cross_segment_issues + ReportService.get_cross_segment_issues_of_single_machine( source_subnet_range, target_subnet_range)
def telemetry_to_displayed_telemetry(telemetry): monkey_guid_dict = {} monkeys = mongo.db.monkey.find({}) for monkey in monkeys: monkey_guid_dict[monkey["guid"]] = NodeService.get_monkey_label(monkey) objects = [] for x in telemetry: telem_monkey_guid = x.pop("monkey_guid") monkey_label = monkey_guid_dict.get(telem_monkey_guid) if monkey_label is None: monkey_label = telem_monkey_guid x["monkey"] = monkey_label objects.append(x) if x['telem_type'] == 'system_info_collection' and 'credentials' in x['data']: for user in x['data']['credentials']: if -1 != user.find(','): new_user = user.replace(',', '.') x['data']['credentials'][new_user] = x['data']['credentials'].pop(user) return objects
def get_stolen_creds(): PASS_TYPE_DICT = {'password': '******', 'lm_hash': 'LM hash', 'ntlm_hash': 'NTLM hash'} creds = [] for telem in mongo.db.telemetry.find( {'telem_type': 'system_info_collection', 'data.credentials': {'$exists': True}}, {'data.credentials': 1, 'monkey_guid': 1} ): monkey_creds = telem['data']['credentials'] if len(monkey_creds) == 0: continue origin = NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname'] for user in monkey_creds: for pass_type in monkey_creds[user]: creds.append( { 'username': user.replace(',', '.'), 'type': PASS_TYPE_DICT[pass_type], 'origin': origin } ) return creds
def telemetry_to_displayed_telemetry(telemetry): monkey_guid_dict = {} monkeys = mongo.db.monkey.find({}) for monkey in monkeys: monkey_guid_dict[monkey["guid"]] = NodeService.get_monkey_label(monkey) objects = [] for x in telemetry: telem_monkey_guid = x.pop("monkey_guid") monkey_label = monkey_guid_dict.get(telem_monkey_guid) if monkey_label is None: monkey_label = telem_monkey_guid x["monkey"] = monkey_label objects.append(x) if x['telem_type'] == 'system_info_collection' and 'credentials' in x['data']: for user in x['data']['credentials']: if -1 != user.find(','): new_user = user.replace(',', '.') x['data']['credentials'][new_user] = x['data']['credentials'].pop(user) return objects
def get_report(): issues = ReportService.get_issues() config_users = ReportService.get_config_users() config_passwords = ReportService.get_config_passwords() report = \ { 'overview': { 'manual_monkeys': ReportService.get_manual_monkeys(), 'config_users': config_users, 'config_passwords': config_passwords, 'config_exploits': ReportService.get_config_exploits(), 'config_ips': ReportService.get_config_ips(), 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), 'issues': ReportService.get_issues_overview(issues, config_users, config_passwords), 'warnings': ReportService.get_warnings_overview(issues) }, 'glance': { 'scanned': ReportService.get_scanned(), 'exploited': ReportService.get_exploited(), 'stolen_creds': ReportService.get_stolen_creds() }, 'recommendations': { 'issues': issues } } finished_run = NodeService.is_monkey_finished_running() if finished_run: ReportService.set_report_generated() return report
def get_report(): issues = ReportService.get_issues() config_users = ReportService.get_config_users() config_passwords = ReportService.get_config_passwords() report = \ { 'overview': { 'manual_monkeys': ReportService.get_manual_monkeys(), 'config_users': config_users, 'config_passwords': config_passwords, 'config_exploits': ReportService.get_config_exploits(), 'config_ips': ReportService.get_config_ips(), 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), 'issues': ReportService.get_issues_overview(issues, config_users, config_passwords), 'warnings': ReportService.get_warnings_overview(issues) }, 'glance': { 'scanned': ReportService.get_scanned(), 'exploited': ReportService.get_exploited(), 'stolen_creds': ReportService.get_stolen_creds() }, 'recommendations': { 'issues': issues } } finished_run = NodeService.is_monkey_finished_running() if finished_run: ReportService.set_report_generated() return report
def process_state_telemetry(telemetry_json): monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) if telemetry_json['data']['done']: NodeService.set_monkey_dead(monkey, True) else: NodeService.set_monkey_dead(monkey, False)
def post(self, **kw): monkey_json = json.loads(request.data) monkey_json['creds'] = [] monkey_json['dead'] = False if 'keepalive' in monkey_json: monkey_json['keepalive'] = dateutil.parser.parse(monkey_json['keepalive']) else: monkey_json['keepalive'] = datetime.now() monkey_json['modifytime'] = datetime.now() ConfigService.save_initial_config_if_needed() # if new monkey telem, change config according to "new monkeys" config. db_monkey = mongo.db.monkey.find_one({"guid": monkey_json["guid"]}) if not db_monkey: # we pull it encrypted because we then decrypt it for the monkey in get new_config = ConfigService.get_flat_config(False, False) monkey_json['config'] = monkey_json.get('config', {}) monkey_json['config'].update(new_config) else: db_config = db_monkey.get('config', {}) if 'current_server' in db_config: del db_config['current_server'] monkey_json.get('config', {}).update(db_config) # try to find new monkey parent parent = monkey_json.get('parent') parent_to_add = (monkey_json.get('guid'), None) # default values in case of manual run if parent and parent != monkey_json.get('guid'): # current parent is known exploit_telem = [x for x in mongo.db.telemetry.find({'telem_type': {'$eq': 'exploit'}, 'data.result': {'$eq': True}, 'data.machine.ip_addr': {'$in': monkey_json['ip_addresses']}, 'monkey_guid': {'$eq': parent}})] if 1 == len(exploit_telem): parent_to_add = (exploit_telem[0].get('monkey_guid'), exploit_telem[0].get('data').get('exploiter')) else: parent_to_add = (parent, None) elif (not parent or parent == monkey_json.get('guid')) and 'ip_addresses' in monkey_json: exploit_telem = [x for x in mongo.db.telemetry.find({'telem_type': {'$eq': 'exploit'}, 'data.result': {'$eq': True}, 'data.machine.ip_addr': {'$in': monkey_json['ip_addresses']}})] if 1 == len(exploit_telem): parent_to_add = (exploit_telem[0].get('monkey_guid'), exploit_telem[0].get('data').get('exploiter')) if not db_monkey: monkey_json['parent'] = [parent_to_add] else: monkey_json['parent'] = db_monkey.get('parent') + [parent_to_add] tunnel_host_ip = None if 'tunnel' in monkey_json: tunnel_host_ip = monkey_json['tunnel'].split(":")[-2].replace("//", "") monkey_json.pop('tunnel') mongo.db.monkey.update({"guid": monkey_json["guid"]}, {"$set": monkey_json}, upsert=True) # Merge existing scanned node with new monkey new_monkey_id = mongo.db.monkey.find_one({"guid": monkey_json["guid"]})["_id"] if tunnel_host_ip is not None: NodeService.set_monkey_tunnel(new_monkey_id, tunnel_host_ip) existing_node = mongo.db.node.find_one({"ip_addresses": {"$in": monkey_json["ip_addresses"]}}) if existing_node: node_id = existing_node["_id"] for edge in mongo.db.edge.find({"to": node_id}): mongo.db.edge.update({"_id": edge["_id"]}, {"$set": {"to": new_monkey_id}}) for creds in existing_node['creds']: NodeService.add_credentials_to_monkey(new_monkey_id, creds) mongo.db.node.remove({"_id": node_id}) return {"id": new_monkey_id}
def get_manual_monkeys(): return [monkey['hostname'] for monkey in mongo.db.monkey.find({}, {'hostname': 1, 'parent': 1, 'guid': 1}) if NodeService.get_monkey_manual_run(monkey)]
def get(self): node_id = request.args.get('id') if node_id: return NodeService.get_displayed_node_by_id(node_id) return {}
def post(self, **kw): monkey_json = json.loads(request.data) monkey_json['creds'] = [] monkey_json['dead'] = False if 'keepalive' in monkey_json: monkey_json['keepalive'] = dateutil.parser.parse( monkey_json['keepalive']) else: monkey_json['keepalive'] = datetime.now() monkey_json['modifytime'] = datetime.now() ConfigService.save_initial_config_if_needed() # if new monkey telem, change config according to "new monkeys" config. db_monkey = mongo.db.monkey.find_one({"guid": monkey_json["guid"]}) if not db_monkey: new_config = ConfigService.get_flat_config(False, True) monkey_json['config'] = monkey_json.get('config', {}) monkey_json['config'].update(new_config) else: db_config = db_monkey.get('config', {}) if 'current_server' in db_config: del db_config['current_server'] monkey_json.get('config', {}).update(db_config) # try to find new monkey parent parent = monkey_json.get('parent') parent_to_add = (monkey_json.get('guid'), None ) # default values in case of manual run if parent and parent != monkey_json.get( 'guid'): # current parent is known exploit_telem = [ x for x in mongo.db.telemetry.find({ 'telem_type': { '$eq': 'exploit' }, 'data.result': { '$eq': True }, 'data.machine.ip_addr': { '$in': monkey_json['ip_addresses'] }, 'monkey_guid': { '$eq': parent } }) ] if 1 == len(exploit_telem): parent_to_add = (exploit_telem[0].get('monkey_guid'), exploit_telem[0].get('data').get('exploiter')) else: parent_to_add = (parent, None) elif (not parent or parent == monkey_json.get('guid')) and 'ip_addresses' in monkey_json: exploit_telem = [ x for x in mongo.db.telemetry.find({ 'telem_type': { '$eq': 'exploit' }, 'data.result': { '$eq': True }, 'data.machine.ip_addr': { '$in': monkey_json['ip_addresses'] } }) ] if 1 == len(exploit_telem): parent_to_add = (exploit_telem[0].get('monkey_guid'), exploit_telem[0].get('data').get('exploiter')) if not db_monkey: monkey_json['parent'] = [parent_to_add] else: monkey_json['parent'] = db_monkey.get('parent') + [parent_to_add] tunnel_host_ip = None if 'tunnel' in monkey_json: tunnel_host_ip = monkey_json['tunnel'].split(":")[-2].replace( "//", "") monkey_json.pop('tunnel') mongo.db.monkey.update({"guid": monkey_json["guid"]}, {"$set": monkey_json}, upsert=True) # Merge existing scanned node with new monkey new_monkey_id = mongo.db.monkey.find_one({"guid": monkey_json["guid"]})["_id"] if tunnel_host_ip is not None: NodeService.set_monkey_tunnel(new_monkey_id, tunnel_host_ip) existing_node = mongo.db.node.find_one( {"ip_addresses": { "$in": monkey_json["ip_addresses"] }}) if existing_node: node_id = existing_node["_id"] for edge in mongo.db.edge.find({"to": node_id}): mongo.db.edge.update({"_id": edge["_id"]}, {"$set": { "to": new_monkey_id }}) for creds in existing_node['creds']: NodeService.add_credentials_to_monkey(new_monkey_id, creds) mongo.db.node.remove({"_id": node_id}) return {"id": new_monkey_id}
def process_state_telemetry(telemetry_json): monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) if telemetry_json['data']['done']: NodeService.set_monkey_dead(monkey, True) else: NodeService.set_monkey_dead(monkey, False)
def process_general_exploit(exploit): ip_addr = exploit['data']['machine']['ip_addr'] return {'machine': NodeService.get_node_hostname(NodeService.get_node_or_monkey_by_ip(ip_addr)), 'ip_address': ip_addr}
def get_completed_steps(): is_any_exists = NodeService.is_any_monkey_exists() infection_done = NodeService.is_monkey_finished_running() report_done = ReportService.is_report_generated() return dict(run_server=True, run_monkey=is_any_exists, infection_done=infection_done, report_done=report_done)