from cc.services.pth_report_utils import PassTheHashReport, Machine
class PTHReportService(object):
"""
"""
def __init__(self):
pass
@staticmethod
def get_duplicated_password_nodes(pth):
"""
"""
usernames_lists = []
usernames_per_sid_list = []
dups = dict(map(lambda x: (x, len(pth.GetSidsBySecret(x))), pth.GetAllSecrets()))
for secret, count in sorted(dups.iteritems(), key=lambda (k, v): (v, k), reverse=True):
if count <= 1:
continue
for sid in pth.GetSidsBySecret(secret):
usernames_per_sid_list.append(pth.GetUsernameBySid(sid))
usernames_lists.append({'cred_group': usernames_per_sid_list})
return usernames_lists
@staticmethod
def get_shared_local_admins_nodes(pth):
dups = dict(map(lambda x: (x, len(pth.GetSharedAdmins(x))), pth.machines))
shared_admin_machines = []
for m, count in sorted(dups.iteritems(), key=lambda (k, v): (v, k), reverse=True):
if count <= 0:
continue
shared_admin_account_list = []
for sid in pth.GetSharedAdmins(m):
shared_admin_account_list.append(pth.GetUsernameBySid(sid))
machine = {
'ip': m.GetIp(),
'hostname': m.GetHostName(),
'domain': m.GetDomainName(),
'services_names': m.GetCriticalServicesInstalled(),
'user_count': count,
'admins_accounts': shared_admin_account_list
}
shared_admin_machines.append(machine)
return shared_admin_machines
@staticmethod
def get_strong_users_on_crit_services(pth):
threatening = dict(map(lambda x: (x, len(pth.GetThreateningUsersByVictim(x))), pth.GetCritialServers()))
strong_users_crit_list = []
for m, count in sorted(threatening.iteritems(), key=lambda (k, v): (v, k), reverse=True):
if count <= 0:
continue
threatening_users_attackers_dict = {}
for sid in pth.GetThreateningUsersByVictim(m):
username = pth.GetUsernameBySid(sid)
threatening_users_attackers_dict[username] = []
for mm in pth.GetAttackersBySid(sid):
if m == mm:
continue
threatening_users_attackers_dict[username] = mm.GetIp()
machine = {
'ip': m.GetIp(),
'hostname': m.GetHostName(),
'domain': m.GetDomainName(),
'services_names': m.GetCriticalServicesInstalled(),
'user_count': count,
'threatening_users': threatening_users_attackers_dict
}
strong_users_crit_list.append(machine)
return strong_users_crit_list
@staticmethod
def get_strong_users_on_non_crit_services(pth):
threatening = dict(map(lambda x: (x, len(pth.GetThreateningUsersByVictim(x))), pth.GetNonCritialServers()))
strong_users_non_crit_list = []
for m, count in sorted(threatening.iteritems(), key=lambda (k, v): (v, k), reverse=True):
if count <= 0:
continue
threatening_users_attackers_dict = {}
for sid in pth.GetThreateningUsersByVictim(m):
username = pth.GetUsernameBySid(sid)
threatening_users_attackers_dict[username] = []
for mm in pth.GetAttackersBySid(sid):
if m == mm:
continue
threatening_users_attackers_dict[username] = mm.GetIp()
machine = {
'ip': m.GetIp(),
'hostname': m.GetHostName(),
'domain': m.GetDomainName(),
'services_names': [],
'user_count': count,
'threatening_users': threatening_users_attackers_dict
}
strong_users_non_crit_list.append(machine)
return strong_users_non_crit_list
@staticmethod
def get_duplicated_passwords_issues(pth, password_groups):
issues = []
for group in password_groups:
username = group['cred_group'][0]
sid = list(pth.GetSidsByUsername(username.split('\\')[1]))
machine_info = pth.GetSidInfo(sid[0])
issues.append(
{
'type': 'shared_passwords',
'machine': machine_info.get('hostname').split('.')[0],
'shared_with': group['cred_group']
}
)
return issues
@staticmethod
def get_shared_local_admins_issues(shared_admins_machines):
issues = []
for machine in shared_admins_machines:
issues.append(
{
'type': 'shared_admins',
'machine': machine.get('hostname'),
'shared_accounts': machine.get('admins_accounts'),
'ip': machine.get('ip'),
}
)
return issues
@staticmethod
def strong_users_on_crit_issues(strong_users):
issues = []
for machine in strong_users:
issues.append(
{
'type': 'strong_users_on_crit',
'machine': machine.get('hostname'),
'services': machine.get('services_names'),
'ip': machine.get('ip'),
'threatening_users': machine.get('threatening_users')
}
)
return issues
@staticmethod
def generate_map_nodes(pth):
nodes_list = []
for node_id in pth.vertices:
machine = Machine(node_id)
node = {
"id": str(node_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)
return nodes_list
@staticmethod
def get_issues_list(issues):
issues_dict = {}
for issue in issues:
machine = issue['machine']
if machine not in issues_dict:
issues_dict[machine] = []
issues_dict[machine].append(issue)
return issues_dict
@staticmethod
def get_report():
issues = []
pth = PassTheHashReport()
same_password = PTHReportService.get_duplicated_password_nodes(pth)
local_admin_shared = PTHReportService.get_shared_local_admins_nodes(pth)
strong_users_on_crit_services = PTHReportService.get_strong_users_on_crit_services(pth)
strong_users_on_non_crit_services = PTHReportService.get_strong_users_on_non_crit_services(pth)
issues += PTHReportService.get_duplicated_passwords_issues(pth, same_password)
issues += PTHReportService.get_shared_local_admins_issues(local_admin_shared)
issues += PTHReportService.strong_users_on_crit_issues(strong_users_on_crit_services)
#formated_issues = PTHReportService.get_issues_list(issues)
report = \
{
'report_info':
{
'same_password': same_password,
'local_admin_shared': local_admin_shared,
'strong_users_on_crit_services': strong_users_on_crit_services,
'strong_users_on_non_crit_services': strong_users_on_non_crit_services,
'pth_issues': issues
},
'pthmap':
{
'nodes': PTHReportService.generate_map_nodes(pth),
'edges': pth.edges
}
}
return report
# print """
"""
#
# print "
Cached Passwords
"
# print "
On how many machines each secret is cached (possible attacker count)?
"
# cache_counts = dict(map(lambda x: (x, pth.GetAttackCountBySecret(x)), pth.GetAllSecrets()))
#
# print """
"""
# print """Secret | Machine Count |
"""
# for secret, count in sorted(cache_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True):
# if count <= 0:
# continue
# print """{secret} | {count} | """.format(secret=secret, count=count)
# print """
"""
#
# print "
User's Creds
"
# print "
To how many machines each user is able to connect with admin rights
"
# attackable_counts = dict(map(lambda x: (x, pth.GetVictimCountBySid(x)), pth.GetAllSids()))
#
# print """
"""
# print """SID | Username | Machine Count |
"""
# for sid, count in sorted(attackable_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True):
# if count <= 1:
# continue
# print """{sid} | {username} | {count} | """.format(sid=sid, username=pth.GetUsernameBySid(sid), count=count)
# print """
"""
#
# print "
Actual Possible Attacks By SID
"
# print "
How many attacks possible using each SID (aka len(attacker->victim pairs))
"
# possible_attacks_by_sid = dict(map(lambda x: (x, pth.GetPossibleAttackCountBySid(x)), pth.GetAllSids()))
#
# print """
"""
# print """SID | Username | Machine Count |
"""
# for sid, count in sorted(possible_attacks_by_sid.iteritems(), key=lambda (k,v): (v,k), reverse=True):
# if count <= 1:
# continue
# print """{sid} | {username} | {count} | """.format(sid=sid, username=pth.GetUsernameBySid(sid), count=count)
# print """
"""
#
# print "
Machine's Creds
"
# print "
To how many machines each machine is able to directly connect with admin rights?
"
# attackable_counts = dict(map(lambda m: (m, pth.GetVictimCountByMachine(m)), pth.machines))
#
# print """
"""
# print """Attacker Ip | Attacker Hostname | Domain Name | Victim Machine Count |
"""
# for m, count in sorted(attackable_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True):
# if count <= 1:
# continue
# print """{ip} | {hostname} | {domain} | {count} | """.format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName(), count=count)
# print """
"""
#
# print "
Domain Controllers
"
# print "
List of domain controllers (we count them as critical points, so they are listed here)
"
# DCs = dict(map(lambda m: (m, pth.GetInPathCountByVictim(m)), pth.GetAllDomainControllers()))
#
# print """
"""
# print """DC Ip | DC Hostname | Domain Name | In-Path Count |
"""
# for m, path_count in sorted(DCs.iteritems(), key=lambda (k,v): (v,k), reverse=True):
# print """{ip} | {hostname} | {domain} | {path_count} |
""".format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName(), path_count=path_count)
# print """
"""
#
# print "
Most Vulnerable Machines
"
# print "
List all machines in the network sorted by the potincial to attack them
"
# all_machines = dict(map(lambda m: (m, pth.GetInPathCountByVictim(m)), pth.machines))
#
# print """
"""
# print """Ip | Hostname | Domain Name | In-Path Count |
"""
# for m, path_count in sorted(all_machines.iteritems(), key=lambda (k,v): (v,k), reverse=True):
# if count <= 0:
# continue
# print """{ip} | {hostname} | {domain} | {path_count} |
""".format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName(), path_count=path_count)
# print """
"""
#
# print "
Critical Servers
"
# print "
List of all machines identified as critical servers
"
# critical_servers = pth.GetCritialServers()
#
# print """
"""
# print """Ip | Hostname | Domain Name |
"""
# for m in critical_servers:
# print """{ip} | {hostname} | {domain} |
""".format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName())
# print """
"""
#
# print "
"
#
# for m in pth.machines:
# print """
Machine '{ip}'
#
Hostname '{hostname}'
""".format(ip=m.GetIp(), hostname=m.GetHostName())
#
# print """
Cached SIDs
"""
# print """
SIDs cached on this machine
"""
# print """
"""
# for sid in pth.GetCachedSids(m):
# print """- {username} ({sid})
""".format(username=pth.GetUsernameBySid(sid), sid=sid)
# print """
"""
#
# print """
Possible Attackers
"""
# print """
Machines that can attack this machine
"""
# print """
"""
# for attacker in pth.GetAttackersByVictim(m):
# print """- {ip} ({hostname})
""".format(ip=attacker.GetIp(), hostname=attacker.GetHostName())
# print """
"""
#
#
# print """
Admins
"""
# print """
Users that have admin rights on this machine
"""
# print """
"""
# for sid in m.GetAdmins():
# print """- {username} ({sid})
""".format(username=m.GetUsernameBySid(sid), sid=sid)
# print """
"""
#
# print """
Installed Critical Services
"""
# print """
List of crtical services found installed on machine
"""
# print """
"""
# for service_name in m.GetCriticalServicesInstalled():
# print """- {service_name}
""".format(service_name=service_name)
# print """
"""
#
#
# print "
"
#
# for username in pth.GetAllUsernames():
# print """
User '{username}'
""".format(username=username)
#
# print """
Matching SIDs
"""
# print """
"""
# for sid in pth.GetSidsByUsername(username):
# print """- {username} ({sid})
""".format(username=pth.GetUsernameBySid(sid),
# sid=sid)
# print """
"""
#
# print "
"
#
# for sid in pth.GetAllSids():
# print """
SID '{sid}'
#
#
Domain: {domain}
#
# """.format(username=pth.GetUsernameBySid(sid), sid=sid, secret=pth.GetSecretBySid(sid),
# domain=pth.GetSidInfo(sid)["Domain"])
#
# print """
Machines the sid is local admin on
"""
# print """
"""
# for m in pth.GetVictimsBySid(sid):
# print """- {ip} ({hostname})
""".format(ip=m.GetIp(), hostname=m.GetHostName())
# print """
"""
#
# print """
Machines the sid is in thier cache
"""
# print """
"""
# for m in pth.GetAttackersBySid(sid):
# print """- {ip} ({hostname})
""".format(ip=m.GetIp(), hostname=m.GetHostName())
# print """
"""
#
# for secret in pth.GetAllSecrets():
# print """
Secret '{secret}'
""".format(secret=secret)
#
# print """
SIDs that use that secret
"""
# print """
"""
# for sid in pth.GetSidsBySecret(secret):
# print """- {username} ({sid})
""".format(username=pth.GetUsernameBySid(sid),
# sid=sid)
# print """
"""
#
# print """
Attackable Machines with that secret
"""
# print """
"""
# for m in pth.GetVictimsBySecret(secret):
# print """- {hostname}
""".format(ip=m.GetIp(), hostname=m.GetHostName())
# print """
"""
#
# print """
Machines that have this secret cached and can use it to attack other machines
"""
# print """
"""
# for m in pth.GetAttackersBySecret(secret):
# print """- {hostname}
""".format(ip=m.GetIp(), hostname=m.GetHostName())
# print """
"""