diff --git a/monkey/infection_monkey/exploit/HostExploiter.py b/monkey/infection_monkey/exploit/HostExploiter.py index 602dd338a..4b0c78c21 100644 --- a/monkey/infection_monkey/exploit/HostExploiter.py +++ b/monkey/infection_monkey/exploit/HostExploiter.py @@ -4,6 +4,7 @@ from abc import abstractmethod from datetime import datetime from typing import Dict +from common.event_queue import IEventQueue from common.utils.exceptions import FailedExploitationError from infection_monkey.i_puppet import ExploiterResultData from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger @@ -31,6 +32,7 @@ class HostExploiter: self.exploit_attempts = [] self.host = None self.telemetry_messenger = None + self.event_queue = None self.options = {} self.exploit_result = {} @@ -58,6 +60,7 @@ class HostExploiter: host, current_depth: int, telemetry_messenger: ITelemetryMessenger, + event_queue: IEventQueue, agent_repository: IAgentRepository, options: Dict, interrupt: threading.Event, @@ -65,6 +68,7 @@ class HostExploiter: self.host = host self.current_depth = current_depth self.telemetry_messenger = telemetry_messenger + self.event_queue = event_queue self.agent_repository = agent_repository self.options = options self.interrupt = interrupt diff --git a/monkey/infection_monkey/exploit/exploiter_wrapper.py b/monkey/infection_monkey/exploit/exploiter_wrapper.py index 540e0b4a4..8e9d4f22f 100644 --- a/monkey/infection_monkey/exploit/exploiter_wrapper.py +++ b/monkey/infection_monkey/exploit/exploiter_wrapper.py @@ -1,6 +1,7 @@ import threading from typing import Dict, Type +from common.event_queue import IEventQueue from infection_monkey.model import VictimHost from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger @@ -21,10 +22,12 @@ class ExploiterWrapper: self, exploit_class: Type[HostExploiter], telemetry_messenger: ITelemetryMessenger, + event_queue: IEventQueue, agent_repository: IAgentRepository, ): self._exploit_class = exploit_class self._telemetry_messenger = telemetry_messenger + self._event_queue = event_queue self._agent_repository = agent_repository def exploit_host( @@ -35,18 +38,23 @@ class ExploiterWrapper: host, current_depth, self._telemetry_messenger, + self._event_queue, self._agent_repository, options, interrupt, ) def __init__( - self, telemetry_messenger: ITelemetryMessenger, agent_repository: IAgentRepository + self, + telemetry_messenger: ITelemetryMessenger, + event_queue: IEventQueue, + agent_repository: IAgentRepository, ): self._telemetry_messenger = telemetry_messenger + self._event_queue = event_queue self._agent_repository = agent_repository def wrap(self, exploit_class: Type[HostExploiter]): return ExploiterWrapper.Inner( - exploit_class, self._telemetry_messenger, self._agent_repository + exploit_class, self._telemetry_messenger, self._event_queue, self._agent_repository ) diff --git a/monkey/infection_monkey/exploit/zerologon.py b/monkey/infection_monkey/exploit/zerologon.py index 276b0c529..f43a61069 100644 --- a/monkey/infection_monkey/exploit/zerologon.py +++ b/monkey/infection_monkey/exploit/zerologon.py @@ -9,7 +9,7 @@ import os import re import tempfile from binascii import unhexlify -from typing import Dict, List, Optional, Tuple +from typing import Dict, List, Optional, Sequence, Tuple import impacket from impacket.dcerpc.v5 import epm, nrpc, rpcrt, transport @@ -17,6 +17,7 @@ from impacket.dcerpc.v5.dtypes import NULL from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT from common.credentials import Credentials, LMHash, NTHash, Username +from common.events import CredentialsStolenEvent 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 @@ -30,6 +31,19 @@ from infection_monkey.utils.threading import interruptible_iter logger = logging.getLogger(__name__) +ZEROLOGON_EXPLOITER_TAG = "zerologon-exploiter" +T1003_ATTACK_TECHNIQUE_TAG = "attack-t1003" +T1098_ATTACK_TECHNIQUE_TAG = "attack-t1098" + + +ZEROLOGON_EVENT_TAGS = frozenset( + { + ZEROLOGON_EXPLOITER_TAG, + T1003_ATTACK_TECHNIQUE_TAG, + T1098_ATTACK_TECHNIQUE_TAG, + } +) + class ZerologonExploiter(HostExploiter): _EXPLOITED_SERVICE = "Netlogon" @@ -284,14 +298,20 @@ class ZerologonExploiter(HostExploiter): def send_extracted_creds_as_credential_telemetry( self, user: str, lmhash: str, nthash: str ) -> None: - self.telemetry_messenger.send_telemetry( - CredentialsTelem( - [ - Credentials(Username(user), LMHash(lmhash)), - Credentials(Username(user), NTHash(nthash)), - ] - ) + extracted_credentials = [ + Credentials(Username(user), LMHash(lmhash)), + Credentials(Username(user), NTHash(nthash)), + ] + + self.telemetry_messenger.send_telemetry(CredentialsTelem(extracted_credentials)) + self._publish_credentials_stolen_event(extracted_credentials) + + def _publish_credentials_stolen_event(self, extracted_credentials: Sequence[Credentials]): + credentials_stolen_event = CredentialsStolenEvent( + tags=ZEROLOGON_EVENT_TAGS, + stolen_credentials=extracted_credentials, ) + self.event_queue.publish(credentials_stolen_event) def get_original_pwd_nthash(self, username: str, user_pwd_hashes: List[str]) -> str: if not self.save_HKLM_keys_locally(username, user_pwd_hashes): diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 60ad0524a..24e085e87 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -272,7 +272,7 @@ class InfectionMonkey: agent_repository = CachingAgentRepository( f"https://{self._control_client.server_address}", self._control_client.proxies ) - exploit_wrapper = ExploiterWrapper(self._telemetry_messenger, agent_repository) + exploit_wrapper = ExploiterWrapper(self._telemetry_messenger, event_queue, agent_repository) puppet.load_plugin( "HadoopExploiter", exploit_wrapper.wrap(HadoopExploiter), PluginType.EXPLOITER diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py index c5d428f47..a764de832 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py @@ -36,6 +36,7 @@ def powershell_arguments(http_and_https_both_enabled_host): "options": options, "current_depth": 2, "telemetry_messenger": MagicMock(), + "event_queue": MagicMock(), "agent_repository": mock_agent_repository, "interrupt": threading.Event(), }