* finished map's nodes and edges generation for pth report

This commit is contained in:
maor.rayzin 2018-07-24 14:43:41 +03:00
parent 1b45029c5d
commit 2f4a3dc885
2 changed files with 56 additions and 20 deletions

View File

@ -108,11 +108,21 @@ class PTHReportService(object):
@staticmethod @staticmethod
def generate_map_nodes(pth): def generate_map_nodes(pth):
return [{"id": x, "label": Machine(x).GetIp()} for x in pth.vertices] nodes_list = []
for node_id in pth.vertices:
machine = Machine(node_id)
node = {
"id": machine.get_monkey_id,
"label": '{0} : {1}'.format(machine.GetHostName(), machine.GetIp()),
'group': 'critical' if machine.IsCriticalServer() else 'normal',
'users': list(machine.GetCachedUsernames()),
'ips': machine.GetIp(),
'services': machine.GetCriticalServicesInstalled(),
'hostname': machine.GetHostName()
}
nodes_list.append(node)
@staticmethod return nodes_list
def generate_map_edges(pth):
return [{"id": str(s) + str(t), "from": s, "to": t, "label": label} for s, t, label in pth.edges]
@staticmethod @staticmethod
def get_report(): def get_report():
@ -130,7 +140,7 @@ class PTHReportService(object):
'map': 'map':
{ {
'nodes': PTHReportService.generate_map_nodes(pth), 'nodes': PTHReportService.generate_map_nodes(pth),
'edges': PTHReportService.generate_map_edges(pth) 'edges': pth.edges
} }
} }
return report return report

View File

@ -1,8 +1,10 @@
import hashlib import hashlib
import binascii import binascii
import copy import copy
import uuid
from cc.database import mongo from cc.database import mongo
from cc.services.node import NodeService
DsRole_RoleStandaloneWorkstation = 0 DsRole_RoleStandaloneWorkstation = 0
DsRole_RoleMemberWorkstation = 1 DsRole_RoleMemberWorkstation = 1
@ -98,6 +100,8 @@ class Machine(object):
if self.latest_system_info.count() > 0: if self.latest_system_info.count() > 0:
self.latest_system_info = self.latest_system_info[0] self.latest_system_info = self.latest_system_info[0]
self.monkey_info = NodeService.get_monkey_by_guid(self.monkey_guid)
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, self.__class__): if isinstance(other, self.__class__):
return self.monkey_guid == other.monkey_guid return self.monkey_guid == other.monkey_guid
@ -131,6 +135,12 @@ class Machine(object):
return None return None
@cache
def get_monkey_id(self):
doc = self.monkey_info
return str(doc['_id'])
@cache @cache
def GetDomainName(self): def GetDomainName(self):
doc = self.latest_system_info doc = self.latest_system_info
@ -556,10 +566,8 @@ class PassTheHashReport(object):
self.vertices = self.GetAllMachines() self.vertices = self.GetAllMachines()
self.machines = map(Machine, self.vertices) self.machines = map(Machine, self.vertices)
self.edges = self.get_edges_by_sid() # Useful for non-cached domain users
self.edges = set() #self.edges |= self.GetEdgesBySamHash() # This will add edges based only on password hash without caring about username
self.edges |= self.GetEdgesBySid() # Useful for non-cached domain users
self.edges |= self.GetEdgesBySamHash() # This will add edges based only on password hash without caring about username
@cache @cache
def GetAllMachines(self): def GetAllMachines(self):
@ -574,7 +582,7 @@ class PassTheHashReport(object):
@cache @cache
def ReprSidList(self, sid_list, attacker, victim): def ReprSidList(self, sid_list, attacker, victim):
label = set() users_list = []
for sid in sid_list: for sid in sid_list:
username = Machine(victim).GetUsernameBySid(sid) username = Machine(victim).GetUsernameBySid(sid)
@ -583,22 +591,33 @@ class PassTheHashReport(object):
# username = Machine(attacker).GetUsernameBySid(sid) # username = Machine(attacker).GetUsernameBySid(sid)
if username: if username:
label.add(username) users_list.append(username)
return ",\n".join(label) return users_list
@cache @cache
def ReprSecretList(self, secret_list, victim): def ReprSecretList(self, secret_list, victim):
label = set() relevant_users_list = []
for secret in secret_list: for secret in secret_list:
label |= Machine(victim).GetUsernamesBySecret(secret) relevant_users_list.append(Machine(victim).GetUsernamesBySecret(secret))
return ",\n".join(label) return relevant_users_list
@staticmethod
def __get_edge_label(attacker, victim):
attacker_monkey = NodeService.get_monkey_by_guid(attacker)
victim_monkey = NodeService.get_monkey_by_guid(victim)
attacker_label = NodeService.get_node_label(attacker_monkey)
victim_label = NodeService.get_node_label(victim_monkey)
RIGHT_ARROW = u"\u2192"
return "%s %s %s" % (attacker_label, RIGHT_ARROW, victim_label)
@cache @cache
def GetEdgesBySid(self): def get_edges_by_sid(self):
edges = set() edges_list = []
for attacker in self.vertices: for attacker in self.vertices:
cached = self.GetCachedSids(Machine(attacker)) cached = self.GetCachedSids(Machine(attacker))
@ -610,10 +629,17 @@ class PassTheHashReport(object):
admins = Machine(victim).GetAdmins() admins = Machine(victim).GetAdmins()
if len(cached & admins) > 0: if len(cached & admins) > 0:
label = self.ReprSidList(cached & admins, attacker, victim) relevant_users_list = self.ReprSidList(cached & admins, attacker, victim)
edges.add((attacker, victim, label)) edges_list.append(
{
'from': attacker,
'to': victim,
'users': relevant_users_list,
'_label': PassTheHashReport.__get_edge_label(attacker, victim),
'id': uuid.uuid4()
})
return edges return edges_list
@cache @cache
def GetEdgesBySamHash(self): def GetEdgesBySamHash(self):