From 4952a544c009a073965af89fe82a9121a1ca2bb1 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 11:15:46 +0200 Subject: [PATCH 01/25] Agent: Accept IEventQueue in SSHCollector constructor --- .../ssh_collector/ssh_credential_collector.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py index cf18a8efc..04c9e65c2 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py @@ -2,6 +2,7 @@ import logging from typing import Dict, Iterable, Sequence from common.credentials import Credentials, SSHKeypair, Username +from common.event_queue import IEventQueue from infection_monkey.credential_collectors.ssh_collector import ssh_handler from infection_monkey.i_puppet import ICredentialCollector from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger @@ -14,8 +15,9 @@ class SSHCredentialCollector(ICredentialCollector): SSH keys credential collector """ - def __init__(self, telemetry_messenger: ITelemetryMessenger): + def __init__(self, telemetry_messenger: ITelemetryMessenger, event_queue: IEventQueue): self._telemetry_messenger = telemetry_messenger + self._event_queue = event_queue def collect_credentials(self, _options=None) -> Sequence[Credentials]: logger.info("Started scanning for SSH credentials") From 2610666f935dff2d96c95c8ace3793c5822883f3 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 14:24:03 +0200 Subject: [PATCH 02/25] Agent: Publish an CredentialsStolenEvent from SSHCredentialCollector --- .../ssh_collector/ssh_credential_collector.py | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py index 04c9e65c2..45cd227d8 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py @@ -1,14 +1,19 @@ import logging +import time from typing import Dict, Iterable, Sequence from common.credentials import Credentials, SSHKeypair, Username from common.event_queue import IEventQueue +from common.events import CredentialsStolenEvent +from infection_monkey.config import GUID from infection_monkey.credential_collectors.ssh_collector import ssh_handler from infection_monkey.i_puppet import ICredentialCollector from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger logger = logging.getLogger(__name__) +SSH_CREDENTIAL_COLLECTOR_TAG = "SSHCredentialsStolen" + class SSHCredentialCollector(ICredentialCollector): """ @@ -23,8 +28,28 @@ class SSHCredentialCollector(ICredentialCollector): logger.info("Started scanning for SSH credentials") ssh_info = ssh_handler.get_ssh_info(self._telemetry_messenger) logger.info("Finished scanning for SSH credentials") + ssh_collector_credentials = SSHCredentialCollector._to_credentials(ssh_info) - return SSHCredentialCollector._to_credentials(ssh_info) + credentials_stolen_event = SSHCredentialCollector._generate_credentials_stolen_event( + ssh_collector_credentials + ) + self._event_queue.publish(credentials_stolen_event) + + return ssh_collector_credentials + + @staticmethod + def _generate_credentials_stolen_event( + collected_credentials: Sequence[Credentials], + ) -> CredentialsStolenEvent: + credentials_stolen_event = CredentialsStolenEvent( + source=GUID, + target=None, + timestamp=time.time(), + tags=frozenset({SSH_CREDENTIAL_COLLECTOR_TAG, "T1005", "T1145"}), + stolen_credentials=collected_credentials, + ) + + return credentials_stolen_event @staticmethod def _to_credentials(ssh_info: Iterable[Dict]) -> Sequence[Credentials]: From e439a53bdeffd3f9a2538cee1371c518147f7536 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 14:30:42 +0200 Subject: [PATCH 03/25] UT: Fix SSHCredentialCollector test to accept IEventQueue --- .../test_ssh_credentials_collector.py | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py index c6d2a869d..ddfd87426 100644 --- a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py +++ b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py @@ -3,6 +3,7 @@ from unittest.mock import MagicMock import pytest from common.credentials import Credentials, SSHKeypair, Username +from common.event_queue import IEventQueue from infection_monkey.credential_collectors import SSHCredentialCollector @@ -11,6 +12,11 @@ def patch_telemetry_messenger(): return MagicMock() +@pytest.fixture +def mock_event_queue(): + return MagicMock(spec=IEventQueue) + + def patch_ssh_handler(ssh_creds, monkeypatch): monkeypatch.setattr( "infection_monkey.credential_collectors.ssh_collector.ssh_handler.get_ssh_info", @@ -18,16 +24,25 @@ def patch_ssh_handler(ssh_creds, monkeypatch): ) +def patch_guid(monkeypatch): + monkeypatch.setattr("infection_monkey.config.GUID", "1-2-3-4-5-6") + + @pytest.mark.parametrize( "ssh_creds", [([{"name": "", "home_dir": "", "public_key": None, "private_key": None}]), ([])] ) -def test_ssh_credentials_empty_results(monkeypatch, ssh_creds, patch_telemetry_messenger): +def test_ssh_credentials_empty_results( + monkeypatch, ssh_creds, patch_telemetry_messenger, mock_event_queue +): patch_ssh_handler(ssh_creds, monkeypatch) - collected = SSHCredentialCollector(patch_telemetry_messenger).collect_credentials() + collected = SSHCredentialCollector( + patch_telemetry_messenger, mock_event_queue + ).collect_credentials() assert not collected + mock_event_queue.publish.assert_called_once() -def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger): +def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger, mock_event_queue): ssh_creds = [ { @@ -67,5 +82,8 @@ def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger): Credentials(identity=username3, secret=None), Credentials(identity=None, secret=ssh_keypair3), ] - collected = SSHCredentialCollector(patch_telemetry_messenger).collect_credentials() + collected = SSHCredentialCollector( + patch_telemetry_messenger, mock_event_queue + ).collect_credentials() assert expected == collected + mock_event_queue.publish.assert_called_once() From b22ccdb942d37c374ac08178de8be971077d562c Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 17:09:32 +0200 Subject: [PATCH 04/25] Agent: Publish CredentialsStolenEvent each time we find a SSHKeypair --- .../ssh_collector/ssh_credential_collector.py | 26 +------------- .../ssh_collector/ssh_handler.py | 36 +++++++++++++++++-- .../test_ssh_credentials_collector.py | 8 +---- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py index 45cd227d8..c5659e2a8 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py @@ -1,19 +1,14 @@ import logging -import time from typing import Dict, Iterable, Sequence from common.credentials import Credentials, SSHKeypair, Username from common.event_queue import IEventQueue -from common.events import CredentialsStolenEvent -from infection_monkey.config import GUID from infection_monkey.credential_collectors.ssh_collector import ssh_handler from infection_monkey.i_puppet import ICredentialCollector from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger logger = logging.getLogger(__name__) -SSH_CREDENTIAL_COLLECTOR_TAG = "SSHCredentialsStolen" - class SSHCredentialCollector(ICredentialCollector): """ @@ -26,31 +21,12 @@ class SSHCredentialCollector(ICredentialCollector): def collect_credentials(self, _options=None) -> Sequence[Credentials]: logger.info("Started scanning for SSH credentials") - ssh_info = ssh_handler.get_ssh_info(self._telemetry_messenger) + ssh_info = ssh_handler.get_ssh_info(self._telemetry_messenger, self._event_queue) logger.info("Finished scanning for SSH credentials") ssh_collector_credentials = SSHCredentialCollector._to_credentials(ssh_info) - credentials_stolen_event = SSHCredentialCollector._generate_credentials_stolen_event( - ssh_collector_credentials - ) - self._event_queue.publish(credentials_stolen_event) - return ssh_collector_credentials - @staticmethod - def _generate_credentials_stolen_event( - collected_credentials: Sequence[Credentials], - ) -> CredentialsStolenEvent: - credentials_stolen_event = CredentialsStolenEvent( - source=GUID, - target=None, - timestamp=time.time(), - tags=frozenset({SSH_CREDENTIAL_COLLECTOR_TAG, "T1005", "T1145"}), - stolen_credentials=collected_credentials, - ) - - return credentials_stolen_event - @staticmethod def _to_credentials(ssh_info: Iterable[Dict]) -> Sequence[Credentials]: ssh_credentials = [] diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index 98ca0df4a..a48424304 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -1,8 +1,13 @@ import glob import logging import os +import time +import uuid from typing import Dict, Iterable +from common.credentials import Credentials, SSHKeypair, Username +from common.event_queue import IEventQueue +from common.events import CredentialsStolenEvent from common.utils.attack_utils import ScanStatus from infection_monkey.telemetry.attack.t1005_telem import T1005Telem from infection_monkey.telemetry.attack.t1145_telem import T1145Telem @@ -12,9 +17,12 @@ from infection_monkey.utils.environment import is_windows_os logger = logging.getLogger(__name__) DEFAULT_DIRS = ["/.ssh/", "/"] +SSH_CREDENTIAL_COLLECTOR_TAG = "SSHCredentialsStolen" -def get_ssh_info(telemetry_messenger: ITelemetryMessenger) -> Iterable[Dict]: +def get_ssh_info( + telemetry_messenger: ITelemetryMessenger, event_queue: IEventQueue +) -> Iterable[Dict]: # TODO: Remove this check when this is turned into a plugin. if is_windows_os(): logger.debug( @@ -23,7 +31,7 @@ def get_ssh_info(telemetry_messenger: ITelemetryMessenger) -> Iterable[Dict]: return [] home_dirs = _get_home_dirs() - ssh_info = _get_ssh_files(home_dirs, telemetry_messenger) + ssh_info = _get_ssh_files(home_dirs, telemetry_messenger, event_queue) return ssh_info @@ -62,7 +70,7 @@ def _get_ssh_struct(name: str, home_dir: str) -> Dict: def _get_ssh_files( - usr_info: Iterable[Dict], telemetry_messenger: ITelemetryMessenger + usr_info: Iterable[Dict], telemetry_messenger: ITelemetryMessenger, event_queue: IEventQueue ) -> Iterable[Dict]: for info in usr_info: path = info["home_dir"] @@ -101,6 +109,16 @@ def _get_ssh_files( ScanStatus.USED, info["name"], info["home_dir"] ) ) + + collected_credentials = Credentials( + identity=Username(info["name"]), + secrets=SSHKeypair( + info["private_key"], info["public_key"] + ), + ) + _publish_credentials_stolen_event( + collected_credentials, event_queue + ) else: continue except (IOError, OSError): @@ -114,3 +132,15 @@ def _get_ssh_files( pass usr_info = [info for info in usr_info if info["private_key"] or info["public_key"]] return usr_info + + +def _publish_credentials_stolen_event(collected_credentials: Credentials, event_queue: IEventQueue): + credentials_stolen_event = CredentialsStolenEvent( + source=uuid.getnode(), + target=None, + timestamp=time.time(), + tags=frozenset({SSH_CREDENTIAL_COLLECTOR_TAG, "T1005", "T1145"}), + stolen_credentials=[collected_credentials], + ) + + event_queue.publish(credentials_stolen_event) diff --git a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py index ddfd87426..d82236014 100644 --- a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py +++ b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py @@ -20,14 +20,10 @@ def mock_event_queue(): def patch_ssh_handler(ssh_creds, monkeypatch): monkeypatch.setattr( "infection_monkey.credential_collectors.ssh_collector.ssh_handler.get_ssh_info", - lambda _: ssh_creds, + lambda _, __: ssh_creds, ) -def patch_guid(monkeypatch): - monkeypatch.setattr("infection_monkey.config.GUID", "1-2-3-4-5-6") - - @pytest.mark.parametrize( "ssh_creds", [([{"name": "", "home_dir": "", "public_key": None, "private_key": None}]), ([])] ) @@ -39,7 +35,6 @@ def test_ssh_credentials_empty_results( patch_telemetry_messenger, mock_event_queue ).collect_credentials() assert not collected - mock_event_queue.publish.assert_called_once() def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger, mock_event_queue): @@ -86,4 +81,3 @@ def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger, mock_ev patch_telemetry_messenger, mock_event_queue ).collect_credentials() assert expected == collected - mock_event_queue.publish.assert_called_once() From 39f07603a7ea1e007aaa9bfb45eb37add127242a Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 17:13:23 +0200 Subject: [PATCH 05/25] Agent: Define integer GUID and use it in ssh_handler --- monkey/infection_monkey/config.py | 1 + .../credential_collectors/ssh_collector/ssh_handler.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index a4c39ee13..40cbbb739 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -2,3 +2,4 @@ import uuid # TODO: Find a better place for this GUID = str(uuid.getnode()) +IGUID = uuid.getnode() diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index a48424304..0ee4d2346 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -1,14 +1,14 @@ import glob import logging import os -import time -import uuid +from time import time from typing import Dict, Iterable from common.credentials import Credentials, SSHKeypair, Username from common.event_queue import IEventQueue from common.events import CredentialsStolenEvent from common.utils.attack_utils import ScanStatus +from infection_monkey.config import IGUID from infection_monkey.telemetry.attack.t1005_telem import T1005Telem from infection_monkey.telemetry.attack.t1145_telem import T1145Telem from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger @@ -136,9 +136,9 @@ def _get_ssh_files( def _publish_credentials_stolen_event(collected_credentials: Credentials, event_queue: IEventQueue): credentials_stolen_event = CredentialsStolenEvent( - source=uuid.getnode(), + source=IGUID, target=None, - timestamp=time.time(), + timestamp=time(), tags=frozenset({SSH_CREDENTIAL_COLLECTOR_TAG, "T1005", "T1145"}), stolen_credentials=[collected_credentials], ) From 5f631a78f724b241a95b6f7dd03b3749cf6ca3bb Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 18:23:25 +0200 Subject: [PATCH 06/25] Agent: Remove IGUID from config --- monkey/infection_monkey/config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 40cbbb739..a4c39ee13 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -2,4 +2,3 @@ import uuid # TODO: Find a better place for this GUID = str(uuid.getnode()) -IGUID = uuid.getnode() From 486a7a9225758b0c7383f79f164c6e14628477d7 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 18:24:01 +0200 Subject: [PATCH 07/25] Common: Use a temporary hack to define non-defaults from a inherited class event --- monkey/common/events/abstract_event.py | 11 ++++++----- monkey/common/events/credentials_stolen_events.py | 8 ++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/monkey/common/events/abstract_event.py b/monkey/common/events/abstract_event.py index 33bb25506..03629c442 100644 --- a/monkey/common/events/abstract_event.py +++ b/monkey/common/events/abstract_event.py @@ -1,8 +1,9 @@ +import time from abc import ABC -from dataclasses import dataclass +from dataclasses import dataclass, field from ipaddress import IPv4Address from typing import FrozenSet, Union -from uuid import UUID +from uuid import UUID, getnode @dataclass(frozen=True) @@ -21,7 +22,7 @@ class AbstractEvent(ABC): :param tags: The set of tags associated with the event """ - source: UUID - target: Union[UUID, IPv4Address, None] - timestamp: float tags: FrozenSet[str] + target: Union[UUID, IPv4Address, None] + source: UUID = field(default_factory=getnode) + timestamp: float = field(default_factory=time.time) diff --git a/monkey/common/events/credentials_stolen_events.py b/monkey/common/events/credentials_stolen_events.py index f1db1c142..7ad06cb10 100644 --- a/monkey/common/events/credentials_stolen_events.py +++ b/monkey/common/events/credentials_stolen_events.py @@ -1,4 +1,4 @@ -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import Sequence from common.credentials import Credentials @@ -6,6 +6,10 @@ from common.credentials import Credentials from . import AbstractEvent +def hack_event(): + raise TypeError("Missing a required argument") + + @dataclass(frozen=True) class CredentialsStolenEvent(AbstractEvent): """ @@ -15,4 +19,4 @@ class CredentialsStolenEvent(AbstractEvent): :param stolen_credentials: The credentials that were stolen by an agent """ - stolen_credentials: Sequence[Credentials] + stolen_credentials: Sequence[Credentials] = field(default_factory=hack_event) From 4aa71cba7e131b177907a0fcf2b15ac52086d280 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 18:25:51 +0200 Subject: [PATCH 08/25] Agent: Remove default values from CredentialsStolenEvent creation --- .../credential_collectors/ssh_collector/ssh_handler.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index 0ee4d2346..272b34edb 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -1,14 +1,12 @@ import glob import logging import os -from time import time from typing import Dict, Iterable from common.credentials import Credentials, SSHKeypair, Username from common.event_queue import IEventQueue from common.events import CredentialsStolenEvent from common.utils.attack_utils import ScanStatus -from infection_monkey.config import IGUID from infection_monkey.telemetry.attack.t1005_telem import T1005Telem from infection_monkey.telemetry.attack.t1145_telem import T1145Telem from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger @@ -136,9 +134,7 @@ def _get_ssh_files( def _publish_credentials_stolen_event(collected_credentials: Credentials, event_queue: IEventQueue): credentials_stolen_event = CredentialsStolenEvent( - source=IGUID, target=None, - timestamp=time(), tags=frozenset({SSH_CREDENTIAL_COLLECTOR_TAG, "T1005", "T1145"}), stolen_credentials=[collected_credentials], ) From 03d569cc000fa7f1bb4e7e42e2034d95dd24e91e Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 19:09:39 +0200 Subject: [PATCH 09/25] Agent: Init SSHCredentialCollector with an IEventQueue --- monkey/infection_monkey/monkey.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 258d05a36..3eb5c76bf 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -9,7 +9,7 @@ from typing import List from pubsub.core import Publisher import infection_monkey.tunnel as tunnel -from common.event_queue import PyPubSubEventQueue +from common.event_queue import IEventQueue, PyPubSubEventQueue from common.events import CredentialsStolenEvent from common.network.network_utils import address_to_ip_port from common.utils.argparse_types import positive_int @@ -199,8 +199,8 @@ class InfectionMonkey: def _build_master(self): local_network_interfaces = InfectionMonkey._get_local_network_interfaces() - _event_queue = PyPubSubEventQueue(Publisher()) - _event_queue.subscribe_type( + event_queue = PyPubSubEventQueue(Publisher()) + event_queue.subscribe_type( CredentialsStolenEvent, add_credentials_from_event_to_propagation_credentials_repository ) @@ -210,7 +210,7 @@ class InfectionMonkey: ) credentials_store = AggregatingPropagationCredentialsRepository(control_channel) - puppet = self._build_puppet(credentials_store) + puppet = self._build_puppet(credentials_store, event_queue) victim_host_factory = self._build_victim_host_factory(local_network_interfaces) @@ -239,7 +239,9 @@ class InfectionMonkey: return local_network_interfaces - def _build_puppet(self, credentials_store: IPropagationCredentialsRepository) -> IPuppet: + def _build_puppet( + self, credentials_store: IPropagationCredentialsRepository, event_queue: IEventQueue + ) -> IPuppet: puppet = Puppet() puppet.load_plugin( @@ -249,7 +251,7 @@ class InfectionMonkey: ) puppet.load_plugin( "SSHCollector", - SSHCredentialCollector(self._telemetry_messenger), + SSHCredentialCollector(self._telemetry_messenger, event_queue), PluginType.CREDENTIAL_COLLECTOR, ) From d672fcfffe39e9fe25d852e51256d0cb572b571d Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 19:10:05 +0200 Subject: [PATCH 10/25] Agent: Fix a typo in ssh_handler --- .../credential_collectors/ssh_collector/ssh_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index 272b34edb..b671cdaf1 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -110,7 +110,7 @@ def _get_ssh_files( collected_credentials = Credentials( identity=Username(info["name"]), - secrets=SSHKeypair( + secret=SSHKeypair( info["private_key"], info["public_key"] ), ) From 8f5681b1df131fd0a6a0aabba1d17b2ec99117ee Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 15 Aug 2022 19:22:58 +0200 Subject: [PATCH 11/25] Agent: Init a callable class and subscribe to it --- monkey/infection_monkey/monkey.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 3eb5c76bf..8987a0ece 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -199,17 +199,18 @@ class InfectionMonkey: def _build_master(self): local_network_interfaces = InfectionMonkey._get_local_network_interfaces() - event_queue = PyPubSubEventQueue(Publisher()) - event_queue.subscribe_type( - CredentialsStolenEvent, add_credentials_from_event_to_propagation_credentials_repository - ) - # TODO control_channel and control_client have same responsibilities, merge them control_channel = ControlChannel( self._control_client.server_address, GUID, self._control_client.proxies ) credentials_store = AggregatingPropagationCredentialsRepository(control_channel) + event_queue = PyPubSubEventQueue(Publisher()) + event_queue.subscribe_type( + CredentialsStolenEvent, + add_credentials_from_event_to_propagation_credentials_repository(credentials_store), + ) + puppet = self._build_puppet(credentials_store, event_queue) victim_host_factory = self._build_victim_host_factory(local_network_interfaces) From 88bb856859ba99c23dca0a6b2c0fd4f9ac4edb95 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 09:22:13 +0200 Subject: [PATCH 12/25] Common: Reorder params in docstring AbstractEvent --- monkey/common/events/abstract_event.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkey/common/events/abstract_event.py b/monkey/common/events/abstract_event.py index 03629c442..ef2735517 100644 --- a/monkey/common/events/abstract_event.py +++ b/monkey/common/events/abstract_event.py @@ -16,10 +16,10 @@ class AbstractEvent(ABC): about the event. Attributes: - :param source: The UUID of the agent that observed the event - :param target: The target of the event (if not the local system) - :param timestamp: The time that the event occurred (seconds since the Unix epoch) :param tags: The set of tags associated with the event + :param target: The target of the event (if not the local system) + :param source: The UUID of the agent that observed the event + :param timestamp: The time that the event occurred (seconds since the Unix epoch) """ tags: FrozenSet[str] From 2a94a677679d8ad54b65399c23c20e8eb188e594 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 09:28:05 +0200 Subject: [PATCH 13/25] Agent: Rename usr_info to user_info in ssh_handler --- .../credential_collectors/ssh_collector/ssh_handler.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index b671cdaf1..dc035b866 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -68,9 +68,9 @@ def _get_ssh_struct(name: str, home_dir: str) -> Dict: def _get_ssh_files( - usr_info: Iterable[Dict], telemetry_messenger: ITelemetryMessenger, event_queue: IEventQueue + user_info: Iterable[Dict], telemetry_messenger: ITelemetryMessenger, event_queue: IEventQueue ) -> Iterable[Dict]: - for info in usr_info: + for info in user_info: path = info["home_dir"] for directory in DEFAULT_DIRS: # TODO: Use PATH @@ -128,8 +128,8 @@ def _get_ssh_files( pass except OSError: pass - usr_info = [info for info in usr_info if info["private_key"] or info["public_key"]] - return usr_info + user_info = [info for info in user_info if info["private_key"] or info["public_key"]] + return user_info def _publish_credentials_stolen_event(collected_credentials: Credentials, event_queue: IEventQueue): From 706a626d241036bbad140076bc0f49c971f656b8 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 10:31:55 +0200 Subject: [PATCH 14/25] Agent: Move subscribtion to a separate method for readability --- monkey/infection_monkey/monkey.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 8987a0ece..3baf112c3 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -206,10 +206,7 @@ class InfectionMonkey: credentials_store = AggregatingPropagationCredentialsRepository(control_channel) event_queue = PyPubSubEventQueue(Publisher()) - event_queue.subscribe_type( - CredentialsStolenEvent, - add_credentials_from_event_to_propagation_credentials_repository(credentials_store), - ) + InfectionMonkey._subscribe_events(event_queue, credentials_store) puppet = self._build_puppet(credentials_store, event_queue) @@ -232,6 +229,15 @@ class InfectionMonkey: credentials_store, ) + @staticmethod + def _subscribe_events( + event_queue: IEventQueue, credentials_store: IPropagationCredentialsRepository + ): + event_queue.subscribe_type( + CredentialsStolenEvent, + add_credentials_from_event_to_propagation_credentials_repository(credentials_store), + ) + @staticmethod def _get_local_network_interfaces(): local_network_interfaces = get_local_network_interfaces() From fdd03688373f6ef7eef77571f405120058f92af5 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 11:06:54 +0200 Subject: [PATCH 15/25] Agent: Extract SSH collector tags into constants --- .../credential_collectors/ssh_collector/ssh_handler.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index dc035b866..e9896e718 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -16,6 +16,11 @@ logger = logging.getLogger(__name__) DEFAULT_DIRS = ["/.ssh/", "/"] SSH_CREDENTIAL_COLLECTOR_TAG = "SSHCredentialsStolen" +T1003_TAG = "T1003" +T1005_TAG = "T1005" +T1145_TAG = "T1145" + +SSH_COLLECTOR_EVENT_TAG = {SSH_CREDENTIAL_COLLECTOR_TAG, T1003_TAG, T1005_TAG, T1145_TAG} def get_ssh_info( @@ -135,7 +140,7 @@ def _get_ssh_files( def _publish_credentials_stolen_event(collected_credentials: Credentials, event_queue: IEventQueue): credentials_stolen_event = CredentialsStolenEvent( target=None, - tags=frozenset({SSH_CREDENTIAL_COLLECTOR_TAG, "T1005", "T1145"}), + tags=frozenset(SSH_COLLECTOR_EVENT_TAG), stolen_credentials=[collected_credentials], ) From c3557caf1c411c1bc724385df5d92b0f233411ab Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 14:11:16 +0200 Subject: [PATCH 16/25] Agent: Add _ATTACK_TECHNIQUE_ to attack_technique tags --- .../ssh_collector/ssh_handler.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index e9896e718..486211ded 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -16,11 +16,16 @@ logger = logging.getLogger(__name__) DEFAULT_DIRS = ["/.ssh/", "/"] SSH_CREDENTIAL_COLLECTOR_TAG = "SSHCredentialsStolen" -T1003_TAG = "T1003" -T1005_TAG = "T1005" -T1145_TAG = "T1145" +T1003_ATTACK_TECHNIQUE_TAG = "T1003" +T1005_ATTACK_TECHNIQUE_TAG = "T1005" +T1145_ATTACK_TECHNIQUE_TAG = "T1145" -SSH_COLLECTOR_EVENT_TAG = {SSH_CREDENTIAL_COLLECTOR_TAG, T1003_TAG, T1005_TAG, T1145_TAG} +SSH_COLLECTOR_EVENT_TAG = { + SSH_CREDENTIAL_COLLECTOR_TAG, + T1003_ATTACK_TECHNIQUE_TAG, + T1005_ATTACK_TECHNIQUE_TAG, + T1145_ATTACK_TECHNIQUE_TAG, +} def get_ssh_info( From 1d79d9868951bbdc7918c682cf945f33858a418a Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Tue, 16 Aug 2022 08:17:04 -0400 Subject: [PATCH 17/25] Agent: Rename credentials_store -> propagation_credentials_repository --- monkey/infection_monkey/monkey.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 3baf112c3..48cc70c67 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -203,12 +203,14 @@ class InfectionMonkey: control_channel = ControlChannel( self._control_client.server_address, GUID, self._control_client.proxies ) - credentials_store = AggregatingPropagationCredentialsRepository(control_channel) + propagation_credentials_repository = AggregatingPropagationCredentialsRepository( + control_channel + ) event_queue = PyPubSubEventQueue(Publisher()) - InfectionMonkey._subscribe_events(event_queue, credentials_store) + InfectionMonkey._subscribe_events(event_queue, propagation_credentials_repository) - puppet = self._build_puppet(credentials_store, event_queue) + puppet = self._build_puppet(propagation_credentials_repository, event_queue) victim_host_factory = self._build_victim_host_factory(local_network_interfaces) @@ -216,7 +218,7 @@ class InfectionMonkey: ExploitInterceptingTelemetryMessenger( self._telemetry_messenger, self._monkey_inbound_tunnel ), - credentials_store, + propagation_credentials_repository, ) self._master = AutomatedMaster( @@ -226,16 +228,19 @@ class InfectionMonkey: victim_host_factory, control_channel, local_network_interfaces, - credentials_store, + propagation_credentials_repository, ) @staticmethod def _subscribe_events( - event_queue: IEventQueue, credentials_store: IPropagationCredentialsRepository + event_queue: IEventQueue, + propagation_credentials_repository: IPropagationCredentialsRepository, ): event_queue.subscribe_type( CredentialsStolenEvent, - add_credentials_from_event_to_propagation_credentials_repository(credentials_store), + add_credentials_from_event_to_propagation_credentials_repository( + propagation_credentials_repository + ), ) @staticmethod @@ -247,7 +252,9 @@ class InfectionMonkey: return local_network_interfaces def _build_puppet( - self, credentials_store: IPropagationCredentialsRepository, event_queue: IEventQueue + self, + propagation_credentials_repository: IPropagationCredentialsRepository, + event_queue: IEventQueue, ) -> IPuppet: puppet = Puppet() @@ -290,7 +297,7 @@ class InfectionMonkey: ) zerologon_telemetry_messenger = CredentialsInterceptingTelemetryMessenger( - self._telemetry_messenger, credentials_store + self._telemetry_messenger, propagation_credentials_repository ) zerologon_wrapper = ExploiterWrapper(zerologon_telemetry_messenger, agent_repository) puppet.load_plugin( From ea9082d41213792c66eb0c748bb676f50c14c216 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 14:23:25 +0200 Subject: [PATCH 18/25] Agent: Remove hack_event from CredentialsStolenEvent --- monkey/common/events/credentials_stolen_events.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/monkey/common/events/credentials_stolen_events.py b/monkey/common/events/credentials_stolen_events.py index 7ad06cb10..ffd7707e7 100644 --- a/monkey/common/events/credentials_stolen_events.py +++ b/monkey/common/events/credentials_stolen_events.py @@ -6,10 +6,6 @@ from common.credentials import Credentials from . import AbstractEvent -def hack_event(): - raise TypeError("Missing a required argument") - - @dataclass(frozen=True) class CredentialsStolenEvent(AbstractEvent): """ @@ -19,4 +15,4 @@ class CredentialsStolenEvent(AbstractEvent): :param stolen_credentials: The credentials that were stolen by an agent """ - stolen_credentials: Sequence[Credentials] = field(default_factory=hack_event) + stolen_credentials: Sequence[Credentials] = field(default_factory=list) From c18ceff85dfb1c1e7951021be64cd3451fc03b05 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 14:24:26 +0200 Subject: [PATCH 19/25] Agent: Remove unneeded variable in SSHCredentialCollector --- .../ssh_collector/ssh_credential_collector.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py index c5659e2a8..b54f8d464 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py @@ -23,9 +23,8 @@ class SSHCredentialCollector(ICredentialCollector): logger.info("Started scanning for SSH credentials") ssh_info = ssh_handler.get_ssh_info(self._telemetry_messenger, self._event_queue) logger.info("Finished scanning for SSH credentials") - ssh_collector_credentials = SSHCredentialCollector._to_credentials(ssh_info) - return ssh_collector_credentials + return SSHCredentialCollector._to_credentials(ssh_info) @staticmethod def _to_credentials(ssh_info: Iterable[Dict]) -> Sequence[Credentials]: From d38a386f67c62b2a482614af49530bc8f64659cd Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 14:25:28 +0200 Subject: [PATCH 20/25] Agent: Add prefix `attack-` to attack tecniques tags --- .../credential_collectors/ssh_collector/ssh_handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index 486211ded..ed16bbfa2 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -16,9 +16,9 @@ logger = logging.getLogger(__name__) DEFAULT_DIRS = ["/.ssh/", "/"] SSH_CREDENTIAL_COLLECTOR_TAG = "SSHCredentialsStolen" -T1003_ATTACK_TECHNIQUE_TAG = "T1003" -T1005_ATTACK_TECHNIQUE_TAG = "T1005" -T1145_ATTACK_TECHNIQUE_TAG = "T1145" +T1003_ATTACK_TECHNIQUE_TAG = "attack-t1003" +T1005_ATTACK_TECHNIQUE_TAG = "attack-t1005" +T1145_ATTACK_TECHNIQUE_TAG = "attack-t1145" SSH_COLLECTOR_EVENT_TAG = { SSH_CREDENTIAL_COLLECTOR_TAG, From 142136dd410ef2fd29851eb7d4bd0034c209af9f Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 17:14:37 +0200 Subject: [PATCH 21/25] Agent: Remove duplication in SSHCredentialCollector --- .../ssh_collector/ssh_credential_collector.py | 32 ++--------------- .../ssh_collector/ssh_handler.py | 35 +++++++++++++++---- .../test_ssh_credentials_collector.py | 17 +++++---- 3 files changed, 39 insertions(+), 45 deletions(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py index b54f8d464..b696adf40 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py @@ -1,7 +1,7 @@ import logging -from typing import Dict, Iterable, Sequence +from typing import Sequence -from common.credentials import Credentials, SSHKeypair, Username +from common.credentials import Credentials from common.event_queue import IEventQueue from infection_monkey.credential_collectors.ssh_collector import ssh_handler from infection_monkey.i_puppet import ICredentialCollector @@ -24,30 +24,4 @@ class SSHCredentialCollector(ICredentialCollector): ssh_info = ssh_handler.get_ssh_info(self._telemetry_messenger, self._event_queue) logger.info("Finished scanning for SSH credentials") - return SSHCredentialCollector._to_credentials(ssh_info) - - @staticmethod - def _to_credentials(ssh_info: Iterable[Dict]) -> Sequence[Credentials]: - ssh_credentials = [] - - for info in ssh_info: - identity = None - secret = None - - if info.get("name", ""): - identity = Username(info["name"]) - - ssh_keypair = {} - for key in ["public_key", "private_key"]: - if info.get(key) is not None: - ssh_keypair[key] = info[key] - - if len(ssh_keypair): - secret = SSHKeypair( - ssh_keypair.get("private_key", ""), ssh_keypair.get("public_key", "") - ) - - if any([identity, secret]): - ssh_credentials.append(Credentials(identity, secret)) - - return ssh_credentials + return ssh_handler.to_credentials(ssh_info) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index ed16bbfa2..cc4245842 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -1,7 +1,7 @@ import glob import logging import os -from typing import Dict, Iterable +from typing import Dict, Iterable, Sequence from common.credentials import Credentials, SSHKeypair, Username from common.event_queue import IEventQueue @@ -118,12 +118,7 @@ def _get_ssh_files( ) ) - collected_credentials = Credentials( - identity=Username(info["name"]), - secret=SSHKeypair( - info["private_key"], info["public_key"] - ), - ) + collected_credentials = to_credentials([info]) _publish_credentials_stolen_event( collected_credentials, event_queue ) @@ -142,6 +137,32 @@ def _get_ssh_files( return user_info +def to_credentials(ssh_info: Iterable[Dict]) -> Sequence[Credentials]: + ssh_credentials = [] + + for info in ssh_info: + identity = None + secret = None + + if info.get("name", ""): + identity = Username(info["name"]) + + ssh_keypair = {} + for key in ["public_key", "private_key"]: + if info.get(key) is not None: + ssh_keypair[key] = info[key] + + if len(ssh_keypair): + secret = SSHKeypair( + ssh_keypair.get("private_key", ""), ssh_keypair.get("public_key", "") + ) + + if any([identity, secret]): + ssh_credentials.append(Credentials(identity, secret)) + + return ssh_credentials + + def _publish_credentials_stolen_event(collected_credentials: Credentials, event_queue: IEventQueue): credentials_stolen_event = CredentialsStolenEvent( target=None, diff --git a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py index d82236014..14a2e320a 100644 --- a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py +++ b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py @@ -1,9 +1,10 @@ from unittest.mock import MagicMock import pytest +from pubsub.core import Publisher from common.credentials import Credentials, SSHKeypair, Username -from common.event_queue import IEventQueue +from common.event_queue import IEventQueue, PyPubSubEventQueue from infection_monkey.credential_collectors import SSHCredentialCollector @@ -13,8 +14,8 @@ def patch_telemetry_messenger(): @pytest.fixture -def mock_event_queue(): - return MagicMock(spec=IEventQueue) +def event_queue() -> IEventQueue: + return PyPubSubEventQueue(Publisher()) def patch_ssh_handler(ssh_creds, monkeypatch): @@ -27,17 +28,15 @@ def patch_ssh_handler(ssh_creds, monkeypatch): @pytest.mark.parametrize( "ssh_creds", [([{"name": "", "home_dir": "", "public_key": None, "private_key": None}]), ([])] ) -def test_ssh_credentials_empty_results( - monkeypatch, ssh_creds, patch_telemetry_messenger, mock_event_queue -): +def test_ssh_credentials_empty_results(monkeypatch, ssh_creds, patch_telemetry_messenger): patch_ssh_handler(ssh_creds, monkeypatch) collected = SSHCredentialCollector( - patch_telemetry_messenger, mock_event_queue + patch_telemetry_messenger, MagicMock(spec=IEventQueue) ).collect_credentials() assert not collected -def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger, mock_event_queue): +def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger): ssh_creds = [ { @@ -78,6 +77,6 @@ def test_ssh_info_result_parsing(monkeypatch, patch_telemetry_messenger, mock_ev Credentials(identity=None, secret=ssh_keypair3), ] collected = SSHCredentialCollector( - patch_telemetry_messenger, mock_event_queue + patch_telemetry_messenger, MagicMock(spec=IEventQueue) ).collect_credentials() assert expected == collected From 5466bd5dbaba12fd2b51c1c817ce88d2f2b7c888 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 17:26:25 +0200 Subject: [PATCH 22/25] UT: Remove unneeded fixture in SSHCredentialCollector tests --- .../test_ssh_credentials_collector.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py index 14a2e320a..ba12e416f 100644 --- a/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py +++ b/monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py @@ -1,10 +1,9 @@ from unittest.mock import MagicMock import pytest -from pubsub.core import Publisher from common.credentials import Credentials, SSHKeypair, Username -from common.event_queue import IEventQueue, PyPubSubEventQueue +from common.event_queue import IEventQueue from infection_monkey.credential_collectors import SSHCredentialCollector @@ -13,11 +12,6 @@ def patch_telemetry_messenger(): return MagicMock() -@pytest.fixture -def event_queue() -> IEventQueue: - return PyPubSubEventQueue(Publisher()) - - def patch_ssh_handler(ssh_creds, monkeypatch): monkeypatch.setattr( "infection_monkey.credential_collectors.ssh_collector.ssh_handler.get_ssh_info", From b3d37d9223edb3a1ffc57a362c1e4e222e87c304 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 17:27:43 +0200 Subject: [PATCH 23/25] Agent: Change SSHCredentialCollector tag to lowercase --- .../credential_collectors/ssh_collector/ssh_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index cc4245842..73bf5e0c0 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -15,7 +15,7 @@ from infection_monkey.utils.environment import is_windows_os logger = logging.getLogger(__name__) DEFAULT_DIRS = ["/.ssh/", "/"] -SSH_CREDENTIAL_COLLECTOR_TAG = "SSHCredentialsStolen" +SSH_CREDENTIAL_COLLECTOR_TAG = "ssh-credentials-collector" T1003_ATTACK_TECHNIQUE_TAG = "attack-t1003" T1005_ATTACK_TECHNIQUE_TAG = "attack-t1005" T1145_ATTACK_TECHNIQUE_TAG = "attack-t1145" From 205ff84b31e9b11b464e325f12a3a0475f0df84d Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 17:30:30 +0200 Subject: [PATCH 24/25] Common: Add defaults for each argument in AbstractEvent --- monkey/common/events/abstract_event.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/common/events/abstract_event.py b/monkey/common/events/abstract_event.py index ef2735517..4b4edbf99 100644 --- a/monkey/common/events/abstract_event.py +++ b/monkey/common/events/abstract_event.py @@ -16,13 +16,13 @@ class AbstractEvent(ABC): about the event. Attributes: - :param tags: The set of tags associated with the event - :param target: The target of the event (if not the local system) :param source: The UUID of the agent that observed the event + :param target: The target of the event (if not the local system) :param timestamp: The time that the event occurred (seconds since the Unix epoch) + :param tags: The set of tags associated with the event """ - tags: FrozenSet[str] - target: Union[UUID, IPv4Address, None] source: UUID = field(default_factory=getnode) + target: Union[UUID, IPv4Address, None] = field(default=None) timestamp: float = field(default_factory=time.time) + tags: FrozenSet[str] = field(default_factory=frozenset) From eec48e9cd8603313d3d4b489166fe50430e06c1f Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 16 Aug 2022 17:31:02 +0200 Subject: [PATCH 25/25] Agent: Remove target from SSHCredentialCollector event construction --- .../credential_collectors/ssh_collector/ssh_handler.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py index 73bf5e0c0..097d59f40 100644 --- a/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py +++ b/monkey/infection_monkey/credential_collectors/ssh_collector/ssh_handler.py @@ -165,7 +165,6 @@ def to_credentials(ssh_info: Iterable[Dict]) -> Sequence[Credentials]: def _publish_credentials_stolen_event(collected_credentials: Credentials, event_queue: IEventQueue): credentials_stolen_event = CredentialsStolenEvent( - target=None, tags=frozenset(SSH_COLLECTOR_EVENT_TAG), stolen_credentials=[collected_credentials], )