From 84db00b72809bcab2ec06e622ffce84cabe96393 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:05:10 -0400 Subject: [PATCH 01/19] Island: Use AgentConfiguration in IConfigRepository --- monkey/monkey_island/cc/repository/i_config_repository.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/repository/i_config_repository.py b/monkey/monkey_island/cc/repository/i_config_repository.py index 70e59a89f..c9967ad45 100644 --- a/monkey/monkey_island/cc/repository/i_config_repository.py +++ b/monkey/monkey_island/cc/repository/i_config_repository.py @@ -1,5 +1,7 @@ from abc import ABC -from typing import Any, Mapping, Sequence +from typing import Any, Sequence + +from common.configuration import AgentConfiguration class IConfigRepository(ABC): @@ -10,10 +12,10 @@ class IConfigRepository(ABC): # This returns the current config # TODO investigate if encryption should be here or where # TODO potentially should be a DTO as well, but it's structure is defined in schema already - def get_config(self) -> Mapping: + def get_config(self) -> AgentConfiguration: pass - def set_config(self, config: dict): + def set_config(self, config: AgentConfiguration): pass # Used when only a subset of config is submitted, for example only PBAFiles From 62056175a18c1045fc12d15baf79a718b76986ad Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:05:55 -0400 Subject: [PATCH 02/19] Island: Remove unneeded methods in IConfigRepository Also remove stale comments. No encryption is needed here because configuration does not contain anything sensitive. --- .../cc/repository/i_config_repository.py | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/monkey/monkey_island/cc/repository/i_config_repository.py b/monkey/monkey_island/cc/repository/i_config_repository.py index c9967ad45..ce6935b87 100644 --- a/monkey/monkey_island/cc/repository/i_config_repository.py +++ b/monkey/monkey_island/cc/repository/i_config_repository.py @@ -1,32 +1,11 @@ from abc import ABC -from typing import Any, Sequence from common.configuration import AgentConfiguration class IConfigRepository(ABC): - - # Config - ############################################### - - # This returns the current config - # TODO investigate if encryption should be here or where - # TODO potentially should be a DTO as well, but it's structure is defined in schema already def get_config(self) -> AgentConfiguration: pass def set_config(self, config: AgentConfiguration): pass - - # Used when only a subset of config is submitted, for example only PBAFiles - # Used by passing keys, like ['monkey', 'post_breach_actions', 'linux_filename'] - # Using a list is less ambiguous IMO, than using . notation - def set_config_field(self, key_list: Sequence[str], value: Any): - pass - - # Used when only a subset of config is needed, for example only PBAFiles - # Used by passing keys, like ['monkey', 'post_breach_actions', 'linux_filename'] - # Using a list is less ambiguous IMO, than using . notation - # TODO Still in doubt about encryption, this should probably be determined automatically - def get_config_field(self, key_list: Sequence[str]) -> Any: - pass From ae0c440603bbc116bbec16692e5a9ab8723b2d95 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:08:45 -0400 Subject: [PATCH 03/19] Island: Add documentation for IConfigRepository --- .../cc/repository/i_config_repository.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/repository/i_config_repository.py b/monkey/monkey_island/cc/repository/i_config_repository.py index ce6935b87..def95e228 100644 --- a/monkey/monkey_island/cc/repository/i_config_repository.py +++ b/monkey/monkey_island/cc/repository/i_config_repository.py @@ -4,8 +4,21 @@ from common.configuration import AgentConfiguration class IConfigRepository(ABC): + """ + A repository used to store and retrieve the agent configuration. + """ def get_config(self) -> AgentConfiguration: + """ + Retrieve the agent configuration from the repository + + :return: The agent configuration + """ pass - def set_config(self, config: AgentConfiguration): + def set_config(self, agent_config: AgentConfiguration): + """ + Store the agent configuration in the repository + + :param agent_config: The agent configuration to store in the repository + """ pass From 59e29456c03abeddd9ca2e1bea17b216c95f4184 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:09:33 -0400 Subject: [PATCH 04/19] Island: Rename i_config_repository.py -> i_configuration_repository.py --- .../{i_config_repository.py => i_configuration_repository.py} | 1 + 1 file changed, 1 insertion(+) rename monkey/monkey_island/cc/repository/{i_config_repository.py => i_configuration_repository.py} (99%) diff --git a/monkey/monkey_island/cc/repository/i_config_repository.py b/monkey/monkey_island/cc/repository/i_configuration_repository.py similarity index 99% rename from monkey/monkey_island/cc/repository/i_config_repository.py rename to monkey/monkey_island/cc/repository/i_configuration_repository.py index def95e228..8d06fc5c7 100644 --- a/monkey/monkey_island/cc/repository/i_config_repository.py +++ b/monkey/monkey_island/cc/repository/i_configuration_repository.py @@ -7,6 +7,7 @@ class IConfigRepository(ABC): """ A repository used to store and retrieve the agent configuration. """ + def get_config(self) -> AgentConfiguration: """ Retrieve the agent configuration from the repository From 91476a7a066d3d9d71b4822030ee3ef6ad39d25f Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:11:14 -0400 Subject: [PATCH 05/19] Island: Protract config -> configuration in IConfigurationRepository --- .../cc/repository/i_configuration_repository.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/monkey_island/cc/repository/i_configuration_repository.py b/monkey/monkey_island/cc/repository/i_configuration_repository.py index 8d06fc5c7..58a97bce9 100644 --- a/monkey/monkey_island/cc/repository/i_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/i_configuration_repository.py @@ -3,12 +3,12 @@ from abc import ABC from common.configuration import AgentConfiguration -class IConfigRepository(ABC): +class IConfigurationRepository(ABC): """ A repository used to store and retrieve the agent configuration. """ - def get_config(self) -> AgentConfiguration: + def get_configuration(self) -> AgentConfiguration: """ Retrieve the agent configuration from the repository @@ -16,10 +16,10 @@ class IConfigRepository(ABC): """ pass - def set_config(self, agent_config: AgentConfiguration): + def set_configuration(self, agent_configuration: AgentConfiguration): """ Store the agent configuration in the repository - :param agent_config: The agent configuration to store in the repository + :param agent_configuration: The agent configuration to store in the repository """ pass From ace3eb8718475d093bd40462c748782e2beb9904 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:16:44 -0400 Subject: [PATCH 06/19] UT: Extract SingleFileRepository from test_pba_file_upload.py --- monkey/tests/common/SingleFileRepository.py | 23 ++++++++++++++++ monkey/tests/monkey_island/__init__.py | 1 + .../monkey_island/single_file_repository.py | 23 ++++++++++++++++ .../cc/resources/test_pba_file_upload.py | 27 +++---------------- 4 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 monkey/tests/common/SingleFileRepository.py create mode 100644 monkey/tests/monkey_island/__init__.py create mode 100644 monkey/tests/monkey_island/single_file_repository.py diff --git a/monkey/tests/common/SingleFileRepository.py b/monkey/tests/common/SingleFileRepository.py new file mode 100644 index 000000000..d00ee9ae9 --- /dev/null +++ b/monkey/tests/common/SingleFileRepository.py @@ -0,0 +1,23 @@ +import io +from typing import BinaryIO + +from monkey_island.cc.repository import FileRetrievalError, IFileRepository + + +class SingleFileRepository(IFileRepository): + def __init__(self): + self._file = None + + def save_file(self, unsafe_file_name: str, file_contents: BinaryIO): + self._file = io.BytesIO(file_contents.read()) + + def open_file(self, unsafe_file_name: str) -> BinaryIO: + if self._file is None: + raise FileRetrievalError() + return self._file + + def delete_file(self, unsafe_file_name: str): + self._file = None + + def delete_all_files(self): + self.delete_file("") diff --git a/monkey/tests/monkey_island/__init__.py b/monkey/tests/monkey_island/__init__.py new file mode 100644 index 000000000..7bd9a314d --- /dev/null +++ b/monkey/tests/monkey_island/__init__.py @@ -0,0 +1 @@ +from .single_file_repository import SingleFileRepository diff --git a/monkey/tests/monkey_island/single_file_repository.py b/monkey/tests/monkey_island/single_file_repository.py new file mode 100644 index 000000000..d00ee9ae9 --- /dev/null +++ b/monkey/tests/monkey_island/single_file_repository.py @@ -0,0 +1,23 @@ +import io +from typing import BinaryIO + +from monkey_island.cc.repository import FileRetrievalError, IFileRepository + + +class SingleFileRepository(IFileRepository): + def __init__(self): + self._file = None + + def save_file(self, unsafe_file_name: str, file_contents: BinaryIO): + self._file = io.BytesIO(file_contents.read()) + + def open_file(self, unsafe_file_name: str) -> BinaryIO: + if self._file is None: + raise FileRetrievalError() + return self._file + + def delete_file(self, unsafe_file_name: str): + self._file = None + + def delete_all_files(self): + self.delete_file("") diff --git a/monkey/tests/unit_tests/monkey_island/cc/resources/test_pba_file_upload.py b/monkey/tests/unit_tests/monkey_island/cc/resources/test_pba_file_upload.py index 2642c0758..50da88915 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/resources/test_pba_file_upload.py +++ b/monkey/tests/unit_tests/monkey_island/cc/resources/test_pba_file_upload.py @@ -1,12 +1,10 @@ -import io -from typing import BinaryIO - import pytest from tests.common import StubDIContainer +from tests.monkey_island import SingleFileRepository from tests.unit_tests.monkey_island.conftest import get_url_for_resource from tests.utils import raise_ -from monkey_island.cc.repository import FileRetrievalError, IFileRepository +from monkey_island.cc.repository import IFileRepository from monkey_island.cc.resources.pba_file_upload import LINUX_PBA_TYPE, WINDOWS_PBA_TYPE, FileUpload TEST_FILE_CONTENTS = b"m0nk3y" @@ -40,28 +38,9 @@ def mock_get_config_value(monkeypatch): ) -class MockFileRepository(IFileRepository): - def __init__(self): - self._file = None - - def save_file(self, unsafe_file_name: str, file_contents: BinaryIO): - self._file = io.BytesIO(file_contents.read()) - - def open_file(self, unsafe_file_name: str) -> BinaryIO: - if self._file is None: - raise FileRetrievalError() - return self._file - - def delete_file(self, unsafe_file_name: str): - self._file = None - - def delete_all_files(self): - self.delete_file("") - - @pytest.fixture def file_repository(): - return MockFileRepository() + return SingleFileRepository() @pytest.fixture From 7cb7f7ab5a62debb3e9e6b52b769fd017a33a5ec Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:33:01 -0400 Subject: [PATCH 07/19] UT: Extract agent configuration from test_agent_configuration.py --- .../common/example_agent_configuration.py | 75 +++++++++++ .../common/test_agent_configuration.py | 116 +++++------------- 2 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 monkey/tests/common/example_agent_configuration.py diff --git a/monkey/tests/common/example_agent_configuration.py b/monkey/tests/common/example_agent_configuration.py new file mode 100644 index 000000000..640771df4 --- /dev/null +++ b/monkey/tests/common/example_agent_configuration.py @@ -0,0 +1,75 @@ +PLUGIN_NAME = "bond" +PLUGIN_OPTIONS = {"gun": "Walther PPK", "car": "Aston Martin DB5"} +PLUGIN_CONFIGURATION = {"name": PLUGIN_NAME, "options": PLUGIN_OPTIONS} + +LINUX_COMMAND = "a" +LINUX_FILENAME = "b" +WINDOWS_COMMAND = "c" +WINDOWS_FILENAME = "d" +CUSTOM_PBA_CONFIGURATION = { + "linux_command": LINUX_COMMAND, + "linux_filename": LINUX_FILENAME, + "windows_command": WINDOWS_COMMAND, + "windows_filename": WINDOWS_FILENAME, +} + +BLOCKED_IPS = ["10.0.0.1", "192.168.1.1"] +INACCESSIBLE_SUBNETS = ["172.0.0.0/24", "172.2.2.0/24", "192.168.56.0/24"] +LOCAL_NETWORK_SCAN = True +SUBNETS = ["10.0.0.2", "10.0.0.2/16"] +SCAN_TARGET_CONFIGURATION = { + "blocked_ips": BLOCKED_IPS, + "inaccessible_subnets": INACCESSIBLE_SUBNETS, + "local_network_scan": LOCAL_NETWORK_SCAN, + "subnets": SUBNETS, +} + +TIMEOUT = 2.525 +ICMP_CONFIGURATION = {"timeout": TIMEOUT} + +PORTS = [8080, 443] +TCP_SCAN_CONFIGURATION = {"timeout": TIMEOUT, "ports": PORTS} + +FINGERPRINTERS = [{"name": "mssql", "options": {}}] +NETWORK_SCAN_CONFIGURATION = { + "tcp": TCP_SCAN_CONFIGURATION, + "icmp": ICMP_CONFIGURATION, + "fingerprinters": FINGERPRINTERS, + "targets": SCAN_TARGET_CONFIGURATION, +} + +BRUTE_FORCE = [ + {"name": "ex1", "options": {}, "supported_os": ["LINUX"]}, + { + "name": "ex2", + "options": {"smb_download_timeout": 10}, + "supported_os": ["LINUX", "WINDOWS"], + }, +] +VULNERABILITY = [ + { + "name": "ex3", + "options": {"smb_download_timeout": 10}, + "supported_os": ["WINDOWS"], + }, +] +EXPLOITATION_CONFIGURATION = { + "options": {"http_ports": PORTS}, + "brute_force": BRUTE_FORCE, + "vulnerability": VULNERABILITY, +} + +PROPAGATION_CONFIGURATION = { + "maximum_depth": 5, + "network_scan": NETWORK_SCAN_CONFIGURATION, + "exploitation": EXPLOITATION_CONFIGURATION, +} + +AGENT_CONFIGURATION = { + "keep_tunnel_open_time": 30, + "custom_pbas": CUSTOM_PBA_CONFIGURATION, + "post_breach_actions": [PLUGIN_CONFIGURATION], + "credential_collectors": [PLUGIN_CONFIGURATION], + "payloads": [PLUGIN_CONFIGURATION], + "propagation": PROPAGATION_CONFIGURATION, +} diff --git a/monkey/tests/unit_tests/common/test_agent_configuration.py b/monkey/tests/unit_tests/common/test_agent_configuration.py index 512b46bc4..9609a2d3a 100644 --- a/monkey/tests/unit_tests/common/test_agent_configuration.py +++ b/monkey/tests/unit_tests/common/test_agent_configuration.py @@ -1,3 +1,28 @@ +from tests.common.example_agent_configuration import ( + AGENT_CONFIGURATION, + BLOCKED_IPS, + CUSTOM_PBA_CONFIGURATION, + EXPLOITATION_CONFIGURATION, + FINGERPRINTERS, + ICMP_CONFIGURATION, + INACCESSIBLE_SUBNETS, + LINUX_COMMAND, + LINUX_FILENAME, + LOCAL_NETWORK_SCAN, + NETWORK_SCAN_CONFIGURATION, + PLUGIN_CONFIGURATION, + PLUGIN_NAME, + PLUGIN_OPTIONS, + PORTS, + PROPAGATION_CONFIGURATION, + SCAN_TARGET_CONFIGURATION, + SUBNETS, + TCP_SCAN_CONFIGURATION, + TIMEOUT, + WINDOWS_COMMAND, + WINDOWS_FILENAME, +) + from common import OperatingSystems from common.configuration import AgentConfiguration, AgentConfigurationSchema from common.configuration.agent_sub_configuration_schemas import ( @@ -20,30 +45,14 @@ from common.configuration.agent_sub_configurations import ( PropagationConfiguration, ) -NAME = "bond" -OPTIONS = {"gun": "Walther PPK", "car": "Aston Martin DB5"} -PLUGIN_CONFIGURATION = {"name": NAME, "options": OPTIONS} - def test_build_plugin_configuration(): schema = PluginConfigurationSchema() config = schema.load(PLUGIN_CONFIGURATION) - assert config.name == NAME - assert config.options == OPTIONS - - -LINUX_COMMAND = "a" -LINUX_FILENAME = "b" -WINDOWS_COMMAND = "c" -WINDOWS_FILENAME = "d" -CUSTOM_PBA_CONFIGURATION = { - "linux_command": LINUX_COMMAND, - "linux_filename": LINUX_FILENAME, - "windows_command": WINDOWS_COMMAND, - "windows_filename": WINDOWS_FILENAME, -} + assert config.name == PLUGIN_NAME + assert config.options == PLUGIN_OPTIONS def test_custom_pba_configuration_schema(): @@ -57,18 +66,6 @@ def test_custom_pba_configuration_schema(): assert config.windows_filename == WINDOWS_FILENAME -BLOCKED_IPS = ["10.0.0.1", "192.168.1.1"] -INACCESSIBLE_SUBNETS = ["172.0.0.0/24", "172.2.2.0/24", "192.168.56.0/24"] -LOCAL_NETWORK_SCAN = True -SUBNETS = ["10.0.0.2", "10.0.0.2/16"] -SCAN_TARGET_CONFIGURATION = { - "blocked_ips": BLOCKED_IPS, - "inaccessible_subnets": INACCESSIBLE_SUBNETS, - "local_network_scan": LOCAL_NETWORK_SCAN, - "subnets": SUBNETS, -} - - def test_scan_target_configuration(): schema = ScanTargetConfigurationSchema() @@ -80,10 +77,6 @@ def test_scan_target_configuration(): assert config.subnets == SUBNETS -TIMEOUT = 2.525 -ICMP_CONFIGURATION = {"timeout": TIMEOUT} - - def test_icmp_scan_configuration_schema(): schema = ICMPScanConfigurationSchema() @@ -92,11 +85,6 @@ def test_icmp_scan_configuration_schema(): assert config.timeout == TIMEOUT -PORTS = [8080, 443] - -TCP_SCAN_CONFIGURATION = {"timeout": TIMEOUT, "ports": PORTS} - - def test_tcp_scan_configuration_schema(): schema = TCPScanConfigurationSchema() @@ -106,15 +94,6 @@ def test_tcp_scan_configuration_schema(): assert config.ports == PORTS -FINGERPRINTERS = [{"name": "mssql", "options": {}}] -NETWORK_SCAN_CONFIGURATION = { - "tcp": TCP_SCAN_CONFIGURATION, - "icmp": ICMP_CONFIGURATION, - "fingerprinters": FINGERPRINTERS, - "targets": SCAN_TARGET_CONFIGURATION, -} - - def test_network_scan_configuration(): schema = NetworkScanConfigurationSchema() @@ -155,28 +134,6 @@ def test_exploiter_configuration_schema(): assert config.supported_os == supported_os -BRUTE_FORCE = [ - {"name": "ex1", "options": {}, "supported_os": ["LINUX"]}, - { - "name": "ex2", - "options": {"smb_download_timeout": 10}, - "supported_os": ["LINUX", "WINDOWS"], - }, -] -VULNERABILITY = [ - { - "name": "ex3", - "options": {"smb_download_timeout": 10}, - "supported_os": ["WINDOWS"], - }, -] -EXPLOITATION_CONFIGURATION = { - "options": {"http_ports": PORTS}, - "brute_force": BRUTE_FORCE, - "vulnerability": VULNERABILITY, -} - - def test_exploitation_configuration(): schema = ExploitationConfigurationSchema() @@ -187,13 +144,6 @@ def test_exploitation_configuration(): assert config_dict == EXPLOITATION_CONFIGURATION -PROPAGATION_CONFIGURATION = { - "maximum_depth": 5, - "network_scan": NETWORK_SCAN_CONFIGURATION, - "exploitation": EXPLOITATION_CONFIGURATION, -} - - def test_propagation_configuration(): schema = PropagationConfigurationSchema() @@ -208,17 +158,9 @@ def test_propagation_configuration(): def test_agent_configuration(): - agent_configuration = { - "keep_tunnel_open_time": 30, - "custom_pbas": CUSTOM_PBA_CONFIGURATION, - "post_breach_actions": [PLUGIN_CONFIGURATION], - "credential_collectors": [PLUGIN_CONFIGURATION], - "payloads": [PLUGIN_CONFIGURATION], - "propagation": PROPAGATION_CONFIGURATION, - } schema = AgentConfigurationSchema() - config = schema.load(agent_configuration) + config = schema.load(AGENT_CONFIGURATION) config_dict = schema.dump(config) assert isinstance(config, AgentConfiguration) @@ -228,4 +170,4 @@ def test_agent_configuration(): assert isinstance(config.credential_collectors[0], PluginConfiguration) assert isinstance(config.payloads[0], PluginConfiguration) assert isinstance(config.propagation, PropagationConfiguration) - assert config_dict == agent_configuration + assert config_dict == AGENT_CONFIGURATION From a75041e93ff1dca5e8a53e2771411d79672c6f0f Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:36:50 -0400 Subject: [PATCH 08/19] Island: Rename IConfigurationRepository IAgentConfigurationRepository --- ...ration_repository.py => i_agent_configuration_repository.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename monkey/monkey_island/cc/repository/{i_configuration_repository.py => i_agent_configuration_repository.py} (93%) diff --git a/monkey/monkey_island/cc/repository/i_configuration_repository.py b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py similarity index 93% rename from monkey/monkey_island/cc/repository/i_configuration_repository.py rename to monkey/monkey_island/cc/repository/i_agent_configuration_repository.py index 58a97bce9..05817b80d 100644 --- a/monkey/monkey_island/cc/repository/i_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py @@ -3,7 +3,7 @@ from abc import ABC from common.configuration import AgentConfiguration -class IConfigurationRepository(ABC): +class IAgentConfigurationRepository(ABC): """ A repository used to store and retrieve the agent configuration. """ From 5ebdb60ea4297f28ecbfceb05bf6ca8465c552d7 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 11:41:29 -0400 Subject: [PATCH 09/19] Island: Add @abstractmethod in IAgentConfigurationRepository --- .../cc/repository/i_agent_configuration_repository.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py index 05817b80d..4129d119c 100644 --- a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py @@ -1,4 +1,4 @@ -from abc import ABC +from abc import ABC, abstractmethod from common.configuration import AgentConfiguration @@ -8,6 +8,7 @@ class IAgentConfigurationRepository(ABC): A repository used to store and retrieve the agent configuration. """ + @abstractmethod def get_configuration(self) -> AgentConfiguration: """ Retrieve the agent configuration from the repository @@ -16,6 +17,7 @@ class IAgentConfigurationRepository(ABC): """ pass + @abstractmethod def set_configuration(self, agent_configuration: AgentConfiguration): """ Store the agent configuration in the repository From bdce5f84a6dbf43e5b8b38cf72ba7d30c1d8b61c Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 12:09:30 -0400 Subject: [PATCH 10/19] Island: Add FileAgentConfigurationRepository --- .../monkey_island/cc/repository/__init__.py | 2 ++ .../file_agent_configuration_repository.py | 25 +++++++++++++++++++ ...est_file_agent_configuration_repository.py | 16 ++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 monkey/monkey_island/cc/repository/file_agent_configuration_repository.py create mode 100644 monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py diff --git a/monkey/monkey_island/cc/repository/__init__.py b/monkey/monkey_island/cc/repository/__init__.py index 885d467be..ffe00e736 100644 --- a/monkey/monkey_island/cc/repository/__init__.py +++ b/monkey/monkey_island/cc/repository/__init__.py @@ -1,3 +1,5 @@ from .file_storage import FileRetrievalError, IFileRepository, LocalStorageFileRepository from .i_agent_binary_repository import IAgentBinaryRepository, AgentRetrievalError from .agent_binary_repository import AgentBinaryRepository +from .i_agent_configuration_repository import IAgentConfigurationRepository +from .file_agent_configuration_repository import FileAgentConfigurationRepository diff --git a/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py b/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py new file mode 100644 index 000000000..e9724aa4b --- /dev/null +++ b/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py @@ -0,0 +1,25 @@ +import io + +from common.configuration import AgentConfiguration, AgentConfigurationSchema +from monkey_island.cc.repository import IAgentConfigurationRepository, IFileRepository + +AGENT_CONFIGURATION_FILE_NAME = "agent_configuration.json" + + +class FileAgentConfigurationRepository(IAgentConfigurationRepository): + def __init__(self, file_repository: IFileRepository): + self._file_repository = file_repository + self._schema = AgentConfigurationSchema() + + def get_configuration(self) -> AgentConfiguration: + with self._file_repository.open_file(AGENT_CONFIGURATION_FILE_NAME) as f: + configuration_json = f.read().decode() + + return self._schema.loads(configuration_json) + + def set_configuration(self, agent_configuration: AgentConfiguration): + configuration_json = self._schema.dumps(agent_configuration) + + self._file_repository.save_file( + AGENT_CONFIGURATION_FILE_NAME, io.BytesIO(configuration_json.encode()) + ) diff --git a/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py b/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py new file mode 100644 index 000000000..bfb894913 --- /dev/null +++ b/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py @@ -0,0 +1,16 @@ +from tests.common.example_agent_configuration import AGENT_CONFIGURATION +from tests.monkey_island import SingleFileRepository + +from common.configuration import AgentConfigurationSchema +from monkey_island.cc.repository import FileAgentConfigurationRepository + + +def test_store_agent_config(): + repository = FileAgentConfigurationRepository(SingleFileRepository()) + schema = AgentConfigurationSchema() + agent_configuration = schema.load(AGENT_CONFIGURATION) + + repository.set_configuration(agent_configuration) + retrieved_agent_configuration = repository.get_configuration() + + assert retrieved_agent_configuration == agent_configuration From 73ead3bb261944fa0430e462c711d0543541676b Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 12:10:43 -0400 Subject: [PATCH 11/19] Island: Rename set_configuration() -> store_configuration() --- .../cc/repository/file_agent_configuration_repository.py | 2 +- .../cc/repository/i_agent_configuration_repository.py | 2 +- .../cc/repository/test_file_agent_configuration_repository.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py b/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py index e9724aa4b..2cd2c8c93 100644 --- a/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py @@ -17,7 +17,7 @@ class FileAgentConfigurationRepository(IAgentConfigurationRepository): return self._schema.loads(configuration_json) - def set_configuration(self, agent_configuration: AgentConfiguration): + def store_configuration(self, agent_configuration: AgentConfiguration): configuration_json = self._schema.dumps(agent_configuration) self._file_repository.save_file( diff --git a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py index 4129d119c..f91895c8b 100644 --- a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py @@ -18,7 +18,7 @@ class IAgentConfigurationRepository(ABC): pass @abstractmethod - def set_configuration(self, agent_configuration: AgentConfiguration): + def store_configuration(self, agent_configuration: AgentConfiguration): """ Store the agent configuration in the repository diff --git a/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py b/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py index bfb894913..941dd2586 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py +++ b/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py @@ -10,7 +10,7 @@ def test_store_agent_config(): schema = AgentConfigurationSchema() agent_configuration = schema.load(AGENT_CONFIGURATION) - repository.set_configuration(agent_configuration) + repository.store_configuration(agent_configuration) retrieved_agent_configuration = repository.get_configuration() assert retrieved_agent_configuration == agent_configuration From 30065952a5cdbaa794cdf2648e6705cf83b475ed Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 12:13:18 -0400 Subject: [PATCH 12/19] Island: Add RetrievalError --- monkey/monkey_island/cc/repository/__init__.py | 1 + monkey/monkey_island/cc/repository/errors.py | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 monkey/monkey_island/cc/repository/errors.py diff --git a/monkey/monkey_island/cc/repository/__init__.py b/monkey/monkey_island/cc/repository/__init__.py index ffe00e736..0ff63b842 100644 --- a/monkey/monkey_island/cc/repository/__init__.py +++ b/monkey/monkey_island/cc/repository/__init__.py @@ -3,3 +3,4 @@ from .i_agent_binary_repository import IAgentBinaryRepository, AgentRetrievalErr from .agent_binary_repository import AgentBinaryRepository from .i_agent_configuration_repository import IAgentConfigurationRepository from .file_agent_configuration_repository import FileAgentConfigurationRepository +from .errors import RetrievalError diff --git a/monkey/monkey_island/cc/repository/errors.py b/monkey/monkey_island/cc/repository/errors.py new file mode 100644 index 000000000..b7beb36fe --- /dev/null +++ b/monkey/monkey_island/cc/repository/errors.py @@ -0,0 +1,2 @@ +class RetrievalError(RuntimeError): + pass From 922cb8cea97f8744a47615c76e3afb33f4d54a6b Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 12:14:30 -0400 Subject: [PATCH 13/19] Island: Add RetrievalError --- monkey/monkey_island/cc/repository/__init__.py | 2 +- .../cc/repository/file_storage/i_file_repository.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/repository/__init__.py b/monkey/monkey_island/cc/repository/__init__.py index 0ff63b842..cc89c5c57 100644 --- a/monkey/monkey_island/cc/repository/__init__.py +++ b/monkey/monkey_island/cc/repository/__init__.py @@ -1,6 +1,6 @@ +from .errors import RetrievalError from .file_storage import FileRetrievalError, IFileRepository, LocalStorageFileRepository from .i_agent_binary_repository import IAgentBinaryRepository, AgentRetrievalError from .agent_binary_repository import AgentBinaryRepository from .i_agent_configuration_repository import IAgentConfigurationRepository from .file_agent_configuration_repository import FileAgentConfigurationRepository -from .errors import RetrievalError diff --git a/monkey/monkey_island/cc/repository/file_storage/i_file_repository.py b/monkey/monkey_island/cc/repository/file_storage/i_file_repository.py index a0865b797..2531fd711 100644 --- a/monkey/monkey_island/cc/repository/file_storage/i_file_repository.py +++ b/monkey/monkey_island/cc/repository/file_storage/i_file_repository.py @@ -1,8 +1,10 @@ import abc from typing import BinaryIO +from monkey_island.cc.repository import RetrievalError -class FileRetrievalError(RuntimeError): + +class FileRetrievalError(RetrievalError): pass From 9a216e9c3ddb9bd2f668d68a2746aea283b4b05d Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 12:15:55 -0400 Subject: [PATCH 14/19] Island: Add "raises" to docstring in get_configuration() --- .../cc/repository/i_agent_configuration_repository.py | 1 + 1 file changed, 1 insertion(+) diff --git a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py index f91895c8b..d99934ad9 100644 --- a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py @@ -14,6 +14,7 @@ class IAgentConfigurationRepository(ABC): Retrieve the agent configuration from the repository :return: The agent configuration + :raises RetrievalError: if the configuration can not be retrieved """ pass From a3e3e3e3245672e57773277d0a3f49ae75a8f0d9 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 12:48:54 -0400 Subject: [PATCH 15/19] Common: Add DEFAULT_AGENT_CONFIGURATION --- monkey/common/configuration/__init__.py | 1 + .../configuration/agent_configuration.py | 218 ++++++++++++++++++ .../common/test_agent_configuration.py | 14 +- 3 files changed, 232 insertions(+), 1 deletion(-) diff --git a/monkey/common/configuration/__init__.py b/monkey/common/configuration/__init__.py index 59186d56c..29f8f1e2c 100644 --- a/monkey/common/configuration/__init__.py +++ b/monkey/common/configuration/__init__.py @@ -1,4 +1,5 @@ from .agent_configuration import ( AgentConfiguration, AgentConfigurationSchema, + DEFAULT_AGENT_CONFIGURATION, ) diff --git a/monkey/common/configuration/agent_configuration.py b/monkey/common/configuration/agent_configuration.py index 15b338fe0..a4db46f2c 100644 --- a/monkey/common/configuration/agent_configuration.py +++ b/monkey/common/configuration/agent_configuration.py @@ -14,6 +14,224 @@ from .agent_sub_configurations import ( PropagationConfiguration, ) +DEFAULT_AGENT_CONFIGURATION = """{ + "keep_tunnel_open_time": 30, + "post_breach_actions": [ + { + "name": "CommunicateAsBackdoorUser", + "options": {} + }, + { + "name": "ModifyShellStartupFiles", + "options": {} + }, + { + "name": "HiddenFiles", + "options": {} + }, + { + "name": "TrapCommand", + "options": {} + }, + { + "name": "ChangeSetuidSetgid", + "options": {} + }, + { + "name": "ScheduleJobs", + "options": {} + }, + { + "name": "Timestomping", + "options": {} + }, + { + "name": "AccountDiscovery", + "options": {} + }, + { + "name": "ProcessListCollection", + "options": {} + } + ], + "credential_collectors": [ + { + "name": "MimikatzCollector", + "options": {} + }, + { + "name": "SSHCollector", + "options": {} + } + ], + "payloads": [ + { + "name": "ransomware", + "options": { + "encryption": { + "enabled": true, + "directories": { + "linux_target_dir": "", + "windows_target_dir": "" + } + }, + "other_behaviors": { + "readme": true + } + } + } + ], + "custom_pbas": { + "linux_command": "", + "linux_filename": "", + "windows_command": "", + "windows_filename": "" + }, + "propagation": { + "maximum_depth": 2, + "network_scan": { + "tcp": { + "timeout": 3000, + "ports": [ + 22, + 80, + 135, + 443, + 445, + 2222, + 3306, + 3389, + 5985, + 5986, + 7001, + 8008, + 8080, + 8088, + 8983, + 9200, + 9600 + ] + }, + "icmp": { + "timeout": 1000 + }, + "fingerprinters": [ + { + "name": "elastic", + "options": {} + }, + { + "name": "http", + "options": { + "http_ports": [ + 80, + 443, + 7001, + 8008, + 8080, + 8983, + 9200, + 9600 + ] + } + }, + { + "name": "mssql", + "options": {} + }, + { + "name": "smb", + "options": {} + }, + { + "name": "ssh", + "options": {} + } + ], + "targets": { + "blocked_ips": [], + "inaccessible_subnets": [], + "local_network_scan": true, + "subnets": [] + } + }, + "exploitation": { + "options": { + "http_ports": [ + 80, + 443, + 7001, + 8008, + 8080, + 8983, + 9200, + 9600 + ] + }, + "brute_force": [ + { + "name": "MSSQLExploiter", + "options": {}, + "supported_os": [ + "WINDOWS" + ] + }, + { + "name": "PowerShellExploiter", + "options": {}, + "supported_os": [ + "WINDOWS" + ] + }, + { + "name": "SSHExploiter", + "options": {}, + "supported_os": [ + "LINUX" + ] + }, + { + "name": "SmbExploiter", + "options": { + "smb_download_timeout": 30 + }, + "supported_os": [ + "WINDOWS" + ] + }, + { + "name": "WmiExploiter", + "options": { + "smb_download_timeout": 30 + }, + "supported_os": [ + "WINDOWS" + ] + } + ], + "vulnerability": [ + { + "name": "HadoopExploiter", + "options": {}, + "supported_os": [ + "LINUX", + "WINDOWS" + ] + }, + { + "name": "Log4ShellExploiter", + "options": {}, + "supported_os": [ + "LINUX", + "WINDOWS" + ] + } + ] + } + } + } +""" + @dataclass(frozen=True) class AgentConfiguration: diff --git a/monkey/tests/unit_tests/common/test_agent_configuration.py b/monkey/tests/unit_tests/common/test_agent_configuration.py index 9609a2d3a..733e2e708 100644 --- a/monkey/tests/unit_tests/common/test_agent_configuration.py +++ b/monkey/tests/unit_tests/common/test_agent_configuration.py @@ -24,7 +24,11 @@ from tests.common.example_agent_configuration import ( ) from common import OperatingSystems -from common.configuration import AgentConfiguration, AgentConfigurationSchema +from common.configuration import ( + DEFAULT_AGENT_CONFIGURATION, + AgentConfiguration, + AgentConfigurationSchema, +) from common.configuration.agent_sub_configuration_schemas import ( CustomPBAConfigurationSchema, ExploitationConfigurationSchema, @@ -171,3 +175,11 @@ def test_agent_configuration(): assert isinstance(config.payloads[0], PluginConfiguration) assert isinstance(config.propagation, PropagationConfiguration) assert config_dict == AGENT_CONFIGURATION + + +def test_default_agent_configuration(): + schema = AgentConfigurationSchema() + + config = schema.loads(DEFAULT_AGENT_CONFIGURATION) + + assert isinstance(config, AgentConfiguration) From 45168b5ba77a04a29e4b7aa3e238a147bf026f2f Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 12:55:28 -0400 Subject: [PATCH 16/19] Island: Return default configuration from get_configuration() --- .../file_agent_configuration_repository.py | 23 +++++++++++++++---- .../i_agent_configuration_repository.py | 3 ++- ...est_file_agent_configuration_repository.py | 12 +++++++++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py b/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py index 2cd2c8c93..fcccd49a1 100644 --- a/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/file_agent_configuration_repository.py @@ -1,7 +1,15 @@ import io -from common.configuration import AgentConfiguration, AgentConfigurationSchema -from monkey_island.cc.repository import IAgentConfigurationRepository, IFileRepository +from common.configuration import ( + DEFAULT_AGENT_CONFIGURATION, + AgentConfiguration, + AgentConfigurationSchema, +) +from monkey_island.cc.repository import ( + IAgentConfigurationRepository, + IFileRepository, + RetrievalError, +) AGENT_CONFIGURATION_FILE_NAME = "agent_configuration.json" @@ -12,10 +20,15 @@ class FileAgentConfigurationRepository(IAgentConfigurationRepository): self._schema = AgentConfigurationSchema() def get_configuration(self) -> AgentConfiguration: - with self._file_repository.open_file(AGENT_CONFIGURATION_FILE_NAME) as f: - configuration_json = f.read().decode() + try: + with self._file_repository.open_file(AGENT_CONFIGURATION_FILE_NAME) as f: + configuration_json = f.read().decode() - return self._schema.loads(configuration_json) + return self._schema.loads(configuration_json) + # TODO: Handle FileRetrievalError vs FileNotFoundError + # https://github.com/guardicore/monkey/blob/e8001d8cf76340e42bf17ff62523bd2d85fc4841/monkey/monkey_island/cc/repository/file_storage/local_storage_file_repository.py#L47-L50 + except RetrievalError: + return self._schema.loads(DEFAULT_AGENT_CONFIGURATION) def store_configuration(self, agent_configuration: AgentConfiguration): configuration_json = self._schema.dumps(agent_configuration) diff --git a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py index d99934ad9..105d26fe9 100644 --- a/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py +++ b/monkey/monkey_island/cc/repository/i_agent_configuration_repository.py @@ -13,7 +13,8 @@ class IAgentConfigurationRepository(ABC): """ Retrieve the agent configuration from the repository - :return: The agent configuration + :return: The agent configuration as retrieved from the repository, or the default + configuration if none could be retrieved. :raises RetrievalError: if the configuration can not be retrieved """ pass diff --git a/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py b/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py index 941dd2586..7ad066623 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py +++ b/monkey/tests/unit_tests/monkey_island/cc/repository/test_file_agent_configuration_repository.py @@ -1,7 +1,7 @@ from tests.common.example_agent_configuration import AGENT_CONFIGURATION from tests.monkey_island import SingleFileRepository -from common.configuration import AgentConfigurationSchema +from common.configuration import DEFAULT_AGENT_CONFIGURATION, AgentConfigurationSchema from monkey_island.cc.repository import FileAgentConfigurationRepository @@ -14,3 +14,13 @@ def test_store_agent_config(): retrieved_agent_configuration = repository.get_configuration() assert retrieved_agent_configuration == agent_configuration + + +def test_get_default_agent_config(): + repository = FileAgentConfigurationRepository(SingleFileRepository()) + schema = AgentConfigurationSchema() + default_agent_configuration = schema.loads(DEFAULT_AGENT_CONFIGURATION) + + retrieved_agent_configuration = repository.get_configuration() + + assert retrieved_agent_configuration == default_agent_configuration From 764bc1559bf37da23dbebbeaf0cd11d70a5cab46 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 13:08:22 -0400 Subject: [PATCH 17/19] Island: Add IAgentConfigurationRepository to the DIContainer --- monkey/monkey_island/cc/services/initialize.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/services/initialize.py b/monkey/monkey_island/cc/services/initialize.py index a5d283cb3..74d447c90 100644 --- a/monkey/monkey_island/cc/services/initialize.py +++ b/monkey/monkey_island/cc/services/initialize.py @@ -7,7 +7,9 @@ from common.utils.file_utils import get_binary_io_sha256_hash from monkey_island.cc.repository import ( AgentBinaryRepository, AgentRetrievalError, + FileAgentConfigurationRepository, IAgentBinaryRepository, + IAgentConfigurationRepository, IFileRepository, LocalStorageFileRepository, ) @@ -31,11 +33,14 @@ def initialize_services(data_dir: Path) -> DIContainer: container.register_instance(AWSInstance, AWSInstance()) container.register_instance( - IFileRepository, LocalStorageFileRepository(data_dir / "custom_pbas") + IFileRepository, LocalStorageFileRepository(data_dir / "runtime_data") ) container.register_instance(AWSService, container.resolve(AWSService)) container.register_instance(IAgentBinaryRepository, _build_agent_binary_repository()) container.register_instance(LocalMonkeyRunService, container.resolve(LocalMonkeyRunService)) + container.register_instance( + IAgentConfigurationRepository, container.resolve(FileAgentConfigurationRepository) + ) # This is temporary until we get DI all worked out. PostBreachFilesService.initialize(container.resolve(IFileRepository)) From e4a2a04765e20d4d7b0481cf5e11e4bd169d6bd8 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 19:14:38 -0400 Subject: [PATCH 18/19] UT: Remove duplicate SingleFileRepository This was added by mistake. Remove it! --- monkey/tests/common/SingleFileRepository.py | 23 --------------------- 1 file changed, 23 deletions(-) delete mode 100644 monkey/tests/common/SingleFileRepository.py diff --git a/monkey/tests/common/SingleFileRepository.py b/monkey/tests/common/SingleFileRepository.py deleted file mode 100644 index d00ee9ae9..000000000 --- a/monkey/tests/common/SingleFileRepository.py +++ /dev/null @@ -1,23 +0,0 @@ -import io -from typing import BinaryIO - -from monkey_island.cc.repository import FileRetrievalError, IFileRepository - - -class SingleFileRepository(IFileRepository): - def __init__(self): - self._file = None - - def save_file(self, unsafe_file_name: str, file_contents: BinaryIO): - self._file = io.BytesIO(file_contents.read()) - - def open_file(self, unsafe_file_name: str) -> BinaryIO: - if self._file is None: - raise FileRetrievalError() - return self._file - - def delete_file(self, unsafe_file_name: str): - self._file = None - - def delete_all_files(self): - self.delete_file("") From 58ea11ae9fbb101164de79ac5928796acb922be2 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Fri, 17 Jun 2022 19:16:19 -0400 Subject: [PATCH 19/19] Common: Move DEFAULT_AGENT_CONFIGURATION to its own file --- monkey/common/configuration/__init__.py | 2 +- .../configuration/agent_configuration.py | 218 ------------------ .../default_agent_configuration.py | 217 +++++++++++++++++ 3 files changed, 218 insertions(+), 219 deletions(-) create mode 100644 monkey/common/configuration/default_agent_configuration.py diff --git a/monkey/common/configuration/__init__.py b/monkey/common/configuration/__init__.py index 29f8f1e2c..7a9131cc7 100644 --- a/monkey/common/configuration/__init__.py +++ b/monkey/common/configuration/__init__.py @@ -1,5 +1,5 @@ from .agent_configuration import ( AgentConfiguration, AgentConfigurationSchema, - DEFAULT_AGENT_CONFIGURATION, ) +from .default_agent_configuration import DEFAULT_AGENT_CONFIGURATION diff --git a/monkey/common/configuration/agent_configuration.py b/monkey/common/configuration/agent_configuration.py index a4db46f2c..15b338fe0 100644 --- a/monkey/common/configuration/agent_configuration.py +++ b/monkey/common/configuration/agent_configuration.py @@ -14,224 +14,6 @@ from .agent_sub_configurations import ( PropagationConfiguration, ) -DEFAULT_AGENT_CONFIGURATION = """{ - "keep_tunnel_open_time": 30, - "post_breach_actions": [ - { - "name": "CommunicateAsBackdoorUser", - "options": {} - }, - { - "name": "ModifyShellStartupFiles", - "options": {} - }, - { - "name": "HiddenFiles", - "options": {} - }, - { - "name": "TrapCommand", - "options": {} - }, - { - "name": "ChangeSetuidSetgid", - "options": {} - }, - { - "name": "ScheduleJobs", - "options": {} - }, - { - "name": "Timestomping", - "options": {} - }, - { - "name": "AccountDiscovery", - "options": {} - }, - { - "name": "ProcessListCollection", - "options": {} - } - ], - "credential_collectors": [ - { - "name": "MimikatzCollector", - "options": {} - }, - { - "name": "SSHCollector", - "options": {} - } - ], - "payloads": [ - { - "name": "ransomware", - "options": { - "encryption": { - "enabled": true, - "directories": { - "linux_target_dir": "", - "windows_target_dir": "" - } - }, - "other_behaviors": { - "readme": true - } - } - } - ], - "custom_pbas": { - "linux_command": "", - "linux_filename": "", - "windows_command": "", - "windows_filename": "" - }, - "propagation": { - "maximum_depth": 2, - "network_scan": { - "tcp": { - "timeout": 3000, - "ports": [ - 22, - 80, - 135, - 443, - 445, - 2222, - 3306, - 3389, - 5985, - 5986, - 7001, - 8008, - 8080, - 8088, - 8983, - 9200, - 9600 - ] - }, - "icmp": { - "timeout": 1000 - }, - "fingerprinters": [ - { - "name": "elastic", - "options": {} - }, - { - "name": "http", - "options": { - "http_ports": [ - 80, - 443, - 7001, - 8008, - 8080, - 8983, - 9200, - 9600 - ] - } - }, - { - "name": "mssql", - "options": {} - }, - { - "name": "smb", - "options": {} - }, - { - "name": "ssh", - "options": {} - } - ], - "targets": { - "blocked_ips": [], - "inaccessible_subnets": [], - "local_network_scan": true, - "subnets": [] - } - }, - "exploitation": { - "options": { - "http_ports": [ - 80, - 443, - 7001, - 8008, - 8080, - 8983, - 9200, - 9600 - ] - }, - "brute_force": [ - { - "name": "MSSQLExploiter", - "options": {}, - "supported_os": [ - "WINDOWS" - ] - }, - { - "name": "PowerShellExploiter", - "options": {}, - "supported_os": [ - "WINDOWS" - ] - }, - { - "name": "SSHExploiter", - "options": {}, - "supported_os": [ - "LINUX" - ] - }, - { - "name": "SmbExploiter", - "options": { - "smb_download_timeout": 30 - }, - "supported_os": [ - "WINDOWS" - ] - }, - { - "name": "WmiExploiter", - "options": { - "smb_download_timeout": 30 - }, - "supported_os": [ - "WINDOWS" - ] - } - ], - "vulnerability": [ - { - "name": "HadoopExploiter", - "options": {}, - "supported_os": [ - "LINUX", - "WINDOWS" - ] - }, - { - "name": "Log4ShellExploiter", - "options": {}, - "supported_os": [ - "LINUX", - "WINDOWS" - ] - } - ] - } - } - } -""" - @dataclass(frozen=True) class AgentConfiguration: diff --git a/monkey/common/configuration/default_agent_configuration.py b/monkey/common/configuration/default_agent_configuration.py new file mode 100644 index 000000000..933b723ea --- /dev/null +++ b/monkey/common/configuration/default_agent_configuration.py @@ -0,0 +1,217 @@ +DEFAULT_AGENT_CONFIGURATION = """{ + "keep_tunnel_open_time": 30, + "post_breach_actions": [ + { + "name": "CommunicateAsBackdoorUser", + "options": {} + }, + { + "name": "ModifyShellStartupFiles", + "options": {} + }, + { + "name": "HiddenFiles", + "options": {} + }, + { + "name": "TrapCommand", + "options": {} + }, + { + "name": "ChangeSetuidSetgid", + "options": {} + }, + { + "name": "ScheduleJobs", + "options": {} + }, + { + "name": "Timestomping", + "options": {} + }, + { + "name": "AccountDiscovery", + "options": {} + }, + { + "name": "ProcessListCollection", + "options": {} + } + ], + "credential_collectors": [ + { + "name": "MimikatzCollector", + "options": {} + }, + { + "name": "SSHCollector", + "options": {} + } + ], + "payloads": [ + { + "name": "ransomware", + "options": { + "encryption": { + "enabled": true, + "directories": { + "linux_target_dir": "", + "windows_target_dir": "" + } + }, + "other_behaviors": { + "readme": true + } + } + } + ], + "custom_pbas": { + "linux_command": "", + "linux_filename": "", + "windows_command": "", + "windows_filename": "" + }, + "propagation": { + "maximum_depth": 2, + "network_scan": { + "tcp": { + "timeout": 3000, + "ports": [ + 22, + 80, + 135, + 443, + 445, + 2222, + 3306, + 3389, + 5985, + 5986, + 7001, + 8008, + 8080, + 8088, + 8983, + 9200, + 9600 + ] + }, + "icmp": { + "timeout": 1000 + }, + "fingerprinters": [ + { + "name": "elastic", + "options": {} + }, + { + "name": "http", + "options": { + "http_ports": [ + 80, + 443, + 7001, + 8008, + 8080, + 8983, + 9200, + 9600 + ] + } + }, + { + "name": "mssql", + "options": {} + }, + { + "name": "smb", + "options": {} + }, + { + "name": "ssh", + "options": {} + } + ], + "targets": { + "blocked_ips": [], + "inaccessible_subnets": [], + "local_network_scan": true, + "subnets": [] + } + }, + "exploitation": { + "options": { + "http_ports": [ + 80, + 443, + 7001, + 8008, + 8080, + 8983, + 9200, + 9600 + ] + }, + "brute_force": [ + { + "name": "MSSQLExploiter", + "options": {}, + "supported_os": [ + "WINDOWS" + ] + }, + { + "name": "PowerShellExploiter", + "options": {}, + "supported_os": [ + "WINDOWS" + ] + }, + { + "name": "SSHExploiter", + "options": {}, + "supported_os": [ + "LINUX" + ] + }, + { + "name": "SmbExploiter", + "options": { + "smb_download_timeout": 30 + }, + "supported_os": [ + "WINDOWS" + ] + }, + { + "name": "WmiExploiter", + "options": { + "smb_download_timeout": 30 + }, + "supported_os": [ + "WINDOWS" + ] + } + ], + "vulnerability": [ + { + "name": "HadoopExploiter", + "options": {}, + "supported_os": [ + "LINUX", + "WINDOWS" + ] + }, + { + "name": "Log4ShellExploiter", + "options": {}, + "supported_os": [ + "LINUX", + "WINDOWS" + ] + } + ] + } + } + } +"""