monkey/monkey_island/cc/services/report.py

194 lines
8.5 KiB
Python
Raw Normal View History

import datetime
2017-10-16 01:06:26 +08:00
from cc.database import mongo
2017-11-12 22:13:40 +08:00
from cc.services.config import ConfigService
from cc.services.edge import EdgeService
2017-11-07 19:17:02 +08:00
from cc.services.node import NodeService
2017-10-16 01:06:26 +08:00
__author__ = "itay.mizeretz"
class ReportService:
def __init__(self):
pass
@staticmethod
def get_first_monkey_time():
return mongo.db.telemetry.find({}, {'timestamp': 1}).sort([('$natural', 1)]).limit(1)[0]['timestamp']
@staticmethod
def get_last_monkey_dead_time():
return mongo.db.telemetry.find({}, {'timestamp': 1}).sort([('$natural', -1)]).limit(1)[0]['timestamp']
@staticmethod
def get_monkey_duration():
delta = ReportService.get_last_monkey_dead_time() - ReportService.get_first_monkey_time()
st = ""
if delta.days > 0:
2017-11-21 23:39:42 +08:00
st += "%d days, " % delta.days
total = delta.seconds
seconds = total % 60
total = (total - seconds) / 60
minutes = total % 60
total = (total - minutes) / 60
hours = total
if hours > 0:
2017-11-21 23:39:42 +08:00
st += "%d hours, " % hours
st += "%d minutes and %d seconds" % (minutes, seconds)
return st
2017-10-16 01:06:26 +08:00
@staticmethod
def get_breach_count():
return mongo.db.edge.count({'exploits.result': True})
@staticmethod
def get_successful_exploit_types():
exploit_types = mongo.db.command({'distinct': 'edge', 'key': 'exploits.exploiter'})['values']
return [exploit for exploit in exploit_types if ReportService.did_exploit_type_succeed(exploit)]
2017-11-07 19:17:02 +08:00
@staticmethod
def get_tunnels():
return [
(NodeService.get_monkey_label_by_id(tunnel['_id']), NodeService.get_monkey_label_by_id(tunnel['tunnel']))
for tunnel in mongo.db.monkey.find({'tunnel': {'$exists': True}}, {'tunnel': 1})]
2017-11-07 22:33:26 +08:00
@staticmethod
def get_scanned():
nodes =\
[NodeService.get_displayed_node_by_id(node['_id']) for node in mongo.db.node.find({}, {'_id': 1})]\
+ [NodeService.get_displayed_node_by_id(monkey['_id']) for monkey in mongo.db.monkey.find({}, {'_id': 1})]
nodes = [
{
'label':
node['hostname'] if 'hostname' in node else NodeService.get_node_by_id(node['id'])['os']['version'],
2017-11-07 22:33:26 +08:00
'ip_addresses': node['ip_addresses'],
'accessible_from_nodes':
(x['hostname'] for x in
(NodeService.get_displayed_node_by_id(edge['from'])
for edge in EdgeService.get_displayed_edges_by_to(node['id']))),
2017-11-07 22:33:26 +08:00
'services': node['services']
}
for node in nodes]
return nodes
2017-11-12 22:13:40 +08:00
@staticmethod
def get_reused_passwords():
password_dict = {}
password_list = ConfigService.get_config_value(['basic', 'credentials', 'exploit_password_list'])
for password in password_list:
machines_with_password =\
[
NodeService.get_monkey_label_by_id(node['_id'])
for node in mongo.db.monkey.find({'creds.password': password}, {'_id': 1})
]
2017-11-12 22:13:40 +08:00
if len(machines_with_password) >= 2:
password_dict[password] = machines_with_password
return password_dict
2017-11-07 22:33:26 +08:00
@staticmethod
def get_exploited():
exploited =\
[NodeService.get_displayed_node_by_id(monkey['_id']) 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'])
for node in mongo.db.node.find({'exploited': True}, {'_id': 1})]
exploited = [
{
'label': monkey['hostname'] if 'hostname' in monkey else monkey['os']['version'],
2017-11-07 22:33:26 +08:00
'ip_addresses': monkey['ip_addresses'],
'exploits': [exploit['exploiter'] for exploit in monkey['exploits'] if exploit['result']]
}
for monkey in exploited]
return exploited
@staticmethod
def get_stolen_creds():
PASS_TYPE_DICT = {'password': 'Password', 'lm_hash': 'LM', 'ntlm_hash': 'NTLM'}
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,
'password': monkey_creds[user][pass_type],
'type': PASS_TYPE_DICT[pass_type],
'origin': origin
}
)
return creds
2017-10-16 01:06:26 +08:00
@staticmethod
def get_report():
2017-11-21 22:40:26 +08:00
return \
{
'overview':
{
'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"),
'monkey_duration': ReportService.get_monkey_duration(),
2017-11-21 22:40:26 +08:00
'issues': [False, True, True, True, False, True],
'warnings': [True, True]
},
'glance':
{
'scanned': ReportService.get_scanned(),
'exploited': ReportService.get_exploited(),
'stolen_creds': ReportService.get_stolen_creds()
2017-11-21 22:40:26 +08:00
},
'recommendations':
{
'issues':
[
{'type': 'smb_password', 'machine': 'Monkey-SMB',
'ip_addresses': ['192.168.0.1', '10.0.0.18'], 'username': 'Administrator'},
{'type': 'smb_pth', 'machine': 'Monkey-SMB2', 'ip_addresses': ['192.168.0.1', '10.0.0.18'],
'username': 'Administrator'},
{'type': 'wmi_password', 'machine': 'Monkey-WMI',
'ip_addresses': ['192.168.0.1', '10.0.0.18'], 'username': 'Administrator'},
{'type': 'wmi_pth', 'machine': 'Monkey-WMI2', 'ip_addresses': ['192.168.0.1', '10.0.0.18'],
'username': 'Administrator'},
{'type': 'ssh', 'machine': 'Monkey-SMB', 'ip_addresses': ['192.168.0.1', '10.0.0.18'],
'username': 'Administrator'},
{'type': 'rdp', 'machine': 'Monkey-SMB', 'ip_addresses': ['192.168.0.1', '10.0.0.18'],
'username': 'Administrator'},
{'type': 'sambacry', 'machine': 'Monkey-SMB', 'ip_addresses': ['192.168.0.1', '10.0.0.18'],
'username': 'Administrator'},
{'type': 'elastic', 'machine': 'Monkey-SMB', 'ip_addresses': ['192.168.0.1', '10.0.0.18']},
{'type': 'shellshock', 'machine': 'Monkey-SMB', 'ip_addresses': ['192.168.0.1', '10.0.0.18'],
'port': 8080, 'paths': ['/cgi/backserver.cgi', '/cgi/login.cgi']},
{'type': 'conficker', 'machine': 'Monkey-SMB', 'ip_addresses': ['192.168.0.1', '10.0.0.18']},
{'type': 'cross_segment', 'machine': 'Monkey-SMB', 'network': '192.168.0.0/24',
'server_network': '172.168.0.0/24'},
{'type': 'tunnel', 'origin': 'Monkey-SSH', 'dest': 'Monkey-SambaCry'}
]
}
}
# TODO: put implementation in template
"""
2017-10-16 01:06:26 +08:00
return \
{
'breach_count': ReportService.get_breach_count(),
'successful_exploit_types': ReportService.get_successful_exploit_types(),
2017-11-07 22:33:26 +08:00
'tunnels': ReportService.get_tunnels(),
2017-11-12 22:13:40 +08:00
'reused_passwords': ReportService.get_reused_passwords()
2017-10-16 01:06:26 +08:00
}
2017-11-21 22:40:26 +08:00
"""
2017-10-16 01:06:26 +08:00
@staticmethod
def did_exploit_type_succeed(exploit_type):
return mongo.db.edge.count(
{'exploits': {'$elemMatch': {'exploiter': exploit_type, 'result': True}}},
limit=1) > 0