2019-10-01 15:42:51 +08:00
|
|
|
import logging
|
2020-07-15 23:46:04 +08:00
|
|
|
import os
|
|
|
|
from time import sleep
|
2019-10-01 15:42:51 +08:00
|
|
|
|
2019-08-29 20:14:07 +08:00
|
|
|
import pytest
|
2021-03-02 21:01:56 +08:00
|
|
|
from typing_extensions import Type
|
|
|
|
|
|
|
|
from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import \
|
|
|
|
CommunicationAnalyzer
|
2021-03-08 17:07:24 +08:00
|
|
|
from envs.monkey_zoo.blackbox.analyzers.zerologon_analyzer import ZeroLogonAnalyzer
|
2021-03-02 21:01:56 +08:00
|
|
|
from envs.monkey_zoo.blackbox.island_client.island_config_parser import \
|
|
|
|
IslandConfigParser
|
|
|
|
from envs.monkey_zoo.blackbox.island_client.monkey_island_client import \
|
|
|
|
MonkeyIslandClient
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.config_template import ConfigTemplate
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.elastic import Elastic
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.hadoop import Hadoop
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.mssql import Mssql
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.performance import Performance
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.shellshock import ShellShock
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.smb_mimikatz import SmbMimikatz
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.smb_pth import SmbPth
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.ssh import Ssh
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.struts2 import Struts2
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.tunneling import Tunneling
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.weblogic import Weblogic
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.wmi_mimikatz import WmiMimikatz
|
|
|
|
from envs.monkey_zoo.blackbox.island_configs.wmi_pth import WmiPth
|
2021-03-08 17:07:24 +08:00
|
|
|
from envs.monkey_zoo.blackbox.island_configs.zerologon import ZeroLogon
|
2021-03-02 21:01:56 +08:00
|
|
|
from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import \
|
|
|
|
TestLogsHandler
|
2020-04-24 18:19:07 +08:00
|
|
|
from envs.monkey_zoo.blackbox.tests.exploitation import ExploitationTest
|
2021-03-02 21:01:56 +08:00
|
|
|
from envs.monkey_zoo.blackbox.tests.performance.map_generation import \
|
|
|
|
MapGenerationTest
|
|
|
|
from envs.monkey_zoo.blackbox.tests.performance.map_generation_from_telemetries import \
|
|
|
|
MapGenerationFromTelemetryTest
|
|
|
|
from envs.monkey_zoo.blackbox.tests.performance.report_generation import \
|
|
|
|
ReportGenerationTest
|
2020-04-30 21:12:58 +08:00
|
|
|
from envs.monkey_zoo.blackbox.tests.performance.report_generation_from_telemetries import \
|
|
|
|
ReportGenerationFromTelemetryTest
|
2021-03-02 21:01:56 +08:00
|
|
|
from envs.monkey_zoo.blackbox.tests.performance.telemetry_performance_test import \
|
|
|
|
TelemetryPerformanceTest
|
2019-09-11 17:39:28 +08:00
|
|
|
from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers
|
2019-08-27 20:52:39 +08:00
|
|
|
|
2019-09-24 20:38:16 +08:00
|
|
|
DEFAULT_TIMEOUT_SECONDS = 5*60
|
2019-09-13 21:12:58 +08:00
|
|
|
MACHINE_BOOTUP_WAIT_SECONDS = 30
|
2019-10-29 20:04:48 +08:00
|
|
|
GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'hadoop-2', 'hadoop-3', 'mssql-16',
|
2019-10-11 22:08:15 +08:00
|
|
|
'mimikatz-14', 'mimikatz-15', 'struts2-23', 'struts2-24', 'tunneling-9', 'tunneling-10',
|
2021-03-02 21:01:56 +08:00
|
|
|
'tunneling-11', 'tunneling-12', 'weblogic-18', 'weblogic-19', 'shellshock-8', 'zerologon-25']
|
2019-10-01 15:42:51 +08:00
|
|
|
LOG_DIR_PATH = "./logs"
|
2021-03-05 16:46:07 +08:00
|
|
|
logging.basicConfig(level=logging.INFO)
|
2019-10-01 21:11:53 +08:00
|
|
|
LOGGER = logging.getLogger(__name__)
|
2019-08-29 19:57:04 +08:00
|
|
|
|
2019-09-07 01:59:11 +08:00
|
|
|
|
2019-09-11 17:39:28 +08:00
|
|
|
@pytest.fixture(autouse=True, scope='session')
|
2020-05-13 15:44:04 +08:00
|
|
|
def GCPHandler(request, no_gcp):
|
|
|
|
if not no_gcp:
|
|
|
|
GCPHandler = gcp_machine_handlers.GCPHandler()
|
|
|
|
GCPHandler.start_machines(" ".join(GCP_TEST_MACHINE_LIST))
|
|
|
|
wait_machine_bootup()
|
2019-09-07 01:59:11 +08:00
|
|
|
|
2020-05-13 15:44:04 +08:00
|
|
|
def fin():
|
|
|
|
GCPHandler.stop_machines(" ".join(GCP_TEST_MACHINE_LIST))
|
2019-09-07 01:59:11 +08:00
|
|
|
|
2020-05-13 15:44:04 +08:00
|
|
|
request.addfinalizer(fin)
|
2019-09-07 01:59:11 +08:00
|
|
|
|
|
|
|
|
2019-09-13 21:12:58 +08:00
|
|
|
@pytest.fixture(autouse=True, scope='session')
|
|
|
|
def delete_logs():
|
2019-10-01 21:11:53 +08:00
|
|
|
LOGGER.info("Deleting monkey logs before new tests.")
|
2019-10-01 15:42:51 +08:00
|
|
|
TestLogsHandler.delete_log_folder_contents(TestMonkeyBlackbox.get_log_dir_path())
|
2019-09-13 21:12:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
def wait_machine_bootup():
|
|
|
|
sleep(MACHINE_BOOTUP_WAIT_SECONDS)
|
|
|
|
|
|
|
|
|
2019-09-11 17:39:28 +08:00
|
|
|
@pytest.fixture(scope='class')
|
2020-05-13 15:44:04 +08:00
|
|
|
def island_client(island, quick_performance_tests):
|
2019-09-11 17:39:28 +08:00
|
|
|
island_client_object = MonkeyIslandClient(island)
|
2020-05-13 15:44:04 +08:00
|
|
|
if not quick_performance_tests:
|
|
|
|
island_client_object.reset_env()
|
2019-09-11 17:39:28 +08:00
|
|
|
yield island_client_object
|
2019-09-07 01:59:11 +08:00
|
|
|
|
|
|
|
|
2019-09-11 17:39:28 +08:00
|
|
|
@pytest.mark.usefixtures('island_client')
|
|
|
|
# noinspection PyUnresolvedReferences
|
2021-03-02 21:01:56 +08:00
|
|
|
class TestMonkeyBlackbox:
|
2019-09-11 17:39:28 +08:00
|
|
|
|
2019-09-13 21:12:58 +08:00
|
|
|
@staticmethod
|
2021-03-02 21:01:56 +08:00
|
|
|
def run_exploitation_test(island_client: MonkeyIslandClient,
|
|
|
|
config_template: Type[ConfigTemplate],
|
|
|
|
test_name: str,
|
|
|
|
timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS):
|
|
|
|
raw_config = IslandConfigParser.get_raw_config(config_template, island_client)
|
|
|
|
analyzer = CommunicationAnalyzer(island_client,
|
|
|
|
IslandConfigParser.get_ips_of_targets(raw_config))
|
2019-10-01 15:42:51 +08:00
|
|
|
log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path())
|
2020-04-10 19:32:39 +08:00
|
|
|
ExploitationTest(
|
2020-02-25 17:24:28 +08:00
|
|
|
name=test_name,
|
|
|
|
island_client=island_client,
|
2021-03-02 21:01:56 +08:00
|
|
|
raw_config=raw_config,
|
2020-02-25 17:24:28 +08:00
|
|
|
analyzers=[analyzer],
|
|
|
|
timeout=timeout_in_seconds,
|
|
|
|
log_handler=log_handler).run()
|
2019-10-01 15:42:51 +08:00
|
|
|
|
2020-02-23 21:24:44 +08:00
|
|
|
@staticmethod
|
2020-04-10 19:32:39 +08:00
|
|
|
def run_performance_test(performance_test_class, island_client,
|
2021-03-02 21:01:56 +08:00
|
|
|
config_template, timeout_in_seconds, break_on_timeout=False):
|
|
|
|
raw_config = IslandConfigParser.get_raw_config(config_template, island_client)
|
2020-04-10 19:32:39 +08:00
|
|
|
log_handler = TestLogsHandler(performance_test_class.TEST_NAME,
|
|
|
|
island_client,
|
|
|
|
TestMonkeyBlackbox.get_log_dir_path())
|
2021-03-02 21:01:56 +08:00
|
|
|
analyzers = [CommunicationAnalyzer(island_client, IslandConfigParser.get_ips_of_targets(raw_config))]
|
2020-04-15 14:38:08 +08:00
|
|
|
performance_test_class(island_client=island_client,
|
2021-03-02 21:01:56 +08:00
|
|
|
raw_config=raw_config,
|
2020-04-15 14:38:08 +08:00
|
|
|
analyzers=analyzers,
|
|
|
|
timeout=timeout_in_seconds,
|
|
|
|
log_handler=log_handler,
|
|
|
|
break_on_timeout=break_on_timeout).run()
|
2020-02-23 21:24:44 +08:00
|
|
|
|
2019-10-01 15:42:51 +08:00
|
|
|
@staticmethod
|
|
|
|
def get_log_dir_path():
|
|
|
|
return os.path.abspath(LOG_DIR_PATH)
|
2019-09-07 01:59:11 +08:00
|
|
|
|
2019-09-11 17:39:28 +08:00
|
|
|
def test_server_online(self, island_client):
|
|
|
|
assert island_client.get_api_status() is not None
|
2019-09-07 01:59:11 +08:00
|
|
|
|
2020-04-29 15:39:10 +08:00
|
|
|
def test_ssh_exploiter(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, Ssh, "SSH_exploiter_and_keys")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_hadoop_exploiter(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, Hadoop, "Hadoop_exploiter", 6 * 60)
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_mssql_exploiter(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, Mssql, "MSSQL_exploiter")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_smb_and_mimikatz_exploiters(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, SmbMimikatz, "SMB_exploiter_mimikatz")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_smb_pth(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, SmbPth, "SMB_PTH")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_elastic_exploiter(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, Elastic, "Elastic_exploiter")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_struts_exploiter(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, Struts2, "Strtuts2_exploiter")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_weblogic_exploiter(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, Weblogic, "Weblogic_exploiter")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_shellshock_exploiter(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, ShellShock, "Shellschock_exploiter")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_tunneling(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, Tunneling, "Tunneling_exploiter", 15 * 60)
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_wmi_and_mimikatz_exploiters(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, WmiMimikatz, "WMI_exploiter,_mimikatz")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
|
|
|
def test_wmi_pth(self, island_client):
|
2021-03-02 21:01:56 +08:00
|
|
|
TestMonkeyBlackbox.run_exploitation_test(island_client, WmiPth, "WMI_PTH")
|
2020-04-29 15:39:10 +08:00
|
|
|
|
2021-03-08 17:07:24 +08:00
|
|
|
def test_zerologon_exploiter(self, island_client):
|
|
|
|
test_name = "ZeroLogon_exploiter"
|
2021-03-08 18:05:00 +08:00
|
|
|
expected_creds = ["Administrator",
|
|
|
|
"aad3b435b51404eeaad3b435b51404ee",
|
|
|
|
"2864b62ea4496934a5d6e86f50b834a5"]
|
2021-03-08 17:07:24 +08:00
|
|
|
raw_config = IslandConfigParser.get_raw_config(ZeroLogon, island_client)
|
|
|
|
analyzer = ZeroLogonAnalyzer(island_client, expected_creds)
|
|
|
|
log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path())
|
|
|
|
ExploitationTest(
|
|
|
|
name=test_name,
|
|
|
|
island_client=island_client,
|
|
|
|
raw_config=raw_config,
|
|
|
|
analyzers=[analyzer],
|
|
|
|
timeout=DEFAULT_TIMEOUT_SECONDS,
|
|
|
|
log_handler=log_handler).run()
|
|
|
|
|
2020-06-15 16:26:43 +08:00
|
|
|
@pytest.mark.skip(reason="Perfomance test that creates env from fake telemetries is faster, use that instead.")
|
2020-05-13 15:44:04 +08:00
|
|
|
def test_report_generation_performance(self, island_client, quick_performance_tests):
|
2020-04-29 15:39:10 +08:00
|
|
|
"""
|
|
|
|
This test includes the SSH + Elastic + Hadoop + MSSQL machines all in one test
|
|
|
|
for a total of 8 machines including the Monkey Island.
|
|
|
|
|
|
|
|
Is has 2 analyzers - the regular one which checks all the Monkeys
|
|
|
|
and the Timing one which checks how long the report took to execute
|
|
|
|
"""
|
2020-05-13 15:44:04 +08:00
|
|
|
if not quick_performance_tests:
|
|
|
|
TestMonkeyBlackbox.run_performance_test(ReportGenerationTest,
|
|
|
|
island_client,
|
2021-03-02 21:01:56 +08:00
|
|
|
Performance,
|
2020-05-13 15:44:04 +08:00
|
|
|
timeout_in_seconds=10*60)
|
|
|
|
else:
|
|
|
|
LOGGER.error("This test doesn't support 'quick_performance_tests' option.")
|
|
|
|
assert False
|
|
|
|
|
2020-06-15 16:26:43 +08:00
|
|
|
@pytest.mark.skip(reason="Perfomance test that creates env from fake telemetries is faster, use that instead.")
|
2020-05-13 15:44:04 +08:00
|
|
|
def test_map_generation_performance(self, island_client, quick_performance_tests):
|
|
|
|
if not quick_performance_tests:
|
|
|
|
TestMonkeyBlackbox.run_performance_test(MapGenerationTest,
|
|
|
|
island_client,
|
|
|
|
"PERFORMANCE.conf",
|
|
|
|
timeout_in_seconds=10*60)
|
|
|
|
else:
|
|
|
|
LOGGER.error("This test doesn't support 'quick_performance_tests' option.")
|
|
|
|
assert False
|
|
|
|
|
|
|
|
def test_report_generation_from_fake_telemetries(self, island_client, quick_performance_tests):
|
|
|
|
ReportGenerationFromTelemetryTest(island_client, quick_performance_tests).run()
|
|
|
|
|
|
|
|
def test_map_generation_from_fake_telemetries(self, island_client, quick_performance_tests):
|
|
|
|
MapGenerationFromTelemetryTest(island_client, quick_performance_tests).run()
|
|
|
|
|
|
|
|
def test_telem_performance(self, island_client, quick_performance_tests):
|
2020-05-14 15:55:59 +08:00
|
|
|
TelemetryPerformanceTest(island_client, quick_performance_tests).test_telemetry_performance()
|