RE-CR: changed names, added doc, created consts.

This commit is contained in:
maor.rayzin 2018-10-31 14:20:56 +02:00
parent 3a2d9a9cc2
commit 707c88434c
6 changed files with 45 additions and 12 deletions

View File

@ -9,12 +9,12 @@ from flask import request
from cc.auth import jwt_required
from cc.database import mongo
from cc.services import user_info
from cc.services import mimikatz_utils
from cc.services.config import ConfigService
from cc.services.edge import EdgeService
from cc.services.node import NodeService
from cc.encryptor import encryptor
from cc.services.wmi_info_handler import WMIHandler
from cc.services.wmi_handler import WMIHandler
__author__ = 'Barak'
@ -186,7 +186,7 @@ class Telemetry(flask_restful.Resource):
Telemetry.add_system_info_creds_to_config(creds)
Telemetry.replace_user_dot_with_comma(creds)
if 'mimikatz' in telemetry_json['data']:
users_secrets = user_info.MimikatzSecrets.\
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)

View File

@ -0,0 +1,5 @@
"""This file will include consts values regarding the groupsandusers collection"""
USERTYPE = 1
GROUPTYPE = 2

View File

@ -3,6 +3,7 @@ from itertools import product
from cc.database import mongo
from bson import ObjectId
from cc.services.groups_and_users_consts import USERTYPE
from cc.services.node import NodeService
__author__ = 'maor.rayzin'
@ -11,6 +12,19 @@ class PTHReportService(object):
@staticmethod
def __dup_passwords_mongoquery():
"""
This function build and query the mongoDB for users found that are using the same passwords, this is done
by comparing the NTLM hash found for each user by mimikatz.
:return:
A list of mongo documents (dicts in python) that look like this:
{
'_id': The NTLM hash,
'count': How many users share it.
'Docs': the name, domain name, _Id, and machine_id of the users
}
"""
pipeline = [
{"$match": {
'NTLM_secret': {
@ -30,18 +44,31 @@ class PTHReportService(object):
@staticmethod
def __get_admin_on_machines_format(admin_on_machines, domain_name):
"""
This function finds for each admin user, what machines its admin of and compile them to a list.
:param admin_on_machines: A list of "monkey" documents "_id"s
:param domain_name: The admin's domain name
:return:
A list of formatted machines names *domain*\*hostname*, to use in shared admins issues.
"""
machines = mongo.db.monkey.find({'_id': {'$in': admin_on_machines}}, {'hostname': 1})
return [domain_name + '\\' + i['hostname'] for i in list(machines)]
@staticmethod
def __strong_users_on_crit_query():
"""
This function build and query the mongoDB for users that mimikatz was able to find cached NTLM hash and
are administrators on machines with services predefined as important services thus making these machines
critical.
:return:
A list of said users
"""
pipeline = [
{
'$unwind': '$admin_on_machines'
},
{
'$match': {'type': 1, 'domain_name': {'$ne': None}}
'$match': {'type': USERTYPE, 'domain_name': {'$ne': None}}
},
{
'$lookup':
@ -100,7 +127,7 @@ class PTHReportService(object):
# object has at least two objects in it, by making sure any value exists in the array index 1.
# Excluding the name Administrator - its spamming the lists and not a surprise the domain Administrator account
# is shared.
admins = mongo.db.groupsandusers.find({'type': 1, 'name': {'$ne': 'Administrator'},
admins = mongo.db.groupsandusers.find({'type': USERTYPE, 'name': {'$ne': 'Administrator'},
'admin_on_machines.1': {'$exists': True}},
{'admin_on_machines': 1, 'name': 1, 'domain_name': 1})
return [
@ -200,7 +227,7 @@ class PTHReportService(object):
{
'admin_on_machines': {'$ne': []},
'secret_location': {'$ne': []},
'type': 1
'type': USERTYPE
},
{
'admin_on_machines': 1, 'secret_location': 1

View File

@ -561,7 +561,7 @@ class ReportService:
issues_dict = {}
for issue in issues:
if issue.get('is_local', True):
machine = issue.get('machine', '').upper()
machine = issue.get('machine').upper()
if machine not in issues_dict:
issues_dict[machine] = []
issues_dict[machine].append(issue)

View File

@ -1,4 +1,5 @@
from cc.database import mongo
from cc.services.groups_and_users_consts import USERTYPE
__author__ = 'maor.rayzin'
@ -15,8 +16,8 @@ class WMIHandler(object):
self.users_info = wmi_info['Win32_UserAccount']
self.groups_info = wmi_info['Win32_Group']
self.groups_and_users = wmi_info['Win32_GroupUser']
self.products = wmi_info['Win32_Service']
self.services = wmi_info['Win32_Product']
self.services = wmi_info['Win32_Service']
self.products = wmi_info['Win32_Product']
def process_and_handle_wmi_info(self):
@ -128,7 +129,7 @@ class WMIHandler(object):
# if entity is domain entity, add the monkey id of current machine to secrets_location.
# (found on this machine)
if entity.get('NTLM_secret'):
mongo.db.groupsandusers.update_one({'SID': entity['SID'], 'type': 1},
mongo.db.groupsandusers.update_one({'SID': entity['SID'], 'type': USERTYPE},
{'$addToSet': {'secret_location': self.monkey_id}})
def update_admins_retrospective(self):
@ -148,7 +149,7 @@ class WMIHandler(object):
mongo.db.groupsandusers.update_one({'SID': sid},
{'$addToSet': {'admin_on_machines': machine_id}})
entity_details = mongo.db.groupsandusers.find_one({'SID': sid},
{'type': 1, 'entities_list': 1})
{'type': USERTYPE, 'entities_list': 1})
if entity_details.get('type') == 2:
self.add_admin(entity_details, machine_id)