From b73c3d10e157f066214049f8cb1b6f413bfb61d7 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 28 Mar 2022 14:23:04 -0400 Subject: [PATCH 1/4] Island: Add a list of supported OSs to exploiters --- monkey/monkey_island/cc/services/config.py | 24 ++++++++++++++- .../monkey_configs/flat_config.json | 3 +- .../monkey_island/cc/services/test_config.py | 29 ++++++++++++------- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index f90df6847..c5f78e62d 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -3,6 +3,7 @@ import copy import functools import logging import re +from itertools import chain from typing import Any, Dict, List from jsonschema import Draft4Validator, validators @@ -629,9 +630,10 @@ class ConfigService: config.pop(flat_config_exploiter_classes_field, None) - return ConfigService._add_smb_download_timeout_to_exploiters( + formatted_exploiters_config = ConfigService._add_smb_download_timeout_to_exploiters( config, formatted_exploiters_config ) + return ConfigService._add_supported_os_to_exploiters(formatted_exploiters_config) @staticmethod def _add_smb_download_timeout_to_exploiters( @@ -644,3 +646,23 @@ class ConfigService: exploiter["options"]["smb_download_timeout"] = flat_config["smb_download_timeout"] return new_config + + @staticmethod + def _add_supported_os_to_exploiters( + formatted_config: Dict, + ) -> Dict[str, List[Dict[str, Any]]]: + supported_os = { + "HadoopExploiter": ["linux", "windows"], + "Log4ShellExploiter": ["linux", "windows"], + "MSSQLExploiter": ["windows"], + "PowerShellExploiter": ["windows"], + "SSHExploiter": ["linux"], + "SmbExploiter": ["windows"], + "WmiExploiter": ["windows"], + "ZerologonExploiter": ["windows"], + } + new_config = copy.deepcopy(formatted_config) + for exploiter in chain(new_config["brute_force"], new_config["vulnerability"]): + exploiter["supported_os"] = supported_os.get(exploiter["name"], []) + + return new_config diff --git a/monkey/tests/data_for_tests/monkey_configs/flat_config.json b/monkey/tests/data_for_tests/monkey_configs/flat_config.json index f36bc5d18..b9dae9453 100644 --- a/monkey/tests/data_for_tests/monkey_configs/flat_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/flat_config.json @@ -55,7 +55,8 @@ "HadoopExploiter", "MSSQLExploiter", "DrupalExploiter", - "PowerShellExploiter" + "PowerShellExploiter", + "Log4ShellExploiter" ], "export_monkey_telems": false, "finger_classes": [ diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py b/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py index 72dafd168..ae0a44cdc 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py +++ b/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py @@ -177,18 +177,27 @@ def test_format_config_for_agent__exploiters(flat_monkey_config): "http_ports": [80, 443, 7001, 8008, 8080, 9200], }, "brute_force": [ - {"name": "MSSQLExploiter", "options": {}}, - {"name": "PowerShellExploiter", "options": {}}, - {"name": "SSHExploiter", "options": {}}, - {"name": "SmbExploiter", "options": {"smb_download_timeout": 300}}, - {"name": "WmiExploiter", "options": {"smb_download_timeout": 300}}, + {"name": "MSSQLExploiter", "supported_os": ["windows"], "options": {}}, + {"name": "PowerShellExploiter", "supported_os": ["windows"], "options": {}}, + {"name": "SSHExploiter", "supported_os": ["linux"], "options": {}}, + { + "name": "SmbExploiter", + "supported_os": ["windows"], + "options": {"smb_download_timeout": 300}, + }, + { + "name": "WmiExploiter", + "supported_os": ["windows"], + "options": {"smb_download_timeout": 300}, + }, ], "vulnerability": [ - {"name": "DrupalExploiter", "options": {}}, - {"name": "HadoopExploiter", "options": {}}, - {"name": "Struts2Exploiter", "options": {}}, - {"name": "WebLogicExploiter", "options": {}}, - {"name": "ZerologonExploiter", "options": {}}, + {"name": "DrupalExploiter", "supported_os": [], "options": {}}, + {"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}}, + {"name": "Log4ShellExploiter", "supported_os": ["linux", "windows"], "options": {}}, + {"name": "Struts2Exploiter", "supported_os": [], "options": {}}, + {"name": "WebLogicExploiter", "supported_os": [], "options": {}}, + {"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}}, ], } ConfigService.format_flat_config_for_agent(flat_monkey_config) From ddbe5b463f72ab87d95395faf31e17d3e01b057d Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 28 Mar 2022 15:31:01 -0400 Subject: [PATCH 2/4] Agent: Skip exploiter if victim OS is not supported --- monkey/infection_monkey/master/exploiter.py | 10 ++ monkey/infection_monkey/puppet/mock_puppet.py | 12 +-- .../infection_monkey/master/test_exploiter.py | 96 +++++++++++++++---- 3 files changed, 94 insertions(+), 24 deletions(-) diff --git a/monkey/infection_monkey/master/exploiter.py b/monkey/infection_monkey/master/exploiter.py index 9a1aafa05..3f0087af8 100644 --- a/monkey/infection_monkey/master/exploiter.py +++ b/monkey/infection_monkey/master/exploiter.py @@ -114,6 +114,16 @@ class Exploiter: for exploiter in interruptible_iter(exploiters_to_run, stop): exploiter_name = exploiter["name"] + victim_os = victim_host.os.get("type") + + # We want to try all exploiters if the victim's OS is unknown + if victim_os is not None and victim_os not in exploiter["supported_os"]: + logger.debug( + f"Skipping {exploiter_name} because it does not support " + f"the victim's OS ({victim_os})" + ) + continue + exploiter_results = self._run_exploiter( exploiter_name, exploiter["options"], victim_host, current_depth, stop ) diff --git a/monkey/infection_monkey/puppet/mock_puppet.py b/monkey/infection_monkey/puppet/mock_puppet.py index 0196076ad..fecb175f9 100644 --- a/monkey/infection_monkey/puppet/mock_puppet.py +++ b/monkey/infection_monkey/puppet/mock_puppet.py @@ -163,8 +163,8 @@ class MockPuppet(IPuppet): "ssh_key": host, }, ] - info_powershell = { - "display_name": "PowerShell", + info_wmi = { + "display_name": "WMI", "started": "2021-11-25T15:57:06.307696", "finished": "2021-11-25T15:58:33.788238", "vulnerable_urls": [], @@ -189,15 +189,15 @@ class MockPuppet(IPuppet): successful_exploiters = { DOT_1: { - "PowerShellExploiter": ExploiterResultData( - True, True, False, os_windows, info_powershell, attempts, None - ), "ZerologonExploiter": ExploiterResultData( False, False, False, os_windows, {}, [], "Zerologon failed" ), "SSHExploiter": ExploiterResultData( False, False, False, os_linux, info_ssh, attempts, "Failed exploiting" ), + "WmiExploiter": ExploiterResultData( + True, True, False, os_windows, info_wmi, attempts, None + ), }, DOT_3: { "PowerShellExploiter": ExploiterResultData( @@ -205,7 +205,7 @@ class MockPuppet(IPuppet): False, False, os_windows, - info_powershell, + info_wmi, attempts, "PowerShell Exploiter Failed", ), diff --git a/monkey/tests/unit_tests/infection_monkey/master/test_exploiter.py b/monkey/tests/unit_tests/infection_monkey/master/test_exploiter.py index 014b3b912..eba0186a4 100644 --- a/monkey/tests/unit_tests/infection_monkey/master/test_exploiter.py +++ b/monkey/tests/unit_tests/infection_monkey/master/test_exploiter.py @@ -1,6 +1,7 @@ import logging from queue import Queue from threading import Barrier, Event +from typing import Iterable from unittest.mock import MagicMock import pytest @@ -37,29 +38,47 @@ def exploiter_config(): return { "options": {"dropper_path_linux": "/tmp/monkey"}, "brute_force": [ - {"name": "PowerShellExploiter", "options": {"timeout": 10}}, - {"name": "SSHExploiter", "options": {}}, + {"name": "HadoopExploiter", "supported_os": ["windows"], "options": {"timeout": 10}}, + {"name": "SSHExploiter", "supported_os": ["linux"], "options": {}}, + {"name": "WmiExploiter", "supported_os": ["windows"], "options": {"timeout": 10}}, ], "vulnerability": [ - {"name": "ZerologonExploiter", "options": {}}, + {"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}}, ], } @pytest.fixture def hosts(): - return [VictimHost("10.0.0.1"), VictimHost("10.0.0.3")] + host_1 = VictimHost("10.0.0.1") + host_2 = VictimHost("10.0.0.3") + return [host_1, host_2] @pytest.fixture def hosts_to_exploit(hosts): + return enqueue_hosts(hosts) + + +def enqueue_hosts(hosts: Iterable[VictimHost]): q = Queue() - q.put(hosts[0]) - q.put(hosts[1]) + for h in hosts: + q.put(h) return q +def get_host_exploit_combos_from_call_args_list(call_args_list): + host_exploit_combos = set() + + for call_args in call_args_list: + victim_host = call_args[0][0] + exploiter_name = call_args[0][1] + host_exploit_combos.add((victim_host, exploiter_name)) + + return host_exploit_combos + + CREDENTIALS_FOR_PROPAGATION = {"usernames": ["m0nk3y", "user"], "passwords": ["1234", "pword"]} @@ -69,12 +88,12 @@ def get_credentials_for_propagation(): @pytest.fixture def run_exploiters(exploiter_config, hosts_to_exploit, callback, scan_completed, stop): - def inner(puppet, num_workers): + def inner(puppet, num_workers, hosts=hosts_to_exploit): # Set this so that Exploiter() exits once it has processed all victims scan_completed.set() e = Exploiter(puppet, num_workers, get_credentials_for_propagation) - e.exploit_hosts(exploiter_config, hosts_to_exploit, 1, callback, scan_completed, stop) + e.exploit_hosts(exploiter_config, hosts, 1, callback, scan_completed, stop) return inner @@ -82,18 +101,16 @@ def run_exploiters(exploiter_config, hosts_to_exploit, callback, scan_completed, def test_exploiter(callback, hosts, hosts_to_exploit, run_exploiters): run_exploiters(MockPuppet(), 2) - assert callback.call_count == 5 - host_exploit_combos = set() - - for i in range(0, 5): - victim_host = callback.call_args_list[i][0][0] - exploiter_name = callback.call_args_list[i][0][1] - host_exploit_combos.add((victim_host, exploiter_name)) + assert callback.call_count == 8 + host_exploit_combos = get_host_exploit_combos_from_call_args_list(callback.call_args_list) assert ("ZerologonExploiter", hosts[0]) in host_exploit_combos - assert ("PowerShellExploiter", hosts[0]) in host_exploit_combos + assert ("HadoopExploiter", hosts[0]) in host_exploit_combos + assert ("SSHExploiter", hosts[0]) in host_exploit_combos + assert ("WmiExploiter", hosts[0]) in host_exploit_combos assert ("ZerologonExploiter", hosts[1]) in host_exploit_combos - assert ("PowerShellExploiter", hosts[1]) in host_exploit_combos + assert ("HadoopExploiter", hosts[1]) in host_exploit_combos + assert ("WmiExploiter", hosts[1]) in host_exploit_combos assert ("SSHExploiter", hosts[1]) in host_exploit_combos @@ -132,10 +149,53 @@ def test_exploiter_raises_exception(callback, hosts, hosts_to_exploit, run_explo mock_puppet.exploit_host = MagicMock(side_effect=Exception(error_message)) run_exploiters(mock_puppet, 3) - assert callback.call_count == 6 + assert callback.call_count == 8 for i in range(0, 6): exploit_result_data = callback.call_args_list[i][0][2] assert exploit_result_data.exploitation_success is False assert exploit_result_data.propagation_success is False assert error_message in exploit_result_data.error_message + + +def test_windows_exploiters_run_on_windows_host(callback, hosts, hosts_to_exploit, run_exploiters): + host = VictimHost("10.0.0.1") + host.os["type"] = "windows" + q = enqueue_hosts([host]) + run_exploiters(MockPuppet(), 1, q) + + assert callback.call_count == 3 + host_exploit_combos = get_host_exploit_combos_from_call_args_list(callback.call_args_list) + + assert ("SSHExploiter", host) not in host_exploit_combos + + +def test_linux_exploiters_run_on_linux_host(callback, hosts, hosts_to_exploit, run_exploiters): + host = VictimHost("10.0.0.1") + host.os["type"] = "linux" + q = enqueue_hosts([host]) + run_exploiters(MockPuppet(), 1, q) + + assert callback.call_count == 1 + host_exploit_combos = get_host_exploit_combos_from_call_args_list(callback.call_args_list) + + assert ("SSHExploiter", host) in host_exploit_combos + + +def test_all_exploiters_run_on_unknown_host(callback, hosts, hosts_to_exploit, run_exploiters): + host = VictimHost("10.0.0.1") + try: + del host.os["type"] + except KeyError: + pass + + q = enqueue_hosts([host]) + run_exploiters(MockPuppet(), 1, q) + + assert callback.call_count == 4 + host_exploit_combos = get_host_exploit_combos_from_call_args_list(callback.call_args_list) + + assert ("ZerologonExploiter", hosts[0]) in host_exploit_combos + assert ("HadoopExploiter", hosts[0]) in host_exploit_combos + assert ("SSHExploiter", host) in host_exploit_combos + assert ("WmiExploiter", hosts[0]) in host_exploit_combos From 8737a3df89fe8d989ebbb648bb8112d9a38c8776 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 28 Mar 2022 15:33:10 -0400 Subject: [PATCH 3/4] Agent: Remove disused HostExploiter._TARGET_OS_TYPE --- monkey/infection_monkey/exploit/HostExploiter.py | 5 ----- monkey/infection_monkey/exploit/drupal.py | 1 - monkey/infection_monkey/exploit/hadoop.py | 1 - monkey/infection_monkey/exploit/log4shell.py | 1 - monkey/infection_monkey/exploit/mssqlexec.py | 1 - monkey/infection_monkey/exploit/powershell.py | 1 - monkey/infection_monkey/exploit/smbexec.py | 1 - monkey/infection_monkey/exploit/sshexec.py | 1 - monkey/infection_monkey/exploit/struts2.py | 1 - monkey/infection_monkey/exploit/weblogic.py | 3 --- monkey/infection_monkey/exploit/wmiexec.py | 1 - monkey/infection_monkey/exploit/zerologon.py | 1 - 12 files changed, 18 deletions(-) diff --git a/monkey/infection_monkey/exploit/HostExploiter.py b/monkey/infection_monkey/exploit/HostExploiter.py index 17bbee2a3..09a6d274e 100644 --- a/monkey/infection_monkey/exploit/HostExploiter.py +++ b/monkey/infection_monkey/exploit/HostExploiter.py @@ -15,8 +15,6 @@ logger = logging.getLogger(__name__) class HostExploiter: - _TARGET_OS_TYPE = [] - @property @abstractmethod def _EXPLOITED_SERVICE(self): @@ -44,9 +42,6 @@ class HostExploiter: def set_finish_time(self): self.exploit_info["finished"] = datetime.now().isoformat() - def is_os_supported(self): - return self.host.os.get("type") in self._TARGET_OS_TYPE - def report_login_attempt(self, result, user, password="", lm_hash="", ntlm_hash="", ssh_key=""): self.exploit_attempts.append( { diff --git a/monkey/infection_monkey/exploit/drupal.py b/monkey/infection_monkey/exploit/drupal.py index a07b99403..a0842383e 100644 --- a/monkey/infection_monkey/exploit/drupal.py +++ b/monkey/infection_monkey/exploit/drupal.py @@ -19,7 +19,6 @@ logger = logging.getLogger(__name__) class DrupalExploiter(WebRCE): - _TARGET_OS_TYPE = ["linux", "windows"] _EXPLOITED_SERVICE = "Drupal Server" def __init__(self, host): diff --git a/monkey/infection_monkey/exploit/hadoop.py b/monkey/infection_monkey/exploit/hadoop.py index 689120f59..c704f9814 100644 --- a/monkey/infection_monkey/exploit/hadoop.py +++ b/monkey/infection_monkey/exploit/hadoop.py @@ -25,7 +25,6 @@ from infection_monkey.utils.commands import build_monkey_commandline class HadoopExploiter(WebRCE): - _TARGET_OS_TYPE = ["linux", "windows"] _EXPLOITED_SERVICE = "Hadoop" HADOOP_PORTS = [("8088", False)] # How long we have our http server open for downloads in seconds diff --git a/monkey/infection_monkey/exploit/log4shell.py b/monkey/infection_monkey/exploit/log4shell.py index 0a70d6e01..e967ee6cb 100644 --- a/monkey/infection_monkey/exploit/log4shell.py +++ b/monkey/infection_monkey/exploit/log4shell.py @@ -27,7 +27,6 @@ logger = logging.getLogger(__name__) class Log4ShellExploiter(WebRCE): - _TARGET_OS_TYPE = ["linux", "windows"] _EXPLOITED_SERVICE = "Log4j" SERVER_SHUTDOWN_TIMEOUT = LONG_REQUEST_TIMEOUT REQUEST_TO_VICTIM_TIMEOUT = MEDIUM_REQUEST_TIMEOUT diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index b93b18649..f6b44471a 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -23,7 +23,6 @@ logger = logging.getLogger(__name__) class MSSQLExploiter(HostExploiter): _EXPLOITED_SERVICE = "MSSQL" - _TARGET_OS_TYPE = ["windows"] LOGIN_TIMEOUT = LONG_REQUEST_TIMEOUT QUERY_TIMEOUT = LONG_REQUEST_TIMEOUT # Time in seconds to wait between MSSQL queries. diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index f95b21df7..d711bec19 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -31,7 +31,6 @@ class RemoteAgentExecutionError(Exception): class PowerShellExploiter(HostExploiter): - _TARGET_OS_TYPE = ["windows"] _EXPLOITED_SERVICE = "PowerShell Remoting (WinRM)" def __init__(self): diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 2afc74439..10b7009b0 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -21,7 +21,6 @@ logger = getLogger(__name__) class SMBExploiter(HostExploiter): - _TARGET_OS_TYPE = ["windows"] _EXPLOITED_SERVICE = "SMB" KNOWN_PROTOCOLS = { "139/SMB": (r"ncacn_np:%s[\pipe\svcctl]", 139), diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index aa4ec8b54..0e6a9c038 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -31,7 +31,6 @@ TRANSFER_UPDATE_RATE = 15 class SSHExploiter(HostExploiter): - _TARGET_OS_TYPE = ["linux", None] _EXPLOITED_SERVICE = "SSH" def __init__(self): diff --git a/monkey/infection_monkey/exploit/struts2.py b/monkey/infection_monkey/exploit/struts2.py index 5efb7a64d..c576a5fbd 100644 --- a/monkey/infection_monkey/exploit/struts2.py +++ b/monkey/infection_monkey/exploit/struts2.py @@ -20,7 +20,6 @@ DOWNLOAD_TIMEOUT = 300 class Struts2Exploiter(WebRCE): - _TARGET_OS_TYPE = ["linux", "windows"] _EXPLOITED_SERVICE = "Struts2" def __init__(self, host): diff --git a/monkey/infection_monkey/exploit/weblogic.py b/monkey/infection_monkey/exploit/weblogic.py index b2747a3f2..6c2d7d327 100644 --- a/monkey/infection_monkey/exploit/weblogic.py +++ b/monkey/infection_monkey/exploit/weblogic.py @@ -29,7 +29,6 @@ HEADERS = { class WebLogicExploiter(HostExploiter): - _TARGET_OS_TYPE = ["linux", "windows"] _EXPLOITED_SERVICE = "Weblogic" def _exploit_host(self): @@ -58,7 +57,6 @@ class WebLogic201710271(WebRCE): "/wls-wsat/RegistrationRequesterPortType11", ] - _TARGET_OS_TYPE = WebLogicExploiter._TARGET_OS_TYPE _EXPLOITED_SERVICE = WebLogicExploiter._EXPLOITED_SERVICE def __init__(self, host): @@ -257,7 +255,6 @@ class WebLogic20192725(WebRCE): URLS = ["_async/AsyncResponseServiceHttps"] DELAY_BEFORE_EXPLOITING_SECONDS = 5 - _TARGET_OS_TYPE = WebLogicExploiter._TARGET_OS_TYPE _EXPLOITED_SERVICE = WebLogicExploiter._EXPLOITED_SERVICE def __init__(self, host): diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index 9d2af2e32..753dc511b 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -22,7 +22,6 @@ logger = logging.getLogger(__name__) class WmiExploiter(HostExploiter): - _TARGET_OS_TYPE = ["windows"] _EXPLOITED_SERVICE = "WMI (Windows Management Instrumentation)" @WmiTools.impacket_user diff --git a/monkey/infection_monkey/exploit/zerologon.py b/monkey/infection_monkey/exploit/zerologon.py index 8fe9cb52b..df5b7b4c6 100644 --- a/monkey/infection_monkey/exploit/zerologon.py +++ b/monkey/infection_monkey/exploit/zerologon.py @@ -33,7 +33,6 @@ logger = logging.getLogger(__name__) class ZerologonExploiter(HostExploiter): - _TARGET_OS_TYPE = ["windows"] _EXPLOITED_SERVICE = "Netlogon" MAX_ATTEMPTS = 2000 # For 2000, expected average number of attempts needed: 256. ERROR_CODE_ACCESS_DENIED = 0xC0000022 From a2e283e824a1100ba43ddb6b47aa6563eadc074f Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 28 Mar 2022 19:46:36 -0400 Subject: [PATCH 4/4] UT: Update automated_master_config.json --- .../automated_master_config.json | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json b/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json index c89ab6c04..e4712defe 100644 --- a/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json @@ -45,20 +45,21 @@ ] }, "exploiters": { + "options": {}, "brute_force": [ - {"name": "MSSQLExploiter"}, - {"name": "PowerShellExploiter"}, - {"name": "SmbExploiter"}, - {"name": "SSHExploiter"}, - {"name": "WmiExploiter"} + {"name": "MSSQLExploiter", "supported_os": ["windows"], "options": {}}, + {"name": "PowerShellExploiter", "supported_os": ["windows"], "options": {}}, + {"name": "SmbExploiter", "supported_os": ["windows"], "options": {}}, + {"name": "SSHExploiter", "supported_os": ["linux"], "options": {}}, + {"name": "WmiExploiter", "supported_os": ["windows"], "options": {}} ], "vulnerability": [ - {"name": "DrupalExploiter"}, - {"name": "HadoopExploiter"}, - {"name": "ShellShockExploiter"}, - {"name": "Struts2Exploiter"}, - {"name": "WebLogicExploiter"}, - {"name": "ZerologonExploiter"} + {"name": "DrupalExploiter", "supported_os": ["linux", "windows"], "options": {}}, + {"name": "HadoopExploiter", "supported_os": ["linux", "windows"], "options": {}}, + {"name": "ShellShockExploiter", "supported_os": ["linux"], "options": {}}, + {"name": "Struts2Exploiter", "supported_os": ["linux", "windows"], "options": {}}, + {"name": "WebLogicExploiter", "supported_os": ["linux", "windows"], "options": {}}, + {"name": "ZerologonExploiter", "supported_os": ["windows"], "options": {}} ] } }, @@ -102,7 +103,7 @@ "other_behaviors": {"readme": true} } }, - "system_info_collector_classes": [ + "credential_collector_classes": [ "MimikatzCollector", "SSHCollector" ]