From 895db8b446817272819eb7669c7c58b68503bcd5 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 5 Jun 2020 09:36:35 +0300 Subject: [PATCH] Fixed bugs and finished up pypykatz integration --- monkey/infection_monkey/exploit/wmiexec.py | 4 +- .../infection_monkey/system_info/__init__.py | 1 + .../windows_cred_collector.py | 5 +- .../cc/services/mimikatz_utils.py | 51 ------------------- .../cc/services/reporting/report.py | 10 ++-- .../monkey_island/cc/services/wmi_handler.py | 2 +- 6 files changed, 14 insertions(+), 59 deletions(-) delete mode 100644 monkey/monkey_island/cc/services/mimikatz_utils.py diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index 2100c23b0..ea2541381 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -39,9 +39,9 @@ class WmiExploiter(HostExploiter): for user, password, lm_hash, ntlm_hash in creds: password_hashed = self._config.hash_sensitive_data(password) lm_hash_hashed = self._config.hash_sensitive_data(lm_hash) - mtlm_hash_hashed = self._config.hash_sensitive_data(ntlm_hash) + ntlm_hash_hashed = self._config.hash_sensitive_data(ntlm_hash) creds_for_logging = "user, password (SHA-512), lm hash (SHA-512), ntlm hash (SHA-512): " \ - "({},{},{},{})".format(user, password_hashed, lm_hash_hashed, mtlm_hash_hashed) + "({},{},{},{})".format(user, password_hashed, lm_hash_hashed, ntlm_hash_hashed) LOG.debug(("Attempting to connect %r using WMI with " % self.host) + creds_for_logging) wmi_connection = WmiTools.WmiConnection() diff --git a/monkey/infection_monkey/system_info/__init__.py b/monkey/infection_monkey/system_info/__init__.py index 76bc40eb6..c619094b5 100644 --- a/monkey/infection_monkey/system_info/__init__.py +++ b/monkey/infection_monkey/system_info/__init__.py @@ -105,6 +105,7 @@ class InfoCollector(object): # we might be losing passwords in case of multiple reset attempts on same username # or in case another collector already filled in a password for this user self.info["credentials"][username]['password'] = password + self.info["credentials"][username]['username'] = username if len(azure_creds) != 0: self.info["Azure"] = {} self.info["Azure"]['usernames'] = [cred[0] for cred in azure_creds] diff --git a/monkey/infection_monkey/system_info/windows_cred_collector/windows_cred_collector.py b/monkey/infection_monkey/system_info/windows_cred_collector/windows_cred_collector.py index eadc684b4..3e462bbe0 100644 --- a/monkey/infection_monkey/system_info/windows_cred_collector/windows_cred_collector.py +++ b/monkey/infection_monkey/system_info/windows_cred_collector/windows_cred_collector.py @@ -18,5 +18,8 @@ class WindowsCredentialCollector(object): def cred_list_to_cred_dict(creds: List[WindowsCredential]): cred_dict = {} for cred in creds: - cred_dict.update({cred.username: cred.to_dict()}) + # Lets not use "." and "$" in keys, because it will confuse mongo. + # Ideally we should refactor island not to use a dict and simply parse credential list. + key = cred.username.replace(".", ",").replace("$", "") + cred_dict.update({key: cred.to_dict()}) return cred_dict diff --git a/monkey/monkey_island/cc/services/mimikatz_utils.py b/monkey/monkey_island/cc/services/mimikatz_utils.py deleted file mode 100644 index e2ab8ec10..000000000 --- a/monkey/monkey_island/cc/services/mimikatz_utils.py +++ /dev/null @@ -1,51 +0,0 @@ -__author__ = 'maor.rayzin' - - -class MimikatzSecrets(object): - - def __init__(self): - # Static class - pass - - @staticmethod - def extract_sam_secrets(mim_string, users_dict): - users_secrets = mim_string.split("\n42.")[1].split("\nSAMKey :")[1].split("\n\n")[1:] - - if mim_string.count("\n42.") != 2: - return {} - - for sam_user_txt in users_secrets: - sam_user = dict([list(map(str.strip, line.split(":"))) for line in - [l for l in sam_user_txt.splitlines() if l.count(":") == 1]]) - username = sam_user.get("User") - users_dict[username] = {} - - ntlm = sam_user.get("NTLM") - if not ntlm or "[hashed secret]" not in ntlm: - continue - - users_dict[username]['SAM'] = ntlm.replace("[hashed secret]", "").strip() - - @staticmethod - def extract_ntlm_secrets(mim_string, users_dict): - - if mim_string.count("\n42.") != 2: - return {} - - ntds_users = mim_string.split("\n42.")[2].split("\nRID :")[1:] - - for ntds_user_txt in ntds_users: - user = ntds_user_txt.split("User :")[1].splitlines()[0].replace("User :", "").strip() - ntlm = ntds_user_txt.split("* Primary\n NTLM :")[1].splitlines()[0].replace("NTLM :", "").strip() - ntlm = ntlm.replace("[hashed secret]", "").strip() - users_dict[user] = {} - if ntlm: - users_dict[user]['ntlm'] = ntlm - - @staticmethod - def extract_secrets_from_mimikatz(mim_string): - users_dict = {} - MimikatzSecrets.extract_sam_secrets(mim_string, users_dict) - MimikatzSecrets.extract_ntlm_secrets(mim_string, users_dict) - - return users_dict diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 195eac3d6..1685046c5 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -184,10 +184,13 @@ class ReportService: continue origin = NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname'] for user in monkey_creds: - for pass_type in monkey_creds[user]: + for pass_type in PASS_TYPE_DICT: + if pass_type not in monkey_creds[user] or not monkey_creds[user][pass_type]: + continue + username = monkey_creds[user]['username'] if 'username' in monkey_creds[user] else user cred_row = \ { - 'username': user.replace(',', '.'), + 'username': username, 'type': PASS_TYPE_DICT[pass_type], 'origin': origin } @@ -729,8 +732,7 @@ class ReportService: '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() + 'strong_users': PTHReportService.get_strong_users_on_crit_details() }, 'recommendations': { diff --git a/monkey/monkey_island/cc/services/wmi_handler.py b/monkey/monkey_island/cc/services/wmi_handler.py index a802aabf1..413a5f307 100644 --- a/monkey/monkey_island/cc/services/wmi_handler.py +++ b/monkey/monkey_island/cc/services/wmi_handler.py @@ -69,7 +69,7 @@ class WMIHandler(object): base_entity = self.build_entity_document(user) else: base_entity = self.build_entity_document(user, self.monkey_id) - base_entity['NTLM_secret'] = self.users_secrets.get(base_entity['name'], {}).get('ntlm') + base_entity['NTLM_secret'] = self.users_secrets.get(base_entity['name'], {}).get('ntlm_hash') base_entity['SAM_secret'] = self.users_secrets.get(base_entity['name'], {}).get('sam') base_entity['secret_location'] = []